diff options
32 files changed, 11944 insertions, 3369 deletions
diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c b/extras/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c index 08dab8a4d..0c8ef57b9 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c,v 1.1.1.2tsi Exp $ */ /* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. @@ -44,7 +44,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_ioctl.h" #include "r200_tcl.h" #include "r200_sanity.h" -#include "radeon_reg.h" +#include "r200_reg.h" static void print_state_atom( struct r200_state_atom *state ) { @@ -58,112 +58,139 @@ static void print_state_atom( struct r200_state_atom *state ) } -static void r200_emit_state_list( r200ContextPtr rmesa, - struct r200_state_atom *list ) +/* The state atoms will be emitted in the order they appear in the atom list, + * so this step is important. + */ +void r200SetUpAtomList( r200ContextPtr rmesa ) { - struct r200_state_atom *state, *tmp; - char *dest; - int i, size; - - size = 0; - foreach_s( state, tmp, list ) { - if (state->check( rmesa->glCtx, state->idx )) { -/* dest = r200AllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__); - memcpy( dest, state->cmd, state->cmd_size * 4);*/ - size += state->cmd_size; - state->dirty = GL_TRUE; - move_to_head( &(rmesa->hw.clean), state ); - if (R200_DEBUG & DEBUG_STATE) - print_state_atom( state ); - } - else if (R200_DEBUG & DEBUG_STATE) - fprintf(stderr, "skip state %s\n", state->name); - } - - if (!size) - return; + int i, mtu; + + mtu = rmesa->glCtx->Const.MaxTextureUnits; + + make_empty_list(&rmesa->hw.atomlist); + rmesa->hw.atomlist.name = "atom-list"; + + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ctx ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.set ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lin ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msk ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpt ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vtx ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vap ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vte ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msc ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cst ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.zbs ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcl ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msl ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcg ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.grd ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.fog ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tam ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tf ); + for (i = 0; i < mtu; ++i) + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tex[i] ); + for (i = 0; i < mtu; ++i) + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cube[i] ); + for (i = 0; i < 6; ++i) + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] ); - dest = r200AllocCmdBuf( rmesa, size * 4, __FUNCTION__); - -#define EMIT_ATOM(ATOM) \ -do { \ - if (rmesa->hw.ATOM.dirty) { \ - rmesa->hw.ATOM.dirty = GL_FALSE; \ - memcpy( dest, rmesa->hw.ATOM.cmd, rmesa->hw.ATOM.cmd_size * 4); \ - dest += rmesa->hw.ATOM.cmd_size * 4; \ - } \ -} while (0) - - EMIT_ATOM (ctx); - EMIT_ATOM (set); - EMIT_ATOM (lin); - EMIT_ATOM (msk); - EMIT_ATOM (vpt); - EMIT_ATOM (vtx); - EMIT_ATOM (vap); - EMIT_ATOM (vte); - EMIT_ATOM (msc); - EMIT_ATOM (cst); - EMIT_ATOM (zbs); - EMIT_ATOM (tcl); - EMIT_ATOM (msl); - EMIT_ATOM (tcg); - EMIT_ATOM (grd); - EMIT_ATOM (fog); - EMIT_ATOM (tam); - EMIT_ATOM (tf); - for (i = 0; i < 2; ++i) { - EMIT_ATOM (tex[i]); - } - for (i = 0; i < 2; ++i) { - EMIT_ATOM (cube[i]); - } - for (i = 0; i < 5; ++i) - EMIT_ATOM (mat[i]); - EMIT_ATOM (eye); - EMIT_ATOM (glt); - for (i = 0; i < 2; ++i) { - EMIT_ATOM (mtl[i]); - } for (i = 0; i < 8; ++i) - EMIT_ATOM (lit[i]); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] ); + for (i = 0; i < 3 + mtu; ++i) + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mat[i] ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.eye ); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.glt ); + for (i = 0; i < 2; ++i) + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] ); for (i = 0; i < 6; ++i) - EMIT_ATOM (ucp[i]); - for (i = 0; i < 6; ++i) - EMIT_ATOM (pix[i]); + insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] ); +} -#undef EMIT_ATOM +static void r200SaveHwState( r200ContextPtr rmesa ) +{ + struct r200_state_atom *atom; + char * dest = rmesa->backup_store.cmd_buf; -} + if (R200_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + rmesa->backup_store.cmd_used = 0; + foreach( atom, &rmesa->hw.atomlist ) { + if ( atom->check( rmesa->glCtx, atom->idx ) ) { + int size = atom->cmd_size * 4; + memcpy( dest, atom->cmd, size); + dest += size; + rmesa->backup_store.cmd_used += size; + if (R200_DEBUG & DEBUG_STATE) + print_state_atom( atom ); + } + } + + assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ ); + if (R200_DEBUG & DEBUG_STATE) + fprintf(stderr, "Returning to r200EmitState\n"); +} void r200EmitState( r200ContextPtr rmesa ) { - struct r200_state_atom *state, *tmp; + char *dest; + int mtu; + struct r200_state_atom *atom; if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) fprintf(stderr, "%s\n", __FUNCTION__); - /* Somewhat overkill: - */ - if ( rmesa->lost_context) { - if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL)) - fprintf(stderr, "%s - lost context\n", __FUNCTION__); + if (rmesa->save_on_next_emit) { + r200SaveHwState(rmesa); + rmesa->save_on_next_emit = GL_FALSE; + } + + if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty) + return; - foreach_s( state, tmp, &(rmesa->hw.clean) ) - move_to_tail(&(rmesa->hw.dirty), state ); + mtu = rmesa->glCtx->Const.MaxTextureUnits; - rmesa->lost_context = 0; + /* To avoid going across the entire set of states multiple times, just check + * for enough space for the case of emitting all state, and inline the + * r200AllocCmdBuf code here without all the checks. + */ + r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size ); + + /* we need to calculate dest after EnsureCmdBufSpace + as we may flush the buffer - airlied */ + dest = rmesa->store.cmd_buf + rmesa->store.cmd_used; + if (R200_DEBUG & DEBUG_STATE) { + foreach( atom, &rmesa->hw.atomlist ) { + if ( atom->dirty || rmesa->hw.all_dirty ) { + if ( atom->check( rmesa->glCtx, atom->idx ) ) + print_state_atom( atom ); + else + fprintf(stderr, "skip state %s\n", atom->name); + } + } } -/* else { - move_to_tail( &rmesa->hw.dirty, &rmesa->hw.mtl[0] );*/ - /* odd bug? -- isosurf, cycle between reflect & lit */ -/* }*/ - r200_emit_state_list( rmesa, &rmesa->hw.dirty ); -} + foreach( atom, &rmesa->hw.atomlist ) { + if ( rmesa->hw.all_dirty ) + atom->dirty = GL_TRUE; + if ( atom->dirty ) { + if ( atom->check( rmesa->glCtx, atom->idx ) ) { + int size = atom->cmd_size * 4; + memcpy( dest, atom->cmd, size); + dest += size; + rmesa->store.cmd_used += size; + atom->dirty = GL_FALSE; + } + } + } + assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ ); + rmesa->hw.is_dirty = GL_FALSE; + rmesa->hw.all_dirty = GL_FALSE; +} /* Fire a section of the retained (indexed_verts) buffer as a regular * primtive. @@ -172,7 +199,7 @@ extern void r200EmitVbufPrim( r200ContextPtr rmesa, GLuint primitive, GLuint vertex_nr ) { - drmRadeonCmdHeader *cmd; + drm_radeon_cmd_header_t *cmd; assert(!(primitive & R200_VF_PRIM_WALK_IND)); @@ -182,7 +209,7 @@ extern void r200EmitVbufPrim( r200ContextPtr rmesa, fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__, rmesa->store.cmd_used/4, primitive, vertex_nr); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 3 * sizeof(*cmd), + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ, __FUNCTION__ ); cmd[0].i = 0; cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; @@ -225,7 +252,7 @@ GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, GLuint primitive, GLuint min_nr ) { - drmRadeonCmdHeader *cmd; + drm_radeon_cmd_header_t *cmd; GLushort *retval; if (R200_DEBUG & DEBUG_IOCTL) @@ -235,8 +262,7 @@ GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, r200EmitState( rmesa ); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, - 12 + min_nr*2, + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr), __FUNCTION__ ); cmd[0].i = 0; cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; @@ -268,13 +294,13 @@ void r200EmitVertexAOS( r200ContextPtr rmesa, GLuint vertex_size, GLuint offset ) { - drmRadeonCmdHeader *cmd; + drm_radeon_cmd_header_t *cmd; if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL)) fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", __FUNCTION__, vertex_size, offset); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 5 * sizeof(int), + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ, __FUNCTION__ ); cmd[0].header.cmd_type = RADEON_CMD_PACKET3; @@ -290,19 +316,18 @@ void r200EmitAOS( r200ContextPtr rmesa, GLuint nr, GLuint offset ) { - drmRadeonCmdHeader *cmd; - int sz = 3 + ((nr/2)*3) + ((nr&1)*2); + drm_radeon_cmd_header_t *cmd; + int sz = AOS_BUFSZ(nr); int i; int *tmp; if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sz * sizeof(int), - __FUNCTION__ ); + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ ); cmd[0].i = 0; cmd[0].header.cmd_type = RADEON_CMD_PACKET3; - cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | ((sz-3) << 16); + cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16); cmd[2].i = nr; tmp = &cmd[0].i; cmd += 3; @@ -340,7 +365,7 @@ void r200EmitBlit( r200ContextPtr rmesa, GLint dstx, GLint dsty, GLuint w, GLuint h ) { - drmRadeonCmdHeader *cmd; + drm_radeon_cmd_header_t *cmd; if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", @@ -356,7 +381,7 @@ void r200EmitBlit( r200ContextPtr rmesa, assert( w < (1<<16) ); assert( h < (1<<16) ); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 8 * sizeof(int), + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int), __FUNCTION__ ); @@ -383,11 +408,11 @@ void r200EmitBlit( r200ContextPtr rmesa, void r200EmitWait( r200ContextPtr rmesa, GLuint flags ) { if (rmesa->dri.drmMinor >= 6) { - drmRadeonCmdHeader *cmd; + drm_radeon_cmd_header_t *cmd; assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) ); - cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 1 * sizeof(int), + cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int), __FUNCTION__ ); cmd[0].i = 0; cmd[0].wait.cmd_type = RADEON_CMD_WAIT; diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c b/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c index 4471d4bc3..d4492636e 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c,v 1.5tsi Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c,v 1.6tsi Exp $ */ /* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. @@ -47,7 +47,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_ioctl.h" #include "r200_tcl.h" #include "r200_sanity.h" -#include "radeon_reg.h" +#include "r200_reg.h" #include "vblank.h" diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_reg.h b/extras/Mesa/src/mesa/drivers/dri/r200/r200_reg.h index 8e9126342..c60a1ad2b 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_reg.h +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_reg.h,v 1.2 2002/12/16 16:18:54 dawes Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_reg.h,v 1.1.1.2tsi Exp $ */ /* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. @@ -30,6 +30,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef _R200_REG_H_ #define _R200_REG_H_ +#include "radeon_reg.h" + #define R200_PP_MISC 0x1c14 #define R200_REF_ALPHA_MASK 0x000000ff #define R200_ALPHA_TEST_FAIL (0 << 8) @@ -58,6 +60,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_FOG_USE_DIFFUSE_ALPHA (2 << 25) #define R200_FOG_USE_SPEC_ALPHA (3 << 25) #define R200_FOG_USE_VTX_FOG (4 << 25) +#define R200_FOG_USE_MASK (7 << 25) #define R200_RE_SOLID_COLOR 0x1c1c #define R200_RB3D_BLENDCNTL 0x1c20 #define R200_COMB_FCN_MASK (7 << 12) @@ -69,39 +72,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_COMB_FCN_MAX (5 << 12) #define R200_COMB_FCN_RSUB_CLAMP (6 << 12) #define R200_COMB_FCN_RSUB_NOCLAMP (7 << 12) -#define R200_SRC_BLEND_GL_ZERO (32 << 16) -#define R200_SRC_BLEND_GL_ONE (33 << 16) -#define R200_SRC_BLEND_GL_SRC_COLOR (34 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) -#define R200_SRC_BLEND_GL_DST_COLOR (36 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) -#define R200_SRC_BLEND_GL_SRC_ALPHA (38 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) -#define R200_SRC_BLEND_GL_DST_ALPHA (40 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) -#define R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) -#define R200_SRC_BLEND_GL_CONST_COLOR (43 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR (44 << 16) -#define R200_SRC_BLEND_GL_CONST_ALPHA (45 << 16) -#define R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 16) -#define R200_SRC_BLEND_MASK (63 << 16) -#define R200_DST_BLEND_GL_ZERO (32 << 24) -#define R200_DST_BLEND_GL_ONE (33 << 24) -#define R200_DST_BLEND_GL_SRC_COLOR (34 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) -#define R200_DST_BLEND_GL_DST_COLOR (36 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) -#define R200_DST_BLEND_GL_SRC_ALPHA (38 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) -#define R200_DST_BLEND_GL_DST_ALPHA (40 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) -#define R200_DST_BLEND_GL_CONST_COLOR (43 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR (44 << 24) -#define R200_DST_BLEND_GL_CONST_ALPHA (45 << 24) -#define R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 24) -#define R200_DST_BLEND_MASK (63 << 24) -#define R200_RB3D_DEPTHOFFSET 0x1c24 -#define R200_RB3D_DEPTHPITCH 0x1c28 +#define R200_BLEND_GL_ZERO (32) +#define R200_BLEND_GL_ONE (33) +#define R200_BLEND_GL_SRC_COLOR (34) +#define R200_BLEND_GL_ONE_MINUS_SRC_COLOR (35) +#define R200_BLEND_GL_DST_COLOR (36) +#define R200_BLEND_GL_ONE_MINUS_DST_COLOR (37) +#define R200_BLEND_GL_SRC_ALPHA (38) +#define R200_BLEND_GL_ONE_MINUS_SRC_ALPHA (39) +#define R200_BLEND_GL_DST_ALPHA (40) +#define R200_BLEND_GL_ONE_MINUS_DST_ALPHA (41) +#define R200_BLEND_GL_SRC_ALPHA_SATURATE (42) /* src factor only */ +#define R200_BLEND_GL_CONST_COLOR (43) +#define R200_BLEND_GL_ONE_MINUS_CONST_COLOR (44) +#define R200_BLEND_GL_CONST_ALPHA (45) +#define R200_BLEND_GL_ONE_MINUS_CONST_ALPHA (46) +#define R200_BLEND_MASK (63) +#define R200_SRC_BLEND_SHIFT (16) +#define R200_DST_BLEND_SHIFT (24) +#define R200_RB3D_DEPTHOFFSET 0x1c24 +#define R200_RB3D_DEPTHPITCH 0x1c28 #define R200_DEPTHPITCH_MASK 0x00001ff8 #define R200_DEPTH_ENDIAN_NO_SWAP (0 << 18) #define R200_DEPTH_ENDIAN_WORD_SWAP (1 << 18) @@ -501,6 +491,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_OUTPUT_TEX_4 (1<<20) #define R200_OUTPUT_TEX_5 (1<<21) #define R200_OUTPUT_TEX_MASK (0x3f<<16) +#define R200_OUTPUT_DISCRETE_FOG (1<<24) #define R200_OUTPUT_PT_SIZE (1<<25) #define R200_FORCE_INORDER_PROC (1<<31) #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 @@ -1039,6 +1030,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) #define R200_TXC_ARG_A_MASK (31 << 0) #define R200_TXC_ARG_A_SHIFT 0 +#ifndef R200_TXC_ARG_B_ZERO /* Might be in radeon_reg.h */ #define R200_TXC_ARG_B_ZERO (0<<5) #define R200_TXC_ARG_B_CURRENT_COLOR (2<<5) #define R200_TXC_ARG_B_CURRENT_ALPHA (3<<5) @@ -1062,8 +1054,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXC_ARG_B_R5_ALPHA (21<<5) #define R200_TXC_ARG_B_TFACTOR1_COLOR (26<<5) #define R200_TXC_ARG_B_TFACTOR1_ALPHA (27<<5) +#endif #define R200_TXC_ARG_B_MASK (31 << 5) #define R200_TXC_ARG_B_SHIFT 5 +#ifndef R200_TXC_ARG_C_ZERO /* Might be in radeon_reg.h */ #define R200_TXC_ARG_C_ZERO (0<<10) #define R200_TXC_ARG_C_CURRENT_COLOR (2<<10) #define R200_TXC_ARG_C_CURRENT_ALPHA (3<<10) @@ -1087,6 +1081,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXC_ARG_C_R5_ALPHA (21<<10) #define R200_TXC_ARG_C_TFACTOR1_COLOR (26<<10) #define R200_TXC_ARG_C_TFACTOR1_ALPHA (27<<10) +#endif #define R200_TXC_ARG_C_MASK (31 << 10) #define R200_TXC_ARG_C_SHIFT 10 #define R200_TXC_COMP_ARG_A (1 << 16) @@ -1184,6 +1179,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXA_ARG_A_TFACTOR1_BLUE (27) #define R200_TXA_ARG_A_MASK (31 << 0) #define R200_TXA_ARG_A_SHIFT 0 +#ifndef R200_TXA_ARG_B_ZERO /* Might be in radeon_reg.h */ #define R200_TXA_ARG_B_ZERO (0<<5) #define R200_TXA_ARG_B_CURRENT_ALPHA (2<<5) /* guess */ #define R200_TXA_ARG_B_CURRENT_BLUE (3<<5) /* guess */ @@ -1207,8 +1203,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXA_ARG_B_R5_BLUE (21<<5) #define R200_TXA_ARG_B_TFACTOR1_ALPHA (26<<5) #define R200_TXA_ARG_B_TFACTOR1_BLUE (27<<5) +#endif #define R200_TXA_ARG_B_MASK (31 << 5) #define R200_TXA_ARG_B_SHIFT 5 +#ifndef R200_TXA_ARG_C_ZERO /* Might be in radeon_reg.h */ #define R200_TXA_ARG_C_ZERO (0<<10) #define R200_TXA_ARG_C_CURRENT_ALPHA (2<<10) /* guess */ #define R200_TXA_ARG_C_CURRENT_BLUE (3<<10) /* guess */ @@ -1232,6 +1230,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_TXA_ARG_C_R5_BLUE (21<<10) #define R200_TXA_ARG_C_TFACTOR1_ALPHA (26<<10) #define R200_TXA_ARG_C_TFACTOR1_BLUE (27<<10) +#endif #define R200_TXA_ARG_C_MASK (31 << 10) #define R200_TXA_ARG_C_SHIFT 10 #define R200_TXA_COMP_ARG_A (1 << 16) @@ -1320,6 +1319,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define R200_PP_TXABLEND_7 0x2f78 #define R200_PP_TXABLEND2_7 0x2f7c /* gap */ +#define R200_RB3D_BLENDCOLOR 0x3218 /* ARGB 8888 */ #define R200_RB3D_ABLENDCNTL 0x321C /* see BLENDCTL */ #define R200_RB3D_CBLENDCNTL 0x3220 /* see BLENDCTL */ diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c b/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c index 0a44a5882..7aa1ac94e 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c,v 1.1.1.2 2004/12/10 15:05:57 alanh Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c,v 1.2tsi Exp $ */ /************************************************************************** Copyright 2002 ATI Technologies Inc., Ontario, Canada, and @@ -41,7 +41,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_context.h" #include "r200_ioctl.h" #include "r200_sanity.h" -#include "radeon_reg.h" #include "r200_reg.h" /* Set this '1' to get more verbiage. diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c b/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c index c5c0f1e4b..28819b58d 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c,v 1.7tsi Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_screen.c,v 1.8tsi Exp $ */ /* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. @@ -46,7 +46,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r200_context.h" #include "r200_ioctl.h" #include "radeon_macros.h" -#include "radeon_reg.h" +#include "r200_reg.h" #include "utils.h" #include "vblank.h" diff --git a/extras/Mesa/src/mesa/drivers/dri/r200/r200_texmem.c b/extras/Mesa/src/mesa/drivers/dri/r200/r200_texmem.c index 1929397bf..21f55f00e 100644 --- a/extras/Mesa/src/mesa/drivers/dri/r200/r200_texmem.c +++ b/extras/Mesa/src/mesa/drivers/dri/r200/r200_texmem.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_texmem.c,v 1.5 2002/12/17 00:32:56 dawes Exp $ */ +/* $XFree86: xc/extras/Mesa/src/mesa/drivers/dri/r200/r200_texmem.c,v 1.1.1.4tsi Exp $ */ /************************************************************************** Copyright (C) Tungsten Graphics 2002. All Rights Reserved. @@ -43,8 +43,7 @@ SOFTWARE. #include "context.h" #include "colormac.h" #include "macros.h" -#include "simple_list.h" -#include "radeon_reg.h" /* gets definition for usleep */ +#include "r200_reg.h" /* gets definition for usleep */ #include "r200_context.h" #include "r200_state.h" #include "r200_ioctl.h" @@ -73,10 +72,8 @@ r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t ) for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) { if ( t == rmesa->state.texture.unit[i].texobj ) { rmesa->state.texture.unit[i].texobj = NULL; - remove_from_list( &rmesa->hw.tex[i] ); - make_empty_list( &rmesa->hw.tex[i] ); - remove_from_list( &rmesa->hw.cube[i] ); - make_empty_list( &rmesa->hw.cube[i] ); + rmesa->hw.tex[i].dirty = GL_FALSE; + rmesa->hw.cube[i].dirty = GL_FALSE; } } } @@ -231,7 +228,7 @@ static void r200UploadRectSubImage( r200ContextPtr rmesa, tex = (char *)texImage->Data + done * src_pitch; memset(®ion, 0, sizeof(region)); - r200AllocDmaRegion( rmesa, ®ion, lines * dstPitch, 64 ); + r200AllocDmaRegion( rmesa, ®ion, lines * dstPitch, 1024 ); /* Copy texdata to dma: */ @@ -240,10 +237,10 @@ static void r200UploadRectSubImage( r200ContextPtr rmesa, __FUNCTION__, src_pitch, dstPitch); if (src_pitch == dstPitch) { - memcpy( region.address, tex, lines * src_pitch ); + memcpy( region.address + region.start, tex, lines * src_pitch ); } else { - char *buf = region.address; + char *buf = region.address + region.start; int i; for (i = 0 ; i < lines ; i++) { memcpy( buf, tex, src_pitch ); @@ -286,8 +283,8 @@ static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t, GLuint offset; GLint imageWidth, imageHeight; GLint ret; - drmRadeonTexture tex; - drmRadeonTexImage tmp; + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; const int level = hwlevel + t->base.firstLevel; if ( R200_DEBUG & DEBUG_TEXTURE ) { @@ -304,26 +301,7 @@ static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t, return; } - switch (face) { - case 0: - texImage = t->base.tObj->Image[level]; - break; - case 1: - texImage = t->base.tObj->NegX[level]; - break; - case 2: - texImage = t->base.tObj->PosY[level]; - break; - case 3: - texImage = t->base.tObj->NegY[level]; - break; - case 4: - texImage = t->base.tObj->PosZ[level]; - break; - case 5: - texImage = t->base.tObj->NegZ[level]; - break; - } + texImage = t->base.tObj->Image[face][level]; if ( !texImage ) { if ( R200_DEBUG & DEBUG_TEXTURE ) @@ -380,7 +358,7 @@ static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t, t->image[face][hwlevel].data = texImage->Data; - /* Init the DRM_RADEON_TEXTURE command / drmRadeonTexture struct. + /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct. * NOTE: we're always use a 1KB-wide blit and I8 texture format. * We used to use 1, 2 and 4-byte texels and used to use the texture * width to dictate the blit width - but that won't work for compressed @@ -402,12 +380,20 @@ static void uploadSubImage( r200ContextPtr rmesa, r200TexObjPtr t, tex.image = &tmp; /* copy (x,y,width,height,data) */ - memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) ); + memcpy( &tmp, &t->image[face][hwlevel], sizeof(tmp) ); + /* Adjust the base offset to account for the Y-offset. This is done, + * instead of just letting the Y-offset automatically take care of it, + * because it is possible, for very large textures, for the Y-offset + * to exceede the [-8192,+8191] range. + */ + tex.offset += tmp.y * 1024; + tmp.y = 0; + LOCK_HARDWARE( rmesa ); do { ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE, - &tex, sizeof(drmRadeonTexture) ); + &tex, sizeof(drm_radeon_texture_t) ); if (ret) { if (R200_DEBUG & DEBUG_IOCTL) fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n"); diff --git a/programs/Xserver/hw/xfree86/CHANGELOG b/programs/Xserver/hw/xfree86/CHANGELOG index 83287db9f..161b99ed4 100644 --- a/programs/Xserver/hw/xfree86/CHANGELOG +++ b/programs/Xserver/hw/xfree86/CHANGELOG @@ -1,4 +1,11 @@ XFree86 4.7.99.15 (xx April 2008) + 37. Radeon driver changes: + - Merge in various changes from X.Org, via OpenBSD's xenocara repository. + Among other things, this adds support for newer Radeon's. + - Don't use vgaHW if the video mode on server entry is found to be an + accelerator (i.e. non-VGA) video mode (Marc La France). + - Avoid hard-failed master aborts while attempting to read video BIOS + (Marc La France). 36. Rage 128 driver changes: - Add support for dual head on Rage 128 Mobility's (X.Org, via OpenBSD's xenocara repository). @@ -20704,4 +20711,4 @@ XFree86 3.0a (28 April 1994) XFree86 3.0 (26 April 1994) -$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3944 2008/04/01 17:18:20 tsi Exp $ +$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3945 2008/04/02 20:47:56 tsi Exp $ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/Imakefile b/programs/Xserver/hw/xfree86/drivers/ati/Imakefile index eef5a54b2..0e6ab0a7d 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/Imakefile +++ b/programs/Xserver/hw/xfree86/drivers/ati/Imakefile @@ -1,4 +1,4 @@ -XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile,v 1.62tsi Exp $ +XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile,v 1.63tsi Exp $ XCOMM XCOMM Copyright 1997 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org XCOMM @@ -68,7 +68,8 @@ SRCS2 = atiaccel.c atiadjust.c atiaudio.c atibank.c aticlock.c aticonfig.c \ ativga.c atiwonder.c atiwonderio.c atixv.c $(MODSRCS2) SRCS3 = r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ r128_video.c $(DRISRCS3) $(MODSRCS3) -SRCS4 = radeon_accel.c radeon_cursor.c radeon_dga.c radeon_driver.c \ +SRCS4 = radeon_accel.c radeon_bios.c radeon_cursor.c \ + radeon_dga.c radeon_driver.c radeon_mergedfb.c \ radeon_video.c $(DRISRCS4) $(MODSRCS4) OBJS1 = ati.o atiadapter.o atibus.o atichip.o atiendian.o atiident.o \ @@ -82,7 +83,8 @@ OBJS2 = atiaccel.o atiadjust.o atiaudio.o atibank.o aticlock.o aticonfig.o \ ativga.o atiwonder.o atiwonderio.o atixv.o $(MODOBJS2) OBJS3 = r128_accel.o r128_cursor.o r128_dga.o r128_driver.o \ r128_video.o $(DRIOBJS3) $(MODOBJS3) -OBJS4 = radeon_accel.o radeon_cursor.o radeon_dga.o radeon_driver.o \ +OBJS4 = radeon_accel.o radeon_bios.o radeon_cursor.o \ + radeon_dga.o radeon_driver.o radeon_mergedfb.o \ radeon_video.o $(DRIOBJS4) $(MODOBJS4) SRCS = $(SRCS1) $(SRCS2) $(SRCS3) $(SRCS4) @@ -233,6 +235,7 @@ InstallDriverSDKNonExecFile(atixv.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_accel.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(r128_common.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_cursor.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_dga.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_dri.c,$(DRIVERSDKDIR)/drivers/ati) @@ -246,10 +249,13 @@ InstallDriverSDKNonExecFile(r128_reg.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_sarea.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_version.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(r128_video.c,$(DRIVERSDKDIR)/drivers/ati) -InstallDriverSDKNonExecFile(r128_common.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_accel.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_accelfuncs.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_bios.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_common.h,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_commonfuncs.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_cursor.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_dga.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_dri.c,$(DRIVERSDKDIR)/drivers/ati) @@ -257,6 +263,8 @@ InstallDriverSDKNonExecFile(radeon_dri.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_dripriv.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_driver.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_macros.h,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_mergedfb.c,$(DRIVERSDKDIR)/drivers/ati) +InstallDriverSDKNonExecFile(radeon_mergedfb.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_misc.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_probe.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_probe.h,$(DRIVERSDKDIR)/drivers/ati) @@ -264,8 +272,6 @@ InstallDriverSDKNonExecFile(radeon_reg.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_sarea.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_version.h,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKNonExecFile(radeon_video.c,$(DRIVERSDKDIR)/drivers/ati) -InstallDriverSDKNonExecFile(radeon_common.h,$(DRIVERSDKDIR)/drivers/ati) -InstallDriverSDKNonExecFile(radeon_accelfuncs.c,$(DRIVERSDKDIR)/drivers/ati) InstallDriverSDKObjectModule(ati,$(DRIVERSDKMODULEDIR),drivers) InstallDriverSDKObjectModule(atimisc,$(DRIVERSDKMODULEDIR),drivers) diff --git a/programs/Xserver/hw/xfree86/drivers/ati/atichip.c b/programs/Xserver/hw/xfree86/drivers/ati/atichip.c index 25b9d5228..6c4b3ddc1 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/atichip.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/atichip.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.43tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.44tsi Exp $ */ /* * Copyright 1997 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -89,13 +89,23 @@ const char *ATIChipNames[] = "ATI Radeon 8500/9100", "ATI Radeon 9000", "ATI Radeon Mobility M9", - "ATI Radeon 9000 IGP", + "ATI Radeon 9100 IGP", + "ATI Radeon 9200 IGP", "ATI Radeon 9200", "ATI Radeon Mobility M9+", "ATI Radeon 9700/9500", - "ATI Radeon 9600", + "ATI Radeon 9600/9550", "ATI Radeon 9800", "ATI Radeon 9800XT", + "ATI Radeon X300/X550/M22", + "ATI Radeon X600/X550/M24", + "ATI Radeon X800/M18 AGP", + "ATI Radeon X800/M28 PCIE", + "ATI Radeon X800XL PCIE", + "ATI Radeon X850 PCIE", + "ATI Radeon X850 AGP", + "ATI Radeon X700", + "ATI Xpress 200" "ATI unknown Radeon", "ATI Rage HDTV" }; @@ -618,6 +628,7 @@ ATIChipID case NewChipID('Q', 'Y'): case NewChipID('Q', 'Z'): + case NewChipID('Q', '^'): return ATI_CHIP_RADEONVE; case NewChipID('L', 'Y'): @@ -673,10 +684,15 @@ ATIChipID case NewChipID('X', '5'): return ATI_CHIP_RS300; + case NewChipID('x', '4'): + case NewChipID('x', '5'): + return ATI_CHIP_RS350; + case NewChipID('Y', '\''): case NewChipID('Y', 'a'): case NewChipID('Y', 'b'): case NewChipID('Y', 'd'): + case NewChipID('Y', 'e'): return ATI_CHIP_RV280; case NewChipID('\\', 'a'): @@ -707,6 +723,7 @@ ATIChipID case NewChipID('A', 'R'): case NewChipID('A', 'S'): case NewChipID('A', 'T'): + case NewChipID('A', 'U'): case NewChipID('A', 'V'): case NewChipID('N', 'P'): case NewChipID('N', 'Q'): @@ -719,6 +736,96 @@ ATIChipID case NewChipID('N', 'J'): return ATI_CHIP_R360; + case NewChipID('[', '\''): + case NewChipID('[', 'b'): + case NewChipID('[', 'c'): + case NewChipID('[', 'd'): + case NewChipID('[', 'e'): + case NewChipID('T', '\''): + case NewChipID('T', 'b'): + case NewChipID('T', 'd'): + return ATI_CHIP_RV370; + + case NewChipID('>', 'P'): + case NewChipID('>', 'T'): + case NewChipID('1', 'P'): + case NewChipID('1', 'R'): + case NewChipID('1', 'T'): + return ATI_CHIP_RV380; + + case NewChipID('J', 'H'): + case NewChipID('J', 'I'): + case NewChipID('J', 'J'): + case NewChipID('J', 'K'): + case NewChipID('J', 'L'): + case NewChipID('J', 'M'): + case NewChipID('J', 'N'): + case NewChipID('J', 'O'): + case NewChipID('J', 'P'): + case NewChipID('J', 'T'): + return ATI_CHIP_R420; + + case NewChipID('U', 'H'): + case NewChipID('U', 'I'): + case NewChipID('U', 'J'): + case NewChipID('U', 'K'): + case NewChipID('U', 'P'): + case NewChipID('U', 'Q'): + case NewChipID('U', 'R'): + case NewChipID('U', 'T'): + case NewChipID(']', 'W'): + /* + * These are m28, not 100% certain they are r423 could be r480 but not + * r430 as their pci id names indicate... + */ + case NewChipID(']', 'H'): + case NewChipID(']', 'I'): + case NewChipID(']', 'J'): + return ATI_CHIP_R423; + + case NewChipID('U', 'L'): + case NewChipID('U', 'M'): + case NewChipID('U', 'N'): + case NewChipID('U', 'O'): + return ATI_CHIP_R430; + + case NewChipID(']', 'L'): + case NewChipID(']', 'M'): + case NewChipID(']', 'N'): + case NewChipID(']', 'O'): + case NewChipID(']', 'P'): + case NewChipID(']', 'R'): + return ATI_CHIP_R480; + + case NewChipID('K', 'I'): + case NewChipID('K', 'J'): + case NewChipID('K', 'K'): + case NewChipID('K', 'L'): + return ATI_CHIP_R481; + + case NewChipID('^', 'H'): + case NewChipID('^', 'J'): + case NewChipID('^', 'K'): + case NewChipID('^', 'L'): + case NewChipID('^', 'M'): + case NewChipID('^', 'O'): + case NewChipID('V', 'J'): + case NewChipID('V', 'K'): + case NewChipID('V', 'O'): + case NewChipID('V', 'R'): + case NewChipID('V', 'S'): + return ATI_CHIP_RV410; + + case NewChipID('Z', 'A'): + case NewChipID('Z', 'B'): + case NewChipID('Z', 'a'): + case NewChipID('Z', 'b'): + case NewChipID('Y', 'T'): + case NewChipID('Y', 'U'): + case NewChipID('Y', 't'): + case NewChipID('Y', 'u'): + return ATI_CHIP_RS400; + case NewChipID('H', 'D'): return ATI_CHIP_HDTV; diff --git a/programs/Xserver/hw/xfree86/drivers/ati/atichip.h b/programs/Xserver/hw/xfree86/drivers/ati/atichip.h index b125d7fea..1c82db610 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/atichip.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/atichip.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.32tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.33tsi Exp $ */ /* * Copyright 1997 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -85,19 +85,29 @@ typedef enum ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */ ATI_CHIP_RS100, /* IGP320 */ ATI_CHIP_RS200, /* IGP340 */ - ATI_CHIP_RS250, /* Radoen 7000 IGP */ + ATI_CHIP_RS250, /* Radeon 7000 IGP */ ATI_CHIP_RV200, /* RV200 */ ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */ ATI_CHIP_R200, /* R200 */ ATI_CHIP_RV250, /* RV250 */ ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ - ATI_CHIP_RS300, /* Radoen 9000 IGP */ + ATI_CHIP_RS300, /* Radeon 9100 IGP */ + ATI_CHIP_RS350, /* Radeon 9200 IGP */ ATI_CHIP_RV280, /* RV250 */ ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */ ATI_CHIP_R300, /* R300 */ - ATI_CHIP_RV350, /* RV350 */ + ATI_CHIP_RV350, /* RV350/M10/M11 */ ATI_CHIP_R350, /* R350 */ ATI_CHIP_R360, /* R360 */ + ATI_CHIP_RV370, /* RV370/M22 */ + ATI_CHIP_RV380, /* RV380/M24 */ + ATI_CHIP_R420, /* R420/M18 */ + ATI_CHIP_R423, /* R423/M28? */ + ATI_CHIP_R430, /* R430 */ + ATI_CHIP_R480, /* R480/M28? */ + ATI_CHIP_R481, /* R481 */ + ATI_CHIP_RV410, /* RV410, M26 */ + ATI_CHIP_RS400, /* RS400, RS410, RS480, RS482, ... */ ATI_CHIP_Radeon, /* Last among Radeon's */ ATI_CHIP_HDTV /* HDTV */ } ATIChipType; diff --git a/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c b/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c index 27129b335..2ea442b64 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c,v 1.24tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c,v 1.25tsi Exp $ */ /* * Copyright 1997 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -149,6 +149,7 @@ const char *atiExportedSymbols[] = { "R128Chipsets", "RADEONChipsets", "atiModuleData", + "gR128EntityIndex", "gRADEONEntityIndex", NULL }; diff --git a/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h b/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h index 57e1144ae..24cb5e4e2 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h,v 1.92tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h,v 1.93tsi Exp $ */ /* * Copyright 1997 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -39,7 +39,7 @@ #define ATI_VERSION_MAJOR 7 #define ATI_VERSION_MINOR 0 -#define ATI_VERSION_PATCH 16 +#define ATI_VERSION_PATCH 17 #ifndef ATI_VERSION_EXTRA #define ATI_VERSION_EXTRA "" diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon.h index 075b5f617..1280bacad 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.47tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.48tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -42,6 +42,7 @@ /* PCI support */ #include "xf86Pci.h" +#include "xf86int10.h" /* XAA and Cursor Support */ #include "xaa.h" @@ -53,6 +54,7 @@ /* Xv support */ #include "xf86xv.h" +#include "radeon_probe.h" /* DRI support */ #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -61,10 +63,40 @@ #include "GL/glxint.h" #endif + /* Render support */ +#include "picturestr.h" + +/* ------- mergedfb support ------------- */ + /* Pseudo Xinerama support */ +#define NEED_REPLIES /* ? */ +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" /* required */ +#include <X11/extensions/panoramiXproto.h> /* required */ +#define RADEON_XINERAMA_MAJOR_VERSION 1 +#define RADEON_XINERAMA_MINOR_VERSION 1 + + +/* Relative merge position */ +typedef enum { + radeonLeftOf, + radeonRightOf, + radeonAbove, + radeonBelow, + radeonClone +} RADEONScrn2Rel; + +typedef struct _region { + int x0,x1,y0,y1; +} region; + +/* ------------------------------------- */ + #define RADEON_DEBUG 0 /* Turn off debugging output */ #define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */ #define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */ +/* Buffer are aligned on 4096 byte boundaries */ +#define RADEON_BUFFER_ALIGN 0x00000fff #define RADEON_VBIOS_SIZE 0x00010000 #define RADEON_USE_RMX 0x80000000 /* mode flag for using RMX * Need to comfirm this is not used @@ -72,13 +104,13 @@ */ #if RADEON_DEBUG -#define RADEONTRACE(x) \ +#define RADEONTRACE(x) \ do { \ ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex); \ ErrorF x; \ -} while (0); +} while(0) #else -#define RADEONTRACE(x) +#define RADEONTRACE(x) do { } while(0) #endif @@ -87,6 +119,7 @@ do { \ #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) + typedef struct { /* Common registers */ CARD32 ovr_clr; @@ -102,8 +135,17 @@ typedef struct { CARD32 cap0_trig_cntl; CARD32 cap1_trig_cntl; CARD32 bus_cntl; - CARD32 surface_cntl; + CARD32 bios_4_scratch; CARD32 bios_5_scratch; + CARD32 bios_6_scratch; + CARD32 surface_cntl; + CARD32 surfaces[8][3]; + unsigned mc_agp_location; + unsigned mc_fb_location; + CARD32 display_base_addr; + CARD32 display2_base_addr; + CARD32 ov0_base_addr; + /* Other registers to save for VT switches */ CARD32 dp_datatype; CARD32 rbbm_soft_reset; @@ -184,13 +226,16 @@ typedef struct { Bool palette_valid; CARD32 palette[256]; CARD32 palette2[256]; + + CARD32 tv_dac_cntl; + } RADEONSaveRec, *RADEONSavePtr; typedef struct { CARD16 reference_freq; CARD16 reference_div; - CARD32 min_pll_freq; - CARD32 max_pll_freq; + unsigned min_pll_freq; + unsigned max_pll_freq; CARD16 xclk; } RADEONPLLRec, *RADEONPLLPtr; @@ -198,37 +243,13 @@ typedef struct { int bitsPerPixel; int depth; int displayWidth; + int displayHeight; int pixel_code; int pixel_bytes; DisplayModePtr mode; } RADEONFBLayout; typedef enum { - MT_NONE, - MT_CRT, - MT_LCD, - MT_DFP, - MT_CTV, - MT_STV -} RADEONMonitorType; - -typedef enum { - DDC_NONE_DETECTED, - DDC_MONID, - DDC_DVI, - DDC_VGA, - DDC_CRT2 -} RADEONDDCType; - -typedef enum { - CONNECTOR_NONE, - CONNECTOR_PROPRIETARY, - CONNECTOR_CRT, - CONNECTOR_DVI_I, - CONNECTOR_DVI_D -} RADEONConnectorType; - -typedef enum { CHIP_FAMILY_UNKNOW, CHIP_FAMILY_LEGACY, CHIP_FAMILY_RADEON, @@ -238,17 +259,53 @@ typedef enum { CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */ CHIP_FAMILY_R200, CHIP_FAMILY_RV250, - CHIP_FAMILY_RS300, /* Radeon 9000 IGP */ + CHIP_FAMILY_RS300, /* RS300/RS350 */ CHIP_FAMILY_RV280, CHIP_FAMILY_R300, CHIP_FAMILY_R350, CHIP_FAMILY_RV350, + CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */ + CHIP_FAMILY_R420, /* R420/R423/M18 */ + CHIP_FAMILY_RV410, /* RV410, M26 */ + CHIP_FAMILY_RS400, /* xpress 200, 200m (RS400/410/480) */ CHIP_FAMILY_LAST } RADEONChipFamily; +#define IS_RV100_VARIANT ((info->ChipFamily == CHIP_FAMILY_RV100) || \ + (info->ChipFamily == CHIP_FAMILY_RV200) || \ + (info->ChipFamily == CHIP_FAMILY_RS100) || \ + (info->ChipFamily == CHIP_FAMILY_RS200) || \ + (info->ChipFamily == CHIP_FAMILY_RV250) || \ + (info->ChipFamily == CHIP_FAMILY_RV280) || \ + (info->ChipFamily == CHIP_FAMILY_RS300)) + + +#define IS_R300_VARIANT ((info->ChipFamily == CHIP_FAMILY_R300) || \ + (info->ChipFamily == CHIP_FAMILY_RV350) || \ + (info->ChipFamily == CHIP_FAMILY_R350) || \ + (info->ChipFamily == CHIP_FAMILY_RV380) || \ + (info->ChipFamily == CHIP_FAMILY_R420) || \ + (info->ChipFamily == CHIP_FAMILY_RV410) || \ + (info->ChipFamily == CHIP_FAMILY_RS400)) + +/* + * Errata workarounds + */ +typedef enum { + CHIP_ERRATA_R300_CG = 0x00000001, + CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002, + CHIP_ERRATA_PLL_DELAY = 0x00000004 +} RADEONErrata; + +typedef enum { + CARD_PCI, + CARD_AGP, + CARD_PCIE +} RADEONCardType; + typedef struct { - CARD32 freq; - CARD32 value; + unsigned freq; + unsigned value; }RADEONTMDSPll; typedef struct { @@ -257,20 +314,31 @@ typedef struct { PCITAG PciTag; int Chipset; RADEONChipFamily ChipFamily; + RADEONErrata ChipErrata; Bool FBDev; unsigned long LinearAddr; /* Frame buffer physical address */ unsigned long MMIOAddr; /* MMIO region physical address */ unsigned long BIOSAddr; /* BIOS physical address */ + CARD32 fbLocation; + CARD32 gartLocation; + CARD32 mc_fb_location; + CARD32 mc_agp_location; unsigned char *MMIO; /* Map of MMIO region */ unsigned char *FB; /* Map of frame buffer */ CARD8 *VBIOS; /* Video BIOS pointer */ + Bool IsAtomBios; /* New BIOS used in R420 etc. */ + int ROMHeaderStart; /* Start of the ROM Info Table */ + int MasterDataStart; /* Offset for Master Data Table for ATOM BIOS */ + CARD32 MemCntl; CARD32 BusCntl; unsigned long FbMapSize; /* Size of frame buffer, in bytes */ + unsigned long FbSecureSize; /* Size of secured fb area at end of + framebuffer */ int Flags; /* Saved copy of mode flags */ /* VE/M6 support */ @@ -280,18 +348,12 @@ typedef struct { Bool HasCRTC2; /* All cards except original Radeon */ Bool IsMobility; /* Mobile chips for laptops */ Bool IsIGP; /* IGP chips */ + Bool HasSingleDAC; /* only TVDAC on chip */ Bool IsSecondary; /* Second Screen */ + Bool IsPrimary; /* Primary Screen */ Bool IsSwitching; /* Flag for switching mode */ - Bool Clone; /* Force second head to clone primary*/ - RADEONMonitorType CloneType; - RADEONDDCType CloneDDCType; - DisplayModePtr CloneModes; - DisplayModePtr CurCloneMode; - int CloneFrameX0; - int CloneFrameY0; Bool OverlayOnCRTC2; Bool PanelOff; /* Force panel (LCD/DFP) off */ - int FPBIOSstart; /* Start of the flat panel info */ Bool ddc_mode; /* Validate mode by matching exactly * the modes supported in DDC data */ @@ -339,10 +401,12 @@ typedef struct { XAAInfoRecPtr accel; Bool accelOn; xf86CursorInfoPtr cursor; - unsigned long cursor_start; + unsigned cursor_offset; unsigned long cursor_end; + Bool allowColorTiling; + Bool tilingEnabled; /* mirror of sarea->tiling_enabled */ #ifdef ARGB_CURSOR - Bool cursor_argb; + Bool cursor_argb; #endif int cursor_fg; int cursor_bg; @@ -398,32 +462,37 @@ typedef struct { DGAFunctionRec DGAFuncs; RADEONFBLayout CurrentLayout; + CARD32 dst_pitch_offset; #ifdef XF86DRI Bool noBackBuffer; Bool directRenderingEnabled; + Bool directRenderingInited; + Bool newMemoryMap; + drmVersionPtr pLibDRMVersion; + drmVersionPtr pKernelDRMVersion; DRIInfoPtr pDRIInfo; int drmFD; int numVisualConfigs; __GLXvisualConfig *pVisualConfigs; RADEONConfigPrivPtr pVisualConfigsPriv; + Bool (*DRICloseScreen)(int, ScreenPtr); - drm_handle_t fbHandle; + drm_handle_t fbHandle; drmSize registerSize; - drm_handle_t registerHandle; + drm_handle_t registerHandle; - Bool IsPCI; /* Current card is a PCI card */ + RADEONCardType cardType; /* Current card is a PCI card */ drmSize pciSize; - drm_handle_t pciMemHandle; + drm_handle_t pciMemHandle; unsigned char *PCI; /* Map */ Bool depthMoves; /* Enable depth moves -- slow! */ Bool allowPageFlip; /* Enable 3d page flipping */ Bool have3DWindows; /* Are there any 3d clients? */ - int drmMinor; drmSize gartSize; - drm_handle_t agpMemHandle; /* Handle from drmAgpAlloc */ + drm_handle_t agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long gartOffset; unsigned char *AGP; /* Map */ int agpMode; @@ -440,32 +509,32 @@ typedef struct { /* CP ring buffer data */ unsigned long ringStart; /* Offset into GART space */ - drm_handle_t ringHandle; /* Handle from drmAddMap */ + drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ - unsigned char *ring; /* Map */ + drmAddress ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into GART space */ - drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ + drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ - unsigned char *ringReadPtr; /* Map */ + drmAddress ringReadPtr; /* Map */ /* CP vertex/indirect buffer data */ unsigned long bufStart; /* Offset into GART space */ - drm_handle_t bufHandle; /* Handle from drmAddMap */ + drm_handle_t bufHandle; /* Handle from drmAddMap */ drmSize bufMapSize; /* Size of map */ int bufSize; /* Size of buffers (in MB) */ - unsigned char *buf; /* Map */ + drmAddress buf; /* Map */ int bufNumBufs; /* Number of buffers */ drmBufMapPtr buffers; /* Buffer map */ /* CP GART Texture data */ unsigned long gartTexStart; /* Offset into GART space */ - drm_handle_t gartTexHandle; /* Handle from drmAddMap */ + drm_handle_t gartTexHandle; /* Handle from drmAddMap */ drmSize gartTexMapSize; /* Size of map */ int gartTexSize; /* Size of GART tex space (in MB) */ - unsigned char *gartTex; /* Map */ + drmAddress gartTex; /* Map */ int log2GARTTexGran; /* CP accleration */ @@ -486,16 +555,18 @@ typedef struct { int backPitch; int depthOffset; int depthPitch; + int depthBits; int textureOffset; int textureSize; int log2TexGran; + int pciGartSize; + unsigned pciGartOffset; + void *pciGartBackup; CARD32 frontPitchOffset; CARD32 backPitchOffset; CARD32 depthPitchOffset; - CARD32 dst_pitch_offset; - /* offscreen memory management */ int backLines; FBAreaPtr backArea; @@ -515,23 +586,97 @@ typedef struct { int irq; + Bool DMAForXv; + #ifdef PER_CONTEXT_SAREA int perctx_sarea_size; #endif -#endif + + /* Debugging info for BEGIN_RING/ADVANCE_RING pairs. */ + int dma_begin_count; + char *dma_debug_func; + int dma_debug_lineno; +#endif /* XF86DRI */ /* XVideo */ XF86VideoAdaptorPtr adaptor; void (*VideoTimerCallback)(ScrnInfoPtr, Time); FBLinearPtr videoLinear; int videoKey; - - /* general */ + Bool MM_TABLE_valid; + struct { + CARD8 table_revision; + CARD8 table_size; + CARD8 tuner_type; + CARD8 audio_chip; + CARD8 product_id; + CARD8 tuner_voltage_teletext_fm; + CARD8 i2s_config; /* configuration of the sound chip */ + CARD8 video_decoder_type; + CARD8 video_decoder_host_config; + CARD8 input[5]; + } MM_TABLE; + CARD16 video_decoder_type; + + /* general */ Bool showCache; OptionInfoPtr Options; + #ifdef XFree86LOADER XF86ModReqInfo xaaReq; #endif + + /* X itself has the 3D context */ + Bool XInited3D; + + /* merged fb stuff, also covers clone modes */ + Bool MergedFB; + RADEONScrn2Rel CRT2Position; + char * CRT2HSync; + char * CRT2VRefresh; + char * MetaModes; + ScrnInfoPtr CRT2pScrn; + DisplayModePtr CRT1Modes; + DisplayModePtr CRT1CurrentMode; + int CRT1frameX0; + int CRT1frameY0; + int CRT1frameX1; + int CRT1frameY1; + RADEONMonitorType MergeType; + RADEONDDCType MergeDDCType; + void (*PointerMoved)(int indx, int x, int y); + /* pseudo xinerama support for mergedfb */ + int maxCRT1_X1, maxCRT1_X2, maxCRT1_Y1, maxCRT1_Y2; + int maxCRT2_X1, maxCRT2_X2, maxCRT2_Y1, maxCRT2_Y2; + int maxClone_X1, maxClone_X2, maxClone_Y1, maxClone_Y2; + Bool UseRADEONXinerama; + Bool CRT2IsScrn0; + ExtensionEntry *XineramaExtEntry; + int RADEONXineramaVX, RADEONXineramaVY; + Bool AtLeastOneNonClone; + int MergedFBXDPI, MergedFBYDPI; + Bool NoVirtual; + int CRT1XOffs, CRT1YOffs, CRT2XOffs, CRT2YOffs; + int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX; + Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions; + region NonRectDead, OffDead1, OffDead2; + + int constantDPI; /* -1 = auto, 0 = off, 1 = on */ + int RADEONDPIVX, RADEONDPIVY; + RADEONScrn2Rel MergedDPISRel; + int RADEONMergedDPIVX, RADEONMergedDPIVY, RADEONMergedDPIRot; + + /* special handlings for DELL triple-head server */ + Bool IsDellServer; + + /* enable bios hotkey output switching */ + Bool BiosHotkeys; + + int MaxSurfaceWidth; + int MaxLines; + + Bool UseVGAHW; + } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -541,6 +686,7 @@ do { \ info->fifo_slots -= entries; \ } while (0) +extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); extern void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries); extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn); #ifdef XF86DRI @@ -555,33 +701,68 @@ extern void RADEONEngineFlush(ScrnInfoPtr pScrn); extern void RADEONEngineRestore(ScrnInfoPtr pScrn); extern unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr); +extern void RADEONOUTPLL(ScrnInfoPtr pScrn, int addr, CARD32 data); + extern void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn); extern void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn); -extern void RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer); +extern void RADEONChangeSurfaces(ScrnInfoPtr pScrn); extern Bool RADEONAccelInit(ScreenPtr pScreen); +extern void RADEONAccelInitMMIO(ScreenPtr pScreen, XAAInfoRecPtr a); extern void RADEONEngineInit(ScrnInfoPtr pScrn); extern Bool RADEONCursorInit(ScreenPtr pScreen); extern Bool RADEONDGAInit(ScreenPtr pScreen); +extern void RADEONInit3DEngine(ScrnInfoPtr pScrn); + extern int RADEONMinBits(int val); extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern void R300CGWorkaround(ScrnInfoPtr pScrn); +extern void RADEONPllErrataAfterIndex(RADEONInfoPtr info); +extern void RADEONPllErrataAfterData(RADEONInfoPtr info); + +extern Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10); +extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn); +extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn); + #ifdef XF86DRI +extern void RADEONAccelInitCP(ScreenPtr pScreen, XAAInfoRecPtr a); +extern Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn); extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); extern void RADEONDRICloseScreen(ScreenPtr pScreen); extern void RADEONDRIResume(ScreenPtr pScreen); extern Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen); +extern void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen); +extern void RADEONDRIInitPageFlip(ScreenPtr pScreen); +extern void RADEONDRIStop(ScreenPtr pScreen); extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn); extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard); extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn); extern int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info); +extern void RADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, + CARD32 pitch, int cpp, + CARD32 *dstPitchOffset, int *x, int *y); +extern pointer RADEONHostDataBlit(ScrnInfoPtr pScrn, unsigned int cpp, + unsigned int w, CARD32 dstPitchOff, + CARD32 *bufPitch, int x, int *y, + unsigned int *h, unsigned int *hpass); +extern void RADEONHostDataBlitCopyPass(ScrnInfoPtr pScrn, + unsigned int bpp, + CARD8 *dst, CARD8 *src, + unsigned int hpass, + unsigned int dstPitch, + unsigned int srcPitch); +extern void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, + int swap); #define RADEONCP_START(pScrn, info) \ do { \ @@ -597,12 +778,12 @@ do { \ do { \ int _ret; \ if (info->CPStarted) { \ - _ret = RADEONCPStop(pScrn, info); \ - if (_ret) { \ + _ret = RADEONCPStop(pScrn, info); \ + if (_ret) { \ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ "%s: CP stop %d\n", __FUNCTION__, _ret); \ - } \ - info->CPStarted = FALSE; \ + } \ + info->CPStarted = FALSE; \ } \ RADEONEngineRestore(pScrn); \ info->CPRuns = FALSE; \ @@ -645,13 +826,21 @@ do { \ #define RADEON_VERBOSE 0 -#define RING_LOCALS CARD32 *__head = NULL; int __count = 0 +#define RING_LOCALS CARD32 *__head = NULL; int __expected; int __count = 0 #define BEGIN_RING(n) do { \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ - "BEGIN_RING(%d) in %s\n", n, __FUNCTION__); \ + "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\ } \ + if (++info->dma_begin_count != 1) { \ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ + "BEGIN_RING without end at %s:%d\n", \ + info->dma_debug_func, info->dma_debug_lineno); \ + info->dma_begin_count = 1; \ + } \ + info->dma_debug_func = __FILE__; \ + info->dma_debug_lineno = __LINE__; \ if (!info->indirectBuffer) { \ info->indirectBuffer = RADEONCPGetBuffer(pScrn); \ info->indirectStart = 0; \ @@ -659,12 +848,24 @@ do { \ info->indirectBuffer->total) { \ RADEONCPFlushIndirect(pScrn, 1); \ } \ + __expected = n; \ __head = (pointer)((char *)info->indirectBuffer->address + \ info->indirectBuffer->used); \ __count = 0; \ } while (0) #define ADVANCE_RING() do { \ + if (info->dma_begin_count-- != 1) { \ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ + "ADVANCE_RING without begin at %s:%d\n", \ + __FILE__, __LINE__); \ + info->dma_begin_count = 0; \ + } \ + if (__count != __expected) { \ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \ + "ADVANCE_RING count != expected (%d vs %d) at %s:%d\n", \ + __count, __expected, __FILE__, __LINE__); \ + } \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "ADVANCE_RING() start: %d used: %d count: %d\n", \ @@ -735,16 +936,16 @@ do { \ #define RADEON_FLUSH_CACHE() \ do { \ BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB2D_DC_FLUSH); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH); \ ADVANCE_RING(); \ } while (0) #define RADEON_PURGE_CACHE() \ do { \ BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB2D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB2D_DC_FLUSH_ALL); \ + OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ + OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ ADVANCE_RING(); \ } while (0) diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon.man b/programs/Xserver/hw/xfree86/drivers/ati/radeon.man index 7a7c2a9ae..a908d10a2 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon.man +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon.man @@ -1,4 +1,4 @@ -.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man,v 1.0 2003/01/31 23:04:50 $ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.man,v 1.9tsi Exp $ .ds q \N'34' .TH RADEON __drivermansuffix__ __vendorversion__ .SH NAME @@ -13,10 +13,11 @@ radeon \- ATI RADEON video driver .fi .SH DESCRIPTION .B radeon -is a XFree86 driver for ATI RADEON based video cards. It contains +is an XFree86 driver for ATI RADEON based video cards. It contains full support for 8, 15, 16 and 24 bit pixel depths, dual-head setup, flat panel, hardware 2D acceleration, hardware 3D acceleration -(except R300 and IGP series cards), hardware cursor, XV extension, Xinerama extension. +(experimental on R300 and R400 series cards), hardware cursor, XV extension, +and the Xinerama extension. .SH SUPPORTED HARDWARE The .B radeon @@ -29,16 +30,16 @@ Radeon 7200 Radeon 7000(VE), M6 .TP 12 .B RS100 -Radeon IGP320(M) (2D only) +Radeon IGP320(M) .TP 12 .B RV200 Radeon 7500, M7, FireGL 7800 .TP 12 .B RS200 -Radeon IGP330(M)/IGP340(M) (2D only) +Radeon IGP330(M)/IGP340(M) .TP 12 .B RS250 -Radeon Mobility 7000 IGP (2D only) +Radeon Mobility 7000 IGP .TP 12 .B R200 Radeon 8500, 9100, FireGL 8800/8700 @@ -47,7 +48,13 @@ Radeon 8500, 9100, FireGL 8800/8700 Radeon 9000PRO/9000, M9 .TP 12 .B RS300 -Radeon 9100 IGP (2D only) +Radeon 9100 IGP +.TP 12 +.B RS350 +Radeon 9200 IGP +.TP 12 +.B RS400 +Radeon XPRESS 200/200M IGP .TP 12 .B RV280 Radeon 9200PRO/9200/9200SE, M9+ @@ -64,8 +71,26 @@ Radeon 9800XT (2d only) .B RV350 Radeon 9600PRO/9600SE/9600, M10/M11, FireGL T2 (2D only) .TP 12 -.B RV360 +.B RV360 Radeon 9600XT (2d only) +.TP 12 +.B RV370 +Radeon X300, M22 (2d only) +.TP 12 +.B RV380 +Radeon X600, M24 (2d only) +.TP 12 +.B RV410 +Radeon X700, M26 PCIE (2d only) +.TP 12 +.B R420 +Radeon X800 AGP (2d only) +.TP 12 +.B R423/R430 +Radeon X800, M28 PCIE (2d only) +.TP 12 +.B R480/R481 +Radeon X850 PCIE/AGP (2d only) .SH CONFIGURATION DETAILS Please refer to XF86Config(__filemansuffix__) for general configuration @@ -117,8 +142,8 @@ The default value is .TP .BI "Option \*qUseFBDev\*q \*q" boolean \*q Enable or disable use of an OS\-specific framebuffer device interface -(which is not supported on all OSs). See fbdevhw(__drivermansuffix__) -for further information. +(which is not supported on all OSs). MergedFB does not work when this +option is in use. See fbdevhw(__drivermansuffix__) for further information. .br The default is .B off. @@ -133,12 +158,13 @@ Set AGP data transfer rate. .br 4 \-\- x4 .br +8 \-\- x8 +.br others \-\- invalid .TP .BI "Option \*qAGPFastWrite\*q \*q" boolean \*q -Enable AGP fast write. -.br -(used only when DRI is enabled) +Enable AGP fast write. Enabling this option is frequently the cause of +instability. Used only when the DRI is enabled. .br The default is .B off. @@ -159,12 +185,6 @@ PCIE \-\- PCI Express (falls back to PCI at present) .br The default is .B auto detect. -.TP -.BI "Option \*qForcePCIMode\*q \*q" boolean \*q -Force to use PCI GART for DRI acceleration. -This option is deprecated in favor of the -.BI BusType -option above and will be removed in the next release. .TP .BI "Option \*qDDCMode\*q \*q" boolean \*q Force to use the modes queried from the connected monitor. @@ -184,7 +204,7 @@ BIOS \-\- Remain unchanged from BIOS setting. .br HIGH \-\- Force to the highest priority. Use this if you have problem with above options. - This may affect performence slightly. + This might affect performance slightly. .br The default value is .B AUTO. @@ -200,7 +220,7 @@ NONE \-\- Not connected CRT \-\- Analog CRT monitor .br TMDS \-\- Desktop flat panel -.br +.br LVDS \-\- Laptop flat panel .br This option can be used in following format: @@ -218,9 +238,9 @@ Primary/Secondary head for dual\-head cards: DVI port on DVI+VGA cards .br LCD output on laptops -.br -Internal TMDS prot on DVI+DVI cards -.br +.br +Internal TMDS port on DVI+DVI cards +.br .B Secondary head: .br VGA port on DVI+VGA cards @@ -231,54 +251,212 @@ External TMDS port on DVI+DVI cards The default value is .B undefined. +.TP +.BI "Option \*qMergedFB\*q \*q" boolean \*q +This enables merged framebuffer mode. In this mode you have a single +shared framebuffer with two viewports looking into it. It is similar +to Xinerama, but has some advantages. It is faster than Xinerama, the +DRI works on both heads, and it supports clone modes. +.br +Merged framebuffer mode provides two linked viewports looking into a +single large shared framebuffer. The size of the framebuffer is +determined by the +.B Virtual +keyword defined on the +.B Screen +section of your XF86Config file. It works just like regular virtual +desktop except you have two viewports looking into it instead of one. +.br +For example, if you wanted a desktop composed of two 1024x768 viewports +looking into a single desktop you would create a virtual desktop of +2048x768 (left/right) or 1024x1536 (above/below), e.g., +.br +.B Virtual 2048 768 +or +.B Virtual 1024 1536 +.br +The virtual desktop can be larger than the size of the viewports +looking into it. In this case the linked viewports will scroll around in the +virtual desktop. Viewports with different sizes are also supported (e.g., one +that is 1024x768 and one that is 640x480). In this case the smaller viewport +will scroll relative to the larger one such that none of the virtual desktop +is inaccessible. If you do not define a virtual desktop the driver will create +one based on the orientation of the heads and size of the largest defined mode in +the display section that is supported on each head. +.br +The relation of the viewports in specified by the +.B CRT2Position +Option. The options are +.B Clone +, +.B LeftOf +, +.B RightOf +, +.B Above +, and +.B Below. +MergedFB is enabled by default if a monitor is detected on each output. If +no position is given it defaults to clone mode (the old clone options are now +deprecated, also, the option OverlayOnCRTC2 has been replaced by the Xv +attribute XV_SWITCHCRT; the overlay can be switched to CRT1 or CRT2 on the fly +in clone mode). +.br +The maximum framebuffer size that the 2D acceleration engine can handle is +8192x8192. The maximum framebuffer size that the 3D engine can handle is +2048x2048. +.br +.B Note: +Page flipping does not work well in certain configurations with MergedFB. If you +see rendering errors or other strange behavior, disable page flipping. Also MergedFB +is not compatible with the +.B UseFBDev +option. +.br +The default value is +.B undefined. +.TP +.BI "Option \*qCRT2HSync\*q \*q" "string" \*q +Set the horizontal sync range for the secondary monitor. +It is not required if a DDC\-capable monitor is connected. +.br +For example, Option "CRT2HSync" "30.0-86.0" +.br +The default value is +.B undefined. +.TP +.BI "Option \*qCRT2VRefresh\*q \*q" "string" \*q +Set the vertical refresh range for the secondary monitor. +It is not required if a DDC\-capable monitor is connected. +.br +For example, Option "CRT2VRefresh" "50.0-120.0" +.br +The default value is +.B undefined. .TP -.BI "Option \*qCloneMode\*q \*q" "string" \*q -Set the first mode for the secondary head. -It can be different from the modes used for the primary head. If you don't -have this line while clone is on, the modes specified for the primary head -will be used for the secondary head. +.BI "Option \*qCRT2Position\*q \*q" "string" \*q +Set the relationship of CRT2 relative to CRT1. Valid options are: +.B Clone +, +.B LeftOf +, +.B RightOf +, +.B Above +, and +.B Below +. +.br +For example, Option "CRT2Position" "RightOf" +.br +This option also supports an offset. This is most useful when +.B MergedNonRectangular +is enabled. For example if you want CRT2 to be offset 100 pixels down from +the start of CRT1, you'd type: +.br +Option "CRT2Position" "LeftOf 100" +.br +The offset is vertical for LeftOf and RightOf and horizontal for Above and +Below. Offsets can be positive or negative. .br -For example, Option "CloneMode" "1024x768" +The default value is +.B Clone. +.TP +.BI "Option \*qMetaModes\*q \*q" "string" \*q +MetaModes are mode combinations for CRT1 and CRT2. If you are using merged +frame buffer mode and want to change modes (CTRL-ALT-+/-), these define which +modes will be switched to on CRT1 and CRT2. The MetaModes are defined as +CRT1Mode-CRT2Mode (800x600-1024x768). Modes listed individually (800x600) +define clone modes, that way you can mix clone modes with non-clone modes. +Also some programs require "standard" modes. If you want to add clone modes +of different refreshes or sizes to the mix, they are defined as CRT1Mode+CRT2Mode +(800x600+1024x768). +.br +Note: Any mode you use in the MetaModes must be defined in the +.B Screen +section of your XF86Config file. Modes not defined there will be ignored when +the MetaModes are parsed since the driver uses them to make sure the monitors can +handle those modes. If you do not define a MetaMode the driver will create +one based on the orientation of the heads and size of the largest defined mode in +the display section that is supported on each head. +.br +.B Modes "1024x768" "800x600" "640x480" +.br +For example, Option "MetaModes" "1024x768-1024x768 800x600-1024x768 640x480-800x600 800x600" .br The default value is .B undefined. .TP -.BI "Option \*qCloneHSync\*q \*q" "string" \*q -Set the horizontal sync range for the secondary monitor. -It is not required if a DDC\-capable monitor is connected. +.BI "Option \*qMergedXinerama\*q \*q" boolean \*q +Since merged framebuffer mode does not use Xinerama, apps are not able to intelligently +place windows. Merged framebuffer mode provides its own pseudo-Xinerama. This allows +Xinerama compliant applications to place windows appropriately. There are some caveats. +Since merged framebuffer mode is able to change relative screen sizes and orientations on +the fly, as well has having overlapping viewports, pseudo-Xinerama, might not always +provide the right hints. Also many Xinerama compliant applications only query Xinerama +once at startup; if the information changes, they might not be aware of the change. If +you are already using Xinerama (e.g., a single head card and a dualhead card providing +three heads), pseudo-Xinerama will be disabled. +.br +This option allows you turn off the driver provided pseudo-Xinerama extension. .br -For example, Option "CloneHSync" "30.0-86.0" +The default value is +.B TRUE. +.TP +.BI "Option \*qMergedXineramaCRT2IsScreen0\*q \*q" boolean \*q +By default the pseudo-Xinerama provided by the driver makes the left-most or bottom +head Xinerama screen 0. Certain Xinerama-aware applications do special things with +screen 0. To change that behavior, use this option. .br The default value is .B undefined. .TP -.BI "Option \*qCloneVRefresh\*q \*q" "string" \*q -Set the vertical refresh range for the secondary monitor. -It is not required if a DDC\-capable monitor is connected. +.BI "Option \*qMergedDPI\*q \*q" "string" \*q +The driver will attempt to figure out an appropriate DPI based on the DDC information +and the orientation of the heads when in merged framebuffer mode. If this value does +not suit you, you can manually set the DPI using this option. .br -For example, Option "CloneVRefresh" "50.0-120.0" +For example, Option "MergedDPI" "100 100" .br The default value is .B undefined. .TP -.BI "Option \*qOverlayOnCRTC2\*q \*q" boolean \*q -Force hardware overlay to clone head. +.BI "Option \*qMergedNonRectangular\*q \*q" boolean \*q +If you are using MergedFB with two modes of different sizes, turn this option on to +keep the smaller head from scrolling within the larger virtual desktop and to keep +the mouse from moving into that area. Applications that are not Xinerama aware can +potentially end up stranded in this area. .br The default value is -.B off. +.B FALSE. .TP +.BI "Option \*qColorTiling\*q \*q" "boolean" \*q +Frame buffer can be addressed either in linear or tiled mode. Tiled mode can provide +significant performance benefits with 3D applications, for 2D it shouldn't matter +much. Tiling will be disabled if the virtual x resolution exceeds 2048 (3968 for R300 +and above), if option +.B UseFBDev +is used, or (if DRI is enabled) the drm module is too old. +.br +If this option is enabled, a new dri driver is required for direct rendering too. +.br +Color tiling will be automatically disabled in interlaced or doublescan screen modes. +.br +The default value is +.B on. +.TP .BI "Option \*qIgnoreEDID\*q \*q" boolean \*q Do not use EDID data for mode validation, but DDC is still used for monitor detection. This is different from NoDDC option. .br The default value is .B off. -.TP +.TP .BI "Option \*qPanelSize\*q \*q" "string" \*q Should only be used when driver cannot detect the correct panel size. Apply to both desktop (TMDS) and laptop (LVDS) digital panels. When a valid panel size is specified, the timings collected from -DDC and BIOS will not be used. If you have a panel with timings +DDC and BIOS will not be used. If you have a panel with timings different from that of a standard VESA mode, you have to provide this information through the Modeline. .br @@ -286,9 +464,9 @@ For example, Option "PanelSize" "1400x1050" .br The default value is .B none. -.TP +.TP .BI "Option \*qPanelOff\*q \*q" boolean \*q -Disable panel output. Only used when clone is enabled. +Disable panel output. .br The default value is .B off. @@ -297,21 +475,103 @@ The default value is Enable page flipping for 3D acceleration. This will increase performance but not work correctly in some rare cases, hence the default is .B off. - .TP .BI "Option \*qForceMinDotClock\*q \*q" frequency \*q Override minimum dot clock. Some Radeon BIOSes report a minimum dot clock unsuitable (too high) for use with television sets even when they actually can produce lower dot clocks. If this is the case you can override the value here. -.B Note that using this option may damage your hardware. +.B Note that using this option might damage your hardware. You have been warned. The .B frequency parameter may be specified as a float value with standard suffixes like "k", "kHz", "M", "MHz". +.TP +.BI "Option \*qDepthBits\*q \*q" integer \*q +Precision in bits per pixel of the shared depth buffer used for 3D acceleration. +Valid values are 16 and 24. When this is 24, there will also be a hardware +accelerated stencil buffer, but the combined depth/stencil buffer will take up +twice as much video RAM as when it's 16. +Default: +.B The same as the screen depth. +.TP +.BI "Option \*qDMAForXv\*q \*q" boolean \*q +Try or don't try to use DMA for Xv image transfers. This will reduce CPU +usage when playing big videos like DVDs, but might cause instabilities. +Default: +.B on. +.TP +.BI "Option \*qSubPixelOrder\*q \*q" "string" \*q +Force subpixel order to specified order. +Subpixel order is used for subpixel decimation on flat panels. +.br +NONE \-\- No subpixel (CRT like displays) +.br +RGB \-\- in horizontal RGB order (most flat panels) +.br +BGR \-\- in horizontal BGR order (some flat panels) + +.br +This option is intended to be used in following cases: +.br +1. The default subpixel order is incorrect for your panel. +.br +2. Enable subpixel decimation on analog panels. +.br +3. Adjust to one display type in dual-head clone mode setup. +.br +4. Get better performance with Render acceleration on +digital panels (use NONE setting). +.br +The default is +.B NONE +for CRT, +.B RGB +for digital panels +.TP +.BI "Option \*qDynamicClocks\*q \*q" boolean \*q +Enable dynamic clock scaling. The on-chip clocks will scale dynamically +based on usage. This can help reduce heat and increase battery +life by reducing power usage. Some users report reduced 3D performance +with this enabled. The default is +.B off. +.TP +.BI "Option \*qBIOSHotkeys\*q \*q" boolean \*q +Enable BIOS hotkey output switching. This allows the BIOS to toggle outputs +using hotkeys (e.g., fn-f7, etc.). Since the driver does not support ACPI, +there is no way to validate modes on an output switch and the BIOS can +potentially change things behind the driver's back. The default is +.B off. +.TP +.BI "Option \*qReverseDDC\*q \*q" boolean \*q +When BIOS connector informations aren't available, use this option to +reverse the mapping of the 2 main DDC ports. Use this if the X serve +obviously detects the wrong display for each connector. This is +typically needed on the Radeon 9600 cards bundled with Apple G5s. The +default is +.B off. +.TP +.BI "Option \*qLVDSProbePLL\*q \*q" boolean \*q +When BIOS panel informations aren't available (like on PowerBooks), it +might still be necessary to use the firmware provided PLL values for the +panel or flickering will happen. This option will force probing of +the current value programmed in the chip when X is launched in that +case. This is only useful for LVDS panels (laptop internal panels). +The default is +.B on. +.TP .SH SEE ALSO XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) .SH AUTHORS .nf -Authors include: ... +Authors include: +Rickard E. (Rik) Faith \fIfaith@precisioninsight.com\fP +Kevin E. Martin \fIkem@freedesktop.org\fP +Alan Hourihane \fIalanh@fairlite.demon.co.uk\fP +Marc Aurele La France \fItsi@xfree86.org\fP +Benjamin Herrenschmidt \fIbenh@kernel.crashing.org\fP +Michel Dänzer \fImichel@tungstengraphics.com\fP +Alex Deucher \fIalexdeucher@gmail.com\fP +Bogdan D. \fIbogdand@users.sourceforge.net\fP +Eric Anholt \fIeric@anholt.net\fP diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c index c53c2028a..438457265 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c,v 1.39tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c,v 1.40tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -111,8 +111,6 @@ static struct { { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ }; -extern int gRADEONEntityIndex; - /* The FIFO has 64 slots. This routines waits until at least `entries' * of these slots are empty. */ @@ -128,7 +126,7 @@ void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; if (info->fifo_slots >= entries) return; } - RADEONTRACE(("FIFO timed out: %d entries, stat=0x%08x\n", + RADEONTRACE(("FIFO timed out: %u entries, stat=0x%08x\n", INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, INREG(RADEON_RBBM_STATUS))); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -151,13 +149,17 @@ void RADEONEngineFlush(ScrnInfoPtr pScrn) unsigned char *RADEONMMIO = info->MMIO; int i; - OUTREGP(RADEON_RB2D_DSTCACHE_CTLSTAT, - RADEON_RB2D_DC_FLUSH_ALL, - ~RADEON_RB2D_DC_FLUSH_ALL); + OUTREGP(RADEON_RB3D_DSTCACHE_CTLSTAT, + RADEON_RB3D_DC_FLUSH_ALL, + ~RADEON_RB3D_DC_FLUSH_ALL); for (i = 0; i < RADEON_TIMEOUT; i++) { - if (!(INREG(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY)) + if (!(INREG(RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY)) break; } + if (i == RADEON_TIMEOUT) { + RADEONTRACE(("DC flush timeout: %x\n", + INREG(RADEON_RB3D_DSTCACHE_CTLSTAT))); + } } /* Reset graphics card to known state */ @@ -170,11 +172,37 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) CARD32 rbbm_soft_reset; CARD32 host_path_cntl; + /* The following RBBM_SOFT_RESET sequence can help un-wedge + * an R300 after the command processor got stuck. + */ + rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); + OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | + RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB)); + INREG(RADEON_RBBM_SOFT_RESET); + OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (CARD32) + ~(RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB))); + INREG(RADEON_RBBM_SOFT_RESET); + OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); + INREG(RADEON_RBBM_SOFT_RESET); + RADEONEngineFlush(pScrn); clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + RADEONPllErrataAfterIndex(info); +#if 0 /* taken care of by new PM code */ /* Some ASICs have bugs with dynamic-on feature, which are * ASIC-version dependent, so we force all blocks on for now */ @@ -191,8 +219,11 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) OUTPLL(RADEON_SCLK_MORE_CNTL, tmp | RADEON_SCLK_MORE_FORCEON); } } +#endif /* new PM code */ mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL); + +#if 0 /* handled by new PM code */ OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl | RADEON_FORCEON_MCLKA | RADEON_FORCEON_MCLKB | @@ -200,6 +231,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC | RADEON_FORCEON_AIC)); +#endif /* new PM code */ /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some * unexpected behaviour on some machines. Here we use @@ -208,9 +240,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { CARD32 tmp; OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | @@ -219,12 +249,11 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) RADEON_SOFT_RESET_E2)); INREG(RADEON_RBBM_SOFT_RESET); OUTREG(RADEON_RBBM_SOFT_RESET, 0); - tmp = INREG(RADEON_RB2D_DSTCACHE_MODE); - OUTREG(RADEON_RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ + tmp = INREG(RADEON_RB3D_DSTCACHE_MODE); + OUTREG(RADEON_RB3D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ } else { OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | @@ -233,7 +262,6 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) INREG(RADEON_RBBM_SOFT_RESET); OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (CARD32) ~(RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | RADEON_SOFT_RESET_SE | RADEON_SOFT_RESET_RE | RADEON_SOFT_RESET_PP | @@ -246,14 +274,12 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) INREG(RADEON_HOST_PATH_CNTL); OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl); - if ((info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) + if (!IS_R300_VARIANT) OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); - OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + RADEONPllErrataAfterIndex(info); + OUTPLL(pScrn, RADEON_MCLK_CNTL, mclk_cntl); } /* Restore the acceleration hardware to its previous state */ @@ -261,31 +287,19 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int pitch64; RADEONTRACE(("EngineRestore (%d/%d)\n", info->CurrentLayout.pixel_code, info->CurrentLayout.bitsPerPixel)); - RADEONWaitForFifo(pScrn, 1); - - /* NOTE: The following RB2D_DSTCACHE_MODE setting will cause the - * R300 to hang. ATI does not see a reason to change it from the - * default BIOS settings (even on non-R300 cards). This setting - * might be removed in future versions of the Radeon driver. + /* Setup engine location. This shouldn't be necessary since we + * set them appropriately before any accel ops, but let's avoid + * random bogus DMA in case we inadvertently trigger the engine + * in the wrong place (happened). */ - - /* Turn of all automatic flushing - we'll do it all */ - if ((info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) - OUTREG(RADEON_RB2D_DSTCACHE_MODE, 0); - - pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - - RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DISPLAY_BASE_ADDR) >> 10) - | (pitch64 << 22))); + RADEONWaitForFifo(pScrn, 2); + OUTREG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset); + OUTREG(RADEON_SRC_PITCH_OFFSET, info->dst_pitch_offset); RADEONWaitForFifo(pScrn, 1); #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -296,10 +310,8 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) OUTREGP(RADEON_DP_DATATYPE, 0, ~RADEON_HOST_BIG_ENDIAN_EN); #endif - /* Restore SURFACE_CNTL - only the first head contains valid data -ReneR */ - if (!info->IsSecondary) { - OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); - } + /* Restore SURFACE_CNTL */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); RADEONWaitForFifo(pScrn, 1); OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX @@ -309,9 +321,7 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) | RADEON_GMC_BRUSH_SOLID_COLOR | RADEON_GMC_SRC_DATATYPE_COLOR)); - RADEONWaitForFifo(pScrn, 7); - OUTREG(RADEON_DST_LINE_START, 0); - OUTREG(RADEON_DST_LINE_END, 0); + RADEONWaitForFifo(pScrn, 5); OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); OUTREG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff); @@ -319,6 +329,8 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff); RADEONWaitForIdleMMIO(pScrn); + + info->XInited3D = FALSE; } /* Initialize the acceleration hardware */ @@ -332,15 +344,6 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->CurrentLayout.bitsPerPixel)); OUTREG(RADEON_RB3D_CNTL, 0); -#ifdef __powerpc__ -#ifdef XF86DRI - if(!info->directRenderingEnabled) -#endif - { - OUTREG(RADEON_MC_FB_LOCATION, 0xffff0000); - OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000); - } -#endif RADEONEngineReset(pScrn); @@ -363,7 +366,8 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->dp_gui_master_cntl = ((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) - | RADEON_GMC_CLR_CMP_CNTL_DIS); + | RADEON_GMC_CLR_CMP_CNTL_DIS + | RADEON_GMC_DST_PITCH_OFFSET_CNTL); #ifdef XF86DRI info->sc_left = 0x00000000; @@ -381,12 +385,14 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) RADEONEngineRestore(pScrn); } + #define ACCEL_MMIO #define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO #define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) #define FINISH_ACCEL() +#include "radeon_commonfuncs.c" #include "radeon_accelfuncs.c" #undef ACCEL_MMIO @@ -405,6 +411,8 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) #define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) #define FINISH_ACCEL() ADVANCE_RING() + +#include "radeon_commonfuncs.c" #include "radeon_accelfuncs.c" #undef ACCEL_CP @@ -582,11 +590,245 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT, &indirect, sizeof(drmRadeonIndirect)); } + +/** \brief Calculate HostDataBlit parameters from pointer and pitch + * + * This is a helper for the trivial HostDataBlit users that don't need to worry + * about tiling etc. + */ +void +RADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, CARD32 pitch, int cpp, + CARD32 *dstPitchOff, int *x, int *y) +{ + RADEONInfoPtr info = RADEONPTR( pScrn ); + CARD32 dstOffs = dst - info->FB + info->fbLocation; + + *dstPitchOff = pitch << 16 | (dstOffs & ~RADEON_BUFFER_ALIGN) >> 10; + *y = ( dstOffs & RADEON_BUFFER_ALIGN ) / pitch; + *x = ( ( dstOffs & RADEON_BUFFER_ALIGN ) - ( *y * pitch ) ) / cpp; +} + +/* Set up a hostdata blit to transfer data from system memory to the + * framebuffer. Returns the address where the data can be written to and sets + * the dstPitch and hpass variables as required. + */ +pointer +RADEONHostDataBlit( + ScrnInfoPtr pScrn, + unsigned int cpp, + unsigned int w, + CARD32 dstPitchOff, + CARD32 *bufPitch, + int x, + int *y, + unsigned int *h, + unsigned int *hpass +){ + RADEONInfoPtr info = RADEONPTR( pScrn ); + CARD32 format; + int dwords; + CARD8 *ret; + RING_LOCALS; + + if ( *h == 0 ) + { + return NULL; + } + + switch ( cpp ) + { + case 4: + format = RADEON_GMC_DST_32BPP; + *bufPitch = 4 * w; + break; + case 2: + format = RADEON_GMC_DST_16BPP; + *bufPitch = 2 * ((w + 1) & ~1); + break; + case 1: + format = RADEON_GMC_DST_8BPP_CI; + *bufPitch = (w + 3) & ~3; + break; + default: + xf86DrvMsg( pScrn->scrnIndex, X_ERROR, + "%s: Unsupported cpp %d!\n", __func__, cpp ); + return NULL; + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* Swap doesn't work on R300 and later, it's handled during the + * copy to ind. buffer pass + */ + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_RING(2); + if (cpp == 2) + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_HDW); + else if (cpp == 1) + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_32BIT); + else + OUT_RING_REG(RADEON_RBBM_GUICNTL, + RADEON_HOST_DATA_SWAP_NONE); + ADVANCE_RING(); + } #endif -/* Initialize XAA for supported acceleration and also initialize the - * graphics hardware for acceleration + /*RADEON_PURGE_CACHE(); + RADEON_WAIT_UNTIL_IDLE();*/ + + *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 10 * 4 ) / *bufPitch ) ); + dwords = *hpass * *bufPitch / 4; + + BEGIN_RING( dwords + 10 ); + OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 10 - 2 ) ); + OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL + | RADEON_GMC_DST_CLIPPING + | RADEON_GMC_BRUSH_NONE + | format + | RADEON_GMC_SRC_DATATYPE_COLOR + | RADEON_ROP3_S + | RADEON_DP_SRC_SOURCE_HOST_DATA + | RADEON_GMC_CLR_CMP_CNTL_DIS + | RADEON_GMC_WR_MSK_DIS ); + OUT_RING( dstPitchOff ); + OUT_RING( (*y << 16) | x ); + OUT_RING( ((*y + *hpass) << 16) | (x + w) ); + OUT_RING( 0xffffffff ); + OUT_RING( 0xffffffff ); + OUT_RING( *y << 16 | x ); + OUT_RING( *hpass << 16 | (*bufPitch / cpp) ); + OUT_RING( dwords ); + + ret = ( CARD8* )&__head[__count]; + + __count += dwords; + ADVANCE_RING(); + + *y += *hpass; + *h -= *hpass; + + return ret; +} + +void RADEONCopySwap(CARD8 *dst, CARD8 *src, unsigned int size, int swap) +{ + switch(swap) { + case RADEON_HOST_DATA_SWAP_HDW: + { + unsigned int *d = (unsigned int *)(pointer)dst; + unsigned int *s = (unsigned int *)(pointer)src; + unsigned int nwords = size >> 2; + + for (; nwords > 0; --nwords, ++d, ++s) + *d = ((*s & 0xffff) << 16) | ((*s >> 16) & 0xffff); + return; + } + case RADEON_HOST_DATA_SWAP_32BIT: + { + unsigned int *d = (unsigned int *)(pointer)dst; + unsigned int *s = (unsigned int *)(pointer)src; + unsigned int nwords = size >> 2; + + for (; nwords > 0; --nwords, ++d, ++s) +#ifdef __powerpc__ + asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); +#else + *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) + | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); +#endif + return; + } + case RADEON_HOST_DATA_SWAP_16BIT: + { + unsigned short *d = (unsigned short *)(pointer)dst; + unsigned short *s = (unsigned short *)(pointer)src; + unsigned int nwords = size >> 1; + + for (; nwords > 0; --nwords, ++d, ++s) +#ifdef __powerpc__ + asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); +#else + *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) + | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); +#endif + return; + } + } + if (src != dst) + memmove(dst, src, size); +} + +/* Copies a single pass worth of data for a hostdata blit set up by + * RADEONHostDataBlit(). */ +void +RADEONHostDataBlitCopyPass( + ScrnInfoPtr pScrn, + unsigned int cpp, + CARD8 *dst, + CARD8 *src, + unsigned int hpass, + unsigned int dstPitch, + unsigned int srcPitch +){ + +#if X_BYTE_ORDER == X_BIG_ENDIAN + RADEONInfoPtr info = RADEONPTR( pScrn ); +#endif + + /* RADEONHostDataBlitCopy can return NULL ! */ + if( (dst==NULL) || (src==NULL)) return; + + if ( dstPitch == srcPitch ) + { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + switch(cpp) { + case 1: + RADEONCopySwap(dst, src, hpass * dstPitch, + RADEON_HOST_DATA_SWAP_32BIT); + return; + case 2: + RADEONCopySwap(dst, src, hpass * dstPitch, + RADEON_HOST_DATA_SWAP_HDW); + return; + } + } +#endif + memcpy( dst, src, hpass * dstPitch ); + } + else + { + unsigned int minPitch = min( dstPitch, srcPitch ); + while ( hpass-- ) + { +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + switch(cpp) { + case 1: + RADEONCopySwap(dst, src, minPitch, + RADEON_HOST_DATA_SWAP_32BIT); + goto next; + case 2: + RADEONCopySwap(dst, src, minPitch, + RADEON_HOST_DATA_SWAP_HDW); + goto next; + } + } +#endif + memcpy( dst, src, minPitch ); +#if X_BYTE_ORDER == X_BIG_ENDIAN + next: +#endif + src += srcPitch; + dst += dstPitch; + } + } +} + +#endif + Bool RADEONAccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -602,7 +844,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen) if (info->directRenderingEnabled) RADEONAccelInitCP(pScreen, a); else -#endif +#endif /* XF86DRI */ RADEONAccelInitMMIO(pScreen, a); RADEONEngineInit(pScrn); @@ -611,6 +853,24 @@ Bool RADEONAccelInit(ScreenPtr pScreen) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n"); return FALSE; } - return TRUE; } + +void RADEONInit3DEngine(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->directRenderingEnabled) { + RADEONSAREAPrivPtr pSAREAPriv; + + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen); + RADEONInit3DEngineCP(pScrn); + } else +#endif + RADEONInit3DEngineMMIO(pScrn); + + info->XInited3D = TRUE; +} + diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c index 0e30de698..01071ef78 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.7tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.8tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -91,107 +91,25 @@ #endif #endif -/* MMIO: - * - * Wait for the graphics engine to be completely idle: the FIFO has - * drained, the Pixel Cache is flushed, and the engine is idle. This is - * a standard "sync" function that will make the hardware "quiescent". - * - * CP: - * - * Wait until the CP is completely idle: the FIFO has drained and the CP - * is idle. - */ -void -FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i = 0; - -#ifdef ACCEL_CP - /* Make sure the CP is idle first */ - if (info->CPStarted) { - int ret; - FLUSH_RING(); - - for (;;) { - do { - ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); - if (ret && ret != -EBUSY) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "%s: CP idle %d\n", __FUNCTION__, ret); - } - } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); - - if (ret == 0) return; - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Idle timed out, resetting engine...\n"); - RADEONEngineReset(pScrn); - RADEONEngineRestore(pScrn); - - /* Always restart the engine when doing CP 2D acceleration */ - RADEONCP_RESET(pScrn, info); - RADEONCP_START(pScrn, info); - } - } -#endif - - RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); - - /* Wait for the engine to go idle */ - RADEONWaitForFifoFunction(pScrn, 64); - - for (;;) { - for (i = 0; i < RADEON_TIMEOUT; i++) { - if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { - RADEONEngineFlush(pScrn); - return; - } - } - RADEONTRACE(("Idle timed out: %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Idle timed out, resetting engine...\n"); - RADEONEngineReset(pScrn); - RADEONEngineRestore(pScrn); -#ifdef XF86DRI - if (info->directRenderingEnabled) { - RADEONCP_RESET(pScrn, info); - RADEONCP_START(pScrn, info); - } -#endif - } -} /* This callback is required for multiheader cards using XAA */ static void FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; + /*RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO;*/ #ifdef ACCEL_MMIO - CARD32 pitch64; - - pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - - OUTREG(RADEON_DEFAULT_OFFSET, (((INREG(RADEON_DISPLAY_BASE_ADDR) + pScrn->fbOffset) >> 10) | - (pitch64 << 22))); - +/* OUTREG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset);*/ /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */ RADEONWaitForIdleMMIO(pScrn); #else /* ACCEL_CP */ - RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset); +/* RADEONWaitForFifo(pScrn, 1); + OUTREG(RADEON_DEFAULT_OFFSET, info->frontPitchOffset);*/ RADEONWaitForIdleMMIO(pScrn); @@ -243,8 +161,10 @@ FUNC_NAME(RADEONSubsequentSolidFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(2); + BEGIN_ACCEL(3); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h); @@ -271,6 +191,7 @@ FUNC_NAME(RADEONSetupForSolidLine)(ScrnInfoPtr pScrn, BEGIN_ACCEL(1); OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, 0x55 << RADEON_BRES_CNTL_SHIFT); + FINISH_ACCEL(); } BEGIN_ACCEL(3); @@ -297,10 +218,12 @@ FUNC_NAME(RADEONSubsequentSolidHorVertLine)(ScrnInfoPtr pScrn, if (dir == DEGREES_0) w = len; else h = len; - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (w << 16) | h); @@ -330,8 +253,10 @@ FUNC_NAME(RADEONSubsequentSolidTwoPointLine)(ScrnInfoPtr pScrn, xb, yb, 1, DEGREES_0); - BEGIN_ACCEL(2); + BEGIN_ACCEL(3); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb); @@ -413,12 +338,14 @@ FUNC_NAME(RADEONDashedLastPel)(ScrnInfoPtr pScrn, dp_gui_master_cntl &= ~RADEON_GMC_SRC_DATATYPE_MASK; dp_gui_master_cntl |= RADEON_GMC_SRC_DATATYPE_COLOR; - BEGIN_ACCEL(7); + BEGIN_ACCEL(8); OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, dp_gui_master_cntl); - OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); OUT_ACCEL_REG(RADEON_DP_CNTL, (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); + OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_WIDTH_HEIGHT, (1 << 16) | 1); @@ -459,8 +386,10 @@ FUNC_NAME(RADEONSubsequentDashedTwoPointLine)(ScrnInfoPtr pScrn, FUNC_NAME(RADEONDashedLastPel)(pScrn, xb, yb, info->dash_bg); } - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_DST_LINE_START, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT, phase); OUT_ACCEL_REG(RADEON_DST_LINE_END, (yb << 16) | xb); @@ -516,7 +445,8 @@ FUNC_NAME(RADEONSetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, | RADEON_GMC_BRUSH_NONE | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP[rop].rop - | RADEON_DP_SRC_SOURCE_MEMORY); + | RADEON_DP_SRC_SOURCE_MEMORY + | RADEON_GMC_SRC_PITCH_OFFSET_CNTL); BEGIN_ACCEL(3); @@ -545,8 +475,12 @@ FUNC_NAME(RADEONSubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, if (info->xdir < 0) xa += w - 1, xb += w - 1; if (info->ydir < 0) ya += h - 1, yb += h - 1; - BEGIN_ACCEL(3); + BEGIN_ACCEL(5); + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (ya <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (yb <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SRC_Y_X, (ya << 16) | xa); OUT_ACCEL_REG(RADEON_DST_Y_X, (yb << 16) | xb); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -630,8 +564,10 @@ FUNC_NAME(RADEONSubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (patterny << 8) | patternx); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -683,8 +619,10 @@ FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); - BEGIN_ACCEL(3); + BEGIN_ACCEL(4); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_BRUSH_Y_X, (paty << 16) | patx); OUT_ACCEL_REG(RADEON_DST_Y_X, (y << 16) | x); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -694,7 +632,7 @@ FUNC_NAME(RADEONSubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, #endif #ifdef ACCEL_CP -#define CP_BUFSIZE (info->indirectBuffer->total/4-9) +#define CP_BUFSIZE (info->indirectBuffer->total/4-10) /* Helper function to write out a HOSTDATA_BLT packet into the indirect * buffer and set the XAA scratch buffer address appropriately. @@ -711,10 +649,12 @@ RADEONCPScanlinePacket(ScrnInfoPtr pScrn, int bufno) "CPScanline Packet h=%d hpass=%d chunkwords=%d\n", info->scanline_h, info->scanline_hpass, chunk_words); } - BEGIN_RING(chunk_words+9); + BEGIN_RING(chunk_words+10); - OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+9-2)); + OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT,chunk_words+10-2)); OUT_RING(info->dp_gui_master_cntl_clip); + OUT_RING(info->dst_pitch_offset | + ((info->tilingEnabled && (info->scanline_y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_RING((info->scanline_y << 16) | (info->scanline_x1clip & 0xffff)); OUT_RING(((info->scanline_y+info->scanline_hpass) << 16) | @@ -755,6 +695,8 @@ FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); + info->scanline_bpp = 0; + /* Save for later clipping */ info->dp_gui_master_cntl_clip = (info->dp_gui_master_cntl | RADEON_GMC_DST_CLIPPING @@ -792,9 +734,12 @@ FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, #if X_BYTE_ORDER == X_LITTLE_ENDIAN BEGIN_ACCEL(1); #else - BEGIN_ACCEL(2); + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_ACCEL(2); - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT); + } else + BEGIN_ACCEL(1); #endif OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); @@ -838,9 +783,11 @@ FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr info->scanline_direct = 0; } - BEGIN_ACCEL(4 + (info->scanline_direct ? + BEGIN_ACCEL(5 + (info->scanline_direct ? (info->scanline_words * h) : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft) & 0xffff)); OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff)); @@ -917,6 +864,22 @@ FUNC_NAME(RADEONSubsequentScanline)(ScrnInfoPtr pScrn, #else /* ACCEL_CP */ +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (info->ChipFamily >= CHIP_FAMILY_R300) { + if (info->scanline_bpp == 16) { + RADEONCopySwap(info->scratch_buffer[bufno], + info->scratch_buffer[bufno], + info->scanline_words << 2, + RADEON_HOST_DATA_SWAP_HDW); + } else if (info->scanline_bpp < 15) { + RADEONCopySwap(info->scratch_buffer[bufno], + info->scratch_buffer[bufno], + info->scanline_words << 2, + RADEON_HOST_DATA_SWAP_32BIT); + } + } +#endif + if (--info->scanline_hpass) { info->scratch_buffer[bufno] += 4 * info->scanline_words; } else if (info->scanline_h) { @@ -972,12 +935,15 @@ FUNC_NAME(RADEONSetupForScanlineImageWrite)(ScrnInfoPtr pScrn, #if X_BYTE_ORDER == X_LITTLE_ENDIAN BEGIN_ACCEL(1); #else - BEGIN_ACCEL(2); - - if (bpp == 16) - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); - else - OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); + if (info->ChipFamily < CHIP_FAMILY_R300) { + BEGIN_ACCEL(2); + + if (bpp == 16) + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_HDW); + else + OUT_ACCEL_REG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); + } else + BEGIN_ACCEL(1); #endif #endif OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); @@ -1028,9 +994,11 @@ FUNC_NAME(RADEONSubsequentScanlineImageWriteRect)(ScrnInfoPtr pScrn, info->scanline_direct = 0; } - BEGIN_ACCEL(4 + (info->scanline_direct ? + BEGIN_ACCEL(5 + (info->scanline_direct ? (info->scanline_words * h) : 0)); + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset | + ((info->tilingEnabled && (y <= pScrn->virtualY)) ? RADEON_DST_TILE_MACRO : 0)); OUT_ACCEL_REG(RADEON_SC_TOP_LEFT, (y << 16) | ((x+skipleft) & 0xffff)); OUT_ACCEL_REG(RADEON_SC_BOTTOM_RIGHT, ((y+h) << 16) | ((x+w) & 0xffff)); @@ -1137,39 +1105,7 @@ FUNC_NAME(RADEONDisableClipping)(ScrnInfoPtr pScrn) FUNC_NAME(RADEONSetTransparency)(pScrn, info->trans_color); } -#ifdef ACCEL_CP -/* Point the DST_PITCH_OFFSET register at the current buffer. This - * allows us to interact with the back and depth buffers. All CP 2D - * acceleration commands use the DST_PITCH_OFFSET register. - */ void -RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ACCEL_PREAMBLE(); - - switch (buffer) { - case RADEON_BACK: - info->dst_pitch_offset = info->backPitchOffset; - break; - case RADEON_DEPTH: - info->dst_pitch_offset = info->depthPitchOffset; - break; - default: - case RADEON_FRONT: - info->dst_pitch_offset = info->frontPitchOffset; - break; - } - - BEGIN_ACCEL(1); - - OUT_ACCEL_REG(RADEON_DEFAULT_OFFSET, info->dst_pitch_offset); - - FINISH_ACCEL(); -} -#endif - -static void FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1224,15 +1160,17 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) | LEFT_EDGE_CLIPPING_NEGATIVE_X); a->NumScanlineColorExpandBuffers = 1; a->ScanlineColorExpandBuffers = info->scratch_buffer; - info->scratch_save - = xalloc(((pScrn->virtualX+31)/32*4) - + (pScrn->virtualX * info->CurrentLayout.pixel_bytes)); + if (!info->scratch_save) + info->scratch_save + = xalloc(((pScrn->virtualX+31)/32*4) + + (pScrn->virtualX * info->CurrentLayout.pixel_bytes)); info->scratch_buffer[0] = info->scratch_save; a->SetupForScanlineCPUToScreenColorExpandFill = FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill); a->SubsequentScanlineCPUToScreenColorExpandFill = FUNC_NAME(RADEONSubsequentScanlineCPUToScreenColorExpandFill); - a->SubsequentColorExpandScanline = FUNC_NAME(RADEONSubsequentScanline); + a->SubsequentColorExpandScanline + = FUNC_NAME(RADEONSubsequentScanline); /* Solid Lines */ a->SetupForSolidLine @@ -1258,7 +1196,7 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) a->SolidLineLimits.x2 = pScrn->virtualX-1; a->SolidLineLimits.y2 = pScrn->virtualY-1; - /* Call miSetZeroLineBias() to have mi/mfb/cfb/fb routines match + /* Call miSetZeroLineBias() to have mi/mfb/fb routines match hardware accel two point lines */ miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8)); diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c new file mode 100644 index 000000000..ecc5f7a32 --- /dev/null +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c @@ -0,0 +1,609 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c,v 1.0tsi Exp $ */ +/* + * Copyright 2004 ATI Technologies Inc., Markham, Ontario + * + * 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, 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS 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. + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "vbe.h" + +/* Read the Video BIOS block and the FP registers (if applicable). */ +Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int tmp; + unsigned short dptr; + + if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot allocate space for hold Video BIOS!\n"); + return FALSE; + } + + if (pInt10) { + info->BIOSAddr = pInt10->BIOSseg << 4; + (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), + RADEON_VBIOS_SIZE); + } else { + xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE); + if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { + if (!xf86DomainHasBIOSSegments(xf86GetPciDomain(info->PciTag))) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "x86 video BIOS not available\n"); + xfree(info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Video BIOS not detected in PCI space!\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Attempting to read Video BIOS from ISA space!\n"); + info->BIOSAddr = 0x000c0000; + xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, + RADEON_VBIOS_SIZE, info->VBIOS); + } + } + + if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unrecognized BIOS signature, BIOS data will not be used\n"); + xfree(info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + /* Verify it's an x86 BIOS not OF firmware, copied from radeonfb */ + dptr = RADEON_BIOS16(0x18); + /* If PCI data signature is wrong assume x86 video BIOS anyway */ + if (RADEON_BIOS32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "ROM PCI data signature incorrect, ignoring\n"); + } + else if (info->VBIOS[dptr + 0x14] != 0x0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Not an x86 BIOS ROM image, BIOS data will not be used\n"); + xfree(info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + if (info->VBIOS) info->ROMHeaderStart = RADEON_BIOS16(0x48); + + if(!info->ROMHeaderStart) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid ROM pointer, BIOS data will not be used\n"); + xfree(info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + + tmp = info->ROMHeaderStart + 4; + if ((RADEON_BIOS8(tmp) == 'A' && + RADEON_BIOS8(tmp+1) == 'T' && + RADEON_BIOS8(tmp+2) == 'O' && + RADEON_BIOS8(tmp+3) == 'M') || + (RADEON_BIOS8(tmp) == 'M' && + RADEON_BIOS8(tmp+1) == 'O' && + RADEON_BIOS8(tmp+2) == 'T' && + RADEON_BIOS8(tmp+3) == 'A')) + info->IsAtomBios = TRUE; + else + info->IsAtomBios = FALSE; + + if (info->IsAtomBios) + info->MasterDataStart = RADEON_BIOS16(info->ROMHeaderStart + 32); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n", + info->IsAtomBios ? "ATOM":"Legacy"); + + return TRUE; +} + +Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int i = 0, j, tmp, tmp0=0, tmp1=0; + + if(!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16(info->MasterDataStart + 22))) { + int crtc = 0, id[2]; + tmp1 = RADEON_BIOS16(tmp + 4); + for (i=0; i<8; i++) { + if(tmp1 & (1<<i)) { + CARD16 portinfo = RADEON_BIOS16(tmp+6+i*2); + if (crtc < 2) { + if ((i==2) || (i==6)) continue; /* ignore TV here */ + + if (crtc == 1) { + /* sharing same port with id[0] */ + if (((portinfo>>8) & 0xf) == id[0]) { + if (i == 3) + pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[0].TMDSType = TMDS_EXT; + + if (pRADEONEnt->PortInfo[0].DACType == DAC_UNKNOWN) + pRADEONEnt->PortInfo[0].DACType = (portinfo & 0xf) - 1; + continue; + } + } + + id[crtc] = (portinfo>>8) & 0xf; + pRADEONEnt->PortInfo[crtc].DACType = (portinfo & 0xf) - 1; + pRADEONEnt->PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf; + if (i == 3) + pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_EXT; + + if((tmp0 = RADEON_BIOS16(info->MasterDataStart + 24)) && id[crtc]) { + switch (RADEON_BIOS16(tmp0 + 4 + 27 * id[crtc]) * 4) + { + case RADEON_GPIO_MONID: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_MONID; + break; + case RADEON_GPIO_DVI_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_DVI; + break; + case RADEON_GPIO_VGA_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_VGA; + break; + case RADEON_GPIO_CRT2_DDC: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_CRT2; + break; + default: + pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE_DETECTED; + break; + } + + } else { + pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE_DETECTED; + } + crtc++; + } else { + /* we have already had two CRTCs assigned. the rest may share the same + * port with the existing connector, fill in them accordingly. + */ + for (j=0; j<2; j++) { + if (((portinfo>>8) & 0xf) == id[j]) { + if (i == 3) + pRADEONEnt->PortInfo[j].TMDSType = TMDS_INT; + else if (i == 7) + pRADEONEnt->PortInfo[j].TMDSType = TMDS_EXT; + + if (pRADEONEnt->PortInfo[j].DACType == DAC_UNKNOWN) + pRADEONEnt->PortInfo[j].DACType = (portinfo & 0xf) - 1; + } + } + } + } + } + + for (i=0; i<2; i++) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, pRADEONEnt->PortInfo[i].DDCType, pRADEONEnt->PortInfo[i].DACType, + pRADEONEnt->PortInfo[i].TMDSType, pRADEONEnt->PortInfo[i].ConnectorType); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); + return FALSE; + } + } else { + /* Some laptops only have one connector (VGA) listed in the connector table, + * we need to add LVDS in as a non-DDC display. + * Note, we can't assume the listed VGA will be filled in PortInfo[0], + * when walking through connector table. connector_found has following meaning: + * 0 -- nothing found, + * 1 -- only PortInfo[0] filled, + * 2 -- only PortInfo[1] filled, + * 3 -- both are filled. + */ + int connector_found = 0; + + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x50))) { + for (i = 1; i < 4; i++) { + + if (!RADEON_BIOS16(tmp + i*2)) + break; /* end of table */ + + tmp0 = RADEON_BIOS16(tmp + i*2); + if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */ + if (connector_found > 0) { + if (pRADEONEnt->PortInfo[tmp1].DDCType == + (RADEONDDCType)((tmp0 >> 8) & 0x0f)) + continue; /* same connector */ + } + + /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */ + tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */ + + pRADEONEnt->PortInfo[tmp1].DDCType = (tmp0 >> 8) & 0x0f; + if (pRADEONEnt->PortInfo[tmp1].DDCType > DDC_CRT2) pRADEONEnt->PortInfo[tmp1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY; + pRADEONEnt->PortInfo[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f; + if (pRADEONEnt->PortInfo[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) pRADEONEnt->PortInfo[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED; + pRADEONEnt->PortInfo[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT; + + /* some sanity checks */ + if (((pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_D) && + (pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_I)) && + pRADEONEnt->PortInfo[tmp1].TMDSType == TMDS_INT) + pRADEONEnt->PortInfo[tmp1].TMDSType = TMDS_UNKNOWN; + + connector_found += (tmp1 + 1); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); + return FALSE; + } + + if (info->IsMobility) { + /* For the cases where only one VGA connector is found, + we assume LVDS is not listed in the connector table, + add it in here as the first port. + */ + if ((connector_found < 3) && (pRADEONEnt->PortInfo[tmp1].ConnectorType == CONNECTOR_CRT)) { + if (connector_found == 1) { + memcpy (&pRADEONEnt->PortInfo[1], &pRADEONEnt->PortInfo[0], + sizeof (pRADEONEnt->PortInfo[0])); + } + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_PROPRIETARY; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS port is not in connector table, added in.\n"); + if (connector_found == 0) connector_found = 1; + else connector_found = 3; + } + + if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) { + if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { + if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { + pRADEONEnt->PortInfo[0].DDCType = tmp1; + if (pRADEONEnt->PortInfo[0].DDCType > DDC_CRT2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown DDCType %d found\n", + pRADEONEnt->PortInfo[0].DDCType); + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } + } else if (connector_found == 2) { + memcpy (&pRADEONEnt->PortInfo[0], &pRADEONEnt->PortInfo[1], + sizeof (pRADEONEnt->PortInfo[0])); + pRADEONEnt->PortInfo[1].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_NONE; + connector_found = 1; + } + + if (connector_found == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No connector found in Connector Info Table.\n"); + } else { + xf86DrvMsg(0, X_INFO, "Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + pRADEONEnt->PortInfo[0].DDCType, pRADEONEnt->PortInfo[0].DACType, + pRADEONEnt->PortInfo[0].TMDSType, pRADEONEnt->PortInfo[0].ConnectorType); + } + if (connector_found == 3) { + xf86DrvMsg(0, X_INFO, "Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + pRADEONEnt->PortInfo[1].DDCType, pRADEONEnt->PortInfo[1].DACType, + pRADEONEnt->PortInfo[1].TMDSType, pRADEONEnt->PortInfo[1].ConnectorType); + } + +#if 0 +/* External TMDS Table, not used now */ + if ((tmp0 = RADEON_BIOS16(info->ROMHeaderStart + 0x58))) { + + pRADEONEnt->PortInfo[1].DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07); + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_DVI_I; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "External TMDS found.\n"); + + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NO External TMDS Info found\n"); + + } +#endif + + } + return TRUE; +} + +/* Read PLL parameters from BIOS block. Default to typical values if there + is no BIOS. */ +Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &info->pll; + CARD16 pll_info_block; + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + pll_info_block = RADEON_BIOS16(info->MasterDataStart + 12); + + pll->reference_freq = RADEON_BIOS16(pll_info_block + 82); + pll->reference_div = 0; /* Need to derive from existing setting + or use a new algorithm to calculate + from min_input and max_input + */ + pll->min_pll_freq = RADEON_BIOS16(pll_info_block + 78); + pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 32); + pll->xclk = RADEON_BIOS16(pll_info_block + 72); + + info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0; + info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0; + if (info->sclk == 0) info->sclk = 200; + if (info->mclk == 0) info->mclk = 200; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %d, max_pll: %d, xclk: %d, sclk: %f, mclk: %f\n", + pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, info->sclk, info->mclk); + + } else { + pll_info_block = RADEON_BIOS16(info->ROMHeaderStart + 0x30); + + pll->reference_freq = RADEON_BIOS16(pll_info_block + 0x0e); + pll->reference_div = RADEON_BIOS16(pll_info_block + 0x10); + pll->min_pll_freq = RADEON_BIOS32(pll_info_block + 0x12); + pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 0x16); + pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); + + info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0; + info->mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0; + } + } + + return TRUE; +} + +Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long tmp, i; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16(info->MasterDataStart + 16))) { + + info->PanelXRes = RADEON_BIOS16(tmp+6); + info->PanelYRes = RADEON_BIOS16(tmp+10); + info->DotClock = RADEON_BIOS16(tmp+4)*10; + info->HBlank = RADEON_BIOS16(tmp+8); + info->HOverPlus = RADEON_BIOS16(tmp+14); + info->HSyncWidth = RADEON_BIOS16(tmp+16); + info->VBlank = RADEON_BIOS16(tmp+12); + info->VOverPlus = RADEON_BIOS16(tmp+18); + info->VSyncWidth = RADEON_BIOS16(tmp+20); + info->PanelPwrDly = RADEON_BIOS16(tmp+40); + + info->Flags = 0; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "LVDS Info:\n" + "XRes: %d, YRes: %d, DotClock: %d\n" + "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" + "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", + info->PanelXRes, info->PanelYRes, info->DotClock, + info->HBlank,info->HOverPlus, info->HSyncWidth, + info->VBlank, info->VOverPlus, info->VSyncWidth); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No LVDS Info Table found in BIOS!\n"); + return FALSE; + } + } else { + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40); + + if (!tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No Panel Info Table found in BIOS!\n"); + return FALSE; + } else { + char stmp[30]; + int tmp0; + + for (i = 0; i < 24; i++) + stmp[i] = RADEON_BIOS8(tmp+i+1); + stmp[24] = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Panel ID string: %s\n", stmp); + + info->PanelXRes = RADEON_BIOS16(tmp+25); + info->PanelYRes = RADEON_BIOS16(tmp+27); + xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", + info->PanelXRes, info->PanelYRes); + + info->PanelPwrDly = RADEON_BIOS16(tmp+44); + if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) + info->PanelPwrDly = 2000; + + /* some panels only work well with certain divider combinations. + */ + info->RefDivider = RADEON_BIOS16(tmp+46); + info->PostDivider = RADEON_BIOS8(tmp+48); + info->FeedbackDivider = RADEON_BIOS16(tmp+49); + if ((info->RefDivider != 0) && + (info->FeedbackDivider > 3)) { + info->UseBiosDividers = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS provided dividers will be used.\n"); + } + + /* We don't use a while loop here just in case we have a corrupted BIOS image. + The max number of table entries is 23 at present, but may grow in future. + To ensure it works with future revisions we loop it to 32. + */ + for (i = 0; i < 32; i++) { + tmp0 = RADEON_BIOS16(tmp+64+i*2); + if (tmp0 == 0) break; + if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && + (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) { + info->HBlank = (RADEON_BIOS16(tmp0+17) - + RADEON_BIOS16(tmp0+19)) * 8; + info->HOverPlus = (RADEON_BIOS16(tmp0+21) - + RADEON_BIOS16(tmp0+19) - 1) * 8; + info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; + info->VBlank = (RADEON_BIOS16(tmp0+24) - + RADEON_BIOS16(tmp0+26)); + info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - + RADEON_BIOS16(tmp0+26)); + info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); + info->DotClock = RADEON_BIOS16(tmp0+9) * 10; + info->Flags = 0; + } + } + } + } + return TRUE; +} + +Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long tmp; + char EDID[256]; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + /* Not yet */ + return FALSE; + } else { + if (!(tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x4c))) { + return FALSE; + } + + memcpy(EDID, (char*)(info->VBIOS + tmp), 256); + + info->DotClock = ((*(CARD8*)(EDID+54)) + ((*(CARD8*)(EDID+55))*256)) * 10; + info->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256; + info->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256; + info->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256); + info->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256); + info->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256; + info->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256); + info->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16)); + info->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256); + info->Flags = V_NHSYNC | V_NVSYNC; /**(CARD8*)(EDID+71);*/ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardcoded EDID data will be used for TMDS panel\n"); + } + return TRUE; +} + +Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 tmp, maxfreq; + int i, n; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + if((tmp = RADEON_BIOS16(info->MasterDataStart + 18))) { + + maxfreq = RADEON_BIOS16(tmp+4); + + for (i=0; i<4; i++) { + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); + /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */ + info->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | + ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) | + ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) | + ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "TMDS PLL from BIOS: %d %x\n", + info->tmds_pll[i].freq, info->tmds_pll[i].value); + + if (maxfreq == info->tmds_pll[i].freq) { + info->tmds_pll[i].freq = 0xffffffff; + break; + } + } + return TRUE; + } + } else { + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x34); + if (tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DFP table revision: %d\n", RADEON_BIOS8(tmp)); + if (RADEON_BIOS8(tmp) == 3) { + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; i<n; i++) { + info->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); + } + return TRUE; + } else if (RADEON_BIOS8(tmp) == 4) { + int stride = 0; + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; i<n; i++) { + info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return TRUE; + } + + /* revision 4 has some problem as it appears in RV280, + comment it off for now, use default instead */ + /* + else if (RADEON_BIOS8(tmp) == 4) { + int stride = 0; + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; i<n; i++) { + info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return TRUE; + } + */ + } + } + return FALSE; +} diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h index b3a2cd8f8..bcd595929 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h @@ -1,3 +1,4 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.11tsi Exp $ */ /* radeon_common.h -- common header definitions for Radeon 2D/3D/DRM suite * * Copyright 2000 VA Linux Systems, Inc., Fremont, California. @@ -30,9 +31,6 @@ * * Converted to common header format: * Jens Owen <jens@tungstengraphics.com> - * - * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.10tsi Exp $ - * */ #ifndef _RADEON_COMMON_H_ @@ -72,6 +70,8 @@ #define DRM_RADEON_IRQ_WAIT 0x17 #define DRM_RADEON_CP_RESUME 0x18 #define DRM_RADEON_SETPARAM 0x19 +#define DRM_RADEON_SURF_ALLOC 0x1a +#define DRM_RADEON_SURF_FREE 0x1b #define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39 @@ -91,7 +91,8 @@ typedef struct { enum { DRM_RADEON_INIT_CP = 0x01, DRM_RADEON_CLEANUP_CP = 0x02, - DRM_RADEON_INIT_R200_CP = 0x03 + DRM_RADEON_INIT_R200_CP = 0x03, + DRM_RADEON_INIT_R300_CP = 0x04 } func; unsigned long sarea_priv_offset; int is_pci; @@ -467,6 +468,20 @@ typedef struct drm_radeon_set_param { } drmRadeonSetParam; #define RADEON_SETPARAM_FB_LOCATION 1 +#define RADEON_SETPARAM_SWITCH_TILING 2 +#define RADEON_SETPARAM_PCIGART_LOCATION 3 +#define RADEON_SETPARAM_NEW_MEMMAP 4 +/* 1.14: Clients can allocate/free a surface + */ +typedef struct drm_radeon_surface_alloc { + unsigned int address; + unsigned int size; + unsigned int flags; +} drmRadeonSurfaceAlloc; + +typedef struct drm_radeon_surface_free { + unsigned int address; +} drmRadeonSurfaceFree; #endif diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_commonfuncs.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_commonfuncs.c new file mode 100644 index 000000000..02d891a39 --- /dev/null +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_commonfuncs.c @@ -0,0 +1,184 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_commaonfuncs.c,v 1.0tsi Exp $ */ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * 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, 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS 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. + */ + +#if defined(ACCEL_MMIO) && defined(ACCEL_CP) +#error Cannot define both MMIO and CP acceleration! +#endif + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix +#else +#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix +#endif + +#ifdef ACCEL_MMIO +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) +#else +#ifdef ACCEL_CP +#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) +#else +#error No accel type defined! +#endif +#endif + +static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + ACCEL_PREAMBLE(); + + if (info->ChipFamily >= CHIP_FAMILY_R300) { + /* Unimplemented */ + } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_R200)) { + + BEGIN_ACCEL(7); + if (info->ChipFamily == CHIP_FAMILY_RS300) { + OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); + } else { + OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0); + } + OUT_ACCEL_REG(R200_PP_CNTL_X, 0); + OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0); + OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0); + OUT_ACCEL_REG(R200_RE_CNTL, 0x0); + /* XXX: correct? Want it to be like RADEON_VTX_ST?_NONPARAMETRIC */ + OUT_ACCEL_REG(R200_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED); + OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE | + R200_VAP_VF_MAX_VTX_NUM); + FINISH_ACCEL(); + } else { + BEGIN_ACCEL(2); + if ((info->ChipFamily == CHIP_FAMILY_RADEON) || + (info->ChipFamily == CHIP_FAMILY_RV200)) + OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0); + else + OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); + OUT_ACCEL_REG(RADEON_SE_COORD_FMT, + RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | + RADEON_VTX_ST0_NONPARAMETRIC | + RADEON_VTX_ST1_NONPARAMETRIC | + RADEON_TEX1_W_ROUTING_USE_W0); + FINISH_ACCEL(); + } + + BEGIN_ACCEL(5); + OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); + OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x07ff07ff); + OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0); + OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff); + OUT_ACCEL_REG(RADEON_SE_CNTL, RADEON_DIFFUSE_SHADE_GOURAUD | + RADEON_BFACE_SOLID | + RADEON_FFACE_SOLID | + RADEON_VTX_PIX_CENTER_OGL | + RADEON_ROUND_MODE_ROUND | + RADEON_ROUND_PREC_4TH_PIX); + FINISH_ACCEL(); +} + + +/* MMIO: + * + * Wait for the graphics engine to be completely idle: the FIFO has + * drained, the Pixel Cache is flushed, and the engine is idle. This is + * a standard "sync" function that will make the hardware "quiescent". + * + * CP: + * + * Wait until the CP is completely idle: the FIFO has drained and the CP + * is idle. + */ +void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i = 0; + +#ifdef ACCEL_CP + /* Make sure the CP is idle first */ + if (info->CPStarted) { + int ret; + + FLUSH_RING(); + + for (;;) { + do { + ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); + if (ret && ret != -EBUSY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: CP idle %d\n", __FUNCTION__, ret); + } + } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); + + if (ret == 0) return; + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Idle timed out, resetting engine...\n"); + RADEONEngineReset(pScrn); + RADEONEngineRestore(pScrn); + + /* Always restart the engine when doing CP 2D acceleration */ + RADEONCP_RESET(pScrn, info); + RADEONCP_START(pScrn, info); + } + } +#endif + +#if 0 + RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS))); +#endif + + /* Wait for the engine to go idle */ + RADEONWaitForFifoFunction(pScrn, 64); + + for (;;) { + for (i = 0; i < RADEON_TIMEOUT; i++) { + if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { + RADEONEngineFlush(pScrn); + return; + } + } + RADEONTRACE(("Idle timed out: %u entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS))); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Idle timed out, resetting engine...\n"); + RADEONEngineReset(pScrn); + RADEONEngineRestore(pScrn); +#ifdef XF86DRI + if (info->directRenderingEnabled) { + RADEONCP_RESET(pScrn, info); + RADEONCP_START(pScrn, info); + } +#endif + } +} diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c index fe54cd988..74c0b4de0 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.25 2003/08/29 21:07:57 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.26tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -46,8 +46,10 @@ /* Driver data structures */ #include "radeon.h" -#include "radeon_macros.h" +#include "radeon_version.h" #include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_mergedfb.h" /* X and server generic header files */ #include "xf86.h" @@ -72,31 +74,40 @@ static CARD32 mono_cursor_color[] = { #if X_BYTE_ORDER == X_BIG_ENDIAN #define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO; -#define CURSOR_SWAPPING_DECL CARD32 __surface_cntl; #define CURSOR_SWAPPING_START() \ + do { \ + if (info->accel) \ + (*info->accel->Sync)(pScrn); \ OUTREG(RADEON_SURFACE_CNTL, \ - ((__surface_cntl = INREG(RADEON_SURFACE_CNTL)) | \ - RADEON_NONSURF_AP0_SWP_32BPP) & \ - ~RADEON_NONSURF_AP0_SWP_16BPP) -#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, __surface_cntl)) + (info->ModeReg.surface_cntl | \ + RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \ + ~(RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP)); \ + } while (0) +#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, \ + info->ModeReg.surface_cntl)) #else #define CURSOR_SWAPPING_DECL_MMIO -#define CURSOR_SWAPPING_DECL -#define CURSOR_SWAPPING_START() +#define CURSOR_SWAPPING_START() \ + do { \ + if (info->accel) \ + (*info->accel->Sync)(pScrn); \ + } while (0) #define CURSOR_SWAPPING_END() #endif + /* Set cursor foreground and background colors */ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset); int pixel, i; CURSOR_SWAPPING_DECL_MMIO - CURSOR_SWAPPING_DECL + + RADEONTRACE(("RADEONSetCursorColors\n")); #ifdef ARGB_CURSOR /* Don't recolour cursors set with SetCursorARGB. */ @@ -119,7 +130,7 @@ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) */ for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) if ((pixel = *pixels)) - *pixels = (pixel == info->cursor_fg) ? fg : bg; + *pixels = (pixel == info->cursor_fg) ? fg : bg; CURSOR_SWAPPING_END(); info->cursor_fg = fg; @@ -138,10 +149,16 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) int xorigin = 0; int yorigin = 0; int total_y = pScrn->frameY1 - pScrn->frameY0; - int X2 = pScrn->frameX0 + x; - int Y2 = pScrn->frameY0 + y; int stride = 256; + if(info->MergedFB) { + RADEONTRACE(("RADEONSetCursorPositionMerged\n")); + RADEONSetCursorPositionMerged(pScrn, x, y); + return; + } + + RADEONTRACE(("RADEONSetCursorPosition\n")); + if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; if (y > total_y) y = total_y; @@ -149,57 +166,6 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - if (info->Clone) { - int X0 = 0; - int Y0 = 0; - - if ((info->CurCloneMode->VDisplay == pScrn->currentMode->VDisplay) && - (info->CurCloneMode->HDisplay == pScrn->currentMode->HDisplay)) { - Y2 = y; - X2 = x; - X0 = pScrn->frameX0; - Y0 = pScrn->frameY0; - } else { - if (y < 0) - Y2 = pScrn->frameY0; - - if (x < 0) - X2 = pScrn->frameX0; - - if (Y2 >= info->CurCloneMode->VDisplay + info->CloneFrameY0) { - Y0 = Y2 - info->CurCloneMode->VDisplay; - Y2 = info->CurCloneMode->VDisplay - 1; - } else if (Y2 < info->CloneFrameY0) { - Y0 = Y2; - Y2 = 0; - } else { - Y2 -= info->CloneFrameY0; - Y0 = info->CloneFrameY0; - } - - if (X2 >= info->CurCloneMode->HDisplay + info->CloneFrameX0) { - X0 = X2 - info->CurCloneMode->HDisplay; - X2 = info->CurCloneMode->HDisplay - 1; - } else if (X2 < info->CloneFrameX0) { - X0 = X2; - X2 = 0; - } else { - X2 -= info->CloneFrameX0; - X0 = info->CloneFrameX0; - } - - if (info->CurCloneMode->Flags & V_DBLSCAN) - Y2 *= 2; - } - - if ((X0 >= 0 || Y0 >= 0) && - ((info->CloneFrameX0 != X0) || (info->CloneFrameY0 != Y0))) { - RADEONDoAdjustFrame(pScrn, X0, Y0, TRUE); - info->CloneFrameX0 = X0; - info->CloneFrameY0 = Y0; - } - } - if (!info->IsSecondary) { OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK | (xorigin << 16) @@ -207,7 +173,9 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); - OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride); + RADEONTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d\n", + info->cursor_offset, yorigin, stride)); + OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride); } else { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) @@ -216,26 +184,9 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); OUTREG(RADEON_CUR2_OFFSET, - info->cursor_start + pScrn->fbOffset + yorigin * stride); + info->cursor_offset + pScrn->fbOffset + yorigin * stride); } - if (info->Clone) { - xorigin = 0; - yorigin = 0; - if (X2 < 0) xorigin = -X2 + 1; - if (Y2 < 0) yorigin = -Y2 + 1; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - - OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK - | (xorigin << 16) - | yorigin)); - OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : X2) << 16) - | (yorigin ? 0 : Y2))); - OUTREG(RADEON_CUR2_OFFSET, - info->cursor_start + pScrn->fbOffset + yorigin * stride); - } } /* Copy cursor image from `image' to video memory. RADEONSetCursorPosition @@ -246,12 +197,13 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD8 *s = (CARD8 *)(pointer)image; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset); CARD32 save1 = 0; CARD32 save2 = 0; CARD8 chunk; CARD32 i, j; - CURSOR_SWAPPING_DECL + + RADEONTRACE(("RADEONLoadCursorImage (at %x)\n", info->cursor_offset)); if (!info->IsSecondary) { save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); @@ -259,7 +211,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -279,8 +231,8 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) */ CURSOR_SWAPPING_START(); #define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2) - for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK; i++) { - chunk = *s++; + for (i = 0; i < (CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK); i++) { + chunk = *s++; for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2) *d++ = mono_cursor_color[chunk & 3]; } @@ -292,7 +244,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } @@ -303,7 +255,9 @@ static void RADEONHideCursor(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + RADEONTRACE(("RADEONHideCursor\n")); + + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); if (!info->IsSecondary) @@ -316,7 +270,9 @@ static void RADEONShowCursor(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + RADEONTRACE(("RADEONShowCursor\n")); + + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, ~RADEON_CRTC2_CUR_EN); @@ -331,7 +287,7 @@ static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - return info->cursor_start ? TRUE : FALSE; + return info->cursor ? TRUE : FALSE; } #ifdef ARGB_CURSOR @@ -339,10 +295,7 @@ static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (info->cursor_start && + if (RADEONUseHWCursor(pScreen, pCurs) && pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH) return TRUE; return FALSE; @@ -352,16 +305,14 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_start); + CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset); int x, y, w, h; CARD32 save1 = 0; CARD32 save2 = 0; CARD32 *image = pCurs->bits->argb; CARD32 *i; - CURSOR_SWAPPING_DECL - if (!image) - return; /* XXX can't happen */ + RADEONTRACE(("RADEONLoadCursorARGB\n")); if (!info->IsSecondary) { save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); @@ -369,7 +320,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -402,12 +353,12 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) for (x = 0; x < CURSOR_WIDTH; x++) *d++ = 0; - CURSOR_SWAPPING_END (); + CURSOR_SWAPPING_END(); if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } @@ -458,29 +409,24 @@ Bool RADEONCursorInit(ScreenPtr pScreen) width = pScrn->displayWidth; width_bytes = width * (pScrn->bitsPerPixel / 8); height = (size_bytes + width_bytes - 1) / width_bytes; - fbarea = xf86AllocateOffscreenArea(pScreen, - width, - height, - 256, - NULL, - NULL, - NULL); + + fbarea = xf86AllocateOffscreenArea(pScreen, width, height, + 256, NULL, NULL, NULL); if (!fbarea) { - info->cursor_start = 0; + info->cursor_offset = 0; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Hardware cursor disabled" " due to insufficient offscreen memory\n"); } else { - info->cursor_start = RADEON_ALIGN((fbarea->box.x1 + - fbarea->box.y1 * width) * - info->CurrentLayout.pixel_bytes, - 256); - info->cursor_end = info->cursor_start + size_bytes; + info->cursor_offset = RADEON_ALIGN((fbarea->box.x1 + + fbarea->box.y1 * width) * + info->CurrentLayout.pixel_bytes, + 256); + info->cursor_end = info->cursor_offset + size_bytes; } - RADEONTRACE(("RADEONCursorInit (0x%08x-0x%08x)\n", - info->cursor_start, info->cursor_end)); + info->cursor_offset, info->cursor_end)); return xf86InitCursor(pScreen, cursor); } diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c index 099222394..34367d909 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.41tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.42tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -59,8 +59,6 @@ static size_t radeon_drm_page_size; -static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen); -static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen); static void RADEONDRITransitionTo2d(ScreenPtr pScreen); static void RADEONDRITransitionTo3d(ScreenPtr pScreen); static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); @@ -124,7 +122,7 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) } i = 0; - for (db = 0; db <= use_db; db++) { + for (db = use_db; db >= 0; db--) { for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) { for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) { pRADEONConfigPtrs[i] = &pRADEONConfigs[i]; @@ -157,14 +155,17 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].doubleBuffer = FALSE; pConfigs[i].stereo = FALSE; pConfigs[i].bufferSize = 16; - pConfigs[i].depthSize = 16; - if (stencil) + pConfigs[i].depthSize = info->depthBits; + if (pConfigs[i].depthSize == 24 ? (RADEON_USE_STENCIL - stencil) + : stencil) { pConfigs[i].stencilSize = 8; - else + } else { pConfigs[i].stencilSize = 0; + } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; - if (accum || stencil) { + if (accum || + (pConfigs[i].stencilSize && pConfigs[i].depthSize == 16)) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; @@ -207,7 +208,7 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) } i = 0; - for (db = 0; db <= use_db; db++) { + for (db = use_db; db >= 0; db--) { for (accum = 0; accum <= RADEON_USE_ACCUM; accum++) { for (stencil = 0; stencil <= RADEON_USE_STENCIL; stencil++) { pRADEONConfigPtrs[i] = &pRADEONConfigs[i]; @@ -240,16 +241,17 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].doubleBuffer = FALSE; pConfigs[i].stereo = FALSE; pConfigs[i].bufferSize = 32; - if (stencil) { - pConfigs[i].depthSize = 24; + pConfigs[i].depthSize = info->depthBits; + if (pConfigs[i].depthSize == 24 ? (RADEON_USE_STENCIL - stencil) + : stencil) { pConfigs[i].stencilSize = 8; } else { - pConfigs[i].depthSize = 24; pConfigs[i].stencilSize = 0; } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; - if (accum) { + if (accum || + (pConfigs[i].stencilSize && pConfigs[i].depthSize == 16)) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; @@ -343,8 +345,57 @@ static void RADEONEnterServer(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSAREAPrivPtr pSAREAPriv; + + SET_SYNC_FLAG(info->accel); + + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen)) + info->XInited3D = FALSE; + + + /* TODO: Fix this more elegantly. + * Sometimes (especially with multiple DRI clients), this code + * runs immediately after a DRI client issues a rendering command. + * + * The accel code regularly inserts WAIT_UNTIL_IDLE into the + * command buffer that is sent with the indirect buffer below. + * The accel code fails to set the 3D cache flush registers for + * the R300 before sending WAIT_UNTIL_IDLE. Sending a cache flush + * on these new registers is not necessary for pure 2D functionality, + * but it *is* necessary after 3D operations. + * Without the cache flushes before WAIT_UNTIL_IDLE, the R300 locks up. + * + * The CP_IDLE call into the DRM indirectly flushes all caches and + * thus avoids the lockup problem, but the solution is far from ideal. + * Better solutions could be: + * - always flush caches when entering the X server + * - track the type of rendering commands somewhere and issue + * cache flushes when they change + * However, I don't feel confident enough with the control flow + * inside the X server to implement either fix. -- nh + */ + + /* On my computer (Radeon Mobility M10) + The fix below results in x11perf -shmput500 rate of 245.0/sec + which is lower than 264.0/sec I get without it. + + Doing the same each time before indirect buffer is submitted + results in x11perf -shmput500 rate of 225.0/sec. + + On the other hand, not using CP acceleration at all benchmarks + at 144.0/sec. + + For now let us accept this as a lesser evil, especially as the + DRM driver for R300 is still in flux. + + Once the code is more stable this should probably be moved into DRM driver. + */ + + if (info->ChipFamily>=CHIP_FAMILY_R300) + drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); + - if (info->accel) info->accel->NeedToSync = TRUE; } /* Called when the X server goes to sleep to allow the X server's @@ -394,73 +445,23 @@ static void RADEONDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, } } -/* The Radeon has depth tiling on all the time, so we have to convert - * the x,y coordinates into the memory bus address (mba) in the same - * manner as the engine. In each case, the linear block address (ba) - * is calculated, and then wired with x and y to produce the final - * memory address. +/* The Radeon has depth tiling on all the time. Rely on surface regs to + * translate the addresses (only works if allowColorTiling is true). */ -static CARD32 radeon_mba_z16(RADEONInfoPtr info, int x, int y) -{ - CARD32 pitch = info->frontPitch; - CARD32 address = 0; /* a[0] = 0 */ - CARD32 ba; - - ba = (y / 16) * (pitch / 32) + (x / 32); - - address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */ - address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */ - address |= (x & 0x8) << 4; /* a[7] = x[3] */ - address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ - address |= (y & 0x8) << 7; /* a[10] = y[3] */ - address |= ((x & 0x10) ^ (y & 0x10)) << 7; /* a[11] = x[4] ^ y[4] */ - address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ - - return address; -} - -static CARD32 radeon_mba_z32(RADEONInfoPtr info, int x, int y) -{ - CARD32 pitch = info->frontPitch; - CARD32 address = 0; /* a[0..1] = 0 */ - CARD32 ba; - - ba = (y / 16) * (pitch / 16) + (x / 16); - - address |= (x & 0x7) << 2; /* a[2..4] = x[0..2] */ - address |= (y & 0x3) << 5; /* a[5..6] = y[0..1] */ - address |= - (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; /* a[7] = x[4] ^ y[2] */ - address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ - - address |= (y & 0x8) << 7; /* a[10] = y[3] */ - address |= - (((x & 0x8) << 1) ^ (y & 0x10)) << 7; /* a[11] = x[3] ^ y[4] */ - address |= (ba & ~0x3u) << 10; /* a[12..] = ba[2..] */ - - return address; -} /* 16-bit depth buffer functions */ #define WRITE_DEPTH16(_x, _y, d) \ - *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) = (d) + *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch)) = (d) #define READ_DEPTH16(d, _x, _y) \ - (d) = *(CARD16 *)(pointer)(buf + radeon_mba_z16(info, (_x), (_y))) - -/* 24 bit depth, 8 bit stencil depthbuffer functions */ -#define WRITE_DEPTH32(_x, _y, d) \ -do { \ - CARD32 tmp = \ - *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))); \ - tmp &= 0xff000000; \ - tmp |= ((d) & 0x00ffffff); \ - *(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) = tmp; \ -} while (0) - -#define READ_DEPTH32(d, _x, _y) \ - d = (*(CARD32 *)(pointer)(buf + radeon_mba_z32(info, (_x), (_y))) \ - & 0x00ffffff) + (d) = *(CARD16 *)(pointer)(buf + 2*(_x + _y*info->frontPitch)) + +/* 32-bit depth buffer (stencil and depth simultaneously) functions */ +#define WRITE_DEPTHSTENCIL32(_x, _y, d) \ + *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch)) = (d) + +#define READ_DEPTHSTENCIL32(d, _x, _y) \ + (d) = *(CARD32 *)(pointer)(buf + 4*(_x + _y*info->frontPitch)) /* Screen to screen copy of data in the depth buffer */ static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, @@ -493,8 +494,8 @@ static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, case 32: for (x = xstart; x != xend; x += xdir) { for (y = ystart; y != yend; y += ydir) { - READ_DEPTH32(d, xa+x, ya+y); - WRITE_DEPTH32(xb+x, yb+y, d); + READ_DEPTHSTENCIL32(d, xa+x, ya+y); + WRITE_DEPTHSTENCIL32(xb+x, yb+y, d); } } break; @@ -632,6 +633,11 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, xdir = 1; } + /* pretty much a hack. */ + info->dst_pitch_offset = info->backPitchOffset; + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; + (*info->accel->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, (CARD32)(-1), -1); @@ -651,14 +657,12 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, if (w <= 0) continue; if (h <= 0) continue; - RADEONSelectBuffer(pScrn, RADEON_BACK); (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, destx, desty, w, h); if (info->depthMoves) { - RADEONSelectBuffer(pScrn, RADEON_DEPTH); RADEONScreenToScreenCopyDepth(pScrn, xa, ya, destx, desty, @@ -666,7 +670,7 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, } } - RADEONSelectBuffer(pScrn, RADEON_FRONT); + info->dst_pitch_offset = info->frontPitchOffset;; DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); @@ -712,23 +716,39 @@ static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) unsigned int device = drmAgpDeviceId(info->drmFD); mode &= ~RADEON_AGP_MODE_MASK; - switch (info->agpMode) { - case 4: mode |= RADEON_AGP_4X_MODE; - case 2: mode |= RADEON_AGP_2X_MODE; - case 1: default: mode |= RADEON_AGP_1X_MODE; + if ((mode & RADEON_AGPv3_MODE) && + (INREG(RADEON_AGP_STATUS) & RADEON_AGPv3_MODE)) { + /* only set one mode bit for AGPv3 */ + switch (info->agpMode) { + case 8: mode |= RADEON_AGPv3_8X_MODE; break; + case 4: default: mode |= RADEON_AGPv3_4X_MODE; + } + /*TODO: need to take care of other bits valid for v3 mode + * currently these bits are not used in all tested cards. + */ + } else { + switch (info->agpMode) { + case 4: mode |= RADEON_AGP_4X_MODE; + case 2: mode |= RADEON_AGP_2X_MODE; + case 1: default: mode |= RADEON_AGP_1X_MODE; + } } - if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; - - if ((vendor == PCI_VENDOR_AMD) && + if (info->agpFastWrite && + (vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) { /* Disable fast write for AMD 761 chipset, since they cause * lockups when enabled. */ - mode &= ~0x10; /* FIXME: Magic number */ + info->agpFastWrite = FALSE; + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[agp] Not enabling Fast Writes on AMD 761 chipset to avoid " + "lockups"); } + if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; + xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", mode, vendor, device, @@ -807,7 +827,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) "[agp] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { + &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); return FALSE; } @@ -826,7 +846,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { + &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring read ptr\n"); return FALSE; @@ -846,7 +866,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) info->bufHandle); if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { + &info->buf) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map vertex/indirect buffers\n"); return FALSE; @@ -866,7 +886,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) info->gartTexHandle); if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize, - (drmAddressPtr)&info->gartTex) < 0) { + &info->gartTex) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map GART texture map\n"); return FALSE; @@ -910,7 +930,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) "[pci] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { + &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); return FALSE; } @@ -932,7 +952,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { + &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring read ptr\n"); return FALSE; @@ -955,7 +975,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) info->bufHandle); if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { + &info->buf) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map vertex/indirect buffers\n"); return FALSE; @@ -978,7 +998,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) info->gartTexHandle); if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize, - (drmAddressPtr)&info->gartTex) < 0) { + &info->gartTex) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map GART texture map\n"); return FALSE; @@ -1015,28 +1035,30 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) drmRadeonInit drmInfo; memset(&drmInfo, 0, sizeof(drmRadeonInit)); - + if ( info->ChipFamily >= CHIP_FAMILY_R300 ) + drmInfo.func = DRM_RADEON_INIT_R300_CP; + else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) drmInfo.func = DRM_RADEON_INIT_R200_CP; else drmInfo.func = DRM_RADEON_INIT_CP; drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); - drmInfo.is_pci = info->IsPCI; + drmInfo.is_pci = (info->cardType!=CARD_AGP); drmInfo.cp_mode = info->CPMode; drmInfo.gart_size = info->gartSize*1024*1024; drmInfo.ring_size = info->ringSize*1024*1024; drmInfo.usec_timeout = info->CPusecTimeout; drmInfo.fb_bpp = info->CurrentLayout.pixel_code; - drmInfo.depth_bpp = info->CurrentLayout.pixel_code; + drmInfo.depth_bpp = (info->depthBits - 8) * 2; drmInfo.front_offset = info->frontOffset; drmInfo.front_pitch = info->frontPitch * cpp; drmInfo.back_offset = info->backOffset; drmInfo.back_pitch = info->backPitch * cpp; drmInfo.depth_offset = info->depthOffset; - drmInfo.depth_pitch = info->depthPitch * cpp; + drmInfo.depth_pitch = info->depthPitch * drmInfo.depth_bpp / 8; drmInfo.fb_offset = info->fbHandle; drmInfo.mmio_offset = info->registerHandle; @@ -1063,24 +1085,18 @@ static void RADEONDRIGartHeapInit(RADEONInfoPtr info, ScreenPtr pScreen) drmRadeonMemInitHeap drmHeap; /* Start up the simple memory manager for GART space */ - if (info->drmMinor >= 6) { - drmHeap.region = RADEON_MEM_REGION_GART; - drmHeap.start = 0; - drmHeap.size = info->gartTexMapSize; - - if (drmCommandWrite(info->drmFD, DRM_RADEON_INIT_HEAP, - &drmHeap, sizeof(drmHeap))) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Failed to initialize GART heap manager\n"); - } else { - xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Initialized kernel GART heap manager, %d\n", - info->gartTexMapSize); - } + drmHeap.region = RADEON_MEM_REGION_GART; + drmHeap.start = 0; + drmHeap.size = info->gartTexMapSize; + + if (drmCommandWrite(info->drmFD, DRM_RADEON_INIT_HEAP, + &drmHeap, sizeof(drmHeap))) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Failed to initialize GART heap manager\n"); } else { xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Kernel module too old (1.%d) for GART heap manager\n", - info->drmMinor); + "[drm] Initialized kernel GART heap manager, %d\n", + info->gartTexMapSize); } } @@ -1093,7 +1109,7 @@ static Bool RADEONDRIBufInit(RADEONInfoPtr info, ScreenPtr pScreen) info->bufNumBufs = drmAddBufs(info->drmFD, info->bufMapSize / RADEON_BUFFER_SIZE, RADEON_BUFFER_SIZE, - info->IsPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER, + (info->cardType!=CARD_AGP) ? DRM_SG_BUFFER : DRM_AGP_BUFFER, info->bufStart); if (info->bufNumBufs <= 0) { @@ -1157,23 +1173,17 @@ static void RADEONDRICPInit(ScrnInfoPtr pScrn) /* Make sure the CP is on for the X server */ RADEONCP_START(pScrn, info); - RADEONSelectBuffer(pScrn, RADEON_FRONT); + info->dst_pitch_offset = info->frontPitchOffset; } -/* Initialize the screen-specific data structures for the DRI and the - * Radeon. This is the main entry point to the device-specific - * initialization code. It calls device-independent DRI functions to - * create the DRI data structures and initialize the DRI state. - */ -Bool RADEONDRIScreenInit(ScreenPtr pScreen) +/* Get the DRM version and do some basic useability checks of DRI */ +Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - DRIInfoPtr pDRIInfo; - RADEONDRIPtr pRADEONDRI; - int major, minor, patch; - drmVersionPtr version; + int major, minor, patch, fd; + int req_minor, req_patch; + char *busId; /* Check that the GLX, DRI, and DRM modules have been loaded by testing * for known symbols in each module. @@ -1182,24 +1192,135 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) if (!xf86LoaderCheckSymbol("DRIScreenInit")) return FALSE; if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[dri] RADEONDRIScreenInit failed (libdri.a too old)\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed (libdri.a too old)\n" + "[dri] Disabling DRI.\n"); return FALSE; } /* Check the DRI version */ DRIQueryVersion(&major, &minor, &patch); if (major != 4 || minor < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[dri] RADEONDRIScreenInit failed because of a version " + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed because of a version " "mismatch.\n" - "[dri] libDRI version is %d.%d.%d but version 4.0.x is " + "[dri] libdri version is %d.%d.%d but version 4.0.x is " "needed.\n" "[dri] Disabling DRI.\n", major, minor, patch); return FALSE; } + /* Check the lib version */ + if (xf86LoaderCheckSymbol("drmGetLibVersion")) + info->pLibDRMVersion = drmGetLibVersion(info->drmFD); + if (info->pLibDRMVersion == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed because libDRM is really " + "way to old to even get a version number out of it.\n" + "[dri] Disabling DRI.\n"); + return FALSE; + } + if (info->pLibDRMVersion->version_major != 1 || + info->pLibDRMVersion->version_minor < 2) { + /* incompatible drm library version */ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed because of a " + "version mismatch.\n" + "[dri] libdrm.a module version is %d.%d.%d but " + "version 1.2.x is needed.\n" + "[dri] Disabling DRI.\n", + info->pLibDRMVersion->version_major, + info->pLibDRMVersion->version_minor, + info->pLibDRMVersion->version_patchlevel); + drmFreeVersion(info->pLibDRMVersion); + info->pLibDRMVersion = NULL; + return FALSE; + } + + /* Create a bus Id */ + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + busId = DRICreatePCIBusID(info->PciInfo); + } else { + busId = xalloc(64); + sprintf(busId, + "PCI:%d:%d:%d", + info->PciInfo->bus, + info->PciInfo->device, + info->PciInfo->func); + } + + /* Low level DRM open */ + fd = drmOpen(RADEON_DRIVER_NAME, busId); + xfree(busId); + if (fd < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed to open the DRM\n" + "[dri] Disabling DRI.\n"); + return FALSE; + } + + /* Get DRM version & close DRM */ + info->pKernelDRMVersion = drmGetVersion(fd); + drmClose(fd); + if (info->pKernelDRMVersion == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed to get the DRM version\n" + "[dri] Disabling DRI.\n"); + return FALSE; + } + + /* Now check if we qualify */ + if (info->ChipFamily >= CHIP_FAMILY_R300) { + req_minor = 17; + req_patch = 0; + } else if (info->IsIGP) { + req_minor = 10; + req_patch = 0; + } else { /* Many problems have been reported with 1.7 in the 2.4 kernel */ + req_minor = 8; + req_patch = 0; + } + + /* We don't, bummer ! */ + if (info->pKernelDRMVersion->version_major != 1 || + info->pKernelDRMVersion->version_minor < req_minor || + (info->pKernelDRMVersion->version_minor == req_minor && + info->pKernelDRMVersion->version_patchlevel < req_patch)) { + /* Incompatible drm version */ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] RADEONDRIGetVersion failed because of a version " + "mismatch.\n" + "[dri] radeon.o kernel module version is %d.%d.%d " + "but version 1.%d.%d or newer is needed.\n" + "[dri] Disabling DRI.\n", + info->pKernelDRMVersion->version_major, + info->pKernelDRMVersion->version_minor, + info->pKernelDRMVersion->version_patchlevel, + req_minor, + req_patch); + drmFreeVersion(info->pKernelDRMVersion); + info->pKernelDRMVersion = NULL; + return FALSE; + } + + return TRUE; +} + +/* Initialize the screen-specific data structures for the DRI and the + * Radeon. This is the main entry point to the device-specific + * initialization code. It calls device-independent DRI functions to + * create the DRI data structures and initialize the DRI state. + */ +Bool RADEONDRIScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + DRIInfoPtr pDRIInfo; + RADEONDRIPtr pRADEONDRI; + + info->DRICloseScreen = NULL; + switch (info->CurrentLayout.pixel_code) { case 8: case 15: @@ -1227,6 +1348,9 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) info->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = RADEON_DRIVER_NAME; + if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) { + pDRIInfo->clientDriverName = R300_DRIVER_NAME; + } else if ( info->ChipFamily >= CHIP_FAMILY_R200 ) pDRIInfo->clientDriverName = R200_DRIVER_NAME; else @@ -1242,11 +1366,12 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) info->PciInfo->device, info->PciInfo->func); } - pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR; + pDRIInfo->ddxDriverMajorVersion = info->allowColorTiling ? + RADEON_VERSION_MAJOR_TILED : RADEON_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH; pDRIInfo->frameBufferPhysicalAddress = info->LinearAddr; - pDRIInfo->frameBufferSize = info->FbMapSize; + pDRIInfo->frameBufferSize = info->FbMapSize - info->FbSecureSize; pDRIInfo->frameBufferStride = (pScrn->displayWidth * info->CurrentLayout.pixel_bytes); pDRIInfo->ddxDrawableTableEntry = RADEON_MAX_DRAWABLES; @@ -1254,6 +1379,9 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) < RADEON_MAX_DRAWABLES ? SAREA_MAX_DRAWABLES : RADEON_MAX_DRAWABLES); + /* kill DRIAdjustFrame. We adjust sarea frame info ourselves to work + correctly with pageflip + mergedfb/color tiling */ + pDRIInfo->wrap.AdjustFrame = NULL; #ifdef PER_CONTEXT_SAREA /* This is only here for testing per-context SAREAs. When used, the @@ -1294,8 +1422,6 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->InitBuffers = RADEONDRIInitBuffers; pDRIInfo->MoveBuffers = RADEONDRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; - pDRIInfo->OpenFullScreen = RADEONDRIOpenFullScreen; - pDRIInfo->CloseFullScreen = RADEONDRICloseFullScreen; pDRIInfo->TransitionTo2d = RADEONDRITransitionTo2d; pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; @@ -1313,102 +1439,8 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo = NULL; return FALSE; } - - /* Check the DRM lib version. - * drmGetLibVersion was not supported in version 1.0, so check for - * symbol first to avoid possible crash or hang. - */ - if (xf86LoaderCheckSymbol("drmGetLibVersion")) { - version = drmGetLibVersion(info->drmFD); - } else { - /* drmlib version 1.0.0 didn't have the drmGetLibVersion - * entry point. Fake it by allocating a version record - * via drmGetVersion and changing it to version 1.0.0. - */ - version = drmGetVersion(info->drmFD); - version->version_major = 1; - version->version_minor = 0; - version->version_patchlevel = 0; - } - - if (version) { - if (version->version_major != 1 || - version->version_minor < 1) { - /* incompatible drm library version */ - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[dri] RADEONDRIScreenInit failed because of a " - "version mismatch.\n" - "[dri] libdrm.a module version is %d.%d.%d but " - "version 1.1.x is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel); - drmFreeVersion(version); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - drmFreeVersion(version); - } - - /* Check the radeon DRM version */ - version = drmGetVersion(info->drmFD); - if (version) { - int req_minor, req_patch; - - if (info->IsIGP) { - req_minor = 10; - req_patch = 0; - } else if (info->ChipFamily >= CHIP_FAMILY_R200) { - req_minor = 5; - req_patch = 0; - } else { -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - req_minor = 1; - req_patch = 0; -#else - req_minor = 2; - req_patch = 1; -#endif - } - - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[dri] RADEONDRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] radeon.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - - if (version->version_minor < 3) { - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[dri] Some DRI features disabled because of version " - "mismatch.\n" - "[dri] radeon.o kernel module version is %d.%d.%d but " - "1.3.1 or later is preferred.\n", - version->version_major, - version->version_minor, - version->version_patchlevel); - } - info->drmMinor = version->version_minor; - drmFreeVersion(version); - } - /* Initialize AGP */ - if (!info->IsPCI && !RADEONDRIAgpInit(info, pScreen)) { + if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP failed to initialize. Disabling the DRI.\n" ); xf86DrvMsg(pScreen->myNum, X_INFO, @@ -1419,7 +1451,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) } /* Initialize PCI */ - if (info->IsPCI && !RADEONDRIPciInit(info, pScreen)) { + if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] PCI failed to initialize. Disabling the DRI.\n" ); RADEONDRICloseScreen(pScreen); @@ -1439,12 +1471,12 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) map, but we need it as well */ { void *scratch_ptr; - int scratch_int; + int scratch_int; DRIGetDeviceInfo(pScreen, &info->fbHandle, - &scratch_int, &scratch_int, - &scratch_int, &scratch_int, - &scratch_ptr); + &scratch_int, &scratch_int, + &scratch_int, &scratch_int, + &scratch_ptr); } /* FIXME: When are these mappings unmapped? */ @@ -1458,6 +1490,17 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) return TRUE; } +static Bool RADEONDRIDoCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONDRICloseScreen(pScreen); + + pScreen->CloseScreen = info->DRICloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + /* Finish initializing the device-dependent DRI state, and call * DRIFinishScreenInit() to complete the device-independent DRI * initialization. @@ -1515,7 +1558,7 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) pRADEONDRI->depth = pScrn->depth; pRADEONDRI->bpp = pScrn->bitsPerPixel; - pRADEONDRI->IsPCI = info->IsPCI; + pRADEONDRI->IsPCI = (info->cardType!=CARD_AGP); pRADEONDRI->AGPMode = info->agpMode; pRADEONDRI->frontOffset = info->frontOffset; @@ -1546,16 +1589,32 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) pRADEONDRI->perctx_sarea_size = info->perctx_sarea_size; #endif - /* Have shadowfb run only while there is 3d active. */ - if (info->allowPageFlip /* && info->drmMinor >= 3 */) { - ShadowFBInit( pScreen, RADEONDRIRefreshArea ); - } else { - info->allowPageFlip = 0; - } + info->directRenderingInited = TRUE; + + /* Wrap CloseScreen */ + info->DRICloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = RADEONDRIDoCloseScreen; return TRUE; } +void RADEONDRIInitPageFlip(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* Have shadowfb run only while there is 3d active. This must happen late, + * after XAAInit has been called + */ + if (!ShadowFBInit( pScreen, RADEONDRIRefreshArea )) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ShadowFB init failed, Page Flipping disabled\n"); + info->allowPageFlip = 0; + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "ShadowFB initialized for Page Flipping\n"); +} + /** * This function will attempt to get the Radeon hardware back into shape * after a resume from disc. @@ -1568,7 +1627,7 @@ void RADEONDRIResume(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->drmMinor >= 9) { + if (info->pKernelDRMVersion->version_minor >= 9) { xf86DrvMsg(pScreen->myNum, X_INFO, "[RESUME] Attempting to re-init Radeon hardware.\n"); } else { @@ -1578,7 +1637,7 @@ void RADEONDRIResume(ScreenPtr pScreen) return; } - if (!info->IsPCI) { + if (info->cardType==CARD_AGP) { if (!RADEONSetAgpMode(info, pScreen)) return; @@ -1597,18 +1656,16 @@ void RADEONDRIResume(ScreenPtr pScreen) RADEONDRICPInit(pScrn); } -/* The screen is being closed, so clean up any state and free any - * resources used by the DRI. - */ -void RADEONDRICloseScreen(ScreenPtr pScreen) +void RADEONDRIStop(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - drmRadeonInit drmInfo; RING_LOCALS; - /* Stop the CP */ - if (info->directRenderingEnabled) { + RADEONTRACE(("RADEONDRIStop\n")); + + /* Stop the CP */ + if (info->directRenderingInited) { /* If we've generated any CP commands, we must flush them to the * kernel module now. */ @@ -1621,26 +1678,39 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) } RADEONCP_STOP(pScrn, info); } + info->directRenderingInited = FALSE; +} + +/* The screen is being closed, so clean up any state and free any + * resources used by the DRI. + */ +void RADEONDRICloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + drmRadeonInit drmInfo; + + RADEONTRACE(("RADEONDRICloseScreen\n")); - if (info->irq) { + if (info->irq) { drmCtlUninstHandler(info->drmFD); info->irq = 0; info->ModeReg.gen_int_cntl = 0; } - /* De-allocate vertex buffers */ + /* De-allocate vertex buffers */ if (info->buffers) { drmUnmapBufs(info->buffers); info->buffers = NULL; } - /* De-allocate all kernel resources */ + /* De-allocate all kernel resources */ memset(&drmInfo, 0, sizeof(drmRadeonInit)); drmInfo.func = DRM_RADEON_CLEANUP_CP; drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drmRadeonInit)); - /* De-allocate all GART resources */ + /* De-allocate all GART resources */ if (info->gartTex) { drmUnmap(info->gartTex, info->gartTexMapSize); info->gartTex = NULL; @@ -1668,10 +1738,15 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) info->pciMemHandle = 0; } - /* De-allocate all DRI resources */ + if (info->pciGartBackup) { + xfree(info->pciGartBackup); + info->pciGartBackup = NULL; + } + + /* De-allocate all DRI resources */ DRICloseScreen(pScreen); - /* De-allocate all DRI data structures */ + /* De-allocate all DRI data structures */ if (info->pDRIInfo) { if (info->pDRIInfo->devPrivate) { xfree(info->pDRIInfo->devPrivate); @@ -1690,24 +1765,6 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) } } - - -/* Fullscreen hooks. The DRI fullscreen mode can probably be removed as - * it adds little or nothing above the mechanism below (and isn't widely - * used). - */ -static Bool RADEONDRIOpenFullScreen(ScreenPtr pScreen) -{ - return TRUE; -} - -static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen) -{ - return TRUE; -} - - - /* Use callbacks from dri.c to support pageflipping mode for a single * 3d context without need for any specific full-screen extension. * @@ -1734,12 +1791,20 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) int i; RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + if (!info->directRenderingInited) + return; + /* Don't want to do this when no 3d is active and pages are * right-way-round */ if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; + /* Make sure accel has been properly inited */ + if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL) + return; + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, (CARD32)(-1), -1); @@ -1756,6 +1821,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) yb - ya + 1); } } + info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; } static void RADEONEnablePageFlip(ScreenPtr pScreen) @@ -1765,6 +1831,9 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); if (info->allowPageFlip) { + /* pretty much a hack. */ + if (info->tilingEnabled) + info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; /* Duplicate the frontbuffer to the backbuffer */ (*info->accel->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, @@ -1778,6 +1847,7 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) pScrn->virtualX, pScrn->virtualY); + info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; pSAREAPriv->pfAllowPageFlip = 1; } } @@ -1827,7 +1897,7 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); /* Free Xv linear offscreen memory if necessary */ - if (height < (info->depthTexLines + info->backLines)) { + if (info->videoLinear && height < (info->depthTexLines + info->backLines)) { xf86FreeOffscreenLinear(info->videoLinear); info->videoLinear = NULL; xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0); @@ -1835,6 +1905,8 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) /* Reserve placeholder area so the other areas will match the * pre-calculated offsets + * FIXME: We may have other locked allocations and thus this would allocate + * in the wrong place. The XV surface allocations seem likely. -- anholt */ fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, height @@ -1851,9 +1923,8 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) pScrn->displayWidth, NULL, NULL, NULL); if (!info->backArea) - xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen " - "area for back buffer, you might experience screen " - "corruption\n"); + xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area " + "for back buffer, you might experience screen corruption\n"); info->depthTexArea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, @@ -1867,11 +1938,12 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) xf86FreeOffscreenArea(fbarea); - RADEONEnablePageFlip(pScreen); - info->have3DWindows = 1; - if (info->cursor_start) + RADEONChangeSurfaces(pScrn); + RADEONEnablePageFlip(pScreen); + + if (info->cursor) xf86ForceHWCursor (pScreen, TRUE); } @@ -1900,6 +1972,32 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) info->have3DWindows = 0; - if (info->cursor_start) - xf86ForceHWCursor (pScreen, FALSE); + RADEONChangeSurfaces(pScrn); + + if (info->cursor) + xf86ForceHWCursor (pScreen, FALSE); +} + +void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->cardType != CARD_PCIE || + info->pKernelDRMVersion->version_minor < 19) + return; + + if (info->FbSecureSize==0) + return; + + info->pciGartSize = RADEON_PCIGART_TABLE_SIZE; + + /* allocate space to back up PCIEGART table */ + info->pciGartBackup = xnfcalloc(1, info->pciGartSize); + if (info->pciGartBackup == NULL) + return; + + info->pciGartOffset = (info->FbMapSize - info->FbSecureSize); + + } diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h index daea1a363..07bbd21e8 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h,v 1.5 2003/09/28 20:15:55 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h,v 1.6tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -54,12 +54,11 @@ #define RADEON_DEFAULT_CP_TIMEOUT 10000 /* usecs */ -#define RADEON_AGP_MAX_MODE 4 +#define RADEON_PCIGART_TABLE_SIZE 32768 -#define RADEON_CARD_TYPE_RADEON 1 +#define RADEON_AGP_MAX_MODE 8 -/* Buffer are aligned on 4096 byte boundaries */ -#define RADEON_BUFFER_ALIGN 0x00000fff +#define RADEON_CARD_TYPE_RADEON 1 #define RADEONCP_USE_RING_BUFFER(m) \ (((m) == RADEON_CSQ_PRIBM_INDDIS) || \ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c index da1619f38..00652b33a 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.136tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.137tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -56,11 +56,15 @@ * overlay planes * * Modified by Marc Aurele La France (tsi@xfree86.org) for ATI driver merge. + * + * Mergedfb and pseudo xinerama support added by Alex Deucher (agd5f@yahoo.com) + * based on the sis driver by Thomas Winischhofer. */ /* Driver data structures */ #include "radeon.h" #include "radeon_macros.h" +#include "radeon_mergedfb.h" #include "radeon_probe.h" #include "radeon_reg.h" #include "radeon_version.h" @@ -69,6 +73,7 @@ #define _XF86DRI_SERVER_ #include "radeon_dri.h" #include "radeon_sarea.h" +#include "sarea.h" #endif #include "fb.h" @@ -108,41 +113,74 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int flags); static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); +static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); +static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); +static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); +static void RADEONForceSomeClocks(ScrnInfoPtr pScrn); +static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn); +static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); + +#ifdef XF86DRI +static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); +#endif + +/* pseudo xinerama support */ + +extern Bool RADEONnoPanoramiXExtension; + typedef enum { OPTION_NOACCEL, OPTION_SW_CURSOR, OPTION_DAC_6BIT, OPTION_DAC_8BIT, #ifdef XF86DRI - OPTION_IS_PCI, OPTION_BUS_TYPE, OPTION_CP_PIO, OPTION_USEC_TIMEOUT, OPTION_AGP_MODE, OPTION_AGP_FW, OPTION_GART_SIZE, + OPTION_GART_SIZE_OLD, OPTION_RING_SIZE, OPTION_BUFFER_SIZE, OPTION_DEPTH_MOVE, OPTION_PAGE_FLIP, OPTION_NO_BACKBUFFER, + OPTION_XV_DMA, + OPTION_FBTEX_PERCENT, + OPTION_DEPTH_BITS, #endif OPTION_PANEL_OFF, OPTION_DDC_MODE, OPTION_MONITOR_LAYOUT, OPTION_IGNORE_EDID, - OPTION_CRTC2_OVERLAY, - OPTION_CLONE_MODE, - OPTION_CLONE_HSYNC, - OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY, + OPTION_MERGEDFB, + OPTION_CRT2HSYNC, + OPTION_CRT2VREFRESH, + OPTION_CRT2POS, + OPTION_METAMODES, + OPTION_MERGEDDPI, + OPTION_RADEONXINERAMA, + OPTION_CRT2ISSCRN0, + OPTION_MERGEDFBNONRECT, + OPTION_MERGEDFBMOUSER, OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, + OPTION_MIN_DOTCLOCK, + OPTION_COLOR_TILING, + OPTION_VIDEO_KEY, + OPTION_SUBPIXEL_ORDER, + OPTION_SHOWCACHE, + OPTION_DYNAMIC_CLOCKS, + OPTION_BIOS_HOTKEYS, + OPTION_VGA_ACCESS, + OPTION_REVERSE_DDC, + OPTION_LVDS_PROBE_PLL, + OPTION_CONSTANTDPI, #ifdef __powerpc__ - OPTION_IBOOKHACKS, + OPTION_IBOOKHACKS #endif - OPTION_MIN_DOTCLOCK } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -151,33 +189,48 @@ const OptionInfoRec RADEONOptions[] = { { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, #ifdef XF86DRI - { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CP_PIO, "CPPIOMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USEC_TIMEOUT, "CPusecTimeout", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_FW, "AGPFastWrite", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_GART_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_GART_SIZE_OLD, "AGPSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_GART_SIZE, "GARTSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_DEPTH_MOVE, "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NO_BACKBUFFER, "NoBackBuffer", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XV_DMA, "DMAForXv", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DEPTH_BITS, "DepthBits", OPTV_INTEGER, {0}, FALSE }, #endif { OPTION_PANEL_OFF, "PanelOff", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CRTC2_OVERLAY , "OverlayOnCRTC2", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CLONE_MODE, "CloneMode", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_HSYNC, "CloneHSync", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2HSYNC, "CRT2HSync", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2VREFRESH, "CRT2VRefresh", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2POS, "CRT2Position", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_MERGEDDPI, "MergedDPI", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_RADEONXINERAMA, "MergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2ISSCRN0, "MergedXineramaCRT2IsScreen0", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MERGEDFBNONRECT, "MergedNonRectangular", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MERGEDFBMOUSER, "MergedMouseRestriction", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, + { OPTION_COLOR_TILING, "ColorTiling", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DYNAMIC_CLOCKS, "DynamicClocks", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_BIOS_HOTKEYS, "BIOSHotkeys", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CONSTANTDPI, "ConstantDPI", OPTV_BOOLEAN, {0}, FALSE }, #ifdef __powerpc__ { OPTION_IBOOKHACKS, "iBookHacks", OPTV_BOOLEAN, {0}, FALSE }, #endif @@ -200,12 +253,14 @@ static const char *fbdevHWSymbols[] = { "fbdevHWInit", "fbdevHWUseBuildinMode", + "fbdevHWGetLineLength", "fbdevHWGetVidmem", "fbdevHWDPMSSet", /* colormap */ "fbdevHWLoadPalette", + /* ScrnInfo hooks */ "fbdevHWAdjustFrame", "fbdevHWEnterVT", @@ -226,7 +281,6 @@ static const char *fbdevHWSymbols[] = { static const char *ddcSymbols[] = { "xf86PrintEDID", - "xf86DoEDID_DDC1", "xf86DoEDID_DDC2", NULL }; @@ -329,6 +383,7 @@ static const char *vbeSymbols[] = { static const char *int10Symbols[] = { "xf86InitInt10", + "xf86ExecX86int10", "xf86FreeInt10", "xf86int10Addr", NULL @@ -401,10 +456,14 @@ static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ - {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x400f7/*0x40111*/}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ }; extern int gRADEONEntityIndex; @@ -418,12 +477,11 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); -static RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) +RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { DevUnion *pPriv; RADEONInfoPtr info = RADEONPTR(pScrn); - pPriv = xf86GetEntityPrivate(info->pEnt->index, - gRADEONEntityIndex); + pPriv = xf86GetEntityPrivate(info->pEnt->index, gRADEONEntityIndex); return pPriv->ptr; } @@ -511,6 +569,48 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn) /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); + if(info->CRT2HSync) xfree(info->CRT2HSync); + info->CRT2HSync = NULL; + if(info->CRT2VRefresh) xfree(info->CRT2VRefresh); + info->CRT2VRefresh = NULL; + if(info->MetaModes) xfree(info->MetaModes); + info->MetaModes = NULL; + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + if(info->CRT1Modes) { + if(info->CRT1Modes != pScrn->modes) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + } + } + if (!pScrn || !pScrn->driverPrivate) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -562,6 +662,7 @@ static Bool RADEONMapFB(ScrnInfoPtr pScrn) if (info->FBDev) { info->FB = fbdevHWMapVidmem(pScrn); } else { + RADEONTRACE(("Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize)); info->FB = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, info->PciTag, @@ -604,24 +705,49 @@ static Bool RADEONUnmapMem(ScrnInfoPtr pScrn) return TRUE; } -/* This function is required to workaround a hardware bug in some (all?) - * revisions of the R300. This workaround should be called after every - * CLOCK_CNTL_INDEX register access. If not, register reads afterward - * may not be correct. - */ -void R300CGWorkaround(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); +void RADEONPllErrataAfterIndex(RADEONInfoPtr info) +{ unsigned char *RADEONMMIO = info->MMIO; - CARD32 save, tmp; - save = INREG(RADEON_CLOCK_CNTL_INDEX); - tmp = save & ~(0x3f | RADEON_PLL_WR_EN); - OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp); - tmp = INREG(RADEON_CLOCK_CNTL_DATA); - OUTREG(RADEON_CLOCK_CNTL_INDEX, save); + if (!(info->ChipErrata & CHIP_ERRATA_PLL_DUMMYREADS)) + return; + + /* This workaround is necessary on rv200 and RS200 or PLL + * reads may return garbage (among others...) + */ + (void)INREG(RADEON_CLOCK_CNTL_DATA); + (void)INREG(RADEON_CRTC_GEN_CNTL); +} + +void RADEONPllErrataAfterData(RADEONInfoPtr info) +{ + unsigned char *RADEONMMIO = info->MMIO; + + /* This workarounds is necessary on RV100, RS100 and RS200 chips + * or the chip could hang on a subsequent access + */ + if (info->ChipErrata & CHIP_ERRATA_PLL_DELAY) { + /* we can't deal with posted writes here ... */ + usleep(5000); + } + + /* This function is required to workaround a hardware bug in some (all?) + * revisions of the R300. This workaround should be called after every + * CLOCK_CNTL_INDEX register access. If not, register reads afterward + * may not be correct. + */ + if (info->ChipErrata & CHIP_ERRATA_R300_CG) { + CARD32 save, tmp; + + save = INREG(RADEON_CLOCK_CNTL_INDEX); + tmp = save & ~(0x3f | RADEON_PLL_WR_EN); + OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp); + tmp = INREG(RADEON_CLOCK_CNTL_DATA); + OUTREG(RADEON_CLOCK_CNTL_INDEX, save); + } } -/* Read PLL information */ +/* Read PLL register */ unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -629,12 +755,27 @@ unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr) CARD32 data; OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f); + RADEONPllErrataAfterIndex(info); data = INREG(RADEON_CLOCK_CNTL_DATA); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + RADEONPllErrataAfterData(info); return data; } +/* Write PLL information */ +void RADEONOUTPLL(ScrnInfoPtr pScrn, int addr, CARD32 data) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | + RADEON_PLL_WR_EN)); + RADEONPllErrataAfterIndex(info); + OUTREG(RADEON_CLOCK_CNTL_DATA, data); + RADEONPllErrataAfterData(info); +} + + #if 0 /* Read PAL information (only used for debugging) */ static int RADEONINPAL(int idx) @@ -652,8 +793,14 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc_gen_cntl; int i; + crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); + if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || + !(crtc_gen_cntl & RADEON_CRTC_EN)) + return; + /* Clear the CRTC_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); @@ -669,8 +816,14 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc2_gen_cntl; int i; + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || + !(crtc2_gen_cntl & RADEON_CRTC2_EN)) + return; + /* Clear the CRTC2_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); @@ -701,7 +854,7 @@ static void RADEONBlank(ScrnInfoPtr pScrn) default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS, ~(RADEON_CRTC2_DISP_DIS)); @@ -732,7 +885,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn) default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~(RADEON_CRTC2_DISP_DIS)); @@ -769,12 +922,13 @@ static int RADEONDiv(int n, int d) return (n + (d / 2)) / d; } -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo) +static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; unsigned long DDCReg; RADEONMonitorType MonType = MT_NONE; + xf86MonPtr* MonInfo = &port->MonInfo; int i, j; DDCReg = info->DDCReg; @@ -857,10 +1011,25 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT MonType = MT_NONE; } + OUTREG(info->DDCReg, INREG(info->DDCReg) & + ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + if (*MonInfo) { if ((*MonInfo)->rawData[0x14] & 0x80) { - if (INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON) MonType = MT_LCD; - else MonType = MT_DFP; + /* Note some laptops have a DVI output that uses internal TMDS, + * when its DVI is enabled by hotkey, LVDS panel is not used. + * In this case, the laptop is configured as DVI+VGA as a normal + * desktop card. + * Also for laptop, when X starts with lid closed (no DVI connection) + * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel. + */ + if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; + else { + if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility) + MonType = MT_DFP; + else + MonType = MT_LCD; + } } else MonType = MT_CRT; } else MonType = MT_NONE; @@ -885,6 +1054,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) if(IsCrtDac) { unsigned long ulOrigVCLK_ECP_CNTL; unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_MACRO_CNTL; unsigned long ulOrigDAC_EXT_CNTL; unsigned long ulOrigCRTC_EXT_CNTL; unsigned long ulData; @@ -919,6 +1089,15 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) OUTREG(RADEON_DAC_EXT_CNTL, ulData); ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + + if (ulOrigDAC_CNTL & RADEON_DAC_PDWN) { + /* turn on power so testing can go through */ + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + } + ulData = ulOrigDAC_CNTL; ulData |= RADEON_DAC_CMP_EN; ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK @@ -926,7 +1105,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) ulData |= 0x2; OUTREG(RADEON_DAC_CNTL, ulData); - usleep(1000); + usleep(10000); ulData = INREG(RADEON_DAC_CNTL); bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; @@ -938,19 +1117,30 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + + if (!bConnected) { + /* Power DAC down if CRT is not connected */ + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + ulData = INREG(RADEON_DAC_CNTL); + ulData |= RADEON_DAC_PDWN ; + OUTREG(RADEON_DAC_CNTL, ulData); + } } else { /* TV DAC */ - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; + /* This doesn't seem to work reliably (maybe worse on some OEM cards), + for now we always return false. If one wants to connected a + non-DDC monitor on the DVI port when CRT port is also connected, + he will need to explicitly tell the driver in the config file + with Option MonitorLayout. + */ + bConnected = FALSE; #if 0 if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; unsigned long ulOrigFP2_GEN_CNTL; unsigned long ulOrigDISP_OUTPUT_CNTL; @@ -1025,7 +1215,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { + } else { unsigned long ulOrigPIXCLKSDATA; unsigned long ulOrigTV_MASTER_CNTL; unsigned long ulOrigTV_DAC_CNTL; @@ -1066,15 +1256,13 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) | RADEON_RED_MX_FORCE_DAC_DATA | RADEON_GRN_MX_FORCE_DAC_DATA | RADEON_BLU_MX_FORCE_DAC_DATA); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) + if (IS_R300_VARIANT) ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; else ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); - usleep(1000); + usleep(10000); ulData = INREG(RADEON_TV_DAC_CNTL); bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; @@ -1094,578 +1282,83 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) return(bConnected ? MT_CRT : MT_NONE); } -static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - const char *s; - Bool ignore_edid = FALSE, ddc_crt2_used = FALSE; - -#define RADEON_BIOS8(v) (info->VBIOS[v]) -#define RADEON_BIOS16(v) (info->VBIOS[v] | \ - (info->VBIOS[(v) + 1] << 8)) -#define RADEON_BIOS32(v) (info->VBIOS[v] | \ - (info->VBIOS[(v) + 1] << 8) | \ - (info->VBIOS[(v) + 2] << 16) | \ - (info->VBIOS[(v) + 3] << 24)) - - pRADEONEnt->MonType1 = MT_NONE; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo1 = NULL; - pRADEONEnt->MonInfo2 = NULL; - pRADEONEnt->ReversedDAC = FALSE; - pRADEONEnt->ReversedTMDS = FALSE; - - /* IgnoreEDID option is different from NoDDC options used by DDC module - * When IgnoreEDID is used, monitor detection will still use DDC - * detection, but all EDID data will not be used in mode validation. - */ - if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { - if (ignore_edid) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "IgnoreEDID is specified, EDID data will be ignored\n"); - } - - /* - * MonitorLayout option takes a string for two monitors connected in following format: - * Option "MonitorLayout" "primary-port-display, secondary-port-display" - * primary and secondary port displays can have one of following: - * NONE, CRT, LVDS, TMDS - * With this option, driver will bring up monitors as specified, - * not using auto-detection routines to probe monitors. - */ - - /* current monitor mapping scheme: - * Two displays connected: - * Primary Port: - * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or - * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or - * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary - * - * Secondary Port - * CRTC2 -> CRT DAC -> VGA port -> CRT monitor --> Secondary or - * CRTC2 -> FP2/Ext. -> DVI port -> TMDS panel --> Secondary - * - * Only DVI (or Int. LDC) conneced: - * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or - * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or - * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary - * - * Only VGA (can be DVI on some dual-DVI boards) connected: - * CRTC1 -> CRT DAC -> VGA port -> CRT monitor --> Primary or - * CRTC1 -> FP2/Ext. -> DVI port -> TMDS panel --> Primary (not supported) - * - * Note, this is different from Windows scheme where - * if a digital panel is connected to DVI port, DVI will be the 1st port - * otherwise, VGA port will be treated as 1st port - * - * Here we always treat DVI port as primary if both ports are connected. - * When only one port is connected, it will be treated as - * primary regardless which port or what type of display is involved. - */ - - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - char s1[5], s2[5]; - int i = 0, second = 0; - - /* When using user specified monitor types, we will not do DDC detection - * - */ - do { - switch(*s) - { - case ',': - s1[i] = '\0'; - i = 0; - second = 1; - break; - case ' ': - case '\t': - case '\n': - case '\r': - break; - default: - if (second) - s2[i] = *s; - else - s1[i] = *s; - i++; - if (i == 4) break; - } - } while(*s++); - s2[i] = '\0'; - - if (strcmp(s1, "NONE") == 0) - pRADEONEnt->MonType1 = MT_NONE; - else if (strcmp(s1, "CRT") == 0) - pRADEONEnt->MonType1 = MT_CRT; - else if (strcmp(s1, "TMDS") == 0) - pRADEONEnt->MonType1 = MT_DFP; - else if (strcmp(s1, "LVDS") == 0) - pRADEONEnt->MonType1 = MT_LCD; - else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 1st port \n"); - if (strcmp(s2, "NONE") == 0) - pRADEONEnt->MonType2 = MT_NONE; - else if (strcmp(s2, "CRT") == 0) - pRADEONEnt->MonType2 = MT_CRT; - else if (strcmp(s2, "TMDS") == 0) - pRADEONEnt->MonType2 = MT_DFP; - else if (strcmp(s2, "LVDS") == 0) - pRADEONEnt->MonType2 = MT_LCD; - else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - if (!ignore_edid) { - if (pRADEONEnt->MonType1) /* assuming the first port using DDC_DVI */ - if(!RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)) { - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1); - ddc_crt2_used = TRUE; - } - if (pRADEONEnt->MonType2) { /* assuming the second port using DDC_VGA/DDC_CRT2 */ - if(!RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2)) - if (!ddc_crt2_used) - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); - } - } - - if (!pRADEONEnt->MonType1) { - if (pRADEONEnt->MonType2) { - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - } else { - pRADEONEnt->MonType1 = MT_CRT; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid monitor specified, force to CRT on 1st port\n"); - } - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } - } else { - /* Auto detection */ - int i; - CARD32 tmp; - - /* Old single head radeon cards */ - if(!info->HasCRTC2) { - if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))); - else if (pInt10) { - pointer pVBEModule; - if ((pVBEModule = xf86LoadVBEModule(pScrn))) { - vbeInfoPtr pVbe; - pVbe = VBEInit(pInt10, info->pEnt->index); - if (pVbe) { - for (i = 0; i < 5; i++) { - pRADEONEnt->MonInfo1 = - vbeDoEDID(pVbe, info->pDDCModule); - } - if (pRADEONEnt->MonInfo1->rawData[0x14] & 0x80) - pRADEONEnt->MonType1 = MT_DFP; - else pRADEONEnt->MonType1 = MT_CRT; - vbeFree(pVbe); - } - xf86UnloadSubModule(pVBEModule); - } - } else - pRADEONEnt->MonType1 = MT_CRT; - - pRADEONEnt->HasSecondary = FALSE; - if (!ignore_edid) { - if (pRADEONEnt->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo1 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - } - return; - } - - /* Normally the port uses DDC_DVI connected with TVDAC, - * But this is not true for OEM cards which have TVDAC and CRT DAC reversed. - * If that's the case, we need also reverse the port arrangement. - * BIOS settings are supposed report this correctly, work fine for all cards tested. - * But there may be some exceptions, in that case, user can reverse their monitor - * definition in config file to correct the problem. - */ - if (info->VBIOS && (tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) { - for (i = 1; i < 4; i++) { - unsigned int tmp0; - if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; - tmp0 = RADEON_BIOS16(tmp + i*2); - if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0xf) == DDC_DVI)) { - pRADEONEnt->ReversedDAC = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DACs detected\n"); - } - if ((((tmp0 >> 8) & 0x0f) == DDC_DVI ) && ((tmp0 >> 4) & 0x1)) { - pRADEONEnt->ReversedTMDS = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed TMDS detected\n"); - } - } - } - - /* Primary Head (DVI or Laptop Int. panel)*/ - /* A ddc capable display connected on DVI port */ - if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); - else if((pRADEONEnt->MonType1 = - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))) { - ddc_crt2_used = TRUE; - } else if ((info->IsMobility) && - (info->VBIOS && (INREG(RADEON_BIOS_4_SCRATCH) & 4))) { - /* non-DDC laptop panel connected on primary */ - pRADEONEnt->MonType1 = MT_LCD; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Non-DDC laptop panel detected\n"); - } else { - /* CRT on DVI, TODO: not reliable, make it always return false for now*/ - pRADEONEnt->MonType1 = RADEONCrtIsPhysicallyConnected(pScrn, pRADEONEnt->ReversedDAC); - } - - /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ - if((pRADEONEnt->MonType2 = - RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2))); - else if(!ddc_crt2_used) - pRADEONEnt->MonType2 = - RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); - if (!pRADEONEnt->MonType2) - pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC); - - if(pRADEONEnt->ReversedTMDS) { - /* always keep internal TMDS as primary head */ - if (pRADEONEnt->MonType1 == MT_DFP || - pRADEONEnt->MonType2 == MT_DFP) { - int tmp1 = pRADEONEnt->MonType1; - xf86MonPtr MonInfo = pRADEONEnt->MonInfo1; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonInfo2 = MonInfo; - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonType2 = tmp1; - if ((pRADEONEnt->MonType1 == MT_CRT) || - (pRADEONEnt->MonType2 == MT_CRT)) { - pRADEONEnt->ReversedDAC ^= 1; - } - } - } - - /* no display detected on DVI port*/ - if (pRADEONEnt->MonType1 == MT_NONE) { - if (pRADEONEnt->MonType2 != MT_NONE) { - /* Only one detected on VGA, let it to be primary */ - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonType2 = MT_NONE; - pRADEONEnt->MonInfo2 = NULL; - } else { - /* Non detected, Default to a CRT connected */ - pRADEONEnt->MonType1 = MT_CRT; - } - } - } - - if(s) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Displays Configured by MonitorLayout: \n\tMonitor1--Type %d, Monitor2--Type %d\n\n", - pRADEONEnt->MonType1, pRADEONEnt->MonType2); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Displays Detected: Monitor1--Type %d, Monitor2--Type %d\n\n", - pRADEONEnt->MonType1, pRADEONEnt->MonType2); - } - - if(ignore_edid) { - pRADEONEnt->MonInfo1 = NULL; - pRADEONEnt->MonInfo2 = NULL; - } - - if (!ignore_edid) { - if (pRADEONEnt->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo1 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - if (pRADEONEnt->MonInfo2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor2 EDID data ---------------------------\n"); - xf86PrintEDID( pRADEONEnt->MonInfo2 ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor2 EDID data --------------------\n"); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - info->OverlayOnCRTC2 = FALSE; - if (xf86ReturnOptValBool(info->Options, OPTION_CRTC2_OVERLAY, FALSE)) { - info->OverlayOnCRTC2 = TRUE; - } - - if (pRADEONEnt->MonType2 == MT_NONE) - pRADEONEnt->HasSecondary = FALSE; -} - - -/* Read the Video BIOS block and the FP registers (if applicable). */ -static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long tmp, i; - - if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Cannot allocate space for hold Video BIOS!\n"); - return FALSE; - } - - if (pInt10) { - info->BIOSAddr = pInt10->BIOSseg << 4; - (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), - RADEON_VBIOS_SIZE); - } else { - xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE); - if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not detected in PCI space!\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Attempting to read Video BIOS from " - "legacy ISA space!\n"); - info->BIOSAddr = 0x000c0000; - xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, - RADEON_VBIOS_SIZE, info->VBIOS); - } - } - - if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { - xfree(info->VBIOS); - info->FPBIOSstart = 0; - info->VBIOS = NULL; - info->BIOSAddr = 0x00000000; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not found!\n"); - } else - info->FPBIOSstart = RADEON_BIOS16(0x48); - info->OverlayOnCRTC2 = FALSE; - - if (!info->IsSecondary) - RADEONQueryConnectedDisplays(pScrn, pInt10); - - { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->Clone = FALSE; - info->CloneType = MT_NONE; - - if(info->HasCRTC2) { - if(info->IsSecondary) { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; - if(info->DisplayType == MT_NONE) return FALSE; - } else { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; - - if(!pRADEONEnt->HasSecondary) { - info->CloneType = (RADEONMonitorType)pRADEONEnt->MonType2; - if (info->CloneType != MT_NONE) - info->Clone = TRUE; - } - } - } else { - info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", - (info->IsSecondary ? "Secondary" : "Primary"), - info->DisplayType); - - if (info->Clone) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n", - info->CloneType); - - info->HBlank = 0; - info->HOverPlus = 0; - info->HSyncWidth = 0; - info->VBlank = 0; - info->VOverPlus = 0; - info->VSyncWidth = 0; - info->DotClock = 0; - info->UseBiosDividers = FALSE; - - if (info->DisplayType == MT_LCD && info->VBIOS && - !(xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40); - if (!tmp) { - info->PanelPwrDly = 200; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No Panel Info Table found in BIOS!\n"); - } else { - char stmp[30]; - int tmp0; - - for (i = 0; i < 24; i++) - stmp[i] = RADEON_BIOS8(tmp+i+1); - stmp[24] = 0; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Panel ID string: %s\n", stmp); - - info->PanelXRes = RADEON_BIOS16(tmp+25); - info->PanelYRes = RADEON_BIOS16(tmp+27); - xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", - info->PanelXRes, info->PanelYRes); - - info->PanelPwrDly = RADEON_BIOS16(tmp+44); - if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) - info->PanelPwrDly = 2000; - - /* some panels only work well with certain divider combinations. - */ - info->RefDivider = RADEON_BIOS16(tmp+46); - info->PostDivider = RADEON_BIOS8(tmp+48); - info->FeedbackDivider = RADEON_BIOS16(tmp+49); - if ((info->RefDivider != 0) && - (info->FeedbackDivider > 3)) { - info->UseBiosDividers = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS provided dividers will be used.\n"); - } - - /* We don't use a while loop here just in case we have a corrupted BIOS image. - The max number of table entries is 23 at present, but may grow in future. - To ensure it works with future revisions we loop it to 32. - */ - for (i = 0; i < 32; i++) { - tmp0 = RADEON_BIOS16(tmp+64+i*2); - if (tmp0 == 0) break; - if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && - (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) { - info->HBlank = (RADEON_BIOS16(tmp0+17) - - RADEON_BIOS16(tmp0+19)) * 8; - info->HOverPlus = (RADEON_BIOS16(tmp0+21) - - RADEON_BIOS16(tmp0+19) - 1) * 8; - info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; - info->VBlank = (RADEON_BIOS16(tmp0+24) - - RADEON_BIOS16(tmp0+26)); - info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - - RADEON_BIOS16(tmp0+26)); - info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); - info->DotClock = RADEON_BIOS16(tmp0+9) * 10; - info->Flags = 0; - } - } - - if (info->DotClock == 0) { - DisplayModePtr tmp_mode = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid timing info from BIOS.\n"); - /* No timing information for the native mode, - use whatever specified in the Modeline. - If no Modeline specified, we'll just pick - the VESA mode at 60Hz refresh rate which - is likely to be the best for a flat panel. - */ - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == info->PanelXRes) && - (tmp_mode->VDisplay == info->PanelYRes)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - tmp_mode = tmp_mode->next; - } - } - if ((info->DotClock == 0) && !pRADEONEnt->MonInfo1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Panel size is not correctly detected.\n" - "Please try to use PanelSize option for correct settings.\n"); - return FALSE; - } - } - } - } - } - - if (info->VBIOS) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x30); - info->sclk = RADEON_BIOS16(tmp + 8) / 100.0; - info->mclk = RADEON_BIOS16(tmp + 10) / 100.0; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No valid info for SCLK/MCLK for display bandwidth calculation.\n"); - info->sclk = 200.00; - info->mclk = 200.00; - } - - return TRUE; -} - static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPLLPtr pll = &info->pll; unsigned char *RADEONMMIO = info->MMIO; unsigned char ppll_div_sel; - unsigned Nx, M; + unsigned mpll_fb_div, spll_fb_div, M; unsigned xclk, tmp, ref_div; int hTotal, vTotal, num, denom, m, n; - float hz, vclk, xtal; + float hz, prev_xtal, vclk, xtal, mpll, spll; long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs; - int i; - - for(i=0; i<1000000; i++) - if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) + long to1_secs, to1_usecs, to2_secs, to2_usecs; + unsigned int f1, f2, f3; + int tries = 0; + + prev_xtal = 0; + again: + xtal = 0; + if (++tries > 10) + goto failed; + + xf86getsecs(&to1_secs, &to1_usecs); + f1 = INREG(RADEON_CRTC_CRNT_FRAME); + for (;;) { + f2 = INREG(RADEON_CRTC_CRNT_FRAME); + if (f1 != f2) break; - + xf86getsecs(&to2_secs, &to2_usecs); + if ((to2_secs - to1_secs) > 1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Clock not counting...\n"); + goto failed; + } + } xf86getsecs(&start_secs, &start_usecs); - - for(i=0; i<1000000; i++) - if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0) - break; - - for(i=0; i<1000000; i++) - if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) + for(;;) { + f3 = INREG(RADEON_CRTC_CRNT_FRAME); + if (f3 != f2) break; - + xf86getsecs(&to2_secs, &to2_usecs); + if ((to2_secs - start_secs) > 1) + goto failed; + } xf86getsecs(&stop_secs, &stop_usecs); + if ((stop_secs - start_secs) != 0) + goto again; total_usecs = abs(stop_usecs - start_usecs); - hz = 1000000/total_usecs; + if (total_usecs == 0) + goto again; + hz = 1000000.0/(float)total_usecs; - hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8; - vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0x3ff) + 1); + hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x3ff) + 1) * 8; + vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0xfff) + 1); vclk = (float)(hTotal * (float)(vTotal * hz)); switch((INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x30000) >> 16) { case 0: default: - num = 1; - denom = 1; - break; + num = 1; + denom = 1; + break; case 1: - n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 16) & 0xff); - m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); - num = 2*n; - denom = 2*m; - break; + n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 16) & 0xff); + m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; case 2: - n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 8) & 0xff); - m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); - num = 2*n; - denom = 2*m; - break; + n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 8) & 0xff); + m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; } - OUTREG(RADEON_CLOCK_CNTL_INDEX, 1); - ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_DATA + 1) & 0x3; + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); n = (INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) & 0x7ff); m = (INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff); @@ -1675,170 +1368,341 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) switch ((INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) { case 1: - denom *= 2; - break; + denom *= 2; + break; case 2: - denom *= 4; - break; + denom *= 4; + break; case 3: - denom *= 8; - break; + denom *= 8; + break; case 4: - denom *= 3; - break; + denom *= 3; + break; case 6: - denom *= 6; - break; + denom *= 6; + break; case 7: - denom *= 12; - break; + denom *= 12; + break; } xtal = (int)(vclk *(float)denom/(float)num); if ((xtal > 26900000) && (xtal < 27100000)) - xtal = 2700; + xtal = 2700; else if ((xtal > 14200000) && (xtal < 14400000)) - xtal = 1432; + xtal = 1432; else if ((xtal > 29400000) && (xtal < 29600000)) - xtal = 2950; + xtal = 2950; else - return FALSE; + goto again; + failed: + if (xtal == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to probe xtal value ! " + "Using default 27Mhz\n"); + xtal = 2700; + } else { + if (prev_xtal == 0) { + prev_xtal = xtal; + tries = 0; + goto again; + } else if (prev_xtal != xtal) { + prev_xtal = 0; + goto again; + } + } tmp = INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV); ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff; - Nx = (tmp & 0xff00) >> 8; + /* Some sanity check based on the BIOS code .... */ + if (ref_div < 2) { + CARD32 tmp2; + tmp2 = INPLL(pScrn, RADEON_PPLL_REF_DIV); + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) + ref_div = (tmp2 & R300_PPLL_REF_DIV_ACC_MASK) >> + R300_PPLL_REF_DIV_ACC_SHIFT; + else + ref_div = tmp2 & RADEON_PPLL_REF_DIV_MASK; + if (ref_div < 2) + ref_div = 12; + } + + /* Calculate "base" xclk straight from MPLL, though that isn't + * really useful (hopefully). This isn't called XCLK anymore on + * radeon's... + */ + mpll_fb_div = (tmp & 0xff00) >> 8; + spll_fb_div = (tmp & 0xff0000) >> 16; M = (tmp & 0xff); - xclk = RADEONDiv((2 * Nx * xtal), (2 * M)); + xclk = RADEONDiv((2 * mpll_fb_div * xtal), (M)); + + /* + * Calculate MCLK based on MCLK-A + */ + mpll = (2.0 * (float)mpll_fb_div * (xtal / 100.0)) / (float)M; + spll = (2.0 * (float)spll_fb_div * (xtal / 100.0)) / (float)M; + + tmp = INPLL(pScrn, RADEON_MCLK_CNTL) & 0x7; + switch(tmp) { + case 1: info->mclk = mpll; break; + case 2: info->mclk = mpll / 2.0; break; + case 3: info->mclk = mpll / 4.0; break; + case 4: info->mclk = mpll / 8.0; break; + case 7: info->mclk = spll; break; + default: + info->mclk = 200.00; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported MCLKA source" + " setting %d, can't probe MCLK value !\n", tmp); + } + + /* + * Calculate SCLK + */ + tmp = INPLL(pScrn, RADEON_SCLK_CNTL) & 0x7; + switch(tmp) { + case 1: info->sclk = spll; break; + case 2: info->sclk = spll / 2.0; break; + case 3: info->sclk = spll / 4.0; break; + case 4: info->sclk = spll / 8.0; break; + case 7: info->sclk = mpll; + default: + info->sclk = 200.00; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported SCLK source" + " setting %d, can't probe SCLK value !\n", tmp); + } /* we're done, hopefully these are sane values */ pll->reference_div = ref_div; pll->xclk = xclk; pll->reference_freq = xtal; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probed PLL values: xtal: %f Mhz, " + "sclk: %f Mhz, mclk: %f Mhz\n", xtal/100.0, info->sclk, info->mclk); + return TRUE; } -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 tmp; - int i, n; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); + CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; + info->PanelPwrDly = 200; + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { + info->PanelYRes = (fp_vert_stretch>>12) + 1; + } else { + info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + } + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { + info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; + } else { + info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; } - if (info->VBIOS) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34); - if (tmp) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DFP table revision: %d\n", RADEON_BIOS8(tmp)); - if (RADEON_BIOS8(tmp) == 3) { - n = RADEON_BIOS8(tmp + 5) + 1; - if (n > 4) n = 4; - for (i=0; i<n; i++) { - info->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); - } - return; - } + if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { + info->PanelXRes = 640; + info->PanelYRes = 480; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { + CARD32 ppll_div_sel, ppll_val; + + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); + ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + goto noprobe; + info->FeedbackDivider = ppll_val & 0x7ff; + info->PostDivider = (ppll_val >> 16) & 0x7; + info->RefDivider = info->pll.reference_div; + info->UseBiosDividers = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Existing panel PLL dividers will be used.\n"); + } + noprobe: + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Panel size %dx%d is derived, this may not be correct.\n" + "If not, use PanelSize option to overwrite this setting\n", + info->PanelXRes, info->PanelYRes); +} - /* revision 4 has some problem as it appears in RV280, - comment it off for new, use default instead */ - /* - else if (RADEON_BIOS8(tmp) == 4) { - int stride = 0; - n = RADEON_BIOS8(tmp + 5) + 1; - if (n > 4) n = 4; - for (i=0; i<n; i++) { - info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); - if (i == 0) stride += 10; - else stride += 6; +static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!RADEONGetLVDSInfoFromBIOS(pScrn)) + RADEONGetPanelInfoFromReg(pScrn); + + /* The panel size we collected from BIOS may not be the + * maximum size supported by the panel. If not, we update + * it now. These will be used if no matching mode can be + * found from EDID data. + */ + RADEONUpdatePanelSize(pScrn); + + /* No timing information for the native mode, + * use whatever specified in the Modeline. + * If no Modeline specified, we'll just pick + * the VESA mode at 60Hz refresh rate which + * is likely to be the best for a flat panel. + */ + if (info->DotClock == 0) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == info->PanelXRes) && + (tmp_mode->VDisplay == info->PanelYRes)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + info->DotClock = tmp_mode->Clock; + info->Flags = 0; + break; } - return; } - */ + tmp_mode = tmp_mode->next; + } + if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; } } + return TRUE; +} + +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int i; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; + for (i=0; i<4; i++) { info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; } } -/* Read PLL parameters from BIOS block. Default to typical values if - * there is no BIOS. - */ -static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) +static void RADEONGetPanelInfo (ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONPLLPtr pll = &info->pll; - CARD16 bios_header; - CARD16 pll_info_block; - double min_dotclock; - - if (!info->VBIOS) { + RADEONInfoPtr info = RADEONPTR(pScrn); + char* s; + + if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + info->PanelPwrDly = 200; + if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); + RADEONGetPanelInfoFromReg(pScrn); + } + } else { - pll->min_pll_freq = 12500; - pll->max_pll_freq = 35000; + if(info->DisplayType == MT_LCD) { + RADEONGetLVDSInfo(pScrn); + } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { + RADEONGetTMDSInfo(pScrn); + if (!pScrn->monitor->DDC) + RADEONGetHardCodedEDIDFromBIOS(pScrn); + else if (!info->IsSecondary) + RADEONUpdatePanelSize(pScrn); + } + } +} +static void RADEONGetClockInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &info->pll; + double min_dotclock; - if (!RADEONProbePLLParameters(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not detected, using default PLL parameters!\n"); - - switch (info->Chipset) { - case PCI_CHIP_R200_QL: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_BB: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 27500; - break; - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 24975; - break; - case PCI_CHIP_RV200_QW: - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 23000; - break; - case PCI_CHIP_RADEON_LW: /* Guess based on iBook OpenFirmware */ - pll->reference_freq = 2700; - pll->reference_div = 12; - pll->xclk = 36000; - break; - default: - pll->reference_freq = 2700; - pll->reference_div = 67; - pll->xclk = 16615; - break; + if (RADEONGetClockInfoFromBIOS(pScrn)) { + if (pll->reference_div < 2) { + /* retrive it from register setting for fitting into current PLL algorithm. + We'll probably need a new routine to calculate the best ref_div from BIOS + provided min_input_pll and max_input_pll + */ + CARD32 tmp; + tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + pll->reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; + } else { + pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; } - } + + if (pll->reference_div < 2) pll->reference_div = 12; + } + } else { - bios_header = RADEON_BIOS16(0x48); - pll_info_block = RADEON_BIOS16(bios_header + 0x30); - RADEONTRACE(("Header at 0x%04x; PLL Information at 0x%04x\n", - bios_header, pll_info_block)); + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, + "Video BIOS not detected, using default clock settings!\n"); + + /* Default min/max PLL values */ + if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) { + pll->min_pll_freq = 20000; + pll->max_pll_freq = 50000; + } else { + pll->min_pll_freq = 12500; + pll->max_pll_freq = 35000; + } + + if (RADEONProbePLLParameters(pScrn)) + return; + + if (info->IsIGP) + pll->reference_freq = 1432; + else + pll->reference_freq = 2700; + + pll->reference_div = 12; + pll->xclk = 10300; + + info->sclk = 200.00; + info->mclk = 200.00; + } - pll->reference_freq = RADEON_BIOS16(pll_info_block + 0x0e); - pll->reference_div = RADEON_BIOS16(pll_info_block + 0x10); - pll->min_pll_freq = RADEON_BIOS32(pll_info_block + 0x12); - pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 0x16); - pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); + if (info->ChipFamily == CHIP_FAMILY_RV100 && !info->HasCRTC2) { + /* Avoid RN50 corruption due to memory bandwidth starvation. + * 18 is an empirical value based on the databook and Windows driver. + * + * Empirical value changed to 24 to raise pixel clock limit and + * allow higher resolution modes on capable monitors + */ + pll->max_pll_freq = min(pll->max_pll_freq, + 24 * info->mclk * 100 / pScrn->bitsPerPixel * + info->RamWidth / 16); } + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n", + pll->reference_freq, + pll->reference_div, + pll->min_pll_freq, pll->max_pll_freq, pll->xclk); + /* (Some?) Radeon BIOSes seem too lie about their minimum dot * clocks. Allow users to override the detected minimum dot clock * value (e.g., and allow it to be suitable for TV sets). @@ -1858,10 +1722,425 @@ static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) pll->min_pll_freq = min_dotclock * 1000; } } +} + +static Bool RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + const char *s; + Bool ignore_edid = FALSE; + int i = 0, second = 0, max_mt; + + const char *MonTypeName[7] = + { + "AUTO", + "NONE", + "CRT", + "LVDS", + "TMDS", + "CTV", + "STV" + }; + + const RADEONMonitorType MonTypeID[7] = + { + MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ + MT_NONE, /* NONE -> NONE */ + MT_CRT, /* CRT -> CRT */ + MT_LCD, /* Laptop LCDs are driven via LVDS port */ + MT_DFP, /* DFPs are driven via TMDS */ + MT_CTV, /* CTV -> CTV */ + MT_STV, /* STV -> STV */ + }; + + const char *TMDSTypeName[3] = + { + "NONE", + "Internal", + "External" + }; + + const char *DDCTypeName[5] = + { + "NONE", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC" + }; + + const char *DACTypeName[3] = + { + "Unknown", + "Primary", + "TVDAC/ExtDAC", + }; + + const char *ConnectorTypeName[8] = + { + "None", + "Proprietary", + "VGA", + "DVI-I", + "DVI-D", + "CTV", + "STV", + "Unsupported" + }; + + const char *ConnectorTypeNameATOM[10] = + { + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "STV", + "CTV", + "LVDS", + "Digital", + "Unsupported" + }; + + max_mt = 5; + + if(info->IsSecondary) { + info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; + if(info->DisplayType == MT_NONE) return FALSE; + return TRUE; + } + + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + * If not, we may have problem -- need to use MonitorLayout option. + */ + for (i = 0; i < 2; i++) { + pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[i].MonInfo = NULL; + pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN; + pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE; + } + + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) { + /* Below is the most common setting, but may not be true */ + pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[0].DDCType = DDC_DVI; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT; + pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D; + + pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + pRADEONEnt->PortInfo[0].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].DDCType = DDC_DVI; + } + } + + /* always make TMDS_INT port first*/ + if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT && + pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) { + /* no TMDS_INT port, make primary DAC port first */ + /* On my Inspiron 8600 both internal and external ports are + marked DAC_PRIMARY in BIOS. So be extra careful - only + swap when the first port is not DAC_PRIMARY */ + if ( (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) && + (pRADEONEnt->PortInfo[0].DACType != DAC_PRIMARY)) { + RADEONConnector connector; + connector = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = connector; + } + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) { + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + } else { + pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + } else if (!info->HasCRTC2) { + pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY; + } + + /* IgnoreEDID option is different from the NoDDCxx options used by DDC module + * When IgnoreEDID is used, monitor detection will still use DDC + * detection, but all EDID data will not be used in mode validation. + * You can use this option when you have a DDC monitor but want specify your own + * monitor timing parameters by using HSync, VRefresh and Modeline, + */ + if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { + if (ignore_edid) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "IgnoreEDID is specified, EDID data will be ignored\n"); + } + + /* + * MonitorLayout option takes a string for two monitors connected in following format: + * Option "MonitorLayout" "primary-port-display, secondary-port-display" + * primary and secondary port displays can have one of following: + * NONE, CRT, LVDS, TMDS + * With this option, driver will bring up monitors as specified, + * not using auto-detection routines to probe monitors. + * + * This option can be used when the false monitor detection occurs. + * + * This option can also be used to disable one connected display. + * For example, if you have a laptop connected to an external CRT + * and you want to disable the internal LCD panel, you can specify + * Option "MonitorLayout" "NONE, CRT" + * + * This option can also used to disable Clone mode. One there is only + * one monitor is specified, clone mode will be turned off automatically + * even you have two monitors connected. + * + * Another usage of this option is you want to config the server + * to start up with a certain monitor arrangement even one monitor + * is not plugged in when server starts. + */ + if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { + char s1[5], s2[5]; + i = 0; + /* When using user specified monitor types, we will not do DDC detection + * + */ + do { + switch(*s) { + case ',': + s1[i] = '\0'; + i = 0; + second = 1; + break; + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + if (second) + s2[i] = *s; + else + s1[i] = *s; + i++; + break; + } + if (i > 4) i = 4; + } while(*s++); + s2[i] = '\0'; + + for (i = 0; i < max_mt; i++) { + if (strcmp(s1, MonTypeName[i]) == 0) { + pRADEONEnt->PortInfo[0].MonType = MonTypeID[i]; + break; + } + } + for (i = 0; i < max_mt; i++) { + if (strcmp(s2, MonTypeName[i]) == 0) { + pRADEONEnt->PortInfo[1].MonType = MonTypeID[i]; + break; + } + } + + if (i == max_mt) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); +#if 0 + if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) { + pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY; + pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[1].DDCType = DDC_VGA; + pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT; + pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC; + pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN; + pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED; + pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1; + pRADEONEnt->PortInfo[0].MonInfo = NULL; + } +#endif + + if (!ignore_edid) { + if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[0].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, + &pRADEONEnt->PortInfo[0]); + if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) && + (pRADEONEnt->PortInfo[1].MonType < MT_STV)) + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, + &pRADEONEnt->PortInfo[1]); + } + + } + + if(((!info->HasCRTC2) || info->IsDellServer)) { + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0]))); + else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0]))); + else + pRADEONEnt->PortInfo[0].MonType = MT_CRT; + } + + if (!ignore_edid) { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); + } + } + + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + info->MergeType = MT_NONE; + info->DisplayType = pRADEONEnt->MonType1; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); + + return TRUE; + } + + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + + /* Primary Head (DVI or Laptop Int. panel)*/ + /* A ddc capable display connected on DVI port */ + if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0]))); + else if (info->IsMobility && + (INREG(RADEON_BIOS_4_SCRATCH) & 4)) { + /* non-DDC laptop panel connected on primary */ + pRADEONEnt->PortInfo[0].MonType = MT_LCD; + } else { + /* CRT on DVI, TODO: not reliable, make it always return false for now*/ + pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType)); + } + } + + /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ + if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) { + if((pRADEONEnt->PortInfo[1].MonType = + RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1]))); + else if (info->IsMobility && + (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) { + /* non-DDC TMDS panel connected through DVO */ + pRADEONEnt->PortInfo[1].MonType = MT_DFP; + } else + pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType)); + } + } + + if(ignore_edid) { + pRADEONEnt->PortInfo[0].MonInfo = NULL; + pRADEONEnt->PortInfo[1].MonInfo = NULL; + } else { + if (pRADEONEnt->PortInfo[0].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 1 ----------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo ); + } + + if (pRADEONEnt->PortInfo[1].MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 2-----------------------\n"); + xf86PrintEDID(pRADEONEnt->PortInfo[1].MonInfo ); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); + + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo; + pRADEONEnt->MonType2 = pRADEONEnt->PortInfo[1].MonType; + pRADEONEnt->MonInfo2 = pRADEONEnt->PortInfo[1].MonInfo; + if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) { + if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) { + pRADEONEnt->MonType1 = MT_CRT; + pRADEONEnt->MonInfo1 = NULL; + } else { + RADEONConnector tmp; + pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[1].MonType; + pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[1].MonInfo; + tmp = pRADEONEnt->PortInfo[0]; + pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; + pRADEONEnt->PortInfo[1] = tmp; + } + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + } + + info->DisplayType = pRADEONEnt->MonType1; + pRADEONEnt->ReversedDAC = FALSE; + info->OverlayOnCRTC2 = FALSE; + info->MergeType = MT_NONE; + if (pRADEONEnt->MonType2 != MT_NONE) { + if(!pRADEONEnt->HasSecondary) { + info->MergeType = pRADEONEnt->MonType2; + } + + if (pRADEONEnt->PortInfo[1].DACType == DAC_TVDAC) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DAC decteced\n"); + pRADEONEnt->ReversedDAC = TRUE; + } + } else { + pRADEONEnt->HasSecondary = FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[0].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[0].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Secondary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + MonTypeName[pRADEONEnt->PortInfo[1].MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1].ConnectorType]: + ConnectorTypeName[pRADEONEnt->PortInfo[1].ConnectorType], + DACTypeName[pRADEONEnt->PortInfo[1].DACType+1], + TMDSTypeName[pRADEONEnt->PortInfo[1].TMDSType+1], + DDCTypeName[pRADEONEnt->PortInfo[1].DDCType]); return TRUE; } + /* This is called by RADEONPreInit to set up the default visual */ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn) { @@ -1951,6 +2230,95 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn) return TRUE; } +static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONInfoPtr info) +{ + save->mc_fb_location = info->mc_fb_location; + save->mc_agp_location = info->mc_agp_location; + save->display_base_addr = info->fbLocation; + save->display2_base_addr = info->fbLocation; + save->ov0_base_addr = info->fbLocation; +} + +static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long mem_size; + CARD32 aper_size; + + /* Default to existing values */ + info->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); + info->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + + /* We shouldn't use info->videoRam here which might have been clipped + * but the real video RAM instead + */ + mem_size = INREG(RADEON_CONFIG_MEMSIZE); + aper_size = INREG(RADEON_CONFIG_APER_SIZE); + if (mem_size == 0) + mem_size = 0x800000; + + /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - + Novell bug 204882 + along with lots of ubuntu ones */ + if (aper_size > mem_size) + mem_size = aper_size; + +#ifdef XF86DRI + /* Apply memory map limitation if using an old DRI */ + if (info->directRenderingEnabled && !info->newMemoryMap) { + if (aper_size < mem_size) + mem_size = aper_size; + } +#endif + + /* We won't try to change MC_FB_LOCATION when using fbdev */ + if (!info->FBDev) { + if (info->IsIGP) + info->mc_fb_location = INREG(RADEON_NB_TOM); + else +#ifdef XF86DRI + /* Old DRI has restrictions on the memory map */ + if ( info->directRenderingEnabled && + info->pKernelDRMVersion->version_minor < 10 ) + info->mc_fb_location = (mem_size - 1) & 0xffff0000U; + else +#endif + { + CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); + + /* Recent chips have an "issue" with the memory controller, the + * location must be aligned to the size. We just align it down, + * too bad if we walk over the top of system memory, we don't + * use DMA without a remapped anyway. + * Affected chips are rv280, all r3xx, and all r4xx, but not IGP + */ + if (info->ChipFamily == CHIP_FAMILY_RV280 || + info->ChipFamily == CHIP_FAMILY_R300 || + info->ChipFamily == CHIP_FAMILY_R350 || + info->ChipFamily == CHIP_FAMILY_RV350 || + info->ChipFamily == CHIP_FAMILY_RV380 || + info->ChipFamily == CHIP_FAMILY_R420 || + info->ChipFamily == CHIP_FAMILY_RV410) + aper0_base &= ~(mem_size - 1); + + info->mc_fb_location = (aper0_base >> 16) | + ((aper0_base + mem_size - 1) & 0xffff0000U); + } + } + info->fbLocation = (info->mc_fb_location & 0xffff) << 16; + + /* Just disable the damn AGP apertures for now, it may be + * re-enabled later by the DRM + */ + info->mc_agp_location = 0xffffffc0; + + RADEONTRACE(("RADEONInitMemoryMap() : \n")); + RADEONTRACE((" mem_size : 0x%08lx\n", mem_size)); + RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", info->mc_fb_location)); + RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", info->mc_agp_location)); +} + static void RADEONGetVRamType(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -1964,9 +2332,7 @@ static void RADEONGetVRamType(ScrnInfoPtr pScrn) info->IsDDR = FALSE; tmp = INREG(RADEON_MEM_CNTL); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { tmp &= R300_MEM_NUM_CHANNELS_MASK; switch (tmp) { case 0: info->RamWidth = 64; break; @@ -1979,6 +2345,10 @@ static void RADEONGetVRamType(ScrnInfoPtr pScrn) (info->ChipFamily == CHIP_FAMILY_RS200)){ if (tmp & RV100_HALF_MODE) info->RamWidth = 32; else info->RamWidth = 64; + if (!info->HasCRTC2) { + info->RamWidth /= 4; + info->IsDDR = TRUE; + } } else { if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) info->RamWidth = 128; else info->RamWidth = 64; @@ -1989,24 +2359,189 @@ static void RADEONGetVRamType(ScrnInfoPtr pScrn) */ } +/* + * Depending on card genertation, chipset bugs, etc... the amount of vram + * accessible to the CPU can vary. This function is our best shot at figuring + * it out. Returns a value in KB. + */ +static CARD32 RADEONGetAccessibleVRAM(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long aper_size = INREG(RADEON_CONFIG_APER_SIZE) / 1024; + +#ifdef XF86DRI + /* If we use the DRI, we need to check if it's a version that has the + * bug of always cropping MC_FB_LOCATION to one aperture, in which case + * we need to limit the amount of accessible video memory + */ + if (info->directRenderingEnabled && + info->pKernelDRMVersion->version_minor < 23) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[dri] limiting video memory to one aperture of %ldK\n", + aper_size); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[dri] detected radeon kernel module version 1.%d but" + " 1.23 or newer is required for full memory mapping.\n", + info->pKernelDRMVersion->version_minor); + info->newMemoryMap = FALSE; + return aper_size; + } + info->newMemoryMap = TRUE; +#endif /* XF86DRI */ + + /* Set HDP_APER_CNTL only on cards that are known not to be broken, + * that is has the 2nd generation multifunction PCI interface + */ + if (info->ChipFamily == CHIP_FAMILY_RV280 || + info->ChipFamily == CHIP_FAMILY_RV350 || + info->ChipFamily == CHIP_FAMILY_RV380 || + info->ChipFamily == CHIP_FAMILY_R420 || + info->ChipFamily == CHIP_FAMILY_RV410) { + OUTREGP(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, + ~RADEON_HDP_APER_CNTL); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Generation 2 PCI interface, using max accessible memory\n"); + return aper_size * 2; + } + + /* Older cards have all sorts of funny issues to deal with. First + * check if it's a multifunction card by reading the PCI config + * header type... Limit those to one aperture size + */ + if (pciReadByte(info->PciTag, 0xe) & 0x80) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Generation 1 PCI interface in multifunction mode" + ", accessible memory limited to one aperture\n"); + return aper_size; + } + + /* Single function older card. We read HDP_APER_CNTL to see how the BIOS + * have set it up. We don't write this as it's broken on some ASICs but + * we expect the BIOS to have done the right thing (might be too optimistic...) + */ + if (INREG(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) + return aper_size * 2; + + return aper_size; +} + +static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + EntityInfoPtr pEnt = info->pEnt; + GDevPtr dev = pEnt->device; + unsigned char *RADEONMMIO = info->MMIO; + MessageType from = X_PROBED; + + if (info->FBDev) + pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; + else if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + CARD32 tom = INREG(RADEON_NB_TOM); + + pScrn->videoRam = (((tom >> 16) - + (tom & 0xffff) + 1) << 6); + + OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024); + } else { + int accessible; + int bar_size; + + /* Read VRAM size from card */ + pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + + /* Some production boards of m6 will return 0 if it's 8 MB */ + if (pScrn->videoRam == 0) { + pScrn->videoRam = 8192; + OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000); + } + + /* Get accessible memory */ + accessible = RADEONGetAccessibleVRAM(pScrn); + + /* Crop it to the size of the PCI BAR */ + bar_size = (1u << info->PciInfo->size[0]) / 1024; + if (bar_size == 0) + bar_size = 0x20000; + if (accessible > bar_size) + accessible = bar_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected total video RAM=%dK, accessible=%dK (PCI BAR=%dK)\n", + pScrn->videoRam, accessible, bar_size); + if (pScrn->videoRam > accessible) + pScrn->videoRam = accessible; + } + + info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); + info->BusCntl = INREG(RADEON_BUS_CNTL); + + RADEONGetVRamType(pScrn); + + if (dev->videoRam) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Video RAM override, using %d kB instead of %d kB\n", + dev->videoRam, + pScrn->videoRam); + from = X_CONFIG; + pScrn->videoRam = dev->videoRam; + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "Mapped VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); + + /* FIXME: For now, split FB into two equal sections. This should + * be able to be adjusted by user with a config option. */ + if (info->IsPrimary) { + pScrn->videoRam /= 2; + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for primary head\n", + pScrn->videoRam); + } + + if (info->IsSecondary) { + pScrn->videoRam /= 2; + info->LinearAddr += pScrn->videoRam * 1024; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for secondary head\n", + pScrn->videoRam); + } + + pScrn->videoRam &= ~1023; + info->FbMapSize = pScrn->videoRam * 1024; + + /* if the card is PCI Express reserve the last 32k for the gart table */ +#ifdef XF86DRI + if (info->cardType == CARD_PCIE && info->directRenderingEnabled) + info->FbSecureSize = RADEON_PCIGART_TABLE_SIZE; + else +#endif + info->FbSecureSize = 0; + + return TRUE; +} + + /* This is called by RADEONPreInit to handle config file overrides for * things like chipset and memory regions. Also determine memory size * and type. If memory type ever needs an override, put it in this * routine. */ -static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) +static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); EntityInfoPtr pEnt = info->pEnt; GDevPtr dev = pEnt->device; - MessageType from; unsigned char *RADEONMMIO = info->MMIO; + MessageType from = X_PROBED; #ifdef XF86DRI - const char *s; - CARD32 agpCommand; + const char *s; #endif - /* Chipset */ + /* Chipset */ from = X_PROBED; if (dev->chipset && *dev->chipset) { info->Chipset = xf86StringToToken(RADEONChipsets, dev->chipset); @@ -2037,6 +2572,8 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->HasCRTC2 = TRUE; info->IsMobility = FALSE; info->IsIGP = FALSE; + info->IsDellServer = FALSE; + info->HasSingleDAC = FALSE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: @@ -2044,9 +2581,29 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->ChipFamily = CHIP_FAMILY_RV100; break; + case PCI_CHIP_RN50_515E: /* RN50 is based on the RV100 but 3D isn't guaranteed to work. YMMV. */ + case PCI_CHIP_RN50_5969: + info->HasCRTC2 = FALSE; case PCI_CHIP_RV100_QY: case PCI_CHIP_RV100_QZ: info->ChipFamily = CHIP_FAMILY_RV100; + + /* DELL triple-head configuration. */ + if ((info->PciInfo->subsysVendor == PCI_VENDOR_DELL) && + ((info->PciInfo->subsysCard == 0x016c) || + (info->PciInfo->subsysCard == 0x016d) || + (info->PciInfo->subsysCard == 0x016e) || + (info->PciInfo->subsysCard == 0x016f) || + (info->PciInfo->subsysCard == 0x0170) || + (info->PciInfo->subsysCard == 0x017d) || + (info->PciInfo->subsysCard == 0x017e) || + (info->PciInfo->subsysCard == 0x0183) || + (info->PciInfo->subsysCard == 0x018a) || + (info->PciInfo->subsysCard == 0x019a))) { + info->IsDellServer = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DELL server detected, force to special setup\n"); + } + break; case PCI_CHIP_RS100_4336: @@ -2096,10 +2653,13 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) break; case PCI_CHIP_RS300_5835: + case PCI_CHIP_RS350_7835: info->IsMobility = TRUE; case PCI_CHIP_RS300_5834: + case PCI_CHIP_RS350_7834: info->ChipFamily = CHIP_FAMILY_RS300; info->IsIGP = TRUE; + info->HasSingleDAC = TRUE; break; case PCI_CHIP_RV280_5C61: @@ -2109,6 +2669,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) case PCI_CHIP_RV280_5961: case PCI_CHIP_RV280_5962: case PCI_CHIP_RV280_5964: + case PCI_CHIP_RV280_5965: info->ChipFamily = CHIP_FAMILY_RV280; break; @@ -2121,7 +2682,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) case PCI_CHIP_R300_NF: case PCI_CHIP_R300_NG: info->ChipFamily = CHIP_FAMILY_R300; - break; + break; case PCI_CHIP_RV350_NP: case PCI_CHIP_RV350_NQ: @@ -2136,8 +2697,9 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) case PCI_CHIP_RV350_AS: case PCI_CHIP_RV350_AT: case PCI_CHIP_RV350_AV: + case PCI_CHIP_RV350_4155: info->ChipFamily = CHIP_FAMILY_RV350; - break; + break; case PCI_CHIP_R350_AH: case PCI_CHIP_R350_AI: @@ -2148,14 +2710,113 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) case PCI_CHIP_R350_NK: case PCI_CHIP_R360_NJ: info->ChipFamily = CHIP_FAMILY_R350; - break; + break; + + case PCI_CHIP_RV380_3150: + case PCI_CHIP_RV380_3152: + case PCI_CHIP_RV380_3154: + info->IsMobility = TRUE; + case PCI_CHIP_RV380_3E50: + case PCI_CHIP_RV380_3E54: + info->ChipFamily = CHIP_FAMILY_RV380; + break; + + case PCI_CHIP_RV370_5460: + case PCI_CHIP_RV370_5462: + case PCI_CHIP_RV370_5464: + info->IsMobility = TRUE; + case PCI_CHIP_RV370_5B60: + case PCI_CHIP_RV370_5B62: + case PCI_CHIP_RV370_5B63: + case PCI_CHIP_RV370_5B64: + case PCI_CHIP_RV370_5B65: + info->ChipFamily = CHIP_FAMILY_RV380; + break; + + case PCI_CHIP_RS400_5A42: + case PCI_CHIP_RC410_5A62: + case PCI_CHIP_RS480_5955: + case PCI_CHIP_RS482_5975: + info->IsMobility = TRUE; + case PCI_CHIP_RS400_5A41: + case PCI_CHIP_RC410_5A61: + case PCI_CHIP_RS480_5954: + case PCI_CHIP_RS482_5974: + info->ChipFamily = CHIP_FAMILY_RS400; + info->IsIGP = TRUE; + /*info->HasSingleDAC = TRUE;*/ /* ??? */ + break; + + case PCI_CHIP_RV410_564A: + case PCI_CHIP_RV410_564B: + case PCI_CHIP_RV410_564F: + case PCI_CHIP_RV410_5652: + case PCI_CHIP_RV410_5653: + info->IsMobility = TRUE; + case PCI_CHIP_RV410_5E48: + case PCI_CHIP_RV410_5E4B: + case PCI_CHIP_RV410_5E4A: + case PCI_CHIP_RV410_5E4D: + case PCI_CHIP_RV410_5E4C: + case PCI_CHIP_RV410_5E4F: + info->ChipFamily = CHIP_FAMILY_RV410; + break; + + case PCI_CHIP_R420_JN: + info->IsMobility = TRUE; + case PCI_CHIP_R420_JH: + case PCI_CHIP_R420_JI: + case PCI_CHIP_R420_JJ: + case PCI_CHIP_R420_JK: + case PCI_CHIP_R420_JL: + case PCI_CHIP_R420_JM: + case PCI_CHIP_R420_JP: + case PCI_CHIP_R420_4A4F: + info->ChipFamily = CHIP_FAMILY_R420; + break; + + case PCI_CHIP_R423_UH: + case PCI_CHIP_R423_UI: + case PCI_CHIP_R423_UJ: + case PCI_CHIP_R423_UK: + case PCI_CHIP_R423_UQ: + case PCI_CHIP_R423_UR: + case PCI_CHIP_R423_UT: + case PCI_CHIP_R423_5D57: + case PCI_CHIP_R423_5550: + info->ChipFamily = CHIP_FAMILY_R420; + break; + + case PCI_CHIP_R430_5D49: + case PCI_CHIP_R430_5D4A: + case PCI_CHIP_R430_5D48: + info->IsMobility = TRUE; + case PCI_CHIP_R430_554F: + case PCI_CHIP_R430_554D: + case PCI_CHIP_R430_554E: + case PCI_CHIP_R430_554C: + info->ChipFamily = CHIP_FAMILY_R420; /*CHIP_FAMILY_R430*/ + break; + + case PCI_CHIP_R480_5D4C: + case PCI_CHIP_R480_5D50: + case PCI_CHIP_R480_5D4E: + case PCI_CHIP_R480_5D4F: + case PCI_CHIP_R480_5D52: + case PCI_CHIP_R480_5D4D: + case PCI_CHIP_R481_4B4B: + case PCI_CHIP_R481_4B4A: + case PCI_CHIP_R481_4B49: + case PCI_CHIP_R481_4B4C: + info->ChipFamily = CHIP_FAMILY_R420; /*CHIP_FAMILY_R480*/ + break; default: /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; info->HasCRTC2 = FALSE; } - /* Framebuffer */ + from = X_PROBED; info->LinearAddr = info->PciInfo->memBase[0] & 0xfe000000; @@ -2192,127 +2853,116 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) } /* Read registers used to determine options */ - from = X_PROBED; - if (info->FBDev) - pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { - CARD32 tom = INREG(RADEON_NB_TOM); - pScrn->videoRam = (((tom >> 16) - - (tom & 0xffff) + 1) << 6); - OUTREG(RADEON_MC_FB_LOCATION, tom); - OUTREG(RADEON_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_DISPLAY2_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_OV0_BASE_ADDR, (tom & 0xffff) << 16); - - /* This is supposed to fix the crtc2 noise problem. - */ - OUTREG(RADEON_GRPH2_BUFFER_CNTL, - INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN, - ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN); - } + /* Check chip errata */ + info->ChipErrata = 0; - } - else - pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + if (info->ChipFamily == CHIP_FAMILY_R300 && + (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) + == RADEON_CFG_ATI_REV_A11) + info->ChipErrata |= CHIP_ERRATA_R300_CG; - /* Some production boards of m6 will return 0 if it's 8 MB */ - if (pScrn->videoRam == 0) pScrn->videoRam = 8192; + if (info->ChipFamily == CHIP_FAMILY_RV200 || + info->ChipFamily == CHIP_FAMILY_RS200) + info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS; - if (info->IsSecondary) { - /* FIXME: For now, split FB into two equal sections. This should - * be able to be adjusted by user with a config option. */ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONInfoPtr info1; + if (info->ChipFamily == CHIP_FAMILY_RV100 || + info->ChipFamily == CHIP_FAMILY_RS100 || + info->ChipFamily == CHIP_FAMILY_RS200) + info->ChipErrata |= CHIP_ERRATA_PLL_DELAY; - pScrn->videoRam /= 2; - pRADEONEnt->pPrimaryScrn->videoRam = pScrn->videoRam; + /* Clear bit for M6 Chipsets */ + if (info->Chipset == PCI_CHIP_RADEON_LY || + info->Chipset == PCI_CHIP_RADEON_LZ) + info->ChipErrata &= ~CHIP_ERRATA_PLL_DELAY; - info1 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - info1->FbMapSize = pScrn->videoRam * 1024; - info->LinearAddr += pScrn->videoRam * 1024; - info1->Clone = FALSE; - info1->CurCloneMode = NULL; - } +#ifdef XF86DRI + /* AGP/PCI */ + /* Proper autodetection of an AGP capable device requires examining + * PCI config registers to determine if the device implements extended + * PCI capabilities, and then walking the capability list as indicated + * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP + * capability is present. The procedure is outlined as follows: + * + * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device + * to determine wether or not this device implements any extended + * capabilities. If this bit is zero, then the device is a PCI 2.1 + * or earlier device and is not AGP capable, and we can conclude it + * to be a PCI device. + * + * 2) If bit 4 of the status register is set, then the device implements + * extended capabilities. There is an 8 bit wide capabilities pointer + * register located at offset 0x34 in PCI config space which points to + * the first capability in a linked list of extended capabilities that + * this device implements. The lower two bits of this register are + * reserved and MBZ so must be masked out. + * + * 3) The extended capabilities list is formed by one or more extended + * capabilities structures which are aligned on DWORD boundaries. + * The first byte of the structure is the capability ID (CAP_ID) + * indicating what extended capability this structure refers to. The + * second byte of the structure is an offset from the beginning of + * PCI config space pointing to the next capability in the linked + * list (NEXT_PTR) or NULL (0x00) at the end of the list. The lower + * two bits of this pointer are reserved and MBZ. By examining the + * CAP_ID of each capability and walking through the list, we will + * either find the AGP_CAP_ID (0x02) indicating this device is an + * AGP device, or we'll reach the end of the list, indicating it is + * a PCI device. + * + * Mike A. Harris <mharris@redhat.com> + * + * References: + * - PCI Local Bus Specification Revision 2.2, Chapter 6 + * - AGP Interface Specification Revision 2.0, Section 6.1.5 + */ - info->R300CGWorkaround = - (info->ChipFamily == CHIP_FAMILY_R300 && - (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) - == RADEON_CFG_ATI_REV_A11); + info->cardType = CARD_PCI; - info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); - info->BusCntl = INREG(RADEON_BUS_CNTL); + if (pciReadLong(info->PciTag, PCI_CMD_STAT_REG) & RADEON_CAP_LIST) { + CARD32 cap_ptr, cap_id; - RADEONGetVRamType(pScrn); + cap_ptr = pciReadLong(info->PciTag, + RADEON_CAPABILITIES_PTR_PCI_CONFIG) + & RADEON_CAP_PTR_MASK; - if (dev->videoRam) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Video RAM override, using %d kB instead of %d kB\n", - dev->videoRam, - pScrn->videoRam); - from = X_CONFIG; - pScrn->videoRam = dev->videoRam; + while(cap_ptr != RADEON_CAP_ID_NULL) { + cap_id = pciReadLong(info->PciTag, cap_ptr); + if ((cap_id & 0xff)== RADEON_CAP_ID_AGP) { + info->cardType = CARD_AGP; + break; + } + if ((cap_id & 0xff)== RADEON_CAP_ID_EXP) { + info->cardType = CARD_PCIE; + break; + } + cap_ptr = (cap_id >> 8) & RADEON_CAP_PTR_MASK; + } } - pScrn->videoRam &= ~1023; - info->FbMapSize = pScrn->videoRam * 1024; - xf86DrvMsg(pScrn->scrnIndex, from, - "VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); - -#ifdef XF86DRI - /* AGP/PCI */ - /* There are signatures in BIOS and PCI-SSID for a PCI card, but - * they are not very reliable. Following detection method works for - * all cards tested so far. Note, checking AGP_ENABLE bit after - * drmAgpEnable call can also give the correct result. However, - * calling drmAgpEnable on a PCI card can cause some strange lockup - * when the server restarts next time. - */ - - agpCommand = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, - agpCommand | RADEON_AGP_ENABLE); - if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) - & RADEON_AGP_ENABLE) { - info->IsPCI = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); - } else { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); - } - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, agpCommand); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n", + (info->cardType==CARD_PCI) ? "PCI" : + (info->cardType==CARD_PCIE) ? "PCIE" : "AGP"); if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { if (strcmp(s, "AGP") == 0) { - info->IsPCI = FALSE; + info->cardType = CARD_AGP; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n"); } else if (strcmp(s, "PCI") == 0) { - info->IsPCI = TRUE; + info->cardType = CARD_PCI; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); } else if (strcmp(s, "PCIE") == 0) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "PCI Express not supported yet, using PCI mode\n"); + info->cardType = CARD_PCIE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI Express mode\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid BusType option, using detected type\n"); } - } else if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "ForcePCIMode is deprecated -- " - "use BusType option instead\n"); } #endif + xf86GetOptValBool(info->Options, OPTION_SHOWCACHE, &info->showCache); + if (info->showCache) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Option ShowCache enabled\n"); return TRUE; } @@ -2366,7 +3016,7 @@ static Bool RADEONI2cInit(ScrnInfoPtr pScrn) static void RADEONPreInitDDC(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); ModuleDescPtr pModule; info->ddc1 = FALSE; @@ -2382,7 +3032,7 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) /* Load I2C if we have the code to use it */ if (info->ddc2) { if ((pModule = xf86LoadSubModule(pScrn, "i2c"))) { - xf86LoaderModReqSymLists(pModule, i2cSymbols,NULL); + xf86LoaderModReqSymLists(pModule, i2cSymbols, NULL); info->ddc2 = RADEONI2cInit(pScrn); } else info->ddc2 = FALSE; @@ -2396,18 +3046,39 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) { int j; - RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); xf86MonPtr ddc = pScrn->monitor->DDC; DisplayModePtr p; + if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) + return; + /* Go thru detailed timing table first */ for (j = 0; j < 4; j++) { if (ddc->det_mon[j].type == 0) { struct detailed_timings *d_timings = &ddc->det_mon[j].section.d_timings; + int match = 0; + + /* If we didn't get a panel clock or guessed one, try to match the + * mode with the panel size. We do that because we _need_ a panel + * clock, or ValidateFPModes will fail, even when UseBiosDividers + * is set. + */ + if (info->DotClock == 0 && + info->PanelXRes == d_timings->h_active && + info->PanelYRes == d_timings->v_active) + match = 1; + + /* If we don't have a BIOS provided panel data with fixed dividers, + * check for a larger panel size + */ if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active) { + info->PanelYRes < d_timings->v_active && + !info->UseBiosDividers) + match = 1; + if (match) { info->PanelXRes = d_timings->h_active; info->PanelYRes = d_timings->v_active; info->DotClock = d_timings->clock / 1000; @@ -2417,10 +3088,24 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) info->VOverPlus = d_timings->v_sync_off; info->VSyncWidth = d_timings->v_sync_width; info->VBlank = d_timings->v_blanking; + info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + if (d_timings->sync == 3) { + switch (d_timings->misc) { + case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", + info->PanelXRes, info->PanelYRes); } } } + if (info->UseBiosDividers && info->DotClock != 0) + return; + /* Search thru standard VESA modes from EDID */ for (j = 0; j < 8; j++) { if ((info->PanelXRes < ddc->timings2[j].hsize) && @@ -2442,26 +3127,14 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) info->VOverPlus = p->VSyncStart - p->VDisplay; info->VSyncWidth = p->VSyncEnd - p->VSyncStart; info->DotClock = p->Clock; - info->Flags = - (ddc->det_mon[j].section.d_timings.interlaced - ? V_INTERLACE - : 0); - if (ddc->det_mon[j].section.d_timings.sync == 3) { - switch (ddc->det_mon[j].section.d_timings.misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } + info->Flags = p->Flags; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", + info->PanelXRes, info->PanelYRes); } } } } } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size found from DDC: %dx%d\n", - info->PanelXRes, info->PanelYRes); } /* This function will sort all modes according to their resolution. @@ -2508,13 +3181,20 @@ static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, static void RADEONSetPitch (ScrnInfoPtr pScrn) { int dummy = pScrn->virtualX; + RADEONInfoPtr info = RADEONPTR(pScrn); /* FIXME: May need to validate line pitch here */ switch (pScrn->depth / 8) { - case 1: dummy = (pScrn->virtualX + 127) & ~127; break; - case 2: dummy = (pScrn->virtualX + 31) & ~31; break; + case 1: if (info->allowColorTiling) dummy = (pScrn->virtualX + 255) & ~255; + else dummy = (pScrn->virtualX + 127) & ~127; + break; + case 2: if (info->allowColorTiling) dummy = (pScrn->virtualX + 127) & ~127; + else dummy = (pScrn->virtualX + 31) & ~31; + break; case 3: - case 4: dummy = (pScrn->virtualX + 15) & ~15; break; + case 4: if (info->allowColorTiling) dummy = (pScrn->virtualX + 63) & ~63; + else dummy = (pScrn->virtualX + 15) & ~15; + break; } pScrn->displayWidth = dummy; } @@ -2582,6 +3262,8 @@ static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn) /* Search thru standard VESA modes from EDID */ for (j = 0; j < 8; j++) { + if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0) + continue; for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { /* Ignore all double scan modes */ if ((ddc->timings2[j].hsize == p->HDisplay) && @@ -2653,33 +3335,28 @@ static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn) /* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, * so here is our own validation routine. */ -static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, - RADEONMonitorType DisplayType) +static int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, + RADEONMonitorType DisplayType, int crtc2) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn1); DisplayModePtr p; DisplayModePtr last = NULL; DisplayModePtr first = NULL; DisplayModePtr ddcModes = NULL; int count = 0; int i, width, height; + ScrnInfoPtr pScrn = pScrn1; - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; + if (crtc2) + pScrn = info->CRT2pScrn; - if (pScrn->monitor->DDC && !info->UseBiosDividers) { + pScrn->virtualX = pScrn1->display->virtualX; + pScrn->virtualY = pScrn1->display->virtualY; + + if (pScrn->monitor->DDC) { int maxVirtX = pScrn->virtualX; int maxVirtY = pScrn->virtualY; - if ((DisplayType != MT_CRT) && !info->IsSecondary) { - /* The panel size we collected from BIOS may not be the - * maximum size supported by the panel. If not, we update - * it now. These will be used if no matching mode can be - * found from EDID data. - */ - RADEONUpdatePanelSize(pScrn); - } - /* Collect all of the DDC modes */ first = last = ddcModes = RADEONDDCModes(pScrn); @@ -2687,7 +3364,7 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, /* If primary head is a flat panel, use RMX by default */ if ((!info->IsSecondary && DisplayType != MT_CRT) && - !info->ddc_mode) { + (!info->ddc_mode) && (!crtc2)) { /* These values are effective values after expansion. * They are not really used to set CRTC registers. */ @@ -2728,7 +3405,7 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, if (p->HDisplay == width && p->VDisplay == height) { /* We found a DDC mode that matches the one - requested in the XF86Config file */ + requested in the XF86Config file */ p->type |= M_T_USERDEF; /* Update the max virtual setttings */ @@ -2794,8 +3471,13 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, p->type |= M_T_USERDEF; } - pScrn->virtualX = pScrn->display->virtualX = maxVirtX; - pScrn->virtualY = pScrn->display->virtualY = maxVirtY; + if (crtc2) { + pScrn->virtualX = maxVirtX; + pScrn->virtualY = maxVirtY; + } else { + pScrn->virtualX = pScrn->display->virtualX = maxVirtX; + pScrn->virtualY = pScrn->display->virtualY = maxVirtY; + } } /* Close the doubly-linked mode list, if we found any usable modes */ @@ -2853,7 +3535,7 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) pScrn->virtualY = MAX(pScrn->virtualY, info->PanelYRes); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No valid mode specified, force to native mdoe\n"); + "No valid mode specified, force to native mode\n"); } return new; @@ -2970,8 +3652,9 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) new->next = NULL; new->prev = last; - last->next = new; + if (last) last->next = new; last = new; + if (!first) first = new; } } } @@ -3087,253 +3770,178 @@ static void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) +static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn1); ClockRangePtr clockRanges; - DisplayModePtr tmp_mode = NULL; - DisplayModePtr clone_mode, save_mode; - int modesFound = 0; - int count = 0; - int tmp_hdisplay = 0; - int tmp_vdisplay = 0; - int i, save_n_hsync, save_n_vrefresh; - range save_hsync, save_vrefresh; - char *s; - char **clone_mode_names = NULL; - Bool ddc_mode = info->ddc_mode; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int modesFound; + ScrnInfoPtr pScrn = info->CRT2pScrn; - /* Save all infomations that will be changed by clone mode validateion */ - save_mode = pScrn->modes; - pScrn->modes = NULL; + /* fill in pScrn2 */ + pScrn->videoRam = pScrn1->videoRam; + pScrn->depth = pScrn1->depth; + pScrn->numClocks = pScrn1->numClocks; + pScrn->progClock = pScrn1->progClock; + pScrn->fbFormat = pScrn1->fbFormat; + pScrn->videoRam = pScrn1->videoRam; + pScrn->maxHValue = pScrn1->maxHValue; + pScrn->maxVValue = pScrn1->maxVValue; + pScrn->xInc = pScrn1->xInc; - /* Clone display mode names, duplicate all mode names for primary - * head. Allocate one more, in case pScrn->display->modes[0] == - * NULL */ - while (pScrn->display->modes[count]) count++; - clone_mode_names = xnfalloc((count+2) * sizeof(char*)); - for (i = 0; i < count; i++) { - clone_mode_names[i] = xnfalloc(strlen(pScrn->display->modes[i]) + 1); - strcpy(clone_mode_names[i], pScrn->display->modes[i]); + if (info->NoVirtual) { + pScrn1->display->virtualX = 0; + pScrn1->display->virtualY = 0; } - clone_mode_names[count] = NULL; - clone_mode_names[count+1] = NULL; - pScrn->progClock = TRUE; + if (pScrn->monitor->DDC) { + /* If we still don't know sync range yet, let's try EDID. + * + * Note that, since we can have dual heads, Xconfigurator + * may not be able to probe both monitors correctly through + * vbe probe function (RADEONProbeDDC). Here we provide an + * additional way to auto-detect sync ranges if they haven't + * been added to XF86Config manually. + */ + if (pScrn->monitor->nHsync <= 0) + RADEONSetSyncRangeFromEdid(pScrn, 1); + if (pScrn->monitor->nVrefresh <= 0) + RADEONSetSyncRangeFromEdid(pScrn, 0); + } + /* Get mode information */ + pScrn->progClock = TRUE; clockRanges = xnfcalloc(sizeof(*clockRanges), 1); clockRanges->next = NULL; clockRanges->minClock = info->pll.min_pll_freq; clockRanges->maxClock = info->pll.max_pll_freq * 10; clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = (info->CloneType == MT_CRT); - clockRanges->doubleScanAllowed = (info->CloneType == MT_CRT); + clockRanges->interlaceAllowed = (info->MergeType == MT_CRT); + clockRanges->doubleScanAllowed = (info->MergeType == MT_CRT); - /* Only take one clone mode from config file for now, rest of clone - * modes will copy from primary head. + /* We'll use our own mode validation routine for DFP/LCD, since + * xf86ValidateModes does not work correctly with the DFP/LCD modes + * 'stretched' from their native mode. */ - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_MODE))) { - if (sscanf(s, "%dx%d", &tmp_hdisplay, &tmp_vdisplay) == 2) { - if(count > 0) free(clone_mode_names[0]); - else count++; - clone_mode_names[0] = xnfalloc(strlen(s)+1); - sprintf(clone_mode_names[0], "%dx%d", tmp_hdisplay, tmp_vdisplay); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone mode %s in config file is used\n", clone_mode_names[0]); - } - } - - for (i = 0; i < count; i++) { - if (sscanf(clone_mode_names[i], "%dx%d", - &tmp_hdisplay, &tmp_vdisplay) == 2) { - if (pScrn->display->virtualX < tmp_hdisplay) - pScrn->display->virtualX = tmp_hdisplay; - if (pScrn->display->virtualY < tmp_vdisplay) - pScrn->display->virtualY = tmp_vdisplay; - } - } - - save_hsync = pScrn->monitor->hsync[0]; - save_vrefresh = pScrn->monitor->vrefresh[0]; - save_n_hsync = pScrn->monitor->nHsync; - save_n_vrefresh = pScrn->monitor->nVrefresh; - - pScrn->monitor->DDC = NULL; - pScrn->monitor->nHsync = 0; - pScrn->monitor->nVrefresh = 0; - - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_HSYNC))) { - if (sscanf(s, "%f-%f", &pScrn->monitor->hsync[0].lo, - &pScrn->monitor->hsync[0].hi) == 2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "HSync for CloneMode from config file: %s\n", s); - pScrn->monitor->nHsync = 1; - } else { - pScrn->monitor->nHsync = 0; - } - } - - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_VREFRESH))) { - if (sscanf(s, "%f-%f", &pScrn->monitor->vrefresh[0].lo, - &pScrn->monitor->vrefresh[0].hi) == 2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "VRefresh for CloneMode from config file: %s\n", s); - pScrn->monitor->nVrefresh = 1; - } else { - pScrn->monitor->nVrefresh = 0; - } - } + if (info->MergeType == MT_CRT && !info->ddc_mode) { - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; - if (pScrn->monitor->DDC) { - if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0)) { - if (pScrn->monitor->nHsync == 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh == 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); - } - } else if (info->ddc_mode) { - ddc_mode = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available for clone mode, " - "DDCMode option is dismissed\n"); - } - - if (info->CloneType == MT_CRT && !ddc_mode) { modesFound = - xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, + xf86ValidateModes(pScrn, + pScrn->monitor->Modes, + pScrn1->display->modes, clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - 2048, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, + NULL, /* linePitches */ + 8 * 64, /* minPitch */ + 8 * 1024, /* maxPitch */ + info->allowColorTiling ? 2048 : + 64 * pScrn1->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + info->MaxLines, /* maxHeight */ + pScrn1->display->virtualX ? pScrn1->virtualX : 0, + pScrn1->display->virtualY ? pScrn1->virtualY : 0, info->FbMapSize, LOOKUP_BEST_REFRESH); - } else { - /* Try to add DDC modes */ - info->IsSecondary = TRUE; /*fake secondary head*/ - modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names, - info->CloneType); - info->IsSecondary = FALSE; - - /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes - */ - if (modesFound < 1 && info->CloneType != MT_CRT) { - modesFound = - xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - 2048, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - } - } - - if (modesFound > 0) { - int valid = 0; - save_mode = pScrn->modes; - xf86SetCrtcForModes(pScrn, 0); - xf86PrintModes(pScrn); - for (i = 0; i < modesFound; i++) { - - while (pScrn->modes->status != MODE_OK) { - pScrn->modes = pScrn->modes->next; - } - if (!pScrn->modes) break; - if (pScrn->modes->Clock != 0.0) { + if (modesFound == -1) return 0; - clone_mode = xnfcalloc (1, sizeof (DisplayModeRec)); - if (!clone_mode) break; - memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec)); - clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1); - strcpy(clone_mode->name, pScrn->modes->name); - - if (!info->CurCloneMode) { - info->CloneModes = clone_mode; - info->CurCloneMode = clone_mode; - clone_mode->prev = NULL; - } else { - clone_mode->prev = tmp_mode; - clone_mode->prev->next = clone_mode; - } - valid++; - - tmp_mode = clone_mode; - clone_mode->next = NULL; - } - pScrn->modes = pScrn->modes->next; + xf86PruneDriverModes(pScrn); + if (!modesFound || !pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + return 0; } - /* no longer needed, free it */ - pScrn->modes = save_mode; + } else { + /* First, free any allocated modes during configuration, since + * we don't need them + */ while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - pScrn->modes = NULL; - - /* modepool is no longer needed, free it */ + xf86DeleteMode(&pScrn->modes, pScrn->modes); while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - pScrn->modePool = NULL; - - modesFound = valid; - } + xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - /* Clone_mode_names list is no longer needed, free it. */ - if (clone_mode_names) { - for (i = 0; clone_mode_names[i]; i++) { - free(clone_mode_names[i]); - clone_mode_names[i] = NULL; - } + /* Next try to add DDC modes */ + modesFound = RADEONValidateDDCModes(pScrn, pScrn1->display->modes, + info->MergeType, 1); - free(clone_mode_names); - clone_mode_names = NULL; - } + /* If that fails and we're connect to a flat panel, then try to + * add the flat panel modes + */ + if (info->MergeType != MT_CRT) { - /* We need to restore all changed info for the primary head */ + /* some panels have DDC, but don't have internal scaler. + * in this case, we need to validate additional modes + * by using on-chip RMX. + */ + int user_modes_asked = 0, user_modes_found = 0, i; + DisplayModePtr tmp_mode = pScrn->modes; + while (pScrn1->display->modes[user_modes_asked]) user_modes_asked++; + if (tmp_mode) { + for (i = 0; i < modesFound; i++) { + if (tmp_mode->type & M_T_USERDEF) user_modes_found++; + tmp_mode = tmp_mode->next; + } + } - pScrn->monitor->hsync[0] = save_hsync; - pScrn->monitor->vrefresh[0] = save_vrefresh; - pScrn->monitor->nHsync = save_n_hsync; - pScrn->monitor->nVrefresh = save_n_vrefresh; + if ((modesFound <= 1) || (user_modes_found < user_modes_asked)) { + /* when panel size is not valid, try to validate + * mode using xf86ValidateModes routine + * This can happen when DDC is disabled. + */ + /* if (info->PanelXRes < 320 || info->PanelYRes < 200) */ + modesFound = + xf86ValidateModes(pScrn, + pScrn->monitor->Modes, + pScrn1->display->modes, + clockRanges, + NULL, /* linePitches */ + 8 * 64, /* minPitch */ + 8 * 1024, /* maxPitch */ + info->allowColorTiling ? 2048 : + 64 * pScrn1->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + info->MaxLines, /* maxHeight */ + pScrn1->display->virtualX, + pScrn1->display->virtualY, + info->FbMapSize, + LOOKUP_BEST_REFRESH); - /* - * Also delete the clockRanges (if it was setup) since it will be - * set up during the primary head initialization. - */ - while (pScrn->clockRanges) { - ClockRangesPtr CRtmp = pScrn->clockRanges; - pScrn->clockRanges = pScrn->clockRanges->next; - xfree(CRtmp); - } + } + } + /* Setup the screen's clockRanges for the VidMode extension */ + if (!pScrn->clockRanges) { + pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1); + memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges)); + pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH; + } + /* Fail if we still don't have any valid modes */ + if (modesFound < 1) { + if (info->MergeType == MT_CRT) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid DDC modes found for this CRT\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Try turning off the \"DDCMode\" option\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid mode found for this DFP/LCD\n"); + } + return 0; + } + } return modesFound; } + /* This is called by RADEONPreInit to validate modes and compute * parameters for all of the valid modes. */ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { - RADEONInfoPtr info = RADEONPTR(pScrn); - ClockRangePtr clockRanges; - int modesFound; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - char *s; + RADEONInfoPtr info = RADEONPTR(pScrn); + ClockRangePtr clockRanges; + int modesFound; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + char *s; ModuleDescPtr pModule; /* This option has two purposes: @@ -3363,56 +3971,33 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) * * Note: This option will be dismissed if no DDC data is available. */ + + if (info->MergedFB) { + if (!(pScrn->display->virtualX)) + info->NoVirtual = TRUE; + else + info->NoVirtual = FALSE; + } + info->ddc_mode = xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); - /* don't use RMX if we have a dual-tdms panels */ + /* don't use RMX if we have a dual-tmds panels */ if (pRADEONEnt->MonType2 == MT_DFP) info->ddc_mode = TRUE; - - /* Here is a hack for cloning first display on the second head. If - * we don't do this, when both heads are connected, the same CRTC - * will be used to drive them according to the capability of the - * primary head. This can cause an unstable or blank screen, or - * even worse it can damage a monitor. This feature is also - * important for laptops (using M6, M7), where the panel can't be - * disconnect when one wants to use the CRT port. Although 2 - * Screens can be set up in the config file for displaying same - * content on two monitors, it has problems with cursor, overlay, - * DRI. - */ - if (info->HasCRTC2) { - if (info->Clone) { - - /* If we have 2 screens from the config file, we don't need - * to do clone thing, let each screen handles one head. - */ - if (!pRADEONEnt->HasSecondary) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Clone modes validation ------------ \n"); - - modesFound = RADEONValidateCloneModes(pScrn); - if (modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for CRTC2 clone\n"); - info->Clone = FALSE; - info->CurCloneMode = NULL; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d clone modes found ------------ \n\n", - modesFound); - } - } - } - + /* don't use RMX if we are Dell Server */ + if (info->IsDellServer) + { + info->ddc_mode = TRUE; + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Validating modes on %s head ---------\n", info->IsSecondary ? "Secondary" : "Primary"); if (info->IsSecondary) - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + pScrn->monitor->DDC = pRADEONEnt->MonInfo2; else - pScrn->monitor->DDC = pRADEONEnt->MonInfo1; + pScrn->monitor->DDC = pRADEONEnt->MonInfo1; if (!pScrn->monitor->DDC && info->ddc_mode) { info->ddc_mode = FALSE; @@ -3470,22 +4055,23 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid PanelSize value: %s\n", s); } - } + } else + RADEONGetPanelInfo(pScrn); } if (pScrn->monitor->DDC) { - /* If we still don't know sync range yet, let's try EDID. - * - * Note that, since we can have dual heads, Xconfigurator - * may not be able to probe both monitors correctly through - * vbe probe function (RADEONProbeDDC). Here we provide an - * additional way to auto-detect sync ranges if they haven't - * been added to XF86Config manually. - */ - if (pScrn->monitor->nHsync <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); + /* If we still don't know sync range yet, let's try EDID. + * + * Note that, since we can have dual heads, Xconfigurator + * may not be able to probe both monitors correctly through + * vbe probe function (RADEONProbeDDC). Here we provide an + * additional way to auto-detect sync ranges if they haven't + * been added to XF86Config manually. + */ + if (pScrn->monitor->nHsync <= 0) + RADEONSetSyncRangeFromEdid(pScrn, 1); + if (pScrn->monitor->nVrefresh <= 0) + RADEONSetSyncRangeFromEdid(pScrn, 0); } /* Get mode information */ @@ -3512,9 +4098,10 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ - 2048, /* maxHeight */ + info->MaxLines, /* maxHeight */ pScrn->display->virtualX, pScrn->display->virtualY, info->FbMapSize, @@ -3522,7 +4109,8 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) if (modesFound < 1 && info->FBDev) { fbdevHWUseBuildinMode(pScrn); - pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */ + pScrn->displayWidth = fbdevHWGetLineLength(pScrn) + / info->CurrentLayout.pixel_bytes; modesFound = 1; } @@ -3545,10 +4133,10 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) /* Next try to add DDC modes */ modesFound = RADEONValidateDDCModes(pScrn, pScrn->display->modes, - info->DisplayType); + info->DisplayType, 0); /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes + * add the flat panel modes */ if (info->DisplayType != MT_CRT) { @@ -3580,9 +4168,10 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ + info->allowColorTiling ? 2048 : + 64 * pScrn->bitsPerPixel, /* pitchInc */ 128, /* minHeight */ - 2048, /* maxHeight */ + info->MaxLines, /* maxHeight */ pScrn->display->virtualX, pScrn->display->virtualY, info->FbMapSize, @@ -3590,7 +4179,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) else if (!info->IsSecondary) modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes); } - } + } /* Setup the screen's clockRanges for the VidMode extension */ if (!pScrn->clockRanges) { @@ -3616,30 +4205,114 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) xf86SetCrtcForModes(pScrn, 0); - /* We need to adjust virtual size if the clone modes have larger - * display size. - */ - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - while (1) { - if ((clone_mode->HDisplay > pScrn->virtualX) || - (clone_mode->VDisplay > pScrn->virtualY)) { - pScrn->virtualX = - pScrn->display->virtualX = clone_mode->HDisplay; - pScrn->virtualY = - pScrn->display->virtualY = clone_mode->VDisplay; - RADEONSetPitch(pScrn); + if (info->HasCRTC2) { + if (info->MergedFB) { + + /* If we have 2 screens from the config file, we don't need + * to do clone thing, let each screen handles one head. + */ + if (!pRADEONEnt->HasSecondary) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Validating CRTC2 modes for MergedFB ------------ \n"); + + modesFound = RADEONValidateMergeModes(pScrn); + if (modesFound < 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid mode found for CRTC2, disabling MergedFB\n"); + info->MergedFB = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total of %d CRTC2 modes found for MergedFB------------ \n", + modesFound); } - if (!clone_mode->next) break; - clone_mode = clone_mode->next; } } pScrn->currentMode = pScrn->modes; + if(info->MergedFB) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT1: ********************\n"); + } xf86PrintModes(pScrn); + if(info->MergedFB) { + + xf86SetCrtcForModes(info->CRT2pScrn, INTERLACE_HALVE_V); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT2: ********************\n"); + + xf86PrintModes(info->CRT2pScrn); + + info->CRT1Modes = pScrn->modes; + info->CRT1CurrentMode = pScrn->currentMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generating MergedFB mode list\n"); + + if (info->NoVirtual) { + pScrn->display->virtualX = 0; + pScrn->display->virtualY = 0; + } + pScrn->modes = RADEONGenerateModeList(pScrn, info->MetaModes, + info->CRT1Modes, info->CRT2pScrn->modes, + info->CRT2Position); + + if(!pScrn->modes) { + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to parse MetaModes or no modes found. MergeFB mode disabled.\n"); + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + pScrn->modes = info->CRT1Modes; + info->CRT1Modes = NULL; + info->MergedFB = FALSE; + + } + } + + if (info->MergedFB) { + /* If no virtual dimension was given by the user, + * calculate a sane one now. Adapts pScrn->virtualX, + * pScrn->virtualY and pScrn->displayWidth. + */ + RADEONRecalcDefaultVirtualSize(pScrn); + info->CRT2pScrn->virtualX = pScrn->virtualX; + info->CRT2pScrn->virtualY = pScrn->virtualY; + RADEONSetPitch(pScrn); + RADEONSetPitch(info->CRT2pScrn); + + pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList() */ + pScrn->currentMode = pScrn->modes; + + /* Update CurrentLayout */ + info->CurrentLayout.mode = pScrn->currentMode; + info->CurrentLayout.displayWidth = pScrn->displayWidth; + } + /* Set DPI */ - xf86SetDpi(pScrn, 0, 0); + /* xf86SetDpi(pScrn, 0, 0); */ + + if (info->MergedFB) { + RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position); + } else { + xf86SetDpi(pScrn, 0, 0); + info->RADEONDPIVX = pScrn->virtualX; + info->RADEONDPIVY = pScrn->virtualY; + } /* Get ScreenInit function */ if (!(pModule = xf86LoadSubModule(pScrn, "fb"))) return FALSE; @@ -3655,7 +4328,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) /* This is called by RADEONPreInit to initialize the hardware cursor */ static Bool RADEONPreInitCursor(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); ModuleDescPtr pModule; if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { @@ -3669,12 +4342,15 @@ static Bool RADEONPreInitCursor(ScrnInfoPtr pScrn) static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) { #ifdef XFree86LOADER - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); ModuleDescPtr pModule; if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { int errmaj = 0, errmin = 0; + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, + "Using XAA acceleration architecture\n"); + info->xaaReq.majorversion = 1; info->xaaReq.minorversion = 1; @@ -3691,7 +4367,7 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) } xf86LoaderModReqSymLists(pModule, xaaSymbols, NULL); } -#endif +#endif /* XFree86Loader */ return TRUE; } @@ -3700,12 +4376,31 @@ static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) { #if !defined(__powerpc__) RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp2_gen_ctl_save = 0; ModuleDescPtr pModule; if ((pModule = xf86LoadSubModule(pScrn, "int10"))) { xf86LoaderModReqSymLists(pModule, int10Symbols, NULL); + + /* The VGA BIOS on the RV100/QY cannot be read when the digital output + * is enabled. Clear and restore FP2_ON around int10 to avoid this. + */ + if (info->PciInfo->chipType == PCI_CHIP_RV100_QY) { + fp2_gen_ctl_save = INREG(RADEON_FP2_GEN_CNTL); + if (fp2_gen_ctl_save & RADEON_FP2_ON) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "disabling digital out\n"); + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_ctl_save & ~RADEON_FP2_ON); + } + } + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); *ppInt10 = xf86InitInt10(info->pEnt->index); + + if (fp2_gen_ctl_save & RADEON_FP2_ON) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "re-enabling digital out\n"); + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_ctl_save); + } } #endif return TRUE; @@ -3714,8 +4409,67 @@ static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) #ifdef XF86DRI static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); ModuleDescPtr pModule; + MessageType from; + + info->directRenderingEnabled = FALSE; + info->directRenderingInited = FALSE; + info->CPInUse = FALSE; + info->CPStarted = FALSE; + info->pLibDRMVersion = NULL; + info->pKernelDRMVersion = NULL; + + if (xf86IsEntityShared(info->pEnt->index)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with " + "DRI at present.\n" + "Please use the radeon MergedFB option if you " + "want Dual-head with DRI.\n"); + return FALSE; + } + if (info->IsSecondary) + return FALSE; + + if (info->Chipset == PCI_CHIP_RN50_515E || + info->Chipset == PCI_CHIP_RN50_5969) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering not supported on RN50\n"); + return FALSE; + } + + if (info->Chipset == PCI_CHIP_RS400_5A41 || + info->Chipset == PCI_CHIP_RS400_5A42 || + info->Chipset == PCI_CHIP_RC410_5A61 || + info->Chipset == PCI_CHIP_RC410_5A62 || + info->Chipset == PCI_CHIP_RS480_5954 || + info->Chipset == PCI_CHIP_RS480_5955 || + info->Chipset == PCI_CHIP_RS482_5974 || + info->Chipset == PCI_CHIP_RS482_5975) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering broken on XPRESS 200 and 200M\n"); + return FALSE; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[dri] Acceleration disabled, not initializing the DRI\n"); + return FALSE; + } + + if (!RADEONDRIGetVersion(pScrn)) + return FALSE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[dri] Found DRI library version %d.%d.%d and kernel" + " module version %d.%d.%d\n", + info->pLibDRMVersion->version_major, + info->pLibDRMVersion->version_minor, + info->pLibDRMVersion->version_patchlevel, + info->pKernelDRMVersion->version_major, + info->pKernelDRMVersion->version_minor, + info->pKernelDRMVersion->version_patchlevel); if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n"); @@ -3733,16 +4487,23 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->CPusecTimeout = RADEON_DEFAULT_CP_TIMEOUT; - if (!info->IsPCI) { + if (info->cardType==CARD_AGP) { if (xf86GetOptValInteger(info->Options, OPTION_AGP_MODE, &(info->agpMode))) { if (info->agpMode < 1 || info->agpMode > RADEON_AGP_MAX_MODE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal AGP Mode: %d\n", info->agpMode); - return FALSE; + "Illegal AGP Mode: %dx, set to default %dx mode\n", + info->agpMode, RADEON_DEFAULT_AGP_MODE); + info->agpMode = RADEON_DEFAULT_AGP_MODE; } + + /* AGP_MAX_MODE is changed to allow v3 8x mode. + * At this time we don't know if the AGP bridge supports + * 8x mode. This will later be verified on both + * AGP master and target sides. + */ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Using AGP %dx mode\n", info->agpMode); + "AGP %dx mode is configured\n", info->agpMode); } if ((info->agpFastWrite = xf86ReturnOptValBool(info->Options, @@ -3756,8 +4517,10 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) } } - if (xf86GetOptValInteger(info->Options, - OPTION_GART_SIZE, (int *)&(info->gartSize))) { + if ((xf86GetOptValInteger(info->Options, + OPTION_GART_SIZE, (int *)&(info->gartSize))) || + (xf86GetOptValInteger(info->Options, + OPTION_GART_SIZE_OLD, (int *)&(info->gartSize)))) { switch (info->gartSize) { case 4: case 8: @@ -3817,15 +4580,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) /* This option checked by the RADEON DRM kernel module */ } - /* Depth moves are disabled by default since they are extremely slow */ - if ((info->depthMoves = xf86ReturnOptValBool(info->Options, - OPTION_DEPTH_MOVE, FALSE))) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Depth moves disabled by default\n"); - } - /* Two options to try and squeeze as much texture memory as possible * for dedicated 3d rendering boxes */ @@ -3850,33 +4604,161 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", info->allowPageFlip ? "en" : "dis"); + info->DMAForXv = TRUE; + from = xf86GetOptValBool(info->Options, OPTION_XV_DMA, &info->DMAForXv) + ? X_CONFIG : X_INFO; + xf86DrvMsg(pScrn->scrnIndex, from, + "Will %stry to use DMA for Xv image transfers\n", + info->DMAForXv ? "" : "not "); + + return TRUE; +} +#endif /* XF86DRI */ + +static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->allowColorTiling = xf86ReturnOptValBool(info->Options, + OPTION_COLOR_TILING, TRUE); + if (IS_R300_VARIANT) { + info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ + info->MaxLines = 4096; + } else { + info->MaxSurfaceWidth = 2048; + info->MaxLines = 2048; + } + + if (!info->allowColorTiling) + return; + +#ifdef XF86DRI + if (info->directRenderingEnabled && + info->pKernelDRMVersion->version_minor < 14) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[dri] color tiling disabled because of version " + "mismatch.\n" + "[dri] radeon.o kernel module version is %d.%d.%d but " + "1.14.0 or later is required for color tiling.\n", + info->pKernelDRMVersion->version_major, + info->pKernelDRMVersion->version_minor, + info->pKernelDRMVersion->version_patchlevel); + info->allowColorTiling = FALSE; + return; + } +#endif /* XF86DRI */ + + if ((info->allowColorTiling) && (info->IsSecondary)) { + /* can't have tiling on the 2nd head (as long as it can't use drm). + * We'd never get the surface save/restore (vt switching) right... + */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); + info->allowColorTiling = FALSE; + } + else if ((info->allowColorTiling) && (info->FBDev)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Color tiling not supported with UseFBDev option\n"); + info->allowColorTiling = FALSE; + } + else if (info->allowColorTiling) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); + } +} + + +static Bool RADEONPreInitXv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD16 mm_table; + CARD16 bios_header; + CARD16 pll_info_block; + + /* Rescue MM_TABLE before VBIOS is freed */ + info->MM_TABLE_valid = FALSE; + + if((info->VBIOS==NULL)||(info->VBIOS[0]!=0x55)||(info->VBIOS[1]!=0xaa)){ + info->MM_TABLE_valid = FALSE; + return TRUE; + } + + bios_header=info->VBIOS[0x48]; + bios_header+=(((int)info->VBIOS[0x49]+0)<<8); + + mm_table=info->VBIOS[bios_header+0x38]; + if(mm_table==0) + { + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"No MM_TABLE found - assuming CARD is not TV-in capable.\n"); + info->MM_TABLE_valid = FALSE; + return TRUE; + } + mm_table+=(((int)info->VBIOS[bios_header+0x39]+0)<<8)-2; + + if(mm_table>0) + { + memcpy(&(info->MM_TABLE), &(info->VBIOS[mm_table]), sizeof(info->MM_TABLE)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MM_TABLE: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + info->MM_TABLE.table_revision, + info->MM_TABLE.table_size, + info->MM_TABLE.tuner_type, + info->MM_TABLE.audio_chip, + info->MM_TABLE.product_id, + info->MM_TABLE.tuner_voltage_teletext_fm, + info->MM_TABLE.i2s_config, + info->MM_TABLE.video_decoder_type, + info->MM_TABLE.video_decoder_host_config, + info->MM_TABLE.input[0], + info->MM_TABLE.input[1], + info->MM_TABLE.input[2], + info->MM_TABLE.input[3], + info->MM_TABLE.input[4]); + + /* Is it an MM_TABLE we know about ? */ + if(info->MM_TABLE.table_size != 0xc){ + info->MM_TABLE_valid = FALSE; + return TRUE; + } + info->MM_TABLE_valid = TRUE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No MM_TABLE found - assuming card is not TV-in capable (mm_table=%d).\n", mm_table); + info->MM_TABLE_valid = FALSE; + } + + pll_info_block=info->VBIOS[bios_header+0x30]; + pll_info_block+=(((int)info->VBIOS[bios_header+0x31]+0)<<8); + + info->video_decoder_type=info->VBIOS[pll_info_block+0x08]; + info->video_decoder_type+=(((int)info->VBIOS[pll_info_block+0x09]+0)<<8); + return TRUE; } -#endif static void RADEONProbeDDC(ScrnInfoPtr pScrn, int indx) { - vbeInfoPtr pVbe; - ModuleDescPtr pModule; + vbeInfoPtr pVbe; + pointer pModule; if ((pModule = xf86LoadVBEModule(pScrn))) { xf86LoaderModReqSymLists(pModule, vbeSymbols, NULL); - pVbe = VBEInit(NULL,indx); - ConfiguredMonitor = vbeDoEDID(pVbe, NULL); - vbeFree(pVbe); + if ((pVbe = VBEInit(NULL, indx))) { + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } xf86UnloadSubModule(pModule); } } -/* RADEONPreInit is called once at server startup */ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; const char *s; + unsigned char *RADEONMMIO; ModuleDescPtr pModule; + MessageType from; RADEONTRACE(("RADEONPreInit\n")); if (pScrn->numEntities != 1) return FALSE; @@ -3885,9 +4767,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info = RADEONPTR(pScrn); info->IsSecondary = FALSE; - info->Clone = FALSE; - info->CurCloneMode = NULL; - info->CloneModes = NULL; + info->IsPrimary = FALSE; + info->MergedFB = FALSE; info->IsSwitching = FALSE; info->MMIO = NULL; @@ -3914,7 +4795,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if(!RADEONMapMMIO(pScrn)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Memory map the MMIO region failed\n"); + "Memory map of MMIO region failed\n"); goto fail1; } @@ -3947,6 +4828,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) } else { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + info->IsPrimary = TRUE; + xf86SetPrimInitDone(info->pEnt->index); pRADEONEnt->pPrimaryScrn = pScrn; @@ -3962,15 +4845,6 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) return TRUE; } - if (!(pModule = xf86LoadSubModule(pScrn, "vgahw"))) return FALSE; - xf86LoaderModReqSymLists(pModule, vgahwSymbols, NULL); - if (!vgaHWGetHWRec(pScrn)) { - RADEONFreeRec(pScrn); - goto fail2; - } - - vgaHWGetIOBase(VGAHWPTR(pScrn)); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI bus %d card %d func %d\n", info->PciInfo->bus, @@ -4021,6 +4895,25 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info->DispPriority = 1; } + info->constantDPI = -1; + from = X_DEFAULT; + if (xf86GetOptValBool(info->Options, OPTION_CONSTANTDPI, &info->constantDPI)) { + from = X_CONFIG; + } else { + if (monitorResolution > 0) { + info->constantDPI = TRUE; + from = X_CMDLINE; + xf86DrvMsg(pScrn->scrnIndex, from, + "\"-dpi %d\" given in command line, assuming \"ConstantDPI\" set\n", + monitorResolution); + } else { + info->constantDPI = FALSE; + } + } + xf86DrvMsg(pScrn->scrnIndex, from, + "X server will %skeep DPI constant for all screen sizes\n", + info->constantDPI ? "" : "not "); + if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { /* check for Linux framebuffer device */ @@ -4048,18 +4941,50 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) RADEONPostInt10Check(pScrn, int10_save); - if (!RADEONPreInitConfig(pScrn)) + RADEONMMIO = info->MMIO; + + /* + * Don't use vgaHW if the adapter is found to be in an accelerator video + * mode on entry, as some Radeons do not respond to VGA accesses when in + * such a mode. This means that saving & restoring video memory contents + * is left up to the background system. + */ + info->UseVGAHW = !(INREG(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EXT_DISP_EN); + if (info->UseVGAHW) { + if (!(pModule = xf86LoadSubModule(pScrn, "vgahw"))) goto fail2; + xf86LoaderModReqSymLists(pModule, vgahwSymbols, NULL); + if (!vgaHWGetHWRec(pScrn)) goto fail2; + + vgaHWGetIOBase(VGAHWPTR(pScrn)); + } + + if (!RADEONPreInitChipType(pScrn)) goto fail; - RADEONPreInitDDC(pScrn); +#ifdef XF86DRI + /* PreInit DRI first of all since we need that for getting a proper + * memory map + */ + info->directRenderingEnabled = RADEONPreInitDRI(pScrn); +#endif - if (!RADEONGetBIOSParameters(pScrn, pInt10)) + if (!RADEONPreInitVRAM(pScrn)) goto fail; - if (info->DisplayType == MT_DFP) - RADEONGetTMDSInfo(pScrn); + RADEONPreInitColorTiling(pScrn); + + RADEONPreInitDDC(pScrn); - if (!RADEONGetPLLParameters(pScrn)) goto fail; + RADEONGetBIOSInfo(pScrn, pInt10); + if (!RADEONQueryConnectedMonitors(pScrn)) goto fail; + RADEONGetClockInfo(pScrn); + + /* collect MergedFB options */ + /* only parse mergedfb options on the primary head. + Mergedfb is already disabled in xinerama/screen based + multihead */ + if (!info->IsSecondary) + RADEONGetMergedFBOptions(pScrn); if (!RADEONPreInitGamma(pScrn)) goto fail; @@ -4069,11 +4994,9 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitAccel(pScrn)) goto fail; -#ifdef XF86DRI - if (!RADEONPreInitDRI(pScrn)) goto fail; -#endif + if (!RADEONPreInitXv(pScrn)) goto fail; - /* Free the video bios (if applicable) */ + /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); info->VBIOS = NULL; @@ -4091,7 +5014,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) fail: /* Pre-init failed. */ if (info->IsSecondary) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); pRADEONEnt->HasSecondary = FALSE; } /* Free the video bios (if applicable) */ @@ -4100,15 +5023,17 @@ fail: info->VBIOS = NULL; } + if (info->UseVGAHW) + vgaHWFreeHWRec(pScrn); + +fail2: /* Free int10 info */ if (pInt10) xf86FreeInt10(pInt10); - vgaHWFreeHWRec(pScrn); - - fail2: if(info->MMIO) RADEONUnmapMMIO(pScrn); info->MMIO = NULL; + fail1: RADEONFreeRec(pScrn); @@ -4126,10 +5051,11 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, unsigned char r, g, b; #ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); + if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn && pScrn->pScreen && info->accel) + (*info->accel->Sync)(pScrn); if (info->FBDev) { fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual); @@ -4190,7 +5116,7 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, } } - if (info->Clone) { + if (info->MergedFB) { PAL_SELECT(1); if (info->CurrentLayout.depth == 15) { /* 15bpp mode. This sends 32 values. */ @@ -4240,7 +5166,7 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, } #ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); + if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif } @@ -4252,10 +5178,10 @@ static void RADEONBlockHandler(int i, pointer blockData, RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingInited) { FLUSH_RING(); + } #endif - pScreen->BlockHandler = info->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = RADEONBlockHandler; @@ -4264,25 +5190,348 @@ static void RADEONBlockHandler(int i, pointer blockData, (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); } + +#ifdef XF86DRI +static Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + int depthCpp = (info->depthBits - 8) / 4; + int width_bytes = pScrn->displayWidth * cpp; + int bufferSize; + int depthSize; + int l; + int scanlines; + int texsizerequest; + BoxRec MemBox; + FBAreaPtr fbarea; + + info->frontOffset = 0; + info->frontPitch = pScrn->displayWidth; + info->backPitch = pScrn->displayWidth; + + /* make sure we use 16 line alignment for tiling (8 might be enough). + * Might need that for non-XF86DRI too? + */ + if (info->allowColorTiling) { + bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; + } else { + bufferSize = (pScrn->virtualY * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN; + } + + /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels, + * which is always the case if color tiling is used due to color pitch + * but not necessarily otherwise, and its height a multiple of 16 lines. + */ + info->depthPitch = (pScrn->displayWidth + 31) & ~31; + depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch + * depthCpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); + + switch (info->CPMode) { + case RADEON_DEFAULT_CP_PIO_MODE: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n"); + break; + case RADEON_DEFAULT_CP_BM_MODE: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n"); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n"); + break; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB GART aperture\n", info->gartSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for the ring buffer\n", info->ringSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for vertex/indirect buffers\n", info->bufSize); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %d MB for GART textures\n", info->gartTexSize); + + /* Try for front, back, depth, and three framebuffers worth of + * pixmap cache. Should be enough for a fullscreen background + * image plus some leftovers. + */ + if (info->textureSize >= 0) { + texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize + - 2 * width_bytes - 16384 - info->FbSecureSize) + /* first divide, then multiply or we'll get an overflow (been there...) */ + / 100 * info->textureSize; + } + else { + texsizerequest = (int)info->FbMapSize / 2; + } + info->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize; + + /* If that gives us less than the requested memory, let's + * be greedy and grab some more. Sorry, I care more about 3D + * performance than playing nicely, and you'll get around a full + * framebuffer's worth of pixmap cache anyway. + */ + if (info->textureSize < texsizerequest) { + info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; + } + if (info->textureSize < texsizerequest) { + info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; + } + + /* If there's still no space for textures, try without pixmap cache, but + * never use the reserved space, the space hw cursor and PCIGART table might + * use. + */ + if (info->textureSize < 0) { + info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize + - 2 * width_bytes - 16384 - info->FbSecureSize; + } + + /* Check to see if there is more room available after the 8192nd + * scanline for textures + */ + /* FIXME: what's this good for? condition is pretty much impossible to meet */ + if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize + > info->textureSize) { + info->textureSize = + info->FbMapSize - 8192*width_bytes - bufferSize - depthSize; + } + + /* If backbuffer is disabled, don't allocate memory for it */ + if (info->noBackBuffer) { + info->textureSize += bufferSize; + } + + /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer! + At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned, + otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee + it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor + area otherwise). + This might cause some space at the end of the video memory to be unused, since it + can't be used (?) due to that log_tex_granularity thing??? + Could use different copyscreentoscreen function for the pageflip copies + (which would use different src and dst offsets) to avoid this. */ + if (info->allowColorTiling && !info->noBackBuffer) { + info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize + + width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16); + } + if (info->textureSize > 0) { + l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) + l = RADEON_LOG_TEX_GRANULARITY; + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't + * round down. + */ + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + } else { + info->textureSize = 0; + } + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (info->textureSize < 512 * 1024) { + info->textureOffset = 0; + info->textureSize = 0; + } + + if (info->allowColorTiling && !info->noBackBuffer) { + info->textureOffset = ((info->FbMapSize - info->textureSize) / + (width_bytes * 16)) * (width_bytes * 16); + } + else { + /* Reserve space for textures */ + info->textureOffset = ((info->FbMapSize - info->textureSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + } + + /* Reserve space for the shared depth + * buffer. + */ + info->depthOffset = ((info->textureOffset - depthSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + + /* Reserve space for the shared back buffer */ + if (info->noBackBuffer) { + info->backOffset = info->depthOffset; + } else { + info->backOffset = ((info->depthOffset - bufferSize + + RADEON_BUFFER_ALIGN) & + ~(CARD32)RADEON_BUFFER_ALIGN); + } + + info->backY = info->backOffset / width_bytes; + info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp; + + scanlines = (info->FbMapSize-info->FbSecureSize) / width_bytes; + if (scanlines > 8191) + scanlines = 8191; + + MemBox.x1 = 0; + MemBox.y1 = 0; + MemBox.x2 = pScrn->displayWidth; + MemBox.y2 = scanlines; + + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to " + "(%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; + } else { + int width, height; + + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + /* why oh why can't we just request modes which are guaranteed to be 16 lines + aligned... sigh */ + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, + info->allowColorTiling ? + ((pScrn->virtualY + 15) & ~15) + - pScrn->virtualY + 2 : 2, + 0, NULL, NULL, + NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + + RADEONDRIAllocatePCIGARTTable(pScreen); + + if (xf86QueryLargestOffscreenArea(pScreen, &width, + &height, 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + + /* Lines in offscreen area needed for depth buffer and + * textures + */ + info->depthTexLines = (scanlines + - info->depthOffset / width_bytes); + info->backLines = (scanlines + - info->backOffset / width_bytes + - info->depthTexLines); + info->backArea = NULL; + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "Unable to determine largest offscreen area " + "available\n"); + return FALSE; + } + } + + xf86DrvMsg(scrnIndex, X_INFO, + "Will use back buffer at offset 0x%x\n", + info->backOffset); + xf86DrvMsg(scrnIndex, X_INFO, + "Will use depth buffer at offset 0x%x\n", + info->depthOffset); + if (info->cardType==CARD_PCIE) + xf86DrvMsg(scrnIndex, X_INFO, + "Will use %d kb for PCI GART table at offset 0x%x\n", + info->pciGartSize/1024, info->pciGartOffset); + xf86DrvMsg(scrnIndex, X_INFO, + "Will use %d kb for textures at offset 0x%x\n", + info->textureSize/1024, info->textureOffset); + + info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | + ((info->frontOffset + info->fbLocation) >> 10)); + + info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | + ((info->backOffset + info->fbLocation) >> 10)); + + info->depthPitchOffset = (((info->depthPitch * depthCpp / 64) << 22) | + ((info->depthOffset + info->fbLocation) >> 10)); + return TRUE; +} +#endif /* XF86DRI */ + +static Bool RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + BoxRec MemBox; + int y2; + + int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; + + MemBox.x1 = 0; + MemBox.y1 = 0; + MemBox.x2 = pScrn->displayWidth; + y2 = info->FbMapSize / width_bytes; + if (y2 >= 32768) + y2 = 32767; /* because MemBox.y2 is signed short */ + MemBox.y2 = y2; + + /* The acceleration engine uses 14 bit + * signed coordinates, so we can't have any + * drawable caches beyond this region. + */ + if (MemBox.y2 > 8191) + MemBox.y2 = 8191; + + if (!xf86InitFBManager(pScreen, &MemBox)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Memory manager initialization to " + "(%d,%d) (%d,%d) failed\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + return FALSE; + } else { + int width, height; + FBAreaPtr fbarea; + + xf86DrvMsg(scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); + if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->displayWidth, + info->allowColorTiling ? + ((pScrn->virtualY + 15) & ~15) + - pScrn->virtualY + 2 : 2, + 0, NULL, NULL, + NULL))) { + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved area from (%d,%d) to (%d,%d)\n", + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); + } + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, + 0, 0, 0)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + } + return TRUE; + } +} + /* Called at the start of each server generation. */ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, const int argc, const char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - BoxRec MemBox; - int y2; + int hasDRI = 0; + int subPixelOrder = SubPixelUnknown; + char* s; - RADEONTRACE(("RADEONScreenInit %x %d\n", + RADEONTRACE(("RADEONScreenInit %lx %ld\n", pScrn->memPhysBase, pScrn->fbOffset)); -#ifdef XF86DRI - /* Turn off the CP for now. */ - info->CPInUse = FALSE; - info->CPStarted = FALSE; - info->directRenderingEnabled = FALSE; -#endif info->accelOn = FALSE; + info->accel = NULL; pScrn->fbOffset = 0; if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; if (!RADEONMapMem(pScrn)) return FALSE; @@ -4295,28 +5544,39 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->PaletteSavedOnVT = FALSE; RADEONSave(pScrn); - if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; - info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); - } else { - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + if ((!info->IsSecondary) && info->IsMobility) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); + } else { + RADEONSetDynamicClock(pScrn, 0); + } } - RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); + if ((!info->IsSecondary) && (IS_R300_VARIANT || IS_RV100_VARIANT)) + RADEONForceSomeClocks(pScrn); - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - - if (info->CurCloneMode) { - info->CloneFrameX0 = - (pScrn->virtualX - info->CurCloneMode->HDisplay) / 2; - info->CloneFrameY0 = - (pScrn->virtualY - info->CurCloneMode->VDisplay) / 2; - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); + if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", + info->MaxSurfaceWidth); + info->allowColorTiling = FALSE; + } + if (info->allowColorTiling) { + if (info->MergedFB) { + if ((((RADEONMergedDisplayModePtr)(pointer)pScrn->currentMode->Private)->CRT1->Flags & + (V_DBLSCAN | V_INTERLACE)) || + (((RADEONMergedDisplayModePtr)(pointer)pScrn->currentMode->Private)->CRT2->Flags & + (V_DBLSCAN | V_INTERLACE))) + info->tilingEnabled = FALSE; + else info->tilingEnabled = TRUE; + } + else { + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; + } } - /* Visual setup */ + /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), @@ -4325,12 +5585,30 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, miSetPixmapDepths (); #ifdef XF86DRI - /* Setup DRI after visuals have been - established, but before fbScreenInit is - called. fbScreenInit will eventually - call the driver's InitGLXVisuals call - back. */ - { + if (info->directRenderingEnabled) { + MessageType from; + + info->depthBits = pScrn->depth; + + from = xf86GetOptValInteger(info->Options, OPTION_DEPTH_BITS, + &info->depthBits) + ? X_CONFIG : X_DEFAULT; + + if (info->depthBits != 16 && info->depthBits != 24) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Value for Option \"DepthBits\" must be 16 or 24\n"); + info->depthBits = pScrn->depth; + from = X_DEFAULT; + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "Using %d bit depth buffer\n", info->depthBits); + } + + /* Setup DRI after visuals have been established, but before fbScreenInit is + * called. fbScreenInit will eventually call the driver's InitGLXVisuals + * call back. */ + if (info->directRenderingEnabled) { /* FIXME: When we move to dynamic allocation of back and depth * buffers, we will want to revisit the following check for 3 * times the virtual size of the screen below. @@ -4339,53 +5617,98 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->CurrentLayout.pixel_bytes); int maxy = info->FbMapSize / width_bytes; - if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { - xf86DrvMsg(scrnIndex, X_WARNING, - "Acceleration disabled, not initializing the DRI\n"); - info->directRenderingEnabled = FALSE; - } else if (maxy <= pScrn->virtualY * 3) { - xf86DrvMsg(scrnIndex, X_WARNING, - "Static buffer allocation failed -- " - "need at least %d kB video memory\n", + if (maxy <= pScrn->virtualY * 3) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Static buffer allocation failed. Disabling DRI.\n"); + xf86DrvMsg(scrnIndex, X_ERROR, + "At least %d kB of video memory needed at this " + "resolution and depth.\n", (pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); info->directRenderingEnabled = FALSE; - } else if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { - info->directRenderingEnabled = FALSE; - xf86DrvMsg(scrnIndex, X_WARNING, - "Direct rendering not yet supported on " - "IGP320/330/340/350, 7000, 9000 integrated chips\n"); - } else if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { - info->directRenderingEnabled = FALSE; - xf86DrvMsg(scrnIndex, X_WARNING, - "Direct rendering not yet supported on " - "Radeon 9500/9700 and newer cards\n"); } else { - if (info->IsSecondary) + info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); + } + } + + /* Tell DRI about new memory map */ + if (info->directRenderingEnabled && info->newMemoryMap) { + drmRadeonSetParam radeonsetparam; + RADEONTRACE(("DRI New memory map param\n")); + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_NEW_MEMMAP; + radeonsetparam.value = 1; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] failed to enable new memory map\n"); + RADEONDRICloseScreen(pScreen); info->directRenderingEnabled = FALSE; - else { - /* Xinerama has sync problem with DRI, disable it for now */ - if (xf86IsEntityShared(info->pEnt->index)) { - info->directRenderingEnabled = FALSE; - xf86DrvMsg(scrnIndex, X_WARNING, - "Direct Rendering Disabled -- " - "Dual-head configuration is not working with " - "DRI at present.\n" - "Please use only one Device/Screen " - "section in your XFConfig file.\n"); - } else { - info->directRenderingEnabled = - RADEONDRIScreenInit(pScreen); - } - } } } + + hasDRI = info->directRenderingEnabled; +#endif /* XF86DRI */ + + /* Initialize the memory map, this basically calculates the values + * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION + */ + RADEONInitMemoryMap(pScrn); + + if (!info->IsSecondary) { + /* empty the surfaces */ + unsigned char *RADEONMMIO = info->MMIO; + unsigned int i; + for (i = 0; i < 8; i++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); + } + } + + if (info->FBDev) { + unsigned char *RADEONMMIO = info->MMIO; + + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; + pScrn->displayWidth = fbdevHWGetLineLength(pScrn) + / info->CurrentLayout.pixel_bytes; + RADEONSaveMemMapRegisters(pScrn, &info->ModeReg); + info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16; + info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); + info->ModeReg.surface_cntl &= ~RADEON_SURF_TRANSLATION_DIS; + } else { + if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + } + + RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); + + pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + +#ifdef XF86DRI + /* Depth moves are disabled by default since they are extremely slow */ + info->depthMoves = xf86ReturnOptValBool(info->Options, + OPTION_DEPTH_MOVE, FALSE); + if (info->depthMoves && info->allowColorTiling) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling depth moves\n"); + } else if (info->depthMoves) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Depth moves don't work without color tiling, disabled\n"); + info->depthMoves = FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Depth moves disabled by default\n"); + } #endif + /* Initial setup of surfaces */ + if (!info->IsSecondary) { + RADEONTRACE(("Setting up initial surfaces\n")); + RADEONChangeSurfaces(pScrn); + } + + RADEONTRACE(("Initializing fb layer\n")); + + /* Init fb layer */ if (!fbScreenInit(pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, @@ -4413,10 +5736,14 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* Must be after RGB order fixed */ fbPictureInit (pScreen, 0, 0); - if (fbPictureGetSubpixelOrder (pScreen) == SubPixelUnknown) - { - int subPixelOrder; + if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) { + if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB; + else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR; + else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone; + fbPictureSetSubpixelOrder (pScreen, subPixelOrder); + } + if (fbPictureGetSubpixelOrder (pScreen) == SubPixelUnknown) { switch (info->DisplayType) { case MT_NONE: subPixelOrder = SubPixelUnknown; break; case MT_LCD: subPixelOrder = SubPixelHorizontalRGB; break; @@ -4425,263 +5752,103 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } fbPictureSetSubpixelOrder (pScreen, subPixelOrder); } - /* Memory manager setup */ -#ifdef XF86DRI - if (info->directRenderingEnabled) { - FBAreaPtr fbarea; - int width_bytes = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); - int cpp = info->CurrentLayout.pixel_bytes; - int bufferSize = ((pScrn->virtualY * width_bytes - + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); - int depthSize = ((((pScrn->virtualY+15) & ~15) * width_bytes - + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); - int l; - int scanlines; - - info->frontOffset = 0; - info->frontPitch = pScrn->displayWidth; - - switch (info->CPMode) { - case RADEON_DEFAULT_CP_PIO_MODE: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n"); - break; - case RADEON_DEFAULT_CP_BM_MODE: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n"); - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n"); - break; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB GART aperture\n", info->gartSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for the ring buffer\n", info->ringSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for vertex/indirect buffers\n", info->bufSize); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for GART textures\n", info->gartTexSize); - /* Try for front, back, depth, and three framebuffers worth of - * pixmap cache. Should be enough for a fullscreen background - * image plus some leftovers. - */ - info->textureSize = info->FbMapSize - 5 * bufferSize - depthSize; + RADEONTRACE(("Setting up accel memmap\n")); - /* If that gives us less than half the available memory, let's - * be greedy and grab some more. Sorry, I care more about 3D - * performance than playing nicely, and you'll get around a full - * framebuffer's worth of pixmap cache anyway. - */ - if (info->textureSize < (int)info->FbMapSize / 2) { - info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; - } - if (info->textureSize < (int)info->FbMapSize / 2) { - info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; - } - /* If there's still no space for textures, try without pixmap cache */ - if (info->textureSize < 0) { - info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize - - 64/4*64; - } - - /* Check to see if there is more room available after the 8192nd - scanline for textures */ - if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize - > info->textureSize) { - info->textureSize = - info->FbMapSize - 8192*width_bytes - bufferSize - depthSize; +#ifdef XF86DRI + if (hasDRI) { + info->textureSize = -1; + if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT, + &(info->textureSize))) { + if (info->textureSize < 0 || info->textureSize > 100) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal texture memory percentage: %dx, using default behaviour\n", + info->textureSize); + info->textureSize = -1; + } } + if (!RADEONSetupMemXAA_DRI(scrnIndex, pScreen)) + return FALSE; + } +#endif - /* If backbuffer is disabled, don't allocate memory for it */ - if (info->noBackBuffer) { - info->textureSize += bufferSize; - } + if (!hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen)) + return FALSE; - if (info->textureSize > 0) { - l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->log2TexGran = l; - info->textureSize = (info->textureSize >> l) << l; - } else { - info->textureSize = 0; - } + /* Backing store setup */ + RADEONTRACE(("Initializing backing store\n")); + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. + /* DRI finalisation */ +#ifdef XF86DRI + if (info->directRenderingEnabled && info->cardType==CARD_PCIE && + info->pciGartOffset && info->pKernelDRMVersion->version_minor >= 19) + { + drmRadeonSetParam radeonsetparam; + RADEONTRACE(("DRI PCIGART param\n")); + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_PCIGART_LOCATION; + radeonsetparam.value = info->pciGartOffset; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed set pci gart location\n"); + } + if (info->directRenderingEnabled) { + RADEONTRACE(("DRI Finishing init !\n")); + info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); + } + if (info->directRenderingEnabled) { + /* DRI final init might have changed the memory map, we need to adjust + * our local image to make sure we restore them properly on mode + * changes or VT switches */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } + RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); - /* Reserve space for textures */ - info->textureOffset = ((info->FbMapSize - info->textureSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - - /* Reserve space for the shared depth - * buffer. - */ - info->depthOffset = ((info->textureOffset - depthSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - info->depthPitch = pScrn->displayWidth; - - /* Reserve space for the shared back buffer */ - if (info->noBackBuffer) { - info->backOffset = info->depthOffset; - info->backPitch = pScrn->displayWidth; - } else { - info->backOffset = ((info->depthOffset - bufferSize + - RADEON_BUFFER_ALIGN) & - ~(CARD32)RADEON_BUFFER_ALIGN); - info->backPitch = pScrn->displayWidth; + if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) { + /* we need to re-calculate bandwidth because of AGPMode difference. */ + RADEONInitDispBandwidth(pScrn); } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); - info->backY = info->backOffset / width_bytes; - info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp; - - scanlines = info->FbMapSize / width_bytes; - if (scanlines > 8191) scanlines = 8191; - - MemBox.x1 = 0; - MemBox.y1 = 0; - MemBox.x2 = pScrn->displayWidth; - MemBox.y2 = scanlines; - - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to " - "(%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->displayWidth, - 2, 0, NULL, NULL, - NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); - } - if (xf86QueryLargestOffscreenArea(pScreen, &width, - &height, 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - - /* Lines in offscreen area needed for depth buffer and - * textures - */ - info->depthTexLines = (scanlines - - info->depthOffset / width_bytes); - info->backLines = (scanlines - - info->backOffset / width_bytes - - info->depthTexLines); - info->backArea = NULL; - } else { - xf86DrvMsg(scrnIndex, X_ERROR, - "Unable to determine largest offscreen area " - "available\n"); - return FALSE; - } + /* we might already be in tiled mode, tell drm about it */ + if (info->directRenderingEnabled && info->tilingEnabled) { + drmRadeonSetParam radeonsetparam; + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING; + radeonsetparam.value = info->tilingEnabled ? 1 : 0; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); } - - xf86DrvMsg(scrnIndex, X_INFO, - "Will use back buffer at offset 0x%x\n", - info->backOffset); - xf86DrvMsg(scrnIndex, X_INFO, - "Will use depth buffer at offset 0x%x\n", - info->depthOffset); - xf86DrvMsg(scrnIndex, X_INFO, - "Will use %d kb for textures at offset 0x%x\n", - info->textureSize/1024, info->textureOffset); - - info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | - (info->frontOffset >> 10)); - - info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | - (info->backOffset >> 10)); - - info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | - (info->depthOffset >> 10)); - } else + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Direct rendering disabled\n"); + } #endif - { - MemBox.x1 = 0; - MemBox.y1 = 0; - MemBox.x2 = pScrn->displayWidth; - y2 = (info->FbMapSize - / (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes)); - if (y2 >= 32768) y2 = 32767; /* because MemBox.y2 is signed short */ - MemBox.y2 = y2; - - /* The acceleration engine uses 14 bit - signed coordinates, so we can't have any - drawable caches beyond this region. */ - if (MemBox.y2 > 8191) MemBox.y2 = 8191; - - if (!xf86InitFBManager(pScreen, &MemBox)) { - xf86DrvMsg(scrnIndex, X_ERROR, - "Memory manager initialization to " - "(%d,%d) (%d,%d) failed\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - return FALSE; - } else { - int width, height; - FBAreaPtr fbarea; - xf86DrvMsg(scrnIndex, X_INFO, - "Memory manager initialized to (%d,%d) (%d,%d)\n", - MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); - if ((fbarea = xf86AllocateOffscreenArea(pScreen, - pScrn->displayWidth, - 2, 0, NULL, NULL, - NULL))) { - xf86DrvMsg(scrnIndex, X_INFO, - "Reserved area from (%d,%d) to (%d,%d)\n", - fbarea->box.x1, fbarea->box.y1, - fbarea->box.x2, fbarea->box.y2); - } else { - xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); - } - if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, - 0, 0, 0)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Largest offscreen area available: %d x %d\n", - width, height); - } - } + /* Make sure surfaces are allright since DRI setup may have changed them */ + if (!info->IsSecondary) { + RADEONTRACE(("Setting up final surfaces\n")); + RADEONChangeSurfaces(pScrn); } - /* Acceleration setup */ + if(info->MergedFB) + /* need this here to fix up sarea values */ + RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* Enable aceleration */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { + RADEONTRACE(("Initializing Acceleration\n")); if (RADEONAccelInit(pScreen)) { xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); info->accelOn = TRUE; - - /* FIXME: Figure out why this was added because it shouldn't be! */ - /* This is needed by the DRI and XAA code for shared entities */ - pScrn->pScreen = pScreen; } else { xf86DrvMsg(scrnIndex, X_ERROR, "Acceleration initialization failed\n"); @@ -4693,27 +5860,34 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->accelOn = FALSE; } - /* DGA setup */ - RADEONDGAInit(pScreen); +#ifdef XF86DRI + /* Init page flipping if enabled now */ + if (info->allowPageFlip) { + RADEONTRACE(("Initializing Page Flipping\n")); + RADEONDRIInitPageFlip(pScreen); + } +#endif - /* Backing store setup */ - miInitializeBackingStore(pScreen); - xf86SetBackingStore(pScreen); + /* Init DPMS */ + RADEONTRACE(("Initializing DPMS\n")); + xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); - /* Set Silken Mouse */ + RADEONTRACE(("Initializing Cursor\n")); + + /* Set Silken Mouse */ xf86SetSilkenMouse(pScreen); - /* Cursor setup */ + /* Cursor setup */ miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - /* Hardware cursor setup */ + /* Hardware cursor setup */ if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { if (RADEONCursorInit(pScreen)) { int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %ld)\n", - info->cursor_start / pScrn->displayWidth + "Using hardware cursor (scanline %d)\n", + info->cursor_offset / pScrn->displayWidth / info->CurrentLayout.pixel_bytes); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { @@ -4727,11 +5901,12 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } } else { - info->cursor_start = 0; + info->cursor_offset = 0; xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } - /* Colormap setup */ + /* Colormap setup */ + RADEONTRACE(("Initializing color map\n")); if (!miCreateDefColormap(pScreen)) return FALSE; if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, RADEONLoadPalette, NULL, @@ -4741,48 +5916,232 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; - /* DPMS setup */ - xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); + /* DGA setup */ + RADEONTRACE(("Initializing DGA\n")); + RADEONDGAInit(pScreen); + /* Wrap some funcs for MergedFB */ + if(info->MergedFB) { + info->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RADEONMergePointerMoved; + /* Pseudo xinerama */ + if(info->UseRADEONXinerama) { + RADEONnoPanoramiXExtension = FALSE; + RADEONXineramaExtensionInit(pScrn); + } else { + info->MouseRestrictions = FALSE; + } + } + + /* Init Xv */ + RADEONTRACE(("Initializing Xv\n")); RADEONInitVideo(pScreen); - /* Provide SaveScreen */ - pScreen->SaveScreen = RADEONSaveScreen; + if(info->MergedFB) + /* need this here to fix up sarea values */ + RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - /* Wrap CloseScreen */ + /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ + /* Wrap CloseScreen */ info->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONCloseScreen; + pScreen->SaveScreen = RADEONSaveScreen; + info->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = RADEONBlockHandler; - /* Note unused options */ + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); -#ifdef XF86DRI - /* DRI finalization */ - if (info->directRenderingEnabled) { - /* Now that mi, fb, drm and others have - done their thing, complete the DRI - setup. */ - info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); - } - if (info->directRenderingEnabled) { - if ((info->DispPriority == 1) && (!info->IsPCI)) { - /* we need to re-calculate bandwidth because of AGPMode difference. */ - RADEONInitDispBandwidth(pScrn); + RADEONTRACE(("RADEONScreenInit finished\n")); + + return TRUE; +} + +/* Write memory mapping registers */ +static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int timeout; + + RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n")); + RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", restore->mc_fb_location)); + RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", restore->mc_agp_location)); + + /* Write memory mapping registers only if their value change + * since we must ensure no access is done while they are + * reprogrammed + */ + if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location || + INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) { + CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; + CARD32 old_mc_status, status_idle; + + RADEONTRACE((" Map Changed ! Applying ...\n")); + + /* Make sure engine is idle. We assume the CCE is stopped + * at this point + */ + RADEONWaitForIdleMMIO(pScrn); + + if (info->IsIGP) + goto igp_no_mcfb; + + /* Capture MC_STATUS in case things go wrong ... */ + old_mc_status = INREG(RADEON_MC_STATUS); + + /* Stop display & memory access */ + ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL); + OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); + crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); + OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); + crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); + RADEONWaitForVerticalSync(pScrn); + OUTREG(RADEON_CRTC_GEN_CNTL, + (crtc_gen_cntl + & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) + | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); + + if (info->HasCRTC2) { + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + RADEONWaitForVerticalSync2(pScrn); + OUTREG(RADEON_CRTC2_GEN_CNTL, + (crtc2_gen_cntl + & ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) + | RADEON_CRTC2_DISP_REQ_EN_B); + } + + /* Make sure the chip settles down (paranoid !) */ + usleep(100000); + + /* Wait for MC idle */ + if (IS_R300_VARIANT) + status_idle = R300_MC_IDLE; + else + status_idle = RADEON_MC_IDLE; + + timeout = 0; + while (!(INREG(RADEON_MC_STATUS) & status_idle)) { + if (++timeout > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout trying to update memory controller settings !\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MC_STATUS = 0x%08x (on entry = 0x%08x)\n", + INREG(RADEON_MC_STATUS), (unsigned int)old_mc_status); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "You will probably crash now ... \n"); + /* Nothing we can do except maybe try to kill the server, + * let's wait 2 seconds to leave the above message a chance + * to maybe hit the disk and continue trying to setup despite + * the MC being non-idle + */ + usleep(2000000); + } + usleep(10); + } + + /* Update maps, first clearing out AGP to make sure we don't get + * a temporary overlap + */ + OUTREG(RADEON_MC_AGP_LOCATION, 0xfffffffc); + OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); + igp_no_mcfb: + OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location); + /* Make sure map fully reached the chip */ + (void)INREG(RADEON_MC_FB_LOCATION); + + RADEONTRACE((" Map applied, resetting engine ...\n")); + + /* Reset the engine and HDP */ + RADEONEngineReset(pScrn); + + /* Make sure we have sane offsets before re-enabling the CRTCs, disable + * stereo, clear offsets, and wait for offsets to catch up with hw + */ + + OUTREG(RADEON_CRTC_OFFSET_CNTL, RADEON_CRTC_OFFSET_FLIP_CNTL); + OUTREG(RADEON_CRTC_OFFSET, 0); + OUTREG(RADEON_CUR_OFFSET, 0); + timeout = 0; + while(INREG(RADEON_CRTC_OFFSET) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) { + if (timeout++ > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout waiting for CRTC offset to update !\n"); + break; + } + usleep(1000); + } + if (info->HasCRTC2) { + OUTREG(RADEON_CRTC2_OFFSET_CNTL, RADEON_CRTC2_OFFSET_FLIP_CNTL); + OUTREG(RADEON_CRTC2_OFFSET, 0); + OUTREG(RADEON_CUR2_OFFSET, 0); + timeout = 0; + while(INREG(RADEON_CRTC2_OFFSET) & RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET) { + if (timeout++ > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout waiting for CRTC2 offset to update !\n"); + break; + } + usleep(1000); + } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); } -#endif - info->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = RADEONBlockHandler; + RADEONTRACE(("Updating display base addresses...\n")); - return TRUE; + OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); + if (info->HasCRTC2) + OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); + OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); + (void)INREG(RADEON_OV0_BASE_ADDR); + + /* More paranoia delays, wait 100ms */ + usleep(100000); + + RADEONTRACE(("Memory map updated.\n")); + } + +#ifdef XF86DRI +static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned fb, agp; + int fb_loc_changed; + + fb = INREG(RADEON_MC_FB_LOCATION); + agp = INREG(RADEON_MC_AGP_LOCATION); + fb_loc_changed = (fb != info->mc_fb_location); + + if (fb_loc_changed || agp != info->mc_agp_location) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRI init changed memory map, adjusting ...\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " MC_FB_LOCATION was: 0x%08x is: 0x%08x\n", + info->mc_fb_location, fb); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " MC_AGP_LOCATION was: 0x%08x is: 0x%08x\n", + info->mc_agp_location, agp); + info->mc_fb_location = fb; + info->mc_agp_location = agp; + info->fbLocation = (save->mc_fb_location & 0xffff) << 16; + info->dst_pitch_offset = + (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); + + + RADEONInitMemMapRegisters(pScrn, save, info); + + /* If MC_FB_LOCATION was changed, adjust the various offsets */ + if (fb_loc_changed) + RADEONRestoreMemMapRegisters(pScrn, save); + } } +#endif -/* Write common registers (initialized to 0) */ +/* Write common registers */ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { @@ -4809,13 +6168,11 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, if (info->HasCRTC2 && !info->IsSwitching && info->ChipFamily != CHIP_FAMILY_R200 && - info->ChipFamily != CHIP_FAMILY_R300 && - info->ChipFamily != CHIP_FAMILY_R350 && - info->ChipFamily != CHIP_FAMILY_RV350) { + !IS_R300_VARIANT) { CARD32 tmp; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (pRADEONEnt->HasSecondary || info->Clone) { + if (pRADEONEnt->HasSecondary || info->MergedFB) { tmp = INREG(RADEON_DAC_CNTL2); OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); usleep(100000); @@ -4855,7 +6212,14 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); + RADEONTRACE(("Programming CRTC1, offset: 0x%08lx\n", + restore->crtc_offset)); + + /* We prevent the CRTC from hitting the memory controller until + * fully programmed + */ + OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl | + RADEON_CRTC_DISP_REQ_EN_B); OUTREGP(RADEON_CRTC_EXT_CNTL, restore->crtc_ext_cntl, @@ -4877,6 +6241,15 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); + + if (info->IsDellServer) { + OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); + OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); + } + + OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl); } /* Write CRTC2 registers */ @@ -4885,20 +6258,28 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc2_gen_cntl; - OUTREGP(RADEON_CRTC2_GEN_CNTL, - restore->crtc2_gen_cntl, - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | - RADEON_CRTC2_DISP_DIS); + RADEONTRACE(("Programming CRTC2, offset: 0x%08lx\n", + restore->crtc2_offset)); + + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & + (RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | + RADEON_CRTC2_DISP_DIS); + crtc2_gen_cntl |= restore->crtc2_gen_cntl; + + /* We prevent the CRTC from hitting the memory controller until + * fully programmed + */ + OUTREG(RADEON_CRTC2_GEN_CNTL, + crtc2_gen_cntl | RADEON_CRTC2_DISP_REQ_EN_B); OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); if ((info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + IS_R300_VARIANT) { OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); } else { OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); @@ -4914,11 +6295,14 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { + info->MergeType == MT_DFP) { OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } + + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + #if 0 /* Hack for restoring text mode -- fixed elsewhere */ usleep(100000); @@ -4949,9 +6333,14 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_GRPH_BUFFER_CNTL, INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); + if (info->IsMobility) { + OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch); + OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); + OUTREG(RADEON_BIOS_6_SCRATCH, restore->bios_6_scratch); + } + if (info->DisplayType != MT_DFP) { unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); if (info->IsMobility || info->IsIGP) { /* Asic bug, when turning off LVDS_ON, we have to make sure @@ -4980,7 +6369,7 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) if (info->IsMobility || info->IsIGP) { if (!(restore->lvds_gen_cntl & RADEON_LVDS_ON)) { - OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); } } } @@ -5002,9 +6391,6 @@ static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) static void RADEONPLLWriteUpdate(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - while (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, @@ -5028,9 +6414,6 @@ static void RADEONPLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) static void RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - while (INPLL(pScrn, RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, @@ -5045,24 +6428,30 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsMobility) { - /* + /* * Never do it on Apple iBook to avoid a blank screen. */ #ifdef __powerpc__ if (xf86ReturnOptValBool(info->Options, OPTION_IBOOKHACKS, FALSE)) - return; + return; #endif - /* A temporal workaround for the occational blanking on certain laptop panels. - This appears to related to the PLL divider registers (fail to lock?). + if (info->IsMobility) { + /* A temporal workaround for the occational blanking on certain laptop panels. + This appears to related to the PLL divider registers (fail to lock?). It occurs even when all dividers are the same with their old settings. - In this case we really don't need to fiddle with PLL registers. - By doing this we can avoid the blanking problem with some panels. - */ - if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && - (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) - return; + In this case we really don't need to fiddle with PLL registers. + By doing this we can avoid the blanking problem with some panels. + */ + if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && + (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & + (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { + OUTREGP(RADEON_CLOCK_CNTL_INDEX, + RADEON_PLL_DIV_SEL, + ~(RADEON_PLL_DIV_SEL)); + RADEONPllErrataAfterIndex(info); + return; + } } OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, @@ -5081,11 +6470,10 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, OUTREGP(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_DIV_SEL, ~(RADEON_PLL_DIV_SEL)); + RADEONPllErrataAfterIndex(info); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_RS300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_RS300)) { if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { /* When restoring console mode, use saved PPLL_REF_DIV * setting. @@ -5116,7 +6504,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEONPLLWriteUpdate(pScrn); RADEONPLLWaitForReadUpdateComplete(pScrn); - OUTPLL(RADEON_HTOTAL_CNTL, restore->htotal_cntl); + OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl); OUTPLLP(pScrn, RADEON_PPLL_CNTL, 0, @@ -5125,12 +6513,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, | RADEON_PPLL_ATOMIC_UPDATE_EN | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); - xf86DrvMsg(0, X_INFO, "Wrote: rd=%d, fd=%d, pd=%d\n", - restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, - (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); - - RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08lx (0x%08x)\n", restore->ppll_ref_div, restore->ppll_div_3, restore->htotal_cntl, @@ -5140,7 +6523,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16)); - usleep(5000); /* Let the clock to lock */ + usleep(50000); /* Let the clock to lock */ OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, RADEON_VCLK_SRC_SEL_PPLLCLK, @@ -5152,9 +6535,6 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, RADEON_PIX2CLK_SRC_SEL_CPUCLK, ~(RADEON_PIX2CLK_SRC_SEL_MASK)); @@ -5183,7 +6563,7 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, RADEONPLL2WriteUpdate(pScrn); RADEONPLL2WaitForReadUpdateComplete(pScrn); - OUTPLL(RADEON_HTOTAL2_CNTL, restore->htotal_cntl2); + OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2); OUTPLLP(pScrn, RADEON_P2PLL_CNTL, 0, @@ -5192,12 +6572,12 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, | RADEON_P2PLL_ATOMIC_UPDATE_EN | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN)); - RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + RADEONTRACE(("Wrote: 0x%08lx 0x%08lx 0x%08lx (0x%08x)\n", restore->p2pll_ref_div, restore->p2pll_div_0, restore->htotal_cntl2, INPLL(pScrn, RADEON_P2PLL_CNTL))); - RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", + RADEONTRACE(("Wrote: rd=%ld, fd=%ld, pd=%ld\n", restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, (restore->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >>16)); @@ -5209,28 +6589,192 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, ~(RADEON_PIX2CLK_SRC_SEL_MASK)); } -/* Write palette data */ -static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) + +/* restore original surface info (for fb console). */ +static void RADEONRestoreSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr restore) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int i; + unsigned int surfnr; - if (!restore->palette_valid) return; + for ( surfnr = 0; surfnr < 8; surfnr++ ) { + OUTREG(RADEON_SURFACE0_INFO + 16 * surfnr, restore->surfaces[surfnr][0]); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr, restore->surfaces[surfnr][1]); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr, restore->surfaces[surfnr][2]); + } +} - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); +/* save original surface info (for fb console). */ +static void RADEONSaveSurfaces(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned int surfnr; + + for ( surfnr = 0; surfnr < 8; surfnr++ ) { + save->surfaces[surfnr][0] = INREG(RADEON_SURFACE0_INFO + 16 * surfnr); + save->surfaces[surfnr][1] = INREG(RADEON_SURFACE0_LOWER_BOUND + 16 * surfnr); + save->surfaces[surfnr][2] = INREG(RADEON_SURFACE0_UPPER_BOUND + 16 * surfnr); } } -#if 1 -#define RADEONRestorePalette2(pScrn, restore) /* Nullify */ -#else -/* This causes hangs on some Radeon's. Why? */ -static void RADEONRestorePalette2(ScrnInfoPtr pScrn, RADEONSavePtr restore) +void RADEONChangeSurfaces(ScrnInfoPtr pScrn) +{ + /* the idea here is to only set up front buffer as tiled, and back/depth buffer when needed. + Everything else is left as untiled. This means we need to use eplicit src/dst pitch control + when blitting, based on the src/target address, and can no longer use a default offset. + But OTOH we don't need to dynamically change surfaces (for xv for instance), and some + ugly offset / fb reservation (cursor) is gone. And as a bonus, everything actually works... + For simplicity, just always update everything (just let the ioctl fail - could do better). + All surface addresses are relative to RADEON_MC_FB_LOCATION */ + + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + /* depth/front/back pitch must be identical (and the same as displayWidth) */ + int width_bytes = pScrn->displayWidth * cpp; + int bufferSize = ((((pScrn->virtualY + 15) & ~15) * width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); + unsigned int color_pattern, swap_pattern; + + if (!info->allowColorTiling) + return; + + swap_pattern = 0; +#if X_BYTE_ORDER == X_BIG_ENDIAN + switch (pScrn->bitsPerPixel) { + case 16: + swap_pattern = RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; + break; + + case 32: + swap_pattern = RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; + break; + } +#endif + if (info->ChipFamily < CHIP_FAMILY_R200) { + color_pattern = RADEON_SURF_TILE_COLOR_MACRO; + } else if (IS_R300_VARIANT) { + color_pattern = R300_SURF_TILE_COLOR_MACRO; + } else { + color_pattern = R200_SURF_TILE_COLOR_MACRO; + } +#ifdef XF86DRI + if (info->directRenderingInited) { + drmRadeonSurfaceFree drmsurffree; + drmRadeonSurfaceAlloc drmsurfalloc; + int retvalue; + int depthCpp = (info->depthBits - 8) / 4; + int depth_width_bytes = pScrn->displayWidth * depthCpp; + int depthBufferSize = ((((pScrn->virtualY + 15) & ~15) * depth_width_bytes + + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN); + unsigned int depth_pattern; + + drmsurffree.address = info->frontOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + + if ((info->ChipFamily != CHIP_FAMILY_RV100) || + (info->ChipFamily != CHIP_FAMILY_RS100) || + (info->ChipFamily != CHIP_FAMILY_RS200)) { + drmsurffree.address = info->depthOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + } + + if (!info->noBackBuffer) { + drmsurffree.address = info->backOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_FREE, + &drmsurffree, sizeof(drmsurffree)); + } + + drmsurfalloc.size = bufferSize; + drmsurfalloc.address = info->frontOffset; + drmsurfalloc.flags = swap_pattern; + + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + drmsurfalloc.flags |= (width_bytes / 8) | color_pattern; + else + drmsurfalloc.flags |= (width_bytes / 16) | color_pattern; + } + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for front buffer!\n"); + + if ((info->have3DWindows) && (!info->noBackBuffer)) { + drmsurfalloc.address = info->backOffset; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for back buffer!\n"); + } + + if (info->ChipFamily < CHIP_FAMILY_R200) { + if (depthCpp == 2) + depth_pattern = RADEON_SURF_TILE_DEPTH_16BPP; + else + depth_pattern = RADEON_SURF_TILE_DEPTH_32BPP; + } else if (IS_R300_VARIANT) { + if (depthCpp == 2) + depth_pattern = R300_SURF_TILE_COLOR_MACRO; + else + depth_pattern = R300_SURF_TILE_COLOR_MACRO | R300_SURF_TILE_DEPTH_32BPP; + } else { + if (depthCpp == 2) + depth_pattern = R200_SURF_TILE_DEPTH_16BPP; + else + depth_pattern = R200_SURF_TILE_DEPTH_32BPP; + } + + /* rv100 and probably the derivative igps don't have depth tiling on all the time? */ + if (info->have3DWindows && ((info->ChipFamily != CHIP_FAMILY_RV100) || + (info->ChipFamily != CHIP_FAMILY_RS100) || + (info->ChipFamily != CHIP_FAMILY_RS200))) { + drmsurfalloc.size = depthBufferSize; + drmsurfalloc.address = info->depthOffset; + if (IS_R300_VARIANT) + drmsurfalloc.flags = swap_pattern | (depth_width_bytes / 8) | depth_pattern; + else + drmsurfalloc.flags = swap_pattern | (depth_width_bytes / 16) | depth_pattern; + retvalue = drmCommandWrite(info->drmFD, DRM_RADEON_SURF_ALLOC, + &drmsurfalloc, sizeof(drmsurfalloc)); + if (retvalue < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "drm: could not allocate surface for depth buffer!\n"); + } + } + else +#endif + { + unsigned int surf_info = swap_pattern; + unsigned char *RADEONMMIO = info->MMIO; + /* we don't need anything like WaitForFifo, no? */ + if (!info->IsSecondary) { + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + surf_info |= (width_bytes / 8) | color_pattern; + else + surf_info |= (width_bytes / 16) | color_pattern; + } + OUTREG(RADEON_SURFACE0_INFO, surf_info); + OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); +/* xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "surface0 set to %x, LB 0x%x UB 0x%x\n", + surf_info, 0, bufferSize - 1024);*/ + } + } + + /* Update surface images */ + RADEONSaveSurfaces(pScrn, &info->ModeReg); +} + +#if 0 +/* Write palette data */ +static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -5244,6 +6788,13 @@ static void RADEONRestorePalette2(ScrnInfoPtr pScrn, RADEONSavePtr restore) RADEONWaitForFifo(pScrn, 32); /* delay */ OUTPAL_NEXT_CARD32(restore->palette2[i]); } + + PAL_SELECT(0); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + RADEONWaitForFifo(pScrn, 32); /* delay */ + OUTPAL_NEXT_CARD32(restore->palette[i]); + } } #endif @@ -5254,9 +6805,11 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); static RADEONSaveRec restore0; + RADEONTRACE(("RADEONRestoreMode()\n")); + /* For Non-dual head card, we don't have private field in the Entity */ if (!info->HasCRTC2) { - RADEONRestorePalette(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtcRegisters(pScrn, restore); RADEONRestoreFPRegisters(pScrn, restore); @@ -5274,15 +6827,18 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) * order. Regardless the order of X server issuing the calls, we * have to ensure we set registers in the right order!!! Otherwise * we may get a blank screen. + * + * We always restore MemMap first, the saverec should be up to date + * in all cases */ if (info->IsSecondary) { - RADEONRestorePalette2(pScrn, restore); - if (!pRADEONEnt->RestorePrimary && !info->IsSwitching) - RADEONRestoreCommonRegisters(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); - if(info->IsSwitching) return; + if (info->IsSwitching) + return; pRADEONEnt->IsSecondaryRestored = TRUE; @@ -5292,15 +6848,12 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) RADEONRestoreCrtcRegisters(pScrn, &restore0); RADEONRestoreFPRegisters(pScrn, &restore0); RADEONRestorePLLRegisters(pScrn, &restore0); - RADEONRestorePalette(pScrn, restore); pRADEONEnt->IsSecondaryRestored = FALSE; } } else { - if (!pRADEONEnt->IsSecondaryRestored) - RADEONRestoreCommonRegisters(pScrn, restore); - - if (info->Clone) { - RADEONRestorePalette2(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); + if (info->MergedFB) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); } @@ -5312,12 +6865,28 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) RADEONRestoreCrtcRegisters(pScrn, restore); RADEONRestoreFPRegisters(pScrn, restore); RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestorePalette(pScrn, restore); } else { memcpy(&restore0, restore, sizeof(restore0)); pRADEONEnt->RestorePrimary = TRUE; } } + +#if 0 + RADEONRestorePalette(pScrn, &info->SavedReg); +#endif +} + +/* Read memory map */ +static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); + save->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + save->display_base_addr = INREG(RADEON_DISPLAY_BASE_ADDR); + save->display2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR); + save->ov0_base_addr = INREG(RADEON_OV0_BASE_ADDR); } /* Read common registers */ @@ -5382,6 +6951,13 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_pitch = INREG(RADEON_CRTC_PITCH); save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + + if (info->IsDellServer) { + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + save->dac2_cntl = INREG(RADEON_DAC_CNTL2); + save->disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG); + save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + } } /* Read flat panel registers */ @@ -5401,7 +6977,9 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL); save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); + save->bios_4_scratch = INREG(RADEON_BIOS_4_SCRATCH); save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH); + save->bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH); if (info->ChipFamily == CHIP_FAMILY_RV280) { /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ @@ -5417,7 +6995,7 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->dac2_cntl = INREG(RADEON_DAC_CNTL2); save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); + save->disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG); save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); @@ -5428,9 +7006,9 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); - save->fp2_h_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); - save->fp2_v_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); - save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL); + save->fp2_h_sync_strt_wid = INREG(RADEON_FP_H2_SYNC_STRT_WID); + save->fp2_v_sync_strt_wid = INREG(RADEON_FP_V2_SYNC_STRT_WID); + save->fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); } @@ -5441,7 +7019,7 @@ static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); - RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", + RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08lx\n", save->ppll_ref_div, save->ppll_div_3, save->htotal_cntl)); @@ -5458,11 +7036,11 @@ static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->p2pll_div_0 = INPLL(pScrn, RADEON_P2PLL_DIV_0); save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); - RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08x\n", + RADEONTRACE(("Read: 0x%08lx 0x%08lx 0x%08lx\n", save->p2pll_ref_div, save->p2pll_div_0, save->htotal_cntl2)); - RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n", + RADEONTRACE(("Read: rd=%ld, fd=%ld, pd=%ld\n", save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, (save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >> 16)); @@ -5475,10 +7053,6 @@ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save) unsigned char *RADEONMMIO = info->MMIO; int i; -#ifdef ENABLE_FLAT_PANEL - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - /* if (info->Port1 == MT_DFP) PAL_SELECT(1); */ -#endif PAL_SELECT(1); INPAL_START(0); for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); @@ -5494,6 +7068,7 @@ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONSaveMode(%p)\n", save)); + RADEONSaveMemMapRegisters(pScrn, save); RADEONSaveCommonRegisters(pScrn, save); if (info->IsSecondary) { RADEONSaveCrtc2Registers(pScrn, save); @@ -5503,11 +7078,11 @@ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONSaveCrtcRegisters(pScrn, save); RADEONSaveFPRegisters(pScrn, save); - if (info->Clone) { + if (info->MergedFB) { RADEONSaveCrtc2Registers(pScrn, save); RADEONSavePLL2Registers(pScrn, save); } - RADEONSavePalette(pScrn, save); + /* RADEONSavePalette(pScrn, save); */ } RADEONTRACE(("RADEONSaveMode returns %p\n", save)); @@ -5519,35 +7094,33 @@ static void RADEONSave(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr save = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); RADEONTRACE(("RADEONSave\n")); if (info->FBDev) { + RADEONSaveMemMapRegisters(pScrn, save); fbdevHWSave(pScrn); return; } if (!info->IsSecondary) { - vgaHWUnlock(hwp); -#if defined(__powerpc__) - /* temporary hack to prevent crashing on PowerMacs when trying to - * read VGA fonts and colormap, will find a better solution - * in the future - */ - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ -#else - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* Save mode - * & fonts & cmap - */ -#endif - vgaHWLock(hwp); + if (info->UseVGAHW) { + vgaHWPtr hwp = VGAHWPTR(pScrn); + + vgaHWUnlock(hwp); + /* Save mode & fonts & cmap */ + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); + vgaHWLock(hwp); + } + save->dp_datatype = INREG(RADEON_DP_DATATYPE); save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + RADEONPllErrataAfterIndex(info); } RADEONSaveMode(pScrn, save); + if (!info->IsSecondary) + RADEONSaveSurfaces(pScrn, save); } /* Restore the original (text) mode */ @@ -5556,7 +7129,6 @@ static void RADEONRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); RADEONTRACE(("RADEONRestore\n")); @@ -5572,7 +7144,7 @@ static void RADEONRestore(ScrnInfoPtr pScrn) RADEONBlank(pScrn); OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); - if (info->R300CGWorkaround) R300CGWorkaround(pScrn); + RADEONPllErrataAfterIndex(info); OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); @@ -5582,12 +7154,14 @@ static void RADEONRestore(ScrnInfoPtr pScrn) /* M6 card has trouble restoring text mode for its CRT. * This is fixed elsewhere and will be removed in the future. */ - if ((xf86IsEntityShared(info->pEnt->index) || info->Clone) + if ((xf86IsEntityShared(info->pEnt->index) || info->MergedFB) && info->IsM6) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif RADEONRestoreMode(pScrn, restore); + if (!info->IsSecondary) + RADEONRestoreSurfaces(pScrn, restore); #if 0 /* Temp fix to "solve" VT switch problems. When switching VTs on @@ -5598,27 +7172,22 @@ static void RADEONRestore(ScrnInfoPtr pScrn) usleep(100000); #endif - if (!info->IsSecondary) { - vgaHWUnlock(hwp); -#if defined(__powerpc__) - /* Temporary hack to prevent crashing on PowerMacs when trying to - * write VGA fonts, will find a better solution in the future - */ - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE); -#else - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL); -#endif - vgaHWLock(hwp); - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - ScrnInfoPtr pScrn0; - vgaHWPtr hwp0; - - pScrn0 = pRADEONEnt->pPrimaryScrn; - hwp0 = VGAHWPTR(pScrn0); - vgaHWUnlock(hwp0); - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); - vgaHWLock(hwp0); + if (info->UseVGAHW) { + vgaHWPtr hwp = VGAHWPTR(pScrn); + if (!info->IsSecondary) { + vgaHWUnlock(hwp); + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL ); + vgaHWLock(hwp); + } else { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + ScrnInfoPtr pScrn0 = pRADEONEnt->pPrimaryScrn; + vgaHWPtr hwp0; + + hwp0 = VGAHWPTR(pScrn0); + vgaHWUnlock(hwp0); + vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); + vgaHWLock(hwp0); + } } RADEONUnblank(pScrn); @@ -5649,6 +7218,7 @@ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } + /* Calculate display buffer watermark to prevent buffer underflow */ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) { @@ -5685,10 +7255,29 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) int stop_req, max_stop_req; float read_return_rate, time_disp1_drop_priority; + /* + * Set display0/1 priority up on r3/4xx in the memory controller for + * high res modes if the user specifies HIGH for displaypriority + * option. + */ + if ((info->DispPriority == 2) && IS_R300_VARIANT) { + CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); + if (info->MergedFB || pRADEONEnt->HasSecondary) { + mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + } else { + mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + } + OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + + /* R420 and RV410 family not supported yet */ + if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; + if (pRADEONEnt->pSecondaryScrn) { if (info->IsSecondary) return; info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (info->Clone) info2 = info; + } else if (info->MergedFB) info2 = info; /* * Determine if there is enough bandwidth for current display mode @@ -5696,12 +7285,14 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); mode1 = info->CurrentLayout.mode; - if (info->Clone) - mode2 = info->CurCloneMode; - else if ((pRADEONEnt->HasSecondary) && info2) + if (info->MergedFB) { + mode1 = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT1; + mode2 = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2; + } else if ((pRADEONEnt->HasSecondary) && info2) { mode2 = info2->CurrentLayout.mode; - else + } else { mode2 = NULL; + } pix_clk = mode1->Clock/1000.0; if (mode2) @@ -5720,19 +7311,13 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) } /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] */ stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; /* setup Max GRPH_STOP_REQ default value */ - if ((info->ChipFamily == CHIP_FAMILY_RV100) || - (info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280) || - (info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) + if (IS_RV100_VARIANT) max_stop_req = 0x5c; else max_stop_req = 0x7c; @@ -5760,15 +7345,13 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) mem_tcas = MemTcas2 [data]; } - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { /* on the R300, Tcas is included in Trbs. */ temp = INREG(RADEON_MEM_CNTL); data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 2) { + if (data == 1) { if (R300_MEM_USE_CD_CH_ONLY & temp) { temp = INREG(R300_MC_IND_INDEX); temp &= ~R300_MC_IND_ADDR_MASK; @@ -5803,9 +7386,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) /* Find the memory controller latency for the display client. */ - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (IS_R300_VARIANT) { /*not enough for R350 ???*/ /* if (!mode2) sclk_delay = 150; @@ -5877,15 +7458,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) if (critical_point < temp) critical_point = temp; */ if (info->DispPriority == 2) { - if (mode2) { - /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point += 0x10; - else - critical_point = 0; - } - else - critical_point = 0; + critical_point = 0; } /* @@ -5894,6 +7467,11 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) */ if (max_stop_req - critical_point < 4) critical_point = 0; + if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + temp = info->SavedReg.grph_buffer_cntl; temp &= ~(RADEON_GRPH_STOP_REQ_MASK); temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); @@ -5915,7 +7493,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", - info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + (unsigned int)info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); if (mode2) { stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; @@ -5947,21 +7525,23 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) disp_latency) * disp_drain_rate2 + 0.5); if (info->DispPriority == 2) { - if (info->ChipFamily == CHIP_FAMILY_R300) - critical_point2 += 0x10; - else - critical_point2 = 0; + critical_point2 = 0; } if (max_stop_req - critical_point2 < 4) critical_point2 = 0; } + if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", - info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); } } @@ -5974,10 +7554,7 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, int format; int hsync_start; int hsync_wid; - int hsync_fudge; int vsync_wid; - int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; - int hsync_fudge_fp[] = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 }; switch (info->CurrentLayout.pixel_code) { case 4: format = 1; break; @@ -5995,7 +7572,6 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, if ((info->DisplayType == MT_DFP) || (info->DisplayType == MT_LCD)) { - hsync_fudge = hsync_fudge_fp[format-1]; if (mode->Flags & RADEON_USE_RMX) { #if 0 mode->CrtcHDisplay = info->PanelXRes; @@ -6010,8 +7586,6 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, mode->Clock = info->DotClock; mode->Flags = info->Flags | RADEON_USE_RMX; } - } else { - hsync_fudge = hsync_fudge_default[format-1]; } save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN @@ -6027,13 +7601,21 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, ? RADEON_CRTC_INTERLACE_EN : 0)); + /* Don't try to be smart and unconditionally enable the analog output + * for now as the dodgy code to handle it for the second head doesn't + * work. This will be correctly fixed when Alex' megapatch gets in that + * reworks the whole output mapping + */ +#if 0 if ((info->DisplayType == MT_DFP) || (info->DisplayType == MT_LCD)) { save->crtc_ext_cntl = RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN; save->crtc_gen_cntl &= ~(RADEON_CRTC_DBL_SCAN_EN | RADEON_CRTC_CSYNC_EN | RADEON_CRTC_INTERLACE_EN); - } else { + } else +#endif + { save->crtc_ext_cntl = (RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN | RADEON_CRTC_CRT_ON); @@ -6049,7 +7631,7 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; + hsync_start = mode->CrtcHSyncStart - 8; save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | ((hsync_wid & 0x3f) << 16) @@ -6080,30 +7662,47 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, ? RADEON_CRTC_V_SYNC_POL : 0)); - save->crtc_offset = 0; + save->crtc_offset = pScrn->fbOffset; save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc_pitch |= save->crtc_pitch << 16; - /* Some versions of BIOS setup CRTC_MORE_CNTL for a DFP, if we - have a CRT here, it should be cleared to avoild a blank screen. - */ - if (info->DisplayType == MT_CRT) - save->crtc_more_cntl = (info->SavedReg.crtc_more_cntl & - ~(RADEON_CRTC_H_CUTOFF_ACTIVE_EN | - RADEON_CRTC_V_CUTOFF_ACTIVE_EN)); - else - save->crtc_more_cntl = info->SavedReg.crtc_more_cntl; + save->crtc_more_cntl = 0; + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. + */ + save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } save->surface_cntl = 0; save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; #if X_BYTE_ORDER == X_BIG_ENDIAN - /* Alhought we current onlu use aperture 0, also setting aperture 1 should not harm -ReneR */ + /* We must set both apertures as they can be both used to map the entire + * video memory. -BenH. + */ switch (pScrn->bitsPerPixel) { case 16: save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; @@ -6117,7 +7716,24 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, } #endif - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", + if (info->IsDellServer) { + save->dac2_cntl = info->SavedReg.dac2_cntl; + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl; + save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl; + save->disp_hw_debug = info->SavedReg.disp_hw_debug; + + save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + + /* For CRT on DAC2, don't turn it on if BIOS didn't + enable it, even it's detected. + */ + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); + save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + } + + RADEONTRACE(("Pitch = %ld bytes (virtualX = %d, displayWidth = %d)\n", save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth)); return TRUE; @@ -6133,9 +7749,7 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, int format; int hsync_start; int hsync_wid; - int hsync_fudge; int vsync_wid; - int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; switch (info->CurrentLayout.pixel_code) { case 4: format = 1; break; @@ -6151,8 +7765,6 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, return FALSE; } - hsync_fudge = hsync_fudge_default[format-1]; - save->crtc2_gen_cntl = (RADEON_CRTC2_EN | RADEON_CRTC2_CRT2_ON | (format << 8) @@ -6167,15 +7779,12 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, : 0)); /* Turn CRT on in case the first head is a DFP */ - save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; save->dac2_cntl = info->SavedReg.dac2_cntl; /* always let TVDAC drive CRT2, we don't support tvout yet */ save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; save->disp_output_cntl = info->SavedReg.disp_output_cntl; if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300 || - info->ChipFamily == CHIP_FAMILY_R350 || - info->ChipFamily == CHIP_FAMILY_RV350) { + IS_R300_VARIANT) { save->disp_output_cntl &= ~(RADEON_DISP_DAC_SOURCE_MASK | RADEON_DISP_DAC2_SOURCE_MASK); if (pRADEONEnt->MonType1 != MT_CRT) { @@ -6216,7 +7825,7 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; + hsync_start = mode->CrtcHSyncStart - 8; save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) | ((hsync_wid & 0x3f) << 16) @@ -6247,33 +7856,57 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, ? RADEON_CRTC2_V_SYNC_POL : 0)); - save->crtc2_offset = 0; - save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); + /* It seems all fancy options apart from pflip can be safely disabled + */ + save->crtc2_offset = pScrn->fbOffset; + save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & RADEON_CRTC_OFFSET_FLIP_CNTL; + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + /* this should be right */ + if (info->MergedFB) { + save->crtc2_pitch = (((info->CRT2pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc2_pitch |= save->crtc2_pitch << 16; + } else { save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc2_pitch |= save->crtc2_pitch << 16; + } save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { + info->MergeType == MT_DFP) { save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; - save->fp2_gen_cntl = (RADEON_FP2_PANEL_FORMAT | - RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - save->fp2_gen_cntl |= RADEON_FP2_DV0_EN; - } - - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300 || - info->ChipFamily == CHIP_FAMILY_R350 || - info->ChipFamily == CHIP_FAMILY_RV350) { - save->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_MASK; - save->fp2_gen_cntl |= RADEON_FP2_SOURCE_SEL_CRTC2; + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | RADEON_FP2_ON; + save->fp2_gen_cntl &= ~(RADEON_FP2_BLANK_EN); + + if ((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + + save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 | + RADEON_FP2_DVO_EN); } else { save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_MASK; save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; @@ -6284,19 +7917,28 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, else save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */ - /* FIXME: When there are two DFPs, the 2nd DFP is driven by the - * external TMDS transmitter. It may have a problem at - * high dot clock for certain panels. - */ + } - /* If BIOS has not turned it on, we'll keep it on so that we'll - * have a valid VGA screen even after X quits or VT is switched - * to the console mode. - */ - info->SavedReg.fp2_gen_cntl = RADEON_FP2_ON; + /* We must set SURFACE_CNTL properly on the second screen too */ + save->surface_cntl = 0; +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* We must set both apertures as they can be both used to map the entire + * video memory. -BenH. + */ + switch (pScrn->bitsPerPixel) { + case 16: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; + break; + + case 32: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; + break; } +#endif - RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", + RADEONTRACE(("Pitch = %ld bytes (virtualX = %d, displayWidth = %d)\n", save->crtc2_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth)); @@ -6318,23 +7960,23 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, */ if ((info->DisplayType != MT_DFP) && (info->DisplayType != MT_LCD)) { - save->fp_crtc_h_total_disp = orig->fp_crtc_h_total_disp; - save->fp_crtc_v_total_disp = orig->fp_crtc_v_total_disp; - save->fp_gen_cntl = 0; - save->fp_h_sync_strt_wid = orig->fp_h_sync_strt_wid; - save->fp_horz_stretch = 0; - save->fp_v_sync_strt_wid = orig->fp_v_sync_strt_wid; - save->fp_vert_stretch = 0; - save->lvds_gen_cntl = orig->lvds_gen_cntl; - save->lvds_pll_cntl = orig->lvds_pll_cntl; - save->tmds_pll_cntl = orig->tmds_pll_cntl; - save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - - save->lvds_gen_cntl |= ( RADEON_LVDS_DISPLAY_DIS | (1 << 23)); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + save->fp_crtc_h_total_disp = orig->fp_crtc_h_total_disp; + save->fp_crtc_v_total_disp = orig->fp_crtc_v_total_disp; + save->fp_gen_cntl = 0; + save->fp_h_sync_strt_wid = orig->fp_h_sync_strt_wid; + save->fp_horz_stretch = 0; + save->fp_v_sync_strt_wid = orig->fp_v_sync_strt_wid; + save->fp_vert_stretch = 0; + save->lvds_gen_cntl = orig->lvds_gen_cntl; + save->lvds_pll_cntl = orig->lvds_pll_cntl; + save->tmds_pll_cntl = orig->tmds_pll_cntl; + save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; + + save->lvds_gen_cntl |= ( RADEON_LVDS_DISPLAY_DIS | (1 << 23)); + save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - return; + return; } if (info->PanelXRes == 0 || info->PanelYRes == 0) { @@ -6407,9 +8049,19 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, RADEON_FP_CRTC_DONT_SHADOW_HEND ); if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; save->lvds_gen_cntl = orig->lvds_gen_cntl; save->lvds_pll_cntl = orig->lvds_pll_cntl; @@ -6424,7 +8076,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->tmds_pll_cntl = orig->tmds_pll_cntl; save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - if (info->PanelOff && info->Clone) { + if (info->PanelOff && info->MergedFB) { info->OverlayOnCRTC2 = TRUE; if (info->DisplayType == MT_LCD) { /* Turning off LVDS_ON seems to make panel white blooming. @@ -6437,15 +8089,6 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else { if (info->DisplayType == MT_LCD) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - /* BIOS will use this setting to reset displays upon lid close/open. - * Here we let BIOS controls LCD, but the driver will control the external CRT. - */ - if (info->Clone || pRADEONEnt->HasSecondary) - save->bios_5_scratch = 0x01020201; - else - save->bios_5_scratch = orig->bios_5_scratch; save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); @@ -6460,9 +8103,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, break; } } - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { if (tmp & 0xfff00000) save->tmds_pll_cntl = tmp; @@ -6470,21 +8111,75 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; } else save->tmds_pll_cntl = tmp; - RADEONTRACE(("TMDS_PLL from %x to %x\n", + RADEONTRACE(("TMDS_PLL from %lx to %lx\n", orig->tmds_pll_cntl, save->tmds_pll_cntl)); - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !info->HasCRTC2) save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); - else /* weird, RV chips got this bit reversed? */ - save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); + else /* weird, RV chips got this bit reversed? */ + save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } + } + } + + info->BiosHotkeys = FALSE; + /* + * Allow the bios to toggle outputs. see below for more. + */ + if (xf86ReturnOptValBool(info->Options, OPTION_BIOS_HOTKEYS, FALSE)) { + info->BiosHotkeys = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS HotKeys Disabled\n"); + } + + if (info->IsMobility && (!info->BiosHotkeys)) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* To work correctly with laptop hotkeys. + * Since there is no machnism for accessing ACPI events + * and the driver currently doesn't know how to validate + * a mode dynamically, we have to tell BIOS don't do + * display switching after X has started. + * If LCD is on, lid close/open should still work + * with below settings + */ + if (info->DisplayType == MT_LCD) { + if (pRADEONEnt->MonType2 == MT_CRT) + save->bios_5_scratch = 0x0201; + else if (pRADEONEnt->MonType2 == MT_DFP) + save->bios_5_scratch = 0x0801; + else + save->bios_5_scratch = orig->bios_5_scratch; + } else { + if (pRADEONEnt->MonType2 == MT_CRT) + save->bios_5_scratch = 0x0200; + else if (pRADEONEnt->MonType2 == MT_DFP) + save->bios_5_scratch = 0x0800; + else + save->bios_5_scratch = 0x0; + } + save->bios_4_scratch = 0x4; + save->bios_6_scratch = orig->bios_6_scratch | 0x40000000; + + } else if (info->IsMobility && (info->DisplayType == MT_LCD)) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* BIOS will use this setting to reset displays upon lid close/open. + * Here we let BIOS controls LCD, but the driver will control the external CRT. + */ + if (info->MergedFB || pRADEONEnt->HasSecondary) + save->bios_5_scratch = 0x01020201; + else + save->bios_5_scratch = orig->bios_5_scratch; + + save->bios_4_scratch = orig->bios_4_scratch; + save->bios_6_scratch = orig->bios_6_scratch; + } save->fp_crtc_h_total_disp = save->crtc_h_total_disp; @@ -6494,11 +8189,11 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, } /* Define PLL registers for requested video mode */ -static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONInfoPtr info, +static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, + RADEONSavePtr save, RADEONPLLPtr pll, double dot_clock) { unsigned long freq = dot_clock * 100; - RADEONPLLPtr pll = &info->pll; struct { int divider; @@ -6520,6 +8215,13 @@ static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONInfoPtr info, { 0, 0 } }; + if (info->UseBiosDividers) { + save->ppll_ref_div = info->RefDivider; + save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl = 0; + return; + } + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; @@ -6541,30 +8243,30 @@ static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONInfoPtr info, pll->reference_freq); save->post_div = post_div->divider; - RADEONTRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", + RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", save->dot_clock_freq, save->pll_output_freq, save->feedback_div, save->post_div)); save->ppll_ref_div = pll->reference_div; - - /* - * on iBooks the LCD pannel needs tweaked PLL timings + /* + * on iBooks the LCD pannel needs tweaked PLL timings */ #ifdef __powerpc__ if (xf86ReturnOptValBool(info->Options, OPTION_IBOOKHACKS, FALSE)) - save->ppll_div_3 = 0x000600ad; + save->ppll_div_3 = 0x000600ad; else #endif - save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); save->htotal_cntl = 0; } /* Define PLL2 registers for requested video mode */ -static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, - double dot_clock) +static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, double dot_clock, + int no_odd_postdiv) { unsigned long freq = dot_clock * 100; @@ -6591,6 +8293,11 @@ static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + /* Odd post divider value don't work properly on the second digital + * output + */ + if (no_odd_postdiv && (post_div->divider & 1)) + continue; save->pll_output_freq_2 = post_div->divider * freq; if (save->pll_output_freq_2 >= pll->min_pll_freq && save->pll_output_freq_2 <= pll->max_pll_freq) break; @@ -6607,7 +8314,7 @@ static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, pll->reference_freq); save->post_div_2 = post_div->divider; - RADEONTRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", + RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", save->dot_clock_freq_2, save->pll_output_freq_2, save->feedback_div_2, @@ -6619,6 +8326,7 @@ static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, save->htotal_cntl2 = 0; } +#if 0 /* Define initial palette for requested video mode. This doesn't do * anything for XFree86 4.0. */ @@ -6626,6 +8334,7 @@ static void RADEONInitPalette(RADEONSavePtr save) { save->palette_valid = FALSE; } +#endif /* Define registers for a requested video mode */ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, @@ -6685,38 +8394,59 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, info->Flags = mode->Flags; + RADEONInitMemMapRegisters(pScrn, save, info); RADEONInitCommonRegisters(save, info); if (info->IsSecondary) { if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) return FALSE; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); + } else if (info->MergedFB) { + if (!RADEONInitCrtcRegisters(pScrn, save, + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT1, info)) + return FALSE; + dot_clock = (((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT1)->Clock / 1000.0; + if (dot_clock) { + RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); + } else { + save->ppll_ref_div = info->SavedReg.ppll_ref_div; + save->ppll_div_3 = info->SavedReg.ppll_div_3; + save->htotal_cntl = info->SavedReg.htotal_cntl; + } + RADEONInitCrtc2Registers(pScrn, save, + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2, info); + dot_clock = (((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2)->Clock / 1000.0; + RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT); } else { if (!RADEONInitCrtcRegisters(pScrn, save, mode, info)) return FALSE; dot_clock = mode->Clock/1000.0; if (dot_clock) { - if (info->UseBiosDividers) { - save->ppll_ref_div = info->RefDivider; - save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - save->htotal_cntl = 0; - } - else - RADEONInitPLLRegisters(save, info, dot_clock); + RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); } else { save->ppll_ref_div = info->SavedReg.ppll_ref_div; save->ppll_div_3 = info->SavedReg.ppll_div_3; save->htotal_cntl = info->SavedReg.htotal_cntl; } - if (info->Clone && info->CurCloneMode) { - RADEONInitCrtc2Registers(pScrn, save, info->CurCloneMode, info); - dot_clock = info->CurCloneMode->Clock / 1000.0; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); - } - if (!info->PaletteSavedOnVT) RADEONInitPalette(save); + /* Not used for now: */ + /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ } - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); + /* make RMX work for mergedfb modes on the LCD */ + if (info->MergedFB) { + if ((info->MergeType == MT_LCD) || (info->MergeType == MT_DFP)) { + /* I suppose crtc2 could drive the FP as well... */ + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2, info); + } + else { + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT1, info); + } + } + else { + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); + } RADEONTRACE(("RADEONInit returns %p\n", save)); return TRUE; @@ -6727,6 +8457,8 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONTRACE(("RADEONModeInit()\n")); + if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE; pScrn->vtSema = TRUE; @@ -6747,6 +8479,8 @@ static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Bool unblank; + RADEONTRACE(("RADEONSaveScreen(%d)\n", mode)); + unblank = xf86IsUnblank(mode); if (unblank) SetTimeSinceLastInputEvent(); @@ -6757,10 +8491,31 @@ static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode) return TRUE; } +static void +RADEONResetDPI(ScrnInfoPtr pScrn, Bool force) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + + if(force || + (info->RADEONDPIVX != pScrn->virtualX) || + (info->RADEONDPIVY != pScrn->virtualY) + ) { + + pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10); + pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10); + + info->RADEONDPIVX = pScrn->virtualX; + info->RADEONDPIVY = pScrn->virtualY; + + } +} + Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + Bool tilingOld = info->tilingEnabled; Bool ret; #ifdef XF86DRI Bool CPStarted = info->CPStarted; @@ -6771,71 +8526,65 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif - if (info->accelOn) info->accel->Sync(pScrn); + RADEONTRACE(("RADEONSwitchMode() !n")); + + if (info->allowColorTiling) { + if (info->MergedFB) { + if ((((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT1->Flags & + (V_DBLSCAN | V_INTERLACE)) || + (((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2->Flags & + (V_DBLSCAN | V_INTERLACE))) + info->tilingEnabled = FALSE; + else info->tilingEnabled = TRUE; + } + else { + info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; + } +#ifdef XF86DRI + if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { + RADEONSAREAPrivPtr pSAREAPriv; + drmRadeonSetParam radeonsetparam; + memset(&radeonsetparam, 0, sizeof(drmRadeonSetParam)); + radeonsetparam.param = RADEON_SETPARAM_SWITCH_TILING; + radeonsetparam.value = info->tilingEnabled ? 1 : 0; + if (drmCommandWrite(info->drmFD, DRM_RADEON_SETPARAM, + &radeonsetparam, sizeof(drmRadeonSetParam)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; + } +#endif + } + + if (info->accelOn && info->accel) + (*info->accel->Sync)(pScrn); if (info->FBDev) { RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); ret = fbdevHWSwitchMode(scrnIndex, mode, flags); + pScrn->displayWidth = fbdevHWGetLineLength(pScrn) + / info->CurrentLayout.pixel_bytes; RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); } else { info->IsSwitching = TRUE; - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - - /* Try to match a mode on primary head - * FIXME: This may not be good if both heads don't have - * exactly the same list of mode. - */ - while (1) { - if ((clone_mode->HDisplay == mode->HDisplay) && - (clone_mode->VDisplay == mode->VDisplay) && - (!info->PanelOff)) { - info->CloneFrameX0 = (info->CurCloneMode->HDisplay + - info->CloneFrameX0 - - clone_mode->HDisplay - 1) / 2; - info->CloneFrameY0 = - (info->CurCloneMode->VDisplay + info->CloneFrameY0 - - clone_mode->VDisplay - 1) / 2; - info->CurCloneMode = clone_mode; - break; - } - - if (!clone_mode->next) { - info->CurCloneMode = info->CloneModes; - break; - } - - clone_mode = clone_mode->next; - } - } ret = RADEONModeInit(xf86Screens[scrnIndex], mode); - - if (info->CurCloneMode) { - if (info->CloneFrameX0 + info->CurCloneMode->HDisplay >= - pScrn->virtualX) - info->CloneFrameX0 = - pScrn->virtualX - info->CurCloneMode->HDisplay; - else if (info->CloneFrameX0 < 0) - info->CloneFrameX0 = 0; - - if (info->CloneFrameY0 + info->CurCloneMode->VDisplay >= - pScrn->virtualY) - info->CloneFrameY0 = - pScrn->virtualY - info->CurCloneMode->VDisplay; - else if (info->CloneFrameY0 < 0) - info->CloneFrameY0 = 0; - - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, - TRUE); - } - info->IsSwitching = FALSE; } + if (info->tilingEnabled != tilingOld) { + /* need to redraw front buffer, I guess this can be considered a hack ? */ + xf86EnableDisableFBAccess(scrnIndex, FALSE); + RADEONChangeSurfaces(pScrn); + xf86EnableDisableFBAccess(scrnIndex, TRUE); + /* xf86SetRootClip would do, but can't access that here */ + } + if (info->accelOn) { - info->accel->Sync(pScrn); + if (info->accel) + (*info->accel->Sync)(pScrn); RADEONEngineRestore(pScrn); } @@ -6846,12 +8595,22 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif + /* Since RandR (indirectly) uses SwitchMode(), we need to + * update our Xinerama info here, too, in case of resizing + */ + if (info->MergedFB) { + RADEONMergedFBResetDpi(pScrn, FALSE); + RADEONUpdateXineramaScreenInfo(pScrn); + } else if(info->constantDPI) { + RADEONResetDPI(pScrn, FALSE); + } + return ret; } #ifdef X_XF86MiscPassMessage Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, - const char* msgval, char** retmsg) + const char* msgval, char** retmsg) { ErrorF("RADEONHandleMessage(%d, \"%s\", \"%s\", retmsg)\n", scrnIndex, msgtype, msgval); @@ -6862,7 +8621,7 @@ Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, /* Used to disallow modes that are not supported by the hardware */ ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, - Bool verbose, int flag) + Bool verbose, int flag) { /* There are problems with double scan mode at high clocks * They're likely related PLL and display buffer settings. @@ -6882,35 +8641,101 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int reg, Base = y * info->CurrentLayout.displayWidth + x; + int reg, Base, regcntl, crtcoffsetcntl, xytilereg, crtcxytile = 0; #ifdef XF86DRI RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; #endif - switch (info->CurrentLayout.pixel_code) { - case 15: - case 16: Base *= 2; break; - case 24: Base *= 3; break; - case 32: Base *= 4; break; +#if 0 /* Verbose */ + RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone)); +#endif + + if (info->showCache && y) { + int lastline = info->FbMapSize / + ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); + + lastline -= pScrn->currentMode->VDisplay; + y += (pScrn->virtualY - 1) * (y / 3 + 1); + if (y > lastline) y = lastline; } - Base &= ~7; /* 3 lower bits are always 0 */ + Base = pScrn->fbOffset; + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ if (clone || info->IsSecondary) { - Base += pScrn->fbOffset; reg = RADEON_CRTC2_OFFSET; + regcntl = RADEON_CRTC2_OFFSET_CNTL; + xytilereg = R300_CRTC2_TILE_X0_Y0; } else { reg = RADEON_CRTC_OFFSET; + regcntl = RADEON_CRTC_OFFSET_CNTL; + xytilereg = R300_CRTC_TILE_X0_Y0; } - + crtcoffsetcntl = INREG(regcntl) & ~0xf; +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (!info->have3DWindows) +#endif + crtcoffsetcntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + if (info->tilingEnabled) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + crtcxytile = x | (y << 16); + Base &= ~0x7ff; + } else { + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + crtcoffsetcntl = crtcoffsetcntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } - pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + Base &= ~7; /* 3 lower bits are always 0 */ + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); if (clone || info->IsSecondary) { pSAREAPriv->crtc2_base = Base; } + else { + pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) + % info->CurrentLayout.displayWidth; + pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) + / info->CurrentLayout.displayWidth; + pSAREA->frame.width = pScrn->frameX1 - x + 1; + pSAREA->frame.height = pScrn->frameY1 - y + 1; + } if (pSAREAPriv->pfCurrentPage == 1) { Base += info->backOffset; @@ -6919,6 +8744,13 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) #endif OUTREG(reg, Base); + + if (IS_R300_VARIANT) { + OUTREG(xytilereg, crtcxytile); + } else { + OUTREG(regcntl, crtcoffsetcntl); + } + } void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) @@ -6927,19 +8759,22 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) RADEONInfoPtr info = RADEONPTR(pScrn); #ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); + if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn && info->accel) + (*info->accel->Sync)(pScrn); - if (info->FBDev) { + if(info->MergedFB) { + RADEONAdjustFrameMerged(scrnIndex, x, y, flags); + } else if (info->FBDev) { fbdevHWAdjustFrame(scrnIndex, x, y, flags); } else { RADEONDoAdjustFrame(pScrn, x, y, FALSE); } #ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); + if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif } @@ -6950,13 +8785,26 @@ Bool RADEONEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; RADEONTRACE(("RADEONEnterVT\n")); - RADEONSave(pScrn); + if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */ + xf86Int10InfoPtr pInt; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n"); + pInt = xf86InitInt10(info->pEnt->index); + if (pInt) { + pInt->num = 0xe6; + xf86ExecX86int10(pInt); + xf86FreeInt10(pInt); + } + } + + /* Makes sure the engine is idle before doing anything */ + RADEONWaitForIdleMMIO(pScrn); if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; info->PaletteSavedOnVT = FALSE; info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); @@ -6965,10 +8813,19 @@ Bool RADEONEnterVT(int scrnIndex, int flags) } else if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (!info->IsSecondary) + RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { - /* get the Radeon back into shape after resume */ + if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) + { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->FB + info->pciGartOffset, info->pciGartBackup, info->pciGartSize); + } + + /* get the DRI back into shape after resume */ RADEONDRIResume(pScrn->pScreen); + RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); } #endif /* this will get XVideo going again, but only if XVideo was initialised @@ -6987,9 +8844,6 @@ Bool RADEONEnterVT(int scrnIndex, int flags) #endif pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - if (info->CurCloneMode) { - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); - } return TRUE; } @@ -7005,9 +8859,15 @@ void RADEONLeaveVT(int scrnIndex, int flags) RADEONTRACE(("RADEONLeaveVT\n")); #ifdef XF86DRI - if (RADEONPTR(pScrn)->directRenderingEnabled) { + if (RADEONPTR(pScrn)->directRenderingInited) { DRILock(pScrn->pScreen, 0); RADEONCP_STOP(pScrn, info); + + if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) + { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); + } } #endif @@ -7021,6 +8881,8 @@ void RADEONLeaveVT(int scrnIndex, int flags) } RADEONRestore(pScrn); + + RADEONTRACE(("Ok, leaving now...\n")); } /* Called at the end of each server generation. Restore the original @@ -7034,30 +8896,38 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) RADEONTRACE(("RADEONCloseScreen\n")); + /* Mark acceleration as stopped or we might try to access the engine at + * wrong times, especially if we had DRI, after DRI has been stopped + */ + info->accelOn = FALSE; + #ifdef XF86DRI - /* Disable direct rendering */ - if (info->directRenderingEnabled) { - RADEONDRICloseScreen(pScreen); - info->directRenderingEnabled = FALSE; - } + RADEONDRIStop(pScreen); #endif if (pScrn->vtSema) { + RADEONDisplayPowerManagementSet(pScrn, DPMSModeOn, 0); RADEONRestore(pScrn); } - RADEONUnmapMem(pScrn); - if (info->accel) XAADestroyInfoRec(info->accel); + RADEONTRACE(("Disposing accel...\n")); + if (info->accel) + XAADestroyInfoRec(info->accel); info->accel = NULL; - if (info->scratch_save) xfree(info->scratch_save); + if (info->scratch_save) + xfree(info->scratch_save); info->scratch_save = NULL; + RADEONTRACE(("Disposing cusor info\n")); if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); info->cursor = NULL; + RADEONTRACE(("Disposing DGA\n")); if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; + RADEONTRACE(("Unmapping memory\n")); + RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; @@ -7071,10 +8941,48 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) void RADEONFreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONFreeScreen\n")); - if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + /* when server quits at PreInit, we don't need do this anymore*/ + if (!info) return; + + if(info->MergedFB) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + } + + if (info->UseVGAHW) vgaHWFreeHWRec(pScrn); RADEONFreeRec(pScrn); } @@ -7084,12 +8992,12 @@ void RADEONFreeScreen(int scrnIndex, int flags) * * Note for current DAC mapping when calling this function: * For most of cards: - * single CRT: Driver doesn't change the existing CRTC->DAC mapping, + * single CRT: Driver doesn't change the existing CRTC->DAC mapping, * CRTC1 could be driving either DAC or both DACs. * CRT+CRT: CRTC1->TV DAC, CRTC2->Primary DAC * DFP/LCD+CRT: CRTC2->TV DAC, CRTC2->Primary DAC. * Some boards have two DACs reversed or don't even have a primary DAC, - * this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't + * this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't * have a second DAC. * It's kind of messy, we'll need to redo DAC mapping part some day. */ @@ -7102,7 +9010,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) CARD32 dac_cntl; CARD32 dac_macro_cntl = 0; dac_cntl = INREG(RADEON_DAC_CNTL); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); if (IsOn) { dac_cntl &= ~RADEON_DAC_PDWN; @@ -7116,7 +9024,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) RADEON_DAC_PDWN_B); } OUTREG(RADEON_DAC_CNTL, dac_cntl); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) + if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } else { if (info->ChipFamily != CHIP_FAMILY_R200) { @@ -7136,9 +9044,9 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) } else { CARD32 fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); if (IsOn) { - fp2_gen_cntl |= RADEON_FP2_DV0_EN; + fp2_gen_cntl |= RADEON_FP2_DVO_EN; } else { - fp2_gen_cntl &= ~RADEON_FP2_DV0_EN; + fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; } OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); } @@ -7154,11 +9062,16 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; + if (!pScrn->vtSema) return; + + RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); + #ifdef XF86DRI if (info->CPStarted) DRILock(pScrn->pScreen, 0); #endif - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn && info->accel) + (*info->accel->Sync)(pScrn); if (info->FBDev) { fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); @@ -7176,7 +9089,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); } @@ -7186,15 +9099,15 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, /* Screen: Off; HSync: Off, VSync: On */ if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask1); } break; @@ -7203,15 +9116,15 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, /* Screen: Off; HSync: On, VSync: Off */ if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, + (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS, + (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask1); } break; @@ -7221,7 +9134,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); } @@ -7231,36 +9144,32 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (PowerManagementMode == DPMSModeOn) { if (info->IsSecondary) { if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DV0_EN, ~RADEON_FP2_DV0_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); } } else if (info->DisplayType == MT_CRT) { RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); } } else { - if (info->Clone) { - if (info->CloneType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DV0_EN, ~RADEON_FP2_DV0_EN); - } - } else if (info->CloneType == MT_CRT) { - RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC); + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN); } } if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), - ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + OUTREGP(RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), + ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); } else if (info->DisplayType == MT_LCD) { - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); + OUTREGP(RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); usleep (info->PanelPwrDly * 1000); - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); + OUTREGP(RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->Clone) { + if ((pRADEONEnt->HasSecondary) || info->MergedFB) { RADEONDacPowerSet(pScrn, TRUE, pRADEONEnt->ReversedDAC); } else { RADEONDacPowerSet(pScrn, TRUE, TRUE); @@ -7274,28 +9183,24 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, (PowerManagementMode == DPMSModeStandby)) { if (info->IsSecondary) { if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DV0_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); } } else if (info->DisplayType == MT_CRT) { RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); } } else { - if (info->Clone) { - if(info->CloneType == MT_DFP) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DV0_EN); - } - } else if (info->CloneType == MT_CRT) { - RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC); + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { + OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); } } if (info->DisplayType == MT_DFP) { - OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + OUTREGP(RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); } else if (info->DisplayType == MT_LCD) { unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); @@ -7306,17 +9211,17 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); } - OUTREGP (RADEON_LVDS_GEN_CNTL, 0, - ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); + OUTREGP(RADEON_LVDS_GEN_CNTL, 0, + ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); if (info->IsMobility || info->IsIGP) { - OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); } } else if (info->DisplayType == MT_CRT) { - if ((pRADEONEnt->HasSecondary) || info->Clone) { + if ((pRADEONEnt->HasSecondary) || info->MergedFB) { RADEONDacPowerSet(pScrn, FALSE, pRADEONEnt->ReversedDAC); } else { - /* single CRT, turning both DACs off, we don't really know + /* single CRT, turning both DACs off, we don't really know * which DAC is actually connected. */ RADEONDacPowerSet(pScrn, FALSE, TRUE); @@ -7332,3 +9237,585 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->CPStarted) DRIUnlock(pScrn->pScreen); #endif } + +static void +RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + char *strptr; + char *default_hsync = "28-33"; + char *default_vrefresh = "43-72"; + Bool val; + Bool default_range = FALSE; + static const char *mybadparm = "\"%s\" is is not a valid parameter for option \"%s\"\n"; + + if (info->FBDev == TRUE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MergedFB does not work with Option UseFBDev, MergedFB mode is disabled\n"); + info->MergedFB = FALSE; + return; + } + + /* collect MergedFB options */ + info->MergedFB = TRUE; + info->UseRADEONXinerama = TRUE; + info->CRT2IsScrn0 = FALSE; + info->CRT2Position = radeonClone; + info->MergedFBXDPI = info->MergedFBYDPI = 0; + info->CRT1XOffs = info->CRT1YOffs = info->CRT2XOffs = info->CRT2YOffs = 0; + info->NonRect = info->HaveNonRect = info->HaveOffsRegions = FALSE; + info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; + info->MouseRestrictions = TRUE; + + if (info->MergeType == MT_NONE) { + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to detect secondary monitor, MergedFB/Clone mode disabled\n"); + } else if (!pRADEONEnt->MonInfo2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to detect secondary monitor DDC, default HSync and VRefresh used\n"); + default_range = TRUE; + } + + if (xf86GetOptValBool(info->Options, OPTION_MERGEDFB, &val)) { + if (val) { + info->MergedFB = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MergedFB mode forced on.\n"); + } else { + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MergedFB mode forced off.\n"); + } + } + + /* Do some MergedFB mode initialisation */ + if(info->MergedFB) { + info->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); + if(!info->CRT2pScrn) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for merged pScrn, MergedFB mode is disabled\n"); + info->MergedFB = FALSE; + } else { + memcpy(info->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); + } + } + if(info->MergedFB) { + int result, ival; + Bool valid = FALSE; + char *tempstr; + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); + if (strptr) { + tempstr = xalloc(strlen(strptr) + 1); + result = sscanf(strptr, "%s %d", tempstr, &ival); + } else { /* Not specified - default is "Clone" */ + tempstr = NULL; + result = 0; + info->CRT2Position = radeonClone; + valid = TRUE; + } + if(result >= 1) { + if(!xf86NameCmp(tempstr,"LeftOf")) { + info->CRT2Position = radeonLeftOf; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1YOffs = -ival; + else info->CRT2YOffs = ival; + } + info->CRT2IsScrn0 = TRUE; + } else if(!xf86NameCmp(tempstr,"RightOf")) { + info->CRT2Position = radeonRightOf; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1YOffs = -ival; + else info->CRT2YOffs = ival; + } + info->CRT2IsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Above")) { + info->CRT2Position = radeonAbove; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1XOffs = -ival; + else info->CRT2XOffs = ival; + } + info->CRT2IsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Below")) { + info->CRT2Position = radeonBelow; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1XOffs = -ival; + else info->CRT2XOffs = ival; + } + info->CRT2IsScrn0 = TRUE; + } else if(!xf86NameCmp(tempstr,"Clone")) { + info->CRT2Position = radeonClone; + if(result == 1) valid = TRUE; + /*info->CRT2IsScrn0 = TRUE;*/ + } + } + if(!valid) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"CRT2Position\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"RightOf\", \"LeftOf\", \"Above\", \"Below\", or \"Clone\"\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Except for \"Clone\", the parameter may be followed by an integer.\n"); + } + xfree(tempstr); + + strptr = (char *)xf86GetOptValString(info->Options, OPTION_METAMODES); + if(strptr) { + info->MetaModes = xalloc(strlen(strptr) + 1); + if(info->MetaModes) memcpy(info->MetaModes, strptr, strlen(strptr) + 1); + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2HSYNC); + if(strptr) { + info->CRT2HSync = xalloc(strlen(strptr) + 1); + if(info->CRT2HSync) memcpy(info->CRT2HSync, strptr, strlen(strptr) + 1); + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2VREFRESH); + if(strptr) { + info->CRT2VRefresh = xalloc(strlen(strptr) + 1); + if(info->CRT2VRefresh) memcpy(info->CRT2VRefresh, strptr, strlen(strptr) + 1); + } + + if(xf86GetOptValBool(info->Options, OPTION_RADEONXINERAMA, &val)) { + if (!val) + info->UseRADEONXinerama = FALSE; + } + if(info->UseRADEONXinerama) { + if(xf86GetOptValBool(info->Options, OPTION_CRT2ISSCRN0, &val)) { + if(val) info->CRT2IsScrn0 = TRUE; + else info->CRT2IsScrn0 = FALSE; + } + if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBNONRECT, &val)) { + info->NonRect = val ? TRUE : FALSE; + } + if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBMOUSER, &val)) { + info->MouseRestrictions = val ? TRUE : FALSE; + } + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_MERGEDDPI); + if(strptr) { + int val1 = 0, val2 = 0; + sscanf(strptr, "%d %d", &val1, &val2); + if(val1 && val2) { + info->MergedFBXDPI = val1; + info->MergedFBYDPI = val2; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, mybadparm, strptr, "MergedDPI"); + } + } + } + + if(info->MergedFB) { + /* fill in monitor */ + info->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); + if(info->CRT2pScrn->monitor) { + DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; + memcpy(info->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); + info->CRT2pScrn->monitor->DDC = NULL; + info->CRT2pScrn->monitor->Modes = NULL; + info->CRT2pScrn->monitor->id = "CRT2 Monitor"; + tempm = pScrn->monitor->Modes; + while(tempm) { + if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; + memcpy(newm, tempm, sizeof(DisplayModeRec)); + if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { + xfree(newm); + break; + } + strcpy(newm->name, tempm->name); + if(!info->CRT2pScrn->monitor->Modes) + info->CRT2pScrn->monitor->Modes = newm; + if(currentm) { + currentm->next = newm; + newm->prev = currentm; + } + currentm = newm; + tempm = tempm->next; + } + + /* xf86SetDDCproperties(info->CRT2pScrn, pRADEONEnt->MonInfo2); */ + info->CRT2pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + if (default_range) { + RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, default_hsync, MAX_HSYNC); + RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, default_vrefresh, MAX_VREFRESH); + } + if(info->CRT2HSync) { + info->CRT2pScrn->monitor->nHsync = + RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, info->CRT2HSync, MAX_HSYNC); + } + if(info->CRT2VRefresh) { + info->CRT2pScrn->monitor->nVrefresh = + RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, info->CRT2VRefresh, MAX_VREFRESH); + } + + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for CRT2 monitor, MergedFB mode disabled.\n"); + if(info->CRT2pScrn) xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + info->MergedFB = FALSE; + } + } +} + +static void RADEONForceSomeClocks(ScrnInfoPtr pScrn) +{ + /* It appears from r300 and rv100 may need some clocks forced-on */ + CARD32 tmp; + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); +} + +static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + switch(mode) { + case 0: /* Turn everything OFF (ForceON to everything)*/ + if ( !info->HasCRTC2 ) { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_RB); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + } else if (info->ChipFamily == CHIP_FAMILY_RV350) { + /* for RV350/M10, no delays are required. */ + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp |= (R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + } else { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); + tmp |= RADEON_SCLK_FORCE_SE; + + if ( !info->HasCRTC2 ) { + tmp |= ( RADEON_SCLK_FORCE_RB | + RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_HDP ); + } else if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + tmp |= ( RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP); + } + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + usleep(16000); + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp |= ( R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + usleep(16000); + } + + if (info->IsIGP) { + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp &= ~(RADEON_FORCEON_MCLKA | + RADEON_FORCEON_YCLKA); + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + usleep(16000); + } + + if ((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + usleep(16000); + } + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + usleep(16000); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Disabled\n"); + break; + case 1: + if (!info->HasCRTC2) { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + if ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) > + RADEON_CFG_ATI_REV_A13) { + tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB); + } + tmp &= ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_TDM); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + } else if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + if (info->ChipFamily == CHIP_FAMILY_RV350) { + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | + R300_SCLK_GA_MAX_DYN_STOP_LAT | + R300_SCLK_CBA_MAX_DYN_STOP_LAT); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + tmp |= RADEON_DYN_STOP_LAT_MASK; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_MISC); + tmp |= (RADEON_MC_MCLK_DYN_ENABLE | + RADEON_IO_MCLK_DYN_ENABLE); + OUTPLL(pScrn, RADEON_MCLK_MISC, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB); + + tmp &= ~(RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + + /* Some releases of vbios have set DISABLE_MC_MCLKA + and DISABLE_MC_MCLKB bits in the vbios table. Setting these + bits will cause H/W hang when reading video memory with dynamic clocking + enabled. */ + if ((tmp & R300_DISABLE_MC_MCLKA) && + (tmp & R300_DISABLE_MC_MCLKB)) { + /* If both bits are set, then check the active channels */ + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + if (info->RamWidth == 64) { + if (INREG(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY) + tmp &= ~R300_DISABLE_MC_MCLKB; + else + tmp &= ~R300_DISABLE_MC_MCLKA; + } else { + tmp &= ~(R300_DISABLE_MC_MCLKA | + R300_DISABLE_MC_MCLKB); + } + } + + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + } else { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp &= ~(R300_SCLK_FORCE_VAP); + tmp |= RADEON_SCLK_FORCE_CP; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + } + } else { + tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); + + tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | + RADEON_DISP_DYN_STOP_LAT_MASK | + RADEON_DYN_STOP_MODE_MASK); + + tmp |= (RADEON_ENGIN_DYNCLK_MODE | + (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); + OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL); + tmp |= RADEON_SCLK_DYN_START_CNTL; + OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp); + usleep(15000); + + /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 + to lockup randomly, leave them as set by BIOS. + */ + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/ + tmp &= ~RADEON_SCLK_FORCEON_MASK; + + /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ + if (((info->ChipFamily == CHIP_FAMILY_RV250) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) || + ((info->ChipFamily == CHIP_FAMILY_RV100) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <= + RADEON_CFG_ATI_REV_A13))){ + tmp |= RADEON_SCLK_FORCE_CP; + tmp |= RADEON_SCLK_FORCE_VIP; + } + + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + if ((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + + /* RV200::A11 A12 RV250::A11 A12 */ + if (((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250)) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp |= RADEON_SCLK_MORE_FORCEON; + } + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + usleep(15000); + } + + /* RV200::A11 A12, RV250::A11 A12 */ + if (((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250)) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp = INPLL(pScrn, RADEON_PLL_PWRMGT_CNTL); + tmp |= RADEON_TCL_BYPASS_DISABLE; + OUTPLL(pScrn, RADEON_PLL_PWRMGT_CNTL, tmp); + } + usleep(15000); + + /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/ + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + usleep(15000); + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Enabled\n"); + break; + default: + break; + } +} diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h index 0da1cb243..63535501b 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h,v 1.3tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h,v 1.4tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -55,6 +55,14 @@ #endif #include "compiler.h" +#define RADEON_BIOS8(v) (info->VBIOS[v]) +#define RADEON_BIOS16(v) (info->VBIOS[v] | \ + (info->VBIOS[(v) + 1] << 8)) +#define RADEON_BIOS32(v) (info->VBIOS[v] | \ + (info->VBIOS[(v) + 1] << 8) | \ + (info->VBIOS[(v) + 2] << 16) | \ + (info->VBIOS[(v) + 3] << 24)) + /* Memory mapped register access macros */ #define INREG8(addr) MMIO_IN8(RADEONMMIO, addr) #define INREG16(addr) MMIO_IN16(RADEONMMIO, addr) @@ -70,25 +78,20 @@ do { \ CARD32 tmp = INREG(addr); \ tmp &= (mask); \ - tmp |= (val); \ + tmp |= ((val) & ~(mask)); \ OUTREG(addr, tmp); \ } while (0) #define INPLL(pScrn, addr) RADEONINPLL(pScrn, addr) -#define OUTPLL(addr, val) \ -do { \ - OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \ - RADEON_PLL_WR_EN)); \ - OUTREG(RADEON_CLOCK_CNTL_DATA, val); \ -} while (0) +#define OUTPLL(pScrn, addr, val) RADEONOUTPLL(pScrn, addr, val) #define OUTPLLP(pScrn, addr, val, mask) \ do { \ CARD32 tmp_ = INPLL(pScrn, addr); \ tmp_ &= (mask); \ - tmp_ |= (val); \ - OUTPLL(addr, tmp_); \ + tmp_ |= ((val) & ~(mask)); \ + OUTPLL(pScrn, addr, tmp_); \ } while (0) #define OUTPAL_START(idx) \ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c new file mode 100644 index 000000000..55b7655f3 --- /dev/null +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c @@ -0,0 +1,2088 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c,v 1.0tsi Exp $ */ +/* + * Copyright 2003 Alex Deucher. + * + * 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, 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ALEX DEUCHER, OR ANY OTHER + * CONTRIBUTORS 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: + * Alex Deucher <agd5f@yahoo.com> + * Based, in large part, on the sis driver by Thomas Winischhofer. + */ + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Resources.h" +#include "xf86_OSproc.h" +#include "extnsionst.h" /* required */ +#include <X11/extensions/panoramiXproto.h> /* required */ +#include "dixstruct.h" +#include "vbe.h" + + +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_mergedfb.h" + +/* pseudo xinerama support */ +static unsigned char RADEONXineramaReqCode = 0; +int RADEONXineramaPixWidth = 0; +int RADEONXineramaPixHeight = 0; +int RADEONXineramaNumScreens = 0; +RADEONXineramaData *RADEONXineramadataPtr = NULL; +static unsigned long RADEONXineramaGeneration; +Bool RADEONnoPanoramiXExtension = TRUE; + +int RADEONProcXineramaQueryVersion(ClientPtr client); +int RADEONProcXineramaGetState(ClientPtr client); +int RADEONProcXineramaGetScreenCount(ClientPtr client); +int RADEONProcXineramaGetScreenSize(ClientPtr client); +int RADEONProcXineramaIsActive(ClientPtr client); +int RADEONProcXineramaQueryScreens(ClientPtr client); +int RADEONSProcXineramaDispatch(ClientPtr client); + +static void +RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y); + +/* mergedfb functions */ +/* Helper function for CRT2 monitor vrefresh/hsync options + * (Taken from mga, sis drivers) + */ +int +RADEONStrToRanges(range *r, char *s, int max) +{ + float num = 0.0; + int rangenum = 0; + Bool gotdash = FALSE; + Bool nextdash = FALSE; + char* strnum = NULL; + do { + switch(*s) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + if(strnum == NULL) { + strnum = s; + gotdash = nextdash; + nextdash = FALSE; + } + break; + case '-': + case ' ': + case 0: + if(strnum == NULL) break; + sscanf(strnum, "%f", &num); + strnum = NULL; + if(gotdash) + r[rangenum - 1].hi = num; + else { + r[rangenum].lo = num; + r[rangenum].hi = num; + rangenum++; + } + if(*s == '-') nextdash = (rangenum != 0); + else if(rangenum >= max) return rangenum; + break; + default : + return 0; + } + } while(*(s++) != 0); + + return rangenum; +} + +/* Copy and link two modes (i, j) for merged-fb mode + * (Taken from mga, sis drivers) + * Copys mode i, merges j to copy of i, links the result to dest, and returns it. + * Links i and j in Private record. + * If dest is NULL, return value is copy of i linked to itself. + * For mergedfb auto-config, we only check the dimension + * against virtualX/Y, if they were user-provided. + */ +static DisplayModePtr +RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + DisplayModePtr mode; + int dx = 0,dy = 0; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; + memcpy(mode, i, sizeof(DisplayModeRec)); + if(!((mode->Private = xalloc(sizeof(RADEONMergedDisplayModeRec))))) { + xfree(mode); + return dest; + } + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT1 = i; + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2 = j; + ((RADEONMergedDisplayModePtr)(pointer)mode->Private)->CRT2Position = srel; + mode->PrivSize = 0; + + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + if(!(pScrn->display->virtualX)) { + dx = i->HDisplay + j->HDisplay; + } else { + dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); + } + dx -= mode->HDisplay; + if(!(pScrn->display->virtualY)) { + dy = max(i->VDisplay, j->VDisplay); + } else { + dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); + } + dy -= mode->VDisplay; + break; + case radeonAbove: + case radeonBelow: + if(!(pScrn->display->virtualY)) { + dy = i->VDisplay + j->VDisplay; + } else { + dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); + } + dy -= mode->VDisplay; + if(!(pScrn->display->virtualX)) { + dx = max(i->HDisplay, j->HDisplay); + } else { + dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); + } + dx -= mode->HDisplay; + break; + case radeonClone: + if(!(pScrn->display->virtualX)) { + dx = max(i->HDisplay, j->HDisplay); + } else { + dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); + } + dx -= mode->HDisplay; + if(!(pScrn->display->virtualY)) { + dy = max(i->VDisplay, j->VDisplay); + } else { + dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); + } + dy -= mode->VDisplay; + break; + } + mode->HDisplay += dx; + mode->HSyncStart += dx; + mode->HSyncEnd += dx; + mode->HTotal += dx; + mode->VDisplay += dy; + mode->VSyncStart += dy; + mode->VSyncEnd += dy; + mode->VTotal += dy; + + /* This is needed for not generating negative refesh rates in xrandr with the + faked DotClock below + */ + if (!(mode->VRefresh)) + mode->VRefresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; + + /* Provide a sophisticated fake DotClock in order to trick the vidmode + * extension to allow selecting among a number of modes whose merged result + * looks identical but consists of different modes for CRT1 and CRT2 + */ + mode->Clock = (((i->Clock >> 3) + i->HTotal) << 16) | ((j->Clock >> 2) + j->HTotal); + mode->Clock ^= ((i->VTotal << 19) | (j->VTotal << 3)); + + if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > + (pScrn->videoRam * 1024)) || + (mode->HDisplay > 8191) || + (mode->VDisplay > 8191) ) { + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", + mode->name, mode->HDisplay, mode->VDisplay); + xfree(mode->Private); + xfree(mode); + + return dest; + } + + if(srel != radeonClone) { + info->AtLeastOneNonClone = TRUE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d%s\n", + i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, + mode->HDisplay, mode->VDisplay, (srel == radeonClone) ? " (Clone)" : ""); + + mode->next = mode; + mode->prev = mode; + + if(dest) { + mode->next = dest->next; /* Insert node after "dest" */ + dest->next->prev = mode; + mode->prev = dest; + dest->next = mode; + } + + return mode; +} + +/* Helper function to find a mode from a given name + * (Taken from mga, sis drivers) + */ +static DisplayModePtr +RADEONGetModeFromName(char* str, DisplayModePtr i) +{ + DisplayModePtr c = i; + if(!i) return NULL; + do { + if(strcmp(str, c->name) == 0) return c; + c = c->next; + } while(c != i); + return NULL; +} + +static DisplayModePtr +RADEONFindWidestTallestMode(DisplayModePtr i, Bool tallest) +{ + DisplayModePtr c = i, d = NULL; + int max = 0; + if(!i) return NULL; + do { + if(tallest) { + if(c->VDisplay > max) { + max = c->VDisplay; + d = c; + } + } else { + if(c->HDisplay > max) { + max = c->HDisplay; + d = c; + } + } + c = c->next; + } while(c != i); + return d; +} + +static void +RADEONFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, + DisplayModePtr *a, DisplayModePtr *b) +{ + DisplayModePtr c = i, d; + int max = 0; + Bool foundone; + + (*a) = (*b) = NULL; + + if(!i || !j) return; + + do { + d = j; + foundone = FALSE; + do { + if( (c->HDisplay == d->HDisplay) && + (c->VDisplay == d->VDisplay) ) { + foundone = TRUE; + break; + } + d = d->next; + } while(d != j); + if(foundone) { + if(tallest) { + if(c->VDisplay > max) { + max = c->VDisplay; + (*a) = c; + (*b) = d; + } + } else { + if(c->HDisplay > max) { + max = c->HDisplay; + (*a) = c; + (*b) = d; + } + } + } + c = c->next; + } while(c != i); +} + +static DisplayModePtr +RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + + RADEONInfoPtr info = RADEONPTR(pScrn); + DisplayModePtr mode1 = NULL; + DisplayModePtr mode2 = NULL; + DisplayModePtr mode3 = NULL; + DisplayModePtr mode4 = NULL; + DisplayModePtr result = NULL; + + info->AtLeastOneNonClone = FALSE; + + /* Now build a default list of MetaModes. + * - Non-clone: If the user enabled NonRectangular, we use the + * largest mode for each CRT1 and CRT2. If not, we use the largest + * common mode for CRT1 and CRT2 (if available). Additionally, and + * regardless if the above, we produce a clone mode consisting of + * the largest common mode (if available) in order to use DGA. + * - Clone: If the (global) CRT2Position is Clone, we use the + * largest common mode if available, otherwise the first two modes + * in each list. + */ + + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + mode1 = RADEONFindWidestTallestMode(i, FALSE); + mode2 = RADEONFindWidestTallestMode(j, FALSE); + RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); + break; + case radeonAbove: + case radeonBelow: + mode1 = RADEONFindWidestTallestMode(i, TRUE); + mode2 = RADEONFindWidestTallestMode(j, TRUE); + RADEONFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); + break; + case radeonClone: + RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); + if(mode3 && mode4) { + mode1 = mode3; + mode2 = mode4; + } else { + mode1 = i; + mode2 = j; + } + } + + if(srel != radeonClone) { + if(mode3 && mode4 && !info->NonRect) { + mode1 = mode3; + mode2 = mode2; + } + } + + if(mode1 && mode2) { + result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel); + } + + if(srel != radeonClone) { + if(mode3 && mode4) { + result = RADEONCopyModeNLink(pScrn, result, mode3, mode4, radeonClone); + } + } + return result; +} + +/* Generate the merged-fb mode modelist + * (Taken from mga, sis drivers) + */ +static DisplayModePtr +RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + char* modestr = str; + char modename[256]; + Bool gotdash = FALSE; + char gotsep = 0; + RADEONScrn2Rel sr; + DisplayModePtr mode1 = NULL; + DisplayModePtr mode2 = NULL; + DisplayModePtr result = NULL; + int myslen; + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->AtLeastOneNonClone = FALSE; + + do { + switch(*str) { + case 0: + case '-': + case '+': + case ' ': + case ',': + case ';': + if(modestr != str) { + + myslen = str - modestr; + if(myslen > 255) myslen = 255; + strncpy(modename, modestr, myslen); + modename[myslen] = 0; + + if(gotdash) { + if(mode1 == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Error parsing MetaModes parameter\n"); + return NULL; + } + mode2 = RADEONGetModeFromName(modename, j); + if(!mode2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for CRT2\n", modename); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); + mode1 = NULL; + gotsep = 0; + } + } else { + mode1 = RADEONGetModeFromName(modename, i); + if(!mode1) { + char* tmps = str; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for CRT1\n", modename); + while(*tmps == ' ' || *tmps == ';') tmps++; + /* skip the next mode */ + if(*tmps == '-' || *tmps == '+' || *tmps == ',') { + tmps++; + /* skip spaces */ + while(*tmps == ' ' || *tmps == ';') tmps++; + /* skip modename */ + while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; + myslen = tmps - modestr; + if(myslen > 255) myslen = 255; + strncpy(modename,modestr,myslen); + modename[myslen] = 0; + str = tmps-1; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s\")\n", modename); + mode1 = NULL; + gotsep = 0; + } + } + gotdash = FALSE; + } + modestr = str + 1; + gotdash |= (*str == '-' || *str == '+' || *str == ','); + if (*str == '-' || *str == '+' || *str == ',') + gotsep = *str; + + if(*str != 0) break; + /* Fall through otherwise */ + + default: + if(!gotdash && mode1) { + sr = srel; + if(gotsep == '+') sr = radeonClone; + if(!mode2) { + mode2 = RADEONGetModeFromName(mode1->name, j); + sr = radeonClone; + } + if(!mode2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\t(Skipping metamode \"%s\")\n", modename); + mode1 = NULL; + } else { + result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr); + mode1 = NULL; + mode2 = NULL; + } + gotsep = 0; + } + break; + + } + + } while(*(str++) != 0); + + return result; +} + +DisplayModePtr +RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if(str != NULL) { + return(RADEONGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); + } else { + if (srel == radeonClone ) { + DisplayModePtr p, q, result = NULL; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Clone mode, list all common modes\n"); + for (p = i; p->next != i; p = p->next) + for (q = j; q->next != j; q = q->next) + if ((p->HDisplay == q->HDisplay) && + (p->VDisplay == q->VDisplay)) + result = RADEONCopyModeNLink(pScrn, result, p, q, srel); + return result; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No MetaModes given, linking %s modes by default\n", + (info->NonRect ? + (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest" : "tallest") + : + (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest common" : "tallest common")) ); + return(RADEONGenerateModeListFromLargestModes(pScrn, i, j, srel)); + } + } +} + +void +RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + DisplayModePtr mode, bmode; + int maxh, maxv; + static const char *str = "MergedFB: Virtual %s %d\n"; + static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; + + mode = bmode = pScrn->modes; + maxh = maxv = 0; + do { + if(mode->HDisplay > maxh) maxh = mode->HDisplay; + if(mode->VDisplay > maxv) maxv = mode->VDisplay; + mode = mode->next; + } while(mode != bmode); + maxh += info->CRT1XOffs + info->CRT2XOffs; + maxv += info->CRT1YOffs + info->CRT2YOffs; + + if(!(pScrn->display->virtualX)) { + if(maxh > 8191) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Virtual width with CRT2Position offset beyond hardware specs\n"); + info->CRT1XOffs = info->CRT2XOffs = 0; + maxh -= (info->CRT1XOffs + info->CRT2XOffs); + } + pScrn->virtualX = maxh; + pScrn->displayWidth = maxh; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); + } else { + if(maxh < pScrn->display->virtualX) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); + info->CRT1XOffs = info->CRT2XOffs = 0; + } + } + + if(!(pScrn->display->virtualY)) { + pScrn->virtualY = maxv; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); + } else { + if(maxv < pScrn->display->virtualY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); + info->CRT1YOffs = info->CRT2YOffs = 0; + } + } +} + +/* Pseudo-Xinerama extension for MergedFB mode */ +void +RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) +{ + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = NULL; + int crt1scrnnum = 0, crt2scrnnum = 1; + /* Upper case to avoid shadow warnings */ + int X1=0, X2=0, Y1=0, Y2=0, H1=0, H2=0, W1=0, W2=0; + int realvirtX, realvirtY; + DisplayModePtr currentMode, firstMode; + Bool infochanged = FALSE; + Bool usenonrect = info->NonRect; + const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; + + info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; + info->HaveNonRect = info->HaveOffsRegions = FALSE; + + if(!info->MergedFB) return; + + if(RADEONnoPanoramiXExtension) return; + + if(!RADEONXineramadataPtr) return; + + if(info->CRT2IsScrn0) { + crt1scrnnum = 1; + crt2scrnnum = 0; + } + + pScrn2 = info->CRT2pScrn; + + /* Attention: Usage of RandR may lead into virtual X and Y values + * actually smaller than our MetaModes! To avoid this, we calculate + * the maxCRT fields here (and not somewhere else, like in CopyNLink) + */ + + /* "Real" virtual: Virtual without the Offset */ + realvirtX = pScrn1->virtualX - info->CRT1XOffs - info->CRT2XOffs; + realvirtY = pScrn1->virtualY - info->CRT1YOffs - info->CRT2YOffs; + + if((info->RADEONXineramaVX != pScrn1->virtualX) || (info->RADEONXineramaVY != pScrn1->virtualY)) { + + if(!(pScrn1->modes)) { + xf86DrvMsg(pScrn1->scrnIndex, X_ERROR, + "Internal error: RADEONUpdateXineramaScreenInfo(): pScrn->modes is NULL\n"); + return; + } + + info->maxCRT1_X1 = info->maxCRT1_X2 = 0; + info->maxCRT1_Y1 = info->maxCRT1_Y2 = 0; + info->maxCRT2_X1 = info->maxCRT2_X2 = 0; + info->maxCRT2_Y1 = info->maxCRT2_Y2 = 0; + info->maxClone_X1 = info->maxClone_X2 = 0; + info->maxClone_Y1 = info->maxClone_Y2 = 0; + + currentMode = firstMode = pScrn1->modes; + + do { + + DisplayModePtr p = currentMode->next; + DisplayModePtr i = ((RADEONMergedDisplayModePtr)(pointer)currentMode->Private)->CRT1; + DisplayModePtr j = ((RADEONMergedDisplayModePtr)(pointer)currentMode->Private)->CRT2; + RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)(pointer)currentMode->Private)->CRT2Position; + + if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && + (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && + (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { + + if(srel != radeonClone) { + if(info->maxCRT1_X1 == i->HDisplay) { + if(info->maxCRT1_X2 < j->HDisplay) { + info->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ + } + } else if(info->maxCRT1_X1 < i->HDisplay) { + info->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ + info->maxCRT1_X2 = j->HDisplay; + } + if(info->maxCRT2_X2 == j->HDisplay) { + if(info->maxCRT2_X1 < i->HDisplay) { + info->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ + } + } else if(info->maxCRT2_X2 < j->HDisplay) { + info->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ + info->maxCRT2_X1 = i->HDisplay; + } + if(info->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ + if(info->maxCRT1_Y2 < j->VDisplay) { + info->maxCRT1_Y2 = j->VDisplay; + } + } else if(info->maxCRT1_Y1 < i->VDisplay) { + info->maxCRT1_Y1 = i->VDisplay; + info->maxCRT1_Y2 = j->VDisplay; + } + if(info->maxCRT2_Y2 == j->VDisplay) { + if(info->maxCRT2_Y1 < i->VDisplay) { + info->maxCRT2_Y1 = i->VDisplay; + } + } else if(info->maxCRT2_Y2 < j->VDisplay) { + info->maxCRT2_Y2 = j->VDisplay; + info->maxCRT2_Y1 = i->VDisplay; + } + } else { + if(info->maxClone_X1 < i->HDisplay) { + info->maxClone_X1 = i->HDisplay; + } + if(info->maxClone_X2 < j->HDisplay) { + info->maxClone_X2 = j->HDisplay; + } + if(info->maxClone_Y1 < i->VDisplay) { + info->maxClone_Y1 = i->VDisplay; + } + if(info->maxClone_Y2 < j->VDisplay) { + info->maxClone_Y2 = j->VDisplay; + } + } + } + currentMode = p; + + } while((currentMode) && (currentMode != firstMode)); + + info->RADEONXineramaVX = pScrn1->virtualX; + info->RADEONXineramaVY = pScrn1->virtualY; + infochanged = TRUE; + + } + + if((usenonrect) && (info->CRT2Position != radeonClone) && info->maxCRT1_X1) { + switch(info->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if((info->maxCRT1_Y1 != realvirtY) && (info->maxCRT2_Y2 != realvirtY)) { + usenonrect = FALSE; + } + break; + case radeonAbove: + case radeonBelow: + if((info->maxCRT1_X1 != realvirtX) && (info->maxCRT2_X2 != realvirtX)) { + usenonrect = FALSE; + } + break; + case radeonClone: + break; + } + + if(infochanged && !usenonrect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Virtual screen size does not match maximum display modes...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + + } + } else if(infochanged && usenonrect) { + usenonrect = FALSE; + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Only clone modes available for this virtual screen size...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + } + + if(info->maxCRT1_X1) { /* Means we have at least one non-clone mode */ + switch(info->CRT2Position) { + case radeonLeftOf: + X1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); + if(X1 < 0) X1 = 0; + Y1 = info->CRT1YOffs; + W1 = pScrn1->virtualX - X1; + H1 = realvirtY; + if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { + H1 = info->MBXNR1YMAX = info->maxCRT1_Y1; + info->NonRectDead.x0 = X1; + info->NonRectDead.x1 = X1 + W1 - 1; + info->NonRectDead.y0 = Y1 + H1; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + X2 = 0; + Y2 = info->CRT2YOffs; + W2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); + if(W2 > pScrn1->virtualX) W2 = pScrn1->virtualX; + H2 = realvirtY; + if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { + H2 = info->MBXNR2YMAX = info->maxCRT2_Y2; + info->NonRectDead.x0 = X2; + info->NonRectDead.x1 = X2 + W2 - 1; + info->NonRectDead.y0 = Y2 + H2; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonRightOf: + X1 = 0; + Y1 = info->CRT1YOffs; + W1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); + if(W1 > pScrn1->virtualX) W1 = pScrn1->virtualX; + H1 = realvirtY; + if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { + H1 = info->MBXNR1YMAX = info->maxCRT1_Y1; + info->NonRectDead.x0 = X1; + info->NonRectDead.x1 = X1 + W1 - 1; + info->NonRectDead.y0 = Y1 + H1; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + X2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); + if(X2 < 0) X2 = 0; + Y2 = info->CRT2YOffs; + W2 = pScrn1->virtualX - X2; + H2 = realvirtY; + if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { + H2 = info->MBXNR2YMAX = info->maxCRT2_Y2; + info->NonRectDead.x0 = X2; + info->NonRectDead.x1 = X2 + W2 - 1; + info->NonRectDead.y0 = Y2 + H2; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonAbove: + X1 = info->CRT1XOffs; + Y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); + if(Y1 < 0) Y1 = 0; + W1 = realvirtX; + H1 = pScrn1->virtualY - Y1; + if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { + W1 = info->MBXNR1XMAX = info->maxCRT1_X1; + info->NonRectDead.x0 = X1 + W1; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = Y1; + info->NonRectDead.y1 = Y1 + H1 - 1; + info->HaveNonRect = TRUE; + } + X2 = info->CRT2XOffs; + Y2 = 0; + W2 = realvirtX; + H2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); + if(H2 > pScrn1->virtualY) H2 = pScrn1->virtualY; + if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { + W2 = info->MBXNR2XMAX = info->maxCRT2_X2; + info->NonRectDead.x0 = X2 + W2; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = Y2; + info->NonRectDead.y1 = Y2 + H2 - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonBelow: + X1 = info->CRT1XOffs; + Y1 = 0; + W1 = realvirtX; + H1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); + if(H1 > pScrn1->virtualY) H1 = pScrn1->virtualY; + if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { + W1 = info->MBXNR1XMAX = info->maxCRT1_X1; + info->NonRectDead.x0 = X1 + W1; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = Y1; + info->NonRectDead.y1 = Y1 + H1 - 1; + info->HaveNonRect = TRUE; + } + X2 = info->CRT2XOffs; + Y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); + if(Y2 < 0) Y2 = 0; + W2 = realvirtX; + H2 = pScrn1->virtualY - Y2; + if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { + W2 = info->MBXNR2XMAX = info->maxCRT2_X2; + info->NonRectDead.x0 = X2 + W2; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = Y2; + info->NonRectDead.y1 = Y2 + H2 - 1; + info->HaveNonRect = TRUE; + } + default: + break; + } + + switch(info->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if(info->CRT1YOffs) { + info->OffDead1.x0 = X1; + info->OffDead1.x1 = X1 + W1 - 1; + info->OffDead1.y0 = 0; + info->OffDead1.y1 = Y1 - 1; + info->OffDead2.x0 = X2; + info->OffDead2.x1 = X2 + W2 - 1; + info->OffDead2.y0 = Y2 + H2; + info->OffDead2.y1 = pScrn1->virtualY - 1; + info->HaveOffsRegions = TRUE; + } else if(info->CRT2YOffs) { + info->OffDead1.x0 = X2; + info->OffDead1.x1 = X2 + W2 - 1; + info->OffDead1.y0 = 0; + info->OffDead1.y1 = Y2 - 1; + info->OffDead2.x0 = X1; + info->OffDead2.x1 = X1 + W1 - 1; + info->OffDead2.y0 = Y1 + H1; + info->OffDead2.y1 = pScrn1->virtualY - 1; + info->HaveOffsRegions = TRUE; + } + break; + case radeonAbove: + case radeonBelow: + if(info->CRT1XOffs) { + info->OffDead1.x0 = X2 + W2; + info->OffDead1.x1 = pScrn1->virtualX - 1; + info->OffDead1.y0 = Y2; + info->OffDead1.y1 = Y2 + H2 - 1; + info->OffDead2.x0 = 0; + info->OffDead2.x1 = X1 - 1; + info->OffDead2.y0 = Y1; + info->OffDead2.y1 = Y1 + H1 - 1; + info->HaveOffsRegions = TRUE; + } else if(info->CRT2XOffs) { + info->OffDead1.x0 = X1 + W1; + info->OffDead1.x1 = pScrn1->virtualX - 1; + info->OffDead1.y0 = Y1; + info->OffDead1.y1 = Y1 + H1 - 1; + info->OffDead2.x0 = 0; + info->OffDead2.x1 = X2 - 1; + info->OffDead2.y0 = Y2; + info->OffDead2.y1 = Y2 + H2 - 1; + info->HaveOffsRegions = TRUE; + } + default: + break; + } + + } else { /* Only clone-modes left */ + + X1 = X2 = 0; + Y1 = Y2 = 0; + W1 = W2 = max(info->maxClone_X1, info->maxClone_X2); + H1 = H2 = max(info->maxClone_Y1, info->maxClone_Y2); + + } + + RADEONXineramadataPtr[crt1scrnnum].x = X1; + RADEONXineramadataPtr[crt1scrnnum].y = Y1; + RADEONXineramadataPtr[crt1scrnnum].width = W1; + RADEONXineramadataPtr[crt1scrnnum].height = H1; + RADEONXineramadataPtr[crt2scrnnum].x = X2; + RADEONXineramadataPtr[crt2scrnnum].y = Y2; + RADEONXineramadataPtr[crt2scrnnum].width = W2; + RADEONXineramadataPtr[crt2scrnnum].height = H2; + + if(infochanged) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", + crt1scrnnum, X1, Y1, W1+X1-1, H1+Y1-1); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", + crt2scrnnum, X2, Y2, W2+X2-1, H2+Y2-1); + if(info->HaveNonRect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", + info->NonRectDead.x0, info->NonRectDead.y0, + info->NonRectDead.x1, info->NonRectDead.y1); + } + if(info->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + info->OffDead1.x0, info->OffDead1.y0, + info->OffDead1.x1, info->OffDead1.y1); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + info->OffDead2.x0, info->OffDead2.y0, + info->OffDead2.x1, info->OffDead2.y1); + } + if(info->HaveNonRect || info->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Mouse restriction for inaccessible areas is %s\n", + info->MouseRestrictions ? "enabled" : "disabled"); + } + } +} +/* Proc */ + +int +RADEONProcXineramaQueryVersion(ClientPtr client) +{ + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = RADEON_XINERAMA_MAJOR_VERSION; + rep.minorVersion = RADEON_XINERAMA_MINOR_VERSION; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +int +RADEONProcXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + pWin = LookupWindow(stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !RADEONnoPanoramiXExtension; + if(client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.state, n); + } + WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); + return client->noClientException; +} + +int +RADEONProcXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + pWin = LookupWindow(stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = RADEONXineramaNumScreens; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.ScreenCount, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); + return client->noClientException; +} + +int +RADEONProcXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + pWin = LookupWindow (stuff->window, client); + if(!pWin) return BadWindow; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.width = RADEONXineramadataPtr[stuff->screen].width; + rep.height = RADEONXineramadataPtr[stuff->screen].height; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + } + WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); + return client->noClientException; +} + +int +RADEONProcXineramaIsActive(ClientPtr client) +{ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !RADEONnoPanoramiXExtension; + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.state, n); + } + WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); + return client->noClientException; +} + +int +RADEONProcXineramaQueryScreens(ClientPtr client) +{ + xXineramaQueryScreensReply rep; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = (RADEONnoPanoramiXExtension) ? 0 : RADEONXineramaNumScreens; + rep.length = rep.number * sz_XineramaScreenInfo >> 2; + if(client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.number, n); + } + WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); + + if(!RADEONnoPanoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < RADEONXineramaNumScreens; i++) { + scratch.x_org = RADEONXineramadataPtr[i].x; + scratch.y_org = RADEONXineramadataPtr[i].y; + scratch.width = RADEONXineramadataPtr[i].width; + scratch.height = RADEONXineramadataPtr[i].height; + if(client->swapped) { + register int n; + swaps(&scratch.x_org, n); + swaps(&scratch.y_org, n); + swaps(&scratch.width, n); + swaps(&scratch.height, n); + } + WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); + } + } + + return client->noClientException; +} + +static int +RADEONProcXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return RADEONProcXineramaQueryVersion(client); + case X_PanoramiXGetState: + return RADEONProcXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return RADEONProcXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return RADEONProcXineramaGetScreenSize(client); + case X_XineramaIsActive: + return RADEONProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return RADEONProcXineramaQueryScreens(client); + } + return BadRequest; +} + +/* SProc */ + +static int +RADEONSProcXineramaQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); + return RADEONProcXineramaQueryVersion(client); +} + +static int +RADEONSProcXineramaGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return RADEONProcXineramaGetState(client); +} + +static int +RADEONSProcXineramaGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return RADEONProcXineramaGetScreenCount(client); +} + +static int +RADEONSProcXineramaGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return RADEONProcXineramaGetScreenSize(client); +} + +static int +RADEONSProcXineramaIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return RADEONProcXineramaIsActive(client); +} + +static int +RADEONSProcXineramaQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return RADEONProcXineramaQueryScreens(client); +} + +int +RADEONSProcXineramaDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_PanoramiXQueryVersion: + return RADEONSProcXineramaQueryVersion(client); + case X_PanoramiXGetState: + return RADEONSProcXineramaGetState(client); + case X_PanoramiXGetScreenCount: + return RADEONSProcXineramaGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return RADEONSProcXineramaGetScreenSize(client); + case X_XineramaIsActive: + return RADEONSProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return RADEONSProcXineramaQueryScreens(client); + } + return BadRequest; +} + +static void +RADEONXineramaResetProc(ExtensionEntry* extEntry) +{ + if(RADEONXineramadataPtr) { + Xfree(RADEONXineramadataPtr); + RADEONXineramadataPtr = NULL; + } +} + +void +RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool success = FALSE; + + if(!(RADEONXineramadataPtr)) { + + if(!info->MergedFB) { + RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; + return; + } + + if(IsXineramaActive()) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Xinerama active, not initializing Radeon Pseudo-Xinerama\n"); + RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; + return; + } + + if(RADEONnoPanoramiXExtension) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Radeon Pseudo-Xinerama disabled\n"); + info->MouseRestrictions = FALSE; + return; + } + + if(info->CRT2Position == radeonClone) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Running MergedFB in Clone mode, Radeon Pseudo-Xinerama disabled\n"); + RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; + return; + } + + if(!(info->AtLeastOneNonClone)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Only Clone modes defined, Radeon Pseudo-Xinerama disabled\n"); + RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; + return; + } + + RADEONXineramaNumScreens = 2; + + while(RADEONXineramaGeneration != serverGeneration) { + + info->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + RADEONProcXineramaDispatch, + RADEONSProcXineramaDispatch, + RADEONXineramaResetProc, + StandardMinorOpcode); + + if(!info->XineramaExtEntry) break; + + RADEONXineramaReqCode = (unsigned char)info->XineramaExtEntry->base; + + if(!(RADEONXineramadataPtr = (RADEONXineramaData *) + xcalloc(RADEONXineramaNumScreens, sizeof(RADEONXineramaData)))) break; + + RADEONXineramaGeneration = serverGeneration; + success = TRUE; + } + + if(!success) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize Radeon Pseudo-Xinerama extension\n"); + RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; + return; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized Radeon Pseudo-Xinerama extension\n"); + + info->RADEONXineramaVX = 0; + info->RADEONXineramaVY = 0; + + } + + RADEONUpdateXineramaScreenInfo(pScrn); + +} +/* End of PseudoXinerama */ + +static Bool +InRegion(int x, int y, region r) +{ + return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); +} + +void +RADEONMergePointerMoved(int scrnIndex, int x, int y) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + region out, in1, in2, f2, f1; + int deltax, deltay; + int temp1, temp2; + int old1x0, old1y0, old2x0, old2y0; + int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + int sigstate; + Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; + RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position; + + if(info->DGAactive) { + return; + /* DGA: There is no cursor and no panning while DGA is active. */ + /* If it were, we would need to do: */ + /* HVirt = info->CurrentLayout.displayWidth; + VVirt = info->CurrentLayout.displayHeight; + BOUND(x, info->CurrentLayout.DGAViewportX, HVirt); + BOUND(y, info->CurrentLayout.DGAViewportY, VVirt); */ + } else { + CRT1XOffs = info->CRT1XOffs; + CRT1YOffs = info->CRT1YOffs; + CRT2XOffs = info->CRT2XOffs; + CRT2YOffs = info->CRT2YOffs; + HaveNonRect = info->HaveNonRect; + HaveOffsRegions = info->HaveOffsRegions; + } + + /* Check if the pointer is inside our dead areas */ + if((info->MouseRestrictions) && (srel != radeonClone) && !RADEONnoPanoramiXExtension) { + if(HaveNonRect) { + if(InRegion(x, y, info->NonRectDead)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->NonRectDead.y0 - 1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->NonRectDead.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(HaveOffsRegions) { + if(InRegion(x, y, info->OffDead1)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->OffDead1.y1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->OffDead1.x1; + doit = TRUE; + default: break; + } + } else if(InRegion(x, y, info->OffDead2)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->OffDead2.y0 - 1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->OffDead2.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(doit) { + UpdateCurrentTime(); + sigstate = xf86BlockSIGIO(); + miPointerAbsoluteCursor(x, y, currentTime.milliseconds); + xf86UnblockSIGIO(sigstate); + return; + } + } + + f1.x0 = old1x0 = info->CRT1frameX0; + f1.x1 = info->CRT1frameX1; + f1.y0 = old1y0 = info->CRT1frameY0; + f1.y1 = info->CRT1frameY1; + f2.x0 = old2x0 = pScrn2->frameX0; + f2.x1 = pScrn2->frameX1; + f2.y0 = old2y0 = pScrn2->frameY0; + f2.y1 = pScrn2->frameY1; + + /* Define the outer region. Crossing this causes all frames to move */ + out.x0 = pScrn1->frameX0; + out.x1 = pScrn1->frameX1; + out.y0 = pScrn1->frameY0; + out.y1 = pScrn1->frameY1; + + /* + * Define the inner sliding window. Being outsize both frames but + * inside the outer clipping window will slide corresponding frame + */ + in1 = out; + in2 = out; + switch(srel) { + case radeonLeftOf: + in1.x0 = f1.x0; + in2.x1 = f2.x1; + break; + case radeonRightOf: + in1.x1 = f1.x1; + in2.x0 = f2.x0; + break; + case radeonBelow: + in1.y1 = f1.y1; + in2.y0 = f2.y0; + break; + case radeonAbove: + in1.y0 = f1.y0; + in2.y1 = f2.y1; + break; + case radeonClone: + break; + } + + deltay = 0; + deltax = 0; + + if(InRegion(x, y, out)) { /* inside outer region */ + + /* xf86DrvMsg(0, X_INFO, "1: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ + + if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { + REBOUND(f1.x0, f1.x1, x); + REBOUND(f1.y0, f1.y1, y); + deltax = 1; + /* xf86DrvMsg(0, X_INFO, "2: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ + } + if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { + REBOUND(f2.x0, f2.x1, x); + REBOUND(f2.y0, f2.y1, y); + deltax = 1; + } + + } else { /* outside outer region */ + + /* xf86DrvMsg(0, X_INFO, "3: %d %d | %d %d %d %d | %d %d %d %d\n", + x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); + xf86DrvMsg(0, X_INFO, "3-out: %d %d %d %d\n", + out.x0, out.x1, out.y0, out.y1); */ + + if(out.x0 > x) { + deltax = x - out.x0; + } + if(out.x1 < x) { + deltax = x - out.x1; + } + if(deltax) { + pScrn1->frameX0 += deltax; + pScrn1->frameX1 += deltax; + f1.x0 += deltax; + f1.x1 += deltax; + f2.x0 += deltax; + f2.x1 += deltax; + } + + if(out.y0 > y) { + deltay = y - out.y0; + } + if(out.y1 < y) { + deltay = y - out.y1; + } + if(deltay) { + pScrn1->frameY0 += deltay; + pScrn1->frameY1 += deltay; + f1.y0 += deltay; + f1.y1 += deltay; + f2.y0 += deltay; + f2.y1 += deltay; + } + + switch(srel) { + case radeonLeftOf: + if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } + if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } + break; + case radeonRightOf: + if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } + if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } + break; + case radeonBelow: + if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } + if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } + break; + case radeonAbove: + if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } + if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } + break; + case radeonClone: + break; + } + + } + + if(deltax || deltay) { + info->CRT1frameX0 = f1.x0; + info->CRT1frameY0 = f1.y0; + pScrn2->frameX0 = f2.x0; + pScrn2->frameY0 = f2.y0; + + switch(((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if(info->CRT1YOffs || info->CRT2YOffs || HaveNonRect) { + if(info->CRT1frameY0 != old1y0) { + if(info->CRT1frameY0 < info->CRT1YOffs) + info->CRT1frameY0 = info->CRT1YOffs; + temp1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay; + /*temp2 = pScrn1->virtualY - info->CRT2YOffs;*/ + temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + info->MBXNR1YMAX)); + if(temp1 > temp2) + info->CRT1frameY0 -= (temp1 - temp2); + } + if(pScrn2->frameY0 != old2y0) { + if(pScrn2->frameY0 < info->CRT2YOffs) + pScrn2->frameY0 = info->CRT2YOffs; + temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; + /*temp2 = pScrn1->virtualY - info->CRT1YOffs;*/ + temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + info->MBXNR2YMAX)); + if(temp1 > temp2) + pScrn2->frameY0 -= (temp1 - temp2); + } + } + break; + case radeonBelow: + case radeonAbove: + if(info->CRT1XOffs || info->CRT2XOffs || HaveNonRect) { + if(info->CRT1frameX0 != old1x0) { + if(info->CRT1frameX0 < info->CRT1XOffs) + info->CRT1frameX0 = info->CRT1XOffs; + temp1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay; + /*temp2 = pScrn1->virtualX - info->CRT2XOffs;*/ + temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + info->MBXNR1XMAX)); + if(temp1 > temp2) + info->CRT1frameX0 -= (temp1 - temp2); + } + if(pScrn2->frameX0 != old2x0) { + if(pScrn2->frameX0 < info->CRT2XOffs) + pScrn2->frameX0 = info->CRT2XOffs; + temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; + /*temp2 = pScrn1->virtualX - info->CRT1XOffs;*/ + temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + info->MBXNR2XMAX)); + if(temp1 > temp2) + pScrn2->frameX0 -= (temp1 - temp2); + } + } + break; + case radeonClone: + break; + } + + info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; + info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; +#if 0 + pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; + pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; +#endif + + RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); + RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); + } +} + +static void +RADEONAdjustFrameMergedHelper(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + int VTotal = info->CurrentLayout.mode->VDisplay; + int HTotal = info->CurrentLayout.mode->HDisplay; + int VMax = VTotal; + int HMax = HTotal; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + /* Uppercase to avoid shadow warnings */ + int X1 = x, X2 = x; + int Y1 = y, Y2 = y; + int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; + int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; + + if(info->DGAactive) { + HVirt = info->CurrentLayout.displayWidth; + VVirt = info->CurrentLayout.displayHeight; + } else { + CRT1XOffs = info->CRT1XOffs; + CRT1YOffs = info->CRT1YOffs; + CRT2XOffs = info->CRT2XOffs; + CRT2YOffs = info->CRT2YOffs; + MBXNR1XMAX = info->MBXNR1XMAX; + MBXNR1YMAX = info->MBXNR1YMAX; + MBXNR2XMAX = info->MBXNR2XMAX; + MBXNR2YMAX = info->MBXNR2YMAX; + } + + + BOUND(x, 0, pScrn1->virtualX - HTotal); + BOUND(y, 0, pScrn1->virtualY - VTotal); + if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { +#if 0 + BOUND(X1, info->CRT1XOffs, pScrn1->virtualX - HTotal - info->CRT2XOffs); + BOUND(Y1, info->CRT1YOffs, pScrn1->virtualY - VTotal - info->CRT2YOffs); + BOUND(X2, info->CRT2XOffs, pScrn1->virtualX - HTotal - info->CRT1XOffs); + BOUND(Y2, info->CRT2YOffs, pScrn1->virtualY - VTotal - info->CRT1YOffs); +#endif + BOUND(X1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); + BOUND(Y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); + BOUND(X2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); + BOUND(Y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); + } + + switch(SDMPTR(pScrn1)->CRT2Position) { + case radeonLeftOf: + pScrn2->frameX0 = X2; + /*BOUND(pScrn2->frameY0, Y2, Y2 + VMax - CDMPTR->CRT2->VDisplay);*/ + BOUND(pScrn2->frameY0, Y2, Y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); + info->CRT1frameX0 = X1 + CDMPTR->CRT2->HDisplay; + /*BOUND(info->CRT1frameY0, Y1, Y1 + VMax - CDMPTR->CRT1->VDisplay);*/ + BOUND(info->CRT1frameY0, Y1, Y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); + break; + case radeonRightOf: + info->CRT1frameX0 = X1; + /*BOUND(info->CRT1frameY0, Y1, Y1 + VMax - CDMPTR->CRT1->VDisplay);*/ + BOUND(info->CRT1frameY0, Y1, Y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); + pScrn2->frameX0 = X2 + CDMPTR->CRT1->HDisplay; + /*BOUND(pScrn2->frameY0, Y2, Y2 + VMax - CDMPTR->CRT2->VDisplay);*/ + BOUND(pScrn2->frameY0, Y2, Y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); + break; + case radeonAbove: + /*BOUND(pScrn2->frameX0, X2, X2 + HMax - CDMPTR->CRT2->HDisplay);*/ + BOUND(pScrn2->frameX0, X2, X2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = Y2; + /*BOUND(info->CRT1frameX0, X1, X1 + HMax - CDMPTR->CRT1->HDisplay);*/ + BOUND(info->CRT1frameX0, X1, X1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = Y1 + CDMPTR->CRT2->VDisplay; + break; + case radeonBelow: + /*BOUND(info->CRT1frameX0, X1, X1 + HMax - CDMPTR->CRT1->HDisplay);*/ + BOUND(info->CRT1frameX0, X1, X1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = Y1; + /*BOUND(pScrn2->frameX0, X2, X2 + HMax - CDMPTR->CRT2->HDisplay);*/ + BOUND(pScrn2->frameX0, X2, X2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = Y2 + CDMPTR->CRT1->VDisplay; + break; + case radeonClone: + BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); + BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); + BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + break; + } + + BOUND(info->CRT1frameX0, 0, pScrn1->virtualX - CDMPTR->CRT1->HDisplay); + BOUND(info->CRT1frameY0, 0, pScrn1->virtualY - CDMPTR->CRT1->VDisplay); + BOUND(pScrn2->frameX0, 0, pScrn1->virtualX - CDMPTR->CRT2->HDisplay); + BOUND(pScrn2->frameY0, 0, pScrn1->virtualY - CDMPTR->CRT2->VDisplay); + + pScrn1->frameX0 = x; + pScrn1->frameY0 = y; + + info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; + info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; + pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; + pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; + pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; + pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; + + if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { + pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; + pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; + } + +/* + RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); + RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); +*/ +} + +void +RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn1); + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + + RADEONAdjustFrameMergedHelper(scrnIndex, x, y, flags); + RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); + RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); +} + +static void +RADEONMergedFBCalcDPI(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel, Bool quiet) +{ + RADEONInfoPtr info = RADEONPTR(pScrn1); + MessageType from = X_DEFAULT; + xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); + xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); + int ddcWidthmm = 0, ddcHeightmm = 0; + const char *dsstr = "MergedFB: Display dimensions: %dx%d mm\n"; + + /* This sets the DPI for MergedFB mode. The problem is that + * this can never be exact, because the output devices may + * have different dimensions. This function tries to compromise + * through a few assumptions, and it just calculates an average + * DPI value for both monitors. + */ + + /* Copy user-given DisplaySize (which should regard BOTH monitors!) */ + pScrn1->widthmm = pScrn1->monitor->widthmm; + pScrn1->heightmm = pScrn1->monitor->heightmm; + + if(monitorResolution > 0) { + + /* Set command line given values (overrules given options) */ + pScrn1->xDpi = monitorResolution; + pScrn1->yDpi = monitorResolution; + from = X_CMDLINE; + + } else if(info->MergedFBXDPI) { + + /* Set option-wise given values (overrules DisplaySize config option) */ + pScrn1->xDpi = info->MergedFBXDPI; + pScrn1->yDpi = info->MergedFBYDPI; + from = X_CONFIG; + + } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { + + /* Set values calculated from given DisplaySize */ + from = X_CONFIG; + if(pScrn1->widthmm > 0) { + pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); + } + if(pScrn1->heightmm > 0) { + pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); + } + if(!quiet) { + xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); + } + + } else if(ddcWidthmm && ddcHeightmm) { + + /* Set values from DDC-provided display size */ + + /* Get DDC display size; if only either CRT1 or CRT2 provided these, + * assume equal dimensions for both, otherwise add dimensions + */ + if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && + (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { + ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; + ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; + break; + case radeonAbove: + case radeonBelow: + ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; + default: + break; + } + } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { + ddcWidthmm = DDC1->features.hsize * 10; + ddcHeightmm = DDC1->features.vsize * 10; + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + ddcWidthmm *= 2; + break; + case radeonAbove: + case radeonBelow: + ddcHeightmm *= 2; + default: + break; + } + } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { + ddcWidthmm = DDC2->features.hsize * 10; + ddcHeightmm = DDC2->features.vsize * 10; + switch(srel) { + case radeonLeftOf: + case radeonRightOf: + ddcWidthmm *= 2; + break; + case radeonAbove: + case radeonBelow: + ddcHeightmm *= 2; + default: + break; + } + } + + from = X_PROBED; + + if(!quiet) { + xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm); + } + + pScrn1->widthmm = ddcWidthmm; + pScrn1->heightmm = ddcHeightmm; + if(pScrn1->widthmm > 0) { + pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); + } + if(pScrn1->heightmm > 0) { + pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); + } + + } else { + + pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; + + } + + /* Sanity check */ + if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) + pScrn1->yDpi = pScrn1->xDpi; + if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) + pScrn1->xDpi = pScrn1->yDpi; + + pScrn2->xDpi = pScrn1->xDpi; + pScrn2->yDpi = pScrn1->yDpi; + + if(!quiet) { + xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", + pScrn1->xDpi, pScrn1->yDpi); + } +} + + +void +RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel) +{ + RADEONInfoPtr info = RADEONPTR(pScrn1); + + RADEONMergedFBCalcDPI(pScrn1, pScrn2, srel, FALSE); + + info->MergedDPISRel = srel; + info->RADEONMergedDPIVX = pScrn1->virtualX; + info->RADEONMergedDPIVY = pScrn1->virtualY; + +} + +void +RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position; + + /* This does the same calculation for the DPI as + * the initial run. This means that an eventually + * given -dpi command line switch will lead to + * constant dpi values, regardless of the virtual + * screen size. + * I consider this consequent. If this is undesired, + * one should use the DisplaySize parameter in the + * config file instead of the command line switch. + * The DPI will be calculated then. + */ + + if(force || + (info->MergedDPISRel != srel) || + (info->RADEONMergedDPIVX != pScrn->virtualX) || + (info->RADEONMergedDPIVY != pScrn->virtualY) + ) { + + RADEONMergedFBCalcDPI(pScrn, info->CRT2pScrn, srel, TRUE); + + pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10); + pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10); + + info->MergedDPISRel = srel; + info->RADEONMergedDPIVX = pScrn->virtualX; + info->RADEONMergedDPIVY = pScrn->virtualY; + + } +} + +/* radeon cursor helpers */ +static void +RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y) +{ + RADEONInfoPtr info = RADEONPTR(pScrn1); + unsigned char *RADEONMMIO = info->MMIO; + RADEONScrn2Rel srel = + ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position; + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + + if (srel == radeonClone) { + /* show cursor 2 */ + OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, + ~RADEON_CRTC2_CUR_EN); + /* show cursor 1 */ + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, + ~RADEON_CRTC_CUR_EN); + } + else { + if (((x >= pScrn1->frameX0) && (x <= pScrn1->frameX1)) && + ((y >= pScrn1->frameY0) && (y <= pScrn1->frameY1))) { + /* hide cursor 2 */ + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); + /* show cursor 1 */ + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, + ~RADEON_CRTC_CUR_EN); + } + if (((x >= pScrn2->frameX0) && (x <= pScrn2->frameX1)) && + ((y >= pScrn2->frameY0) && (y <= pScrn2->frameY1))) { + /* hide cursor 1 */ + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); + /* show cursor 2 */ + OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, + ~RADEON_CRTC2_CUR_EN); + } + } +} + +void +RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + xf86CursorInfoPtr cursor = info->cursor; + int xorigin = 0; + int yorigin = 0; + int stride = 256; + ScrnInfoPtr pScrn2 = info->CRT2pScrn; + DisplayModePtr mode1 = CDMPTR->CRT1; + DisplayModePtr mode2 = CDMPTR->CRT2; + /* Uppercase to avoid shadow warnings */ + int X1, Y1, X2, Y2; + int total_y1 = pScrn->frameY1 - pScrn->frameY0; + int total_y2 = pScrn2->frameY1 - pScrn2->frameY0; + + if (x < 0) xorigin = -x+1; + if (y < 0) yorigin = -y+1; + /* if (y > total_y) y = total_y; */ + if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; + if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; + + x += pScrn->frameX0; + y += pScrn->frameY0; + + X1 = x - info->CRT1frameX0; + Y1 = y - info->CRT1frameY0; + + X2 = x - pScrn2->frameX0; + Y2 = y - pScrn2->frameY0; + + if (Y1 > total_y1) + Y1 = total_y1; + if (Y2 > total_y2) + Y2 = total_y2; + + if(mode1->Flags & V_INTERLACE) + Y1 /= 2; + else if(mode1->Flags & V_DBLSCAN) + Y1 *= 2; + + if(mode2->Flags & V_INTERLACE) + Y2 /= 2; + else if(mode2->Flags & V_DBLSCAN) + Y2 *= 2; + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + RADEONChooseCursorCRTC(pScrn, x, y); + + /* cursor1 */ + OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK + | (xorigin << 16) + | yorigin)); + OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK + | ((xorigin ? 0 : X1) << 16) + | (yorigin ? 0 : Y1))); + OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride); + /* cursor2 */ + OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK + | (xorigin << 16) + | yorigin)); + OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK + | ((xorigin ? 0 : X2) << 16) + | (yorigin ? 0 : Y2))); + OUTREG(RADEON_CUR2_OFFSET, info->cursor_offset + yorigin * stride); +} + +/* radeon Xv helpers */ + +/* choose the crtc for the overlay for mergedfb based on the location + of the output window and the orientation of the crtcs */ + +void +RADEONChooseOverlayCRTC( + ScrnInfoPtr pScrn, + BoxPtr dstBox +) { + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONScrn2Rel srel = + ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position; + + if (srel == radeonLeftOf) { + if (dstBox->x1 >= info->CRT2pScrn->frameX1) + info->OverlayOnCRTC2 = FALSE; + else + info->OverlayOnCRTC2 = TRUE; + } + if (srel == radeonRightOf) { + if (dstBox->x2 <= info->CRT2pScrn->frameX0) + info->OverlayOnCRTC2 = FALSE; + else + info->OverlayOnCRTC2 = TRUE; + } + if (srel == radeonAbove) { + if (dstBox->y1 >= info->CRT2pScrn->frameY1) + info->OverlayOnCRTC2 = FALSE; + else + info->OverlayOnCRTC2 = TRUE; + } + if (srel == radeonBelow) { + if (dstBox->y2 <= info->CRT2pScrn->frameY0) + info->OverlayOnCRTC2 = FALSE; + else + info->OverlayOnCRTC2 = TRUE; + } +} diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.h new file mode 100644 index 000000000..50c2d3603 --- /dev/null +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.h @@ -0,0 +1,100 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.h,v 1.0tsi Exp $ */ +/* + * Copyright 2003 Alex Deucher. + * + * 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, 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL ALEX DEUCHER, OR ANY OTHER + * CONTRIBUTORS 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: + * Alex Deucher <agd5f@yahoo.com> + * + */ + +#ifndef _RADEON_MERGEDFB_H_ +#define _RADEON_MERGEDFB_H_ + +#include "xf86.h" + +#include "radeon.h" + +#define SDMPTR(x) ((RADEONMergedDisplayModePtr)(pointer)(x->currentMode->Private)) +#define CDMPTR ((RADEONMergedDisplayModePtr)(pointer)(info->CurrentLayout.mode->Private)) + +#define BOUND(test,low,hi) { \ + if(test < low) test = low; \ + if(test > hi) test = hi; } + +#define REBOUND(low,hi,test) { \ + if(test < low) { \ + hi += test-low; \ + low = test; } \ + if(test > hi) { \ + low += test-hi; \ + hi = test; } } + +typedef struct _MergedDisplayModeRec { + DisplayModePtr CRT1; + DisplayModePtr CRT2; + RADEONScrn2Rel CRT2Position; +} RADEONMergedDisplayModeRec, *RADEONMergedDisplayModePtr; + +typedef struct _RADEONXineramaData { + int x; + int y; + int width; + int height; +} RADEONXineramaData; + +/* needed by radeon_driver.c */ +extern void +RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags); +extern void +RADEONMergePointerMoved(int scrnIndex, int x, int y); +extern DisplayModePtr +RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, + DisplayModePtr i, DisplayModePtr j, + RADEONScrn2Rel srel); +extern int +RADEONStrToRanges(range *r, char *s, int max); +extern void +RADEONXineramaExtensionInit(ScrnInfoPtr pScrn); +extern void +RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1); +extern void +RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel); +extern void +RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force); +extern void +RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn); + +/* needed by radeon_cursor.c */ +extern void +RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y); + +/* needed by radeon_video.c */ +extern void +RADEONChooseOverlayCRTC(ScrnInfoPtr, BoxPtr); + +#endif /* _RADEON_MERGEDFB_H_ */ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c index 9bbbcc53d..12e0d604e 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.34tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.35tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -89,6 +89,8 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RADEON_QG, "ATI Radeon QG (AGP)" }, { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP/PCI)" }, { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP/PCI)" }, + { PCI_CHIP_RN50_515E, "ATI ES1000 515E (PCI)" }, + { PCI_CHIP_RN50_5969, "ATI ES1000 5969 (PCI)" }, { PCI_CHIP_RADEON_LW, "ATI Radeon Mobility M7 LW (AGP)" }, { PCI_CHIP_RADEON_LX, "ATI Mobility FireGL 7800 M7 LX (AGP)" }, { PCI_CHIP_RADEON_LY, "ATI Radeon Mobility M6 LY (AGP)" }, @@ -113,10 +115,13 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility 9000 (M9) Lg (AGP)" }, { PCI_CHIP_RS300_5834, "ATI Radeon 9100 IGP (A5) 5834" }, { PCI_CHIP_RS300_5835, "ATI Radeon Mobility 9100 IGP (U3) 5835" }, - { PCI_CHIP_RV280_5960, "ATI Radeon 9200PRO 5960 (AGP)" }, + { PCI_CHIP_RS350_7834, "ATI Radeon 9100 PRO IGP 7834" }, + { PCI_CHIP_RS350_7835, "ATI Radeon Mobility 9200 IGP 7835" }, + { PCI_CHIP_RV280_5960, "ATI Radeon 9250 5960 (AGP)" }, { PCI_CHIP_RV280_5961, "ATI Radeon 9200 5961 (AGP)" }, { PCI_CHIP_RV280_5962, "ATI Radeon 9200 5962 (AGP)" }, { PCI_CHIP_RV280_5964, "ATI Radeon 9200SE 5964 (AGP)" }, + { PCI_CHIP_RV280_5965, "ATI FireMV 2200 (PCI)" }, { PCI_CHIP_RV280_5C61, "ATI Radeon Mobility 9200 (M9+) 5C61 (AGP)" }, { PCI_CHIP_RV280_5C63, "ATI Radeon Mobility 9200 (M9+) 5C63 (AGP)" }, { PCI_CHIP_R300_AD, "ATI Radeon 9500 AD (AGP)" }, @@ -125,7 +130,7 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_R300_AG, "ATI FireGL Z1 AG (AGP)" }, { PCI_CHIP_R300_ND, "ATI Radeon 9700 Pro ND (AGP)" }, { PCI_CHIP_R300_NE, "ATI Radeon 9700/9500Pro NE (AGP)" }, - { PCI_CHIP_R300_NF, "ATI Radeon 9700 NF (AGP)" }, + { PCI_CHIP_R300_NF, "ATI Radeon 9600TX NF (AGP)" }, { PCI_CHIP_R300_NG, "ATI FireGL X1 NG (AGP)" }, { PCI_CHIP_RV350_AP, "ATI Radeon 9600 AP (AGP)" }, { PCI_CHIP_RV350_AQ, "ATI Radeon 9600SE AQ (AGP)" }, @@ -133,12 +138,13 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RV350_AS, "ATI Radeon 9600 AS (AGP)" }, { PCI_CHIP_RV350_AT, "ATI FireGL T2 AT (AGP)" }, { PCI_CHIP_RV350_AV, "ATI FireGL RV360 AV (AGP)" }, - { PCI_CHIP_RV350_NP, "ATI Radeon Mobility 9600 (M10) NP (AGP)" }, + { PCI_CHIP_RV350_NP, "ATI Radeon Mobility 9600/9700 (M10/M11) NP (AGP)" }, { PCI_CHIP_RV350_NQ, "ATI Radeon Mobility 9600 (M10) NQ (AGP)" }, { PCI_CHIP_RV350_NR, "ATI Radeon Mobility 9600 (M11) NR (AGP)" }, { PCI_CHIP_RV350_NS, "ATI Radeon Mobility 9600 (M10) NS (AGP)" }, { PCI_CHIP_RV350_NT, "ATI FireGL Mobility T2 (M10) NT (AGP)" }, - { PCI_CHIP_RV350_NV, "ATI FireGL Mobility T2 (M11) NV (AGP)" }, + { PCI_CHIP_RV350_NV, "ATI FireGL Mobility T2e (M11) NV (AGP)" }, + { PCI_CHIP_RV350_4155, "ATI Radeon 9650" }, { PCI_CHIP_R350_AH, "ATI Radeon 9800SE AH (AGP)" }, { PCI_CHIP_R350_AI, "ATI Radeon 9800 AI (AGP)" }, { PCI_CHIP_R350_AJ, "ATI Radeon 9800 AJ (AGP)" }, @@ -147,6 +153,75 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_R350_NI, "ATI Radeon 9800 NI (AGP)" }, { PCI_CHIP_R350_NK, "ATI FireGL X2 NK (AGP)" }, { PCI_CHIP_R360_NJ, "ATI Radeon 9800XT NJ (AGP)" }, + { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" }, + { PCI_CHIP_RV380_3E54, "ATI FireGL V3200 (RV380) 3E54 (PCIE)" }, + { PCI_CHIP_RV380_3150, "ATI Radeon Mobility X600 (M24) 3150 (PCIE)" }, + { PCI_CHIP_RV380_3152, "ATI Radeon Mobility X300 (M24) 3152 (PCIE)" }, + { PCI_CHIP_RV380_3154, "ATI FireGL M24 GL 3154 (PCIE)" }, + { PCI_CHIP_RV370_5B60, "ATI Radeon X300 (RV370) 5B60 (PCIE)" }, + { PCI_CHIP_RV370_5B62, "ATI Radeon X600 (RV370) 5B62 (PCIE)" }, + { PCI_CHIP_RV370_5B63, "ATI Radeon X550 (RV370) 5B63 (PCIE)" }, + { PCI_CHIP_RV370_5B64, "ATI FireGL V3100 (RV370) 5B64 (PCIE)" }, + { PCI_CHIP_RV370_5B65, "ATI FireMV 2200 PCIE (RV370) 5B65 (PCIE)" }, + { PCI_CHIP_RV370_5460, "ATI Radeon Mobility X300 (M22) 5460 (PCIE)" }, + { PCI_CHIP_RV370_5462, "ATI Radeon Mobility X600 SE (M24C) 5462 (PCIE)" }, + { PCI_CHIP_RV370_5464, "ATI FireGL M22 GL 5464 (PCIE)" }, + { PCI_CHIP_RS400_5A41, "ATI Radeon XPRESS 200 5A41 (PCIE)" }, + { PCI_CHIP_RS400_5A42, "ATI Radeon XPRESS 200M 5A42 (PCIE)" }, + { PCI_CHIP_RC410_5A61, "ATI Radeon XPRESS 200 5A61 (PCIE)" }, + { PCI_CHIP_RC410_5A62, "ATI Radeon XPRESS 200M 5A62 (PCIE)" }, + { PCI_CHIP_RS480_5954, "ATI Radeon XPRESS 200 5954 (PCIE)" }, + { PCI_CHIP_RS480_5955, "ATI Radeon XPRESS 200M 5955 (PCIE)" }, + { PCI_CHIP_RS482_5974, "ATI Radeon XPRESS 200 5974 (PCIE)" }, + { PCI_CHIP_RS482_5975, "ATI Radeon XPRESS 200M 5975 (PCIE)" }, + { PCI_CHIP_RV410_5E48, "ATI FireGL V5000 (RV410) (PCIE)" }, + { PCI_CHIP_RV410_564A, "ATI Mobility FireGL V5000 (M26) (PCIE)" }, + { PCI_CHIP_RV410_564B, "ATI Mobility FireGL V5000 (M26) (PCIE)" }, + { PCI_CHIP_RV410_564F, "ATI Mobility Radeon X700 XL (M26) (PCIE)" }, + { PCI_CHIP_RV410_5652, "ATI Mobility Radeon X700 (M26) (PCIE)" }, + { PCI_CHIP_RV410_5653, "ATI Mobility Radeon X700 (M26) (PCIE)" }, + { PCI_CHIP_RV410_5E4B, "ATI Radeon X700 PRO (RV410) (PCIE)" }, + { PCI_CHIP_RV410_5E4A, "ATI Radeon X700 XT (RV410) (PCIE)" }, + { PCI_CHIP_RV410_5E4D, "ATI Radeon X700 (RV410) (PCIE)" }, + { PCI_CHIP_RV410_5E4C, "ATI Radeon X700 SE (RV410) (PCIE)" }, + { PCI_CHIP_RV410_5E4F, "ATI Radeon X700 SE (RV410) (PCIE)" }, + { PCI_CHIP_R420_JH, "ATI Radeon X800 (R420) JH (AGP)" }, + { PCI_CHIP_R420_JI, "ATI Radeon X800PRO (R420) JI (AGP)" }, + { PCI_CHIP_R420_JJ, "ATI Radeon X800SE (R420) JJ (AGP)" }, + { PCI_CHIP_R420_JK, "ATI Radeon X800 (R420) JK (AGP)" }, + { PCI_CHIP_R420_JL, "ATI Radeon X800 (R420) JL (AGP)" }, + { PCI_CHIP_R420_JM, "ATI FireGL X3 (R420) JM (AGP)" }, + { PCI_CHIP_R420_JN, "ATI Radeon Mobility 9800 (M18) JN (AGP)" }, + { PCI_CHIP_R420_JP, "ATI Radeon X800XT (R420) JP (AGP)" }, + { PCI_CHIP_R420_4A4F, "ATI Radeon X800 SE (R420) (AGP)" }, + { PCI_CHIP_R420_4A54, "ATI Radeon AIW X800 VE (R420) JT (AGP)" }, + { PCI_CHIP_R423_UH, "ATI Radeon X800 (R423) UH (PCIE)" }, + { PCI_CHIP_R423_UI, "ATI Radeon X800PRO (R423) UI (PCIE)" }, + { PCI_CHIP_R423_UJ, "ATI Radeon X800LE (R423) UJ (PCIE)" }, + { PCI_CHIP_R423_UK, "ATI Radeon X800SE (R423) UK (PCIE)" }, + { PCI_CHIP_R423_UQ, "ATI FireGL V5100 (R423) UQ (PCIE)" }, + { PCI_CHIP_R423_UR, "ATI FireGL V5100 (R423) UR (PCIE)" }, + { PCI_CHIP_R423_UT, "ATI FireGL V7100 (R423) UT (PCIE)" }, + { PCI_CHIP_R423_5D57, "ATI Radeon X800XT (R423) 5D57 (PCIE)" }, + { PCI_CHIP_R423_5550, "ATI FireGL V7100 (R423) (PCIE)" }, + { PCI_CHIP_R430_5D49, "ATI Mobility FireGL V5100 (M28) (PCIE)" }, + { PCI_CHIP_R430_5D4A, "ATI Mobility Radeon X800 (M28) (PCIE)" }, + { PCI_CHIP_R430_5D48, "ATI Mobility Radeon X800 XT (M28) (PCIE)" }, + { PCI_CHIP_R430_554F, "ATI Radeon X800 (R430) (PCIE)" }, + { PCI_CHIP_R430_554D, "ATI Radeon X800 XL (R430) (PCIE)" }, + { PCI_CHIP_R430_554E, "ATI Radeon X800 SE (R430) (PCIE)" }, + { PCI_CHIP_R430_554C, "ATI Radeon X800 XTP (R430) (PCIE)" }, + { PCI_CHIP_R480_5D4C, "ATI Radeon X850 5D4C (PCIE)" }, + { PCI_CHIP_R480_5D50, "ATI FireGL V7200 (R480) 5D50 (PCIE)" }, + { PCI_CHIP_R480_5D4E, "ATI Radeon X850 SE (R480) (PCIE)" }, + { PCI_CHIP_R480_5D4F, "ATI Radeon X850 PRO (R480) (PCIE)" }, + { PCI_CHIP_R480_5D52, "ATI Radeon X850 XT (R480) (PCIE)" }, + { PCI_CHIP_R480_5D4D, "ATI Radeon X850 XT PE (R480) (PCIE)" }, + { PCI_CHIP_R481_4B4B, "ATI Radeon X850 PRO (R480) (AGP)" }, + { PCI_CHIP_R481_4B4A, "ATI Radeon X850 SE (R480) (AGP)" }, + { PCI_CHIP_R481_4B49, "ATI Radeon X850 XT (R480) (AGP)" }, + { PCI_CHIP_R481_4B4C, "ATI Radeon X850 XT PE (R480) (AGP)" }, + { -1, NULL } }; @@ -157,6 +232,8 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RADEON_QG, PCI_CHIP_RADEON_QG, RES_SHARED_VGA }, { PCI_CHIP_RV100_QY, PCI_CHIP_RV100_QY, RES_SHARED_VGA }, { PCI_CHIP_RV100_QZ, PCI_CHIP_RV100_QZ, RES_SHARED_VGA }, + { PCI_CHIP_RN50_515E, PCI_CHIP_RN50_515E, RES_SHARED_VGA }, + { PCI_CHIP_RN50_5969, PCI_CHIP_RN50_5969, RES_SHARED_VGA }, { PCI_CHIP_RADEON_LW, PCI_CHIP_RADEON_LW, RES_SHARED_VGA }, { PCI_CHIP_RADEON_LX, PCI_CHIP_RADEON_LX, RES_SHARED_VGA }, { PCI_CHIP_RADEON_LY, PCI_CHIP_RADEON_LY, RES_SHARED_VGA }, @@ -181,10 +258,13 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA }, { PCI_CHIP_RS300_5834, PCI_CHIP_RS300_5834, RES_SHARED_VGA }, { PCI_CHIP_RS300_5835, PCI_CHIP_RS300_5835, RES_SHARED_VGA }, + { PCI_CHIP_RS350_7834, PCI_CHIP_RS350_7834, RES_SHARED_VGA }, + { PCI_CHIP_RS350_7835, PCI_CHIP_RS350_7835, RES_SHARED_VGA }, { PCI_CHIP_RV280_5960, PCI_CHIP_RV280_5960, RES_SHARED_VGA }, { PCI_CHIP_RV280_5961, PCI_CHIP_RV280_5961, RES_SHARED_VGA }, { PCI_CHIP_RV280_5962, PCI_CHIP_RV280_5962, RES_SHARED_VGA }, { PCI_CHIP_RV280_5964, PCI_CHIP_RV280_5964, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5965, PCI_CHIP_RV280_5965, RES_SHARED_VGA }, { PCI_CHIP_RV280_5C61, PCI_CHIP_RV280_5C61, RES_SHARED_VGA }, { PCI_CHIP_RV280_5C63, PCI_CHIP_RV280_5C63, RES_SHARED_VGA }, { PCI_CHIP_R300_AD, PCI_CHIP_R300_AD, RES_SHARED_VGA }, @@ -207,6 +287,7 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RV350_NS, PCI_CHIP_RV350_NS, RES_SHARED_VGA }, { PCI_CHIP_RV350_NT, PCI_CHIP_RV350_NT, RES_SHARED_VGA }, { PCI_CHIP_RV350_NV, PCI_CHIP_RV350_NV, RES_SHARED_VGA }, + { PCI_CHIP_RV350_4155, PCI_CHIP_RV350_4155, RES_SHARED_VGA }, { PCI_CHIP_R350_AH, PCI_CHIP_R350_AH, RES_SHARED_VGA }, { PCI_CHIP_R350_AI, PCI_CHIP_R350_AI, RES_SHARED_VGA }, { PCI_CHIP_R350_AJ, PCI_CHIP_R350_AJ, RES_SHARED_VGA }, @@ -215,6 +296,75 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_R350_NI, PCI_CHIP_R350_NI, RES_SHARED_VGA }, { PCI_CHIP_R350_NK, PCI_CHIP_R350_NK, RES_SHARED_VGA }, { PCI_CHIP_R360_NJ, PCI_CHIP_R360_NJ, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3E50, PCI_CHIP_RV380_3E50, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3E54, PCI_CHIP_RV380_3E54, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3150, PCI_CHIP_RV380_3150, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3152, PCI_CHIP_RV380_3152, RES_SHARED_VGA }, + { PCI_CHIP_RV380_3154, PCI_CHIP_RV380_3154, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B60, PCI_CHIP_RV370_5B60, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B62, PCI_CHIP_RV370_5B62, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B63, PCI_CHIP_RV370_5B63, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B64, PCI_CHIP_RV370_5B64, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5B65, PCI_CHIP_RV370_5B65, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5460, PCI_CHIP_RV370_5460, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5462, PCI_CHIP_RV370_5462, RES_SHARED_VGA }, + { PCI_CHIP_RV370_5464, PCI_CHIP_RV370_5464, RES_SHARED_VGA }, + { PCI_CHIP_RS400_5A41, PCI_CHIP_RS400_5A41, RES_SHARED_VGA }, + { PCI_CHIP_RS400_5A42, PCI_CHIP_RS400_5A42, RES_SHARED_VGA }, + { PCI_CHIP_RC410_5A61, PCI_CHIP_RC410_5A61, RES_SHARED_VGA }, + { PCI_CHIP_RC410_5A62, PCI_CHIP_RC410_5A62, RES_SHARED_VGA }, + { PCI_CHIP_RS480_5954, PCI_CHIP_RS480_5954, RES_SHARED_VGA }, + { PCI_CHIP_RS480_5955, PCI_CHIP_RS480_5955, RES_SHARED_VGA }, + { PCI_CHIP_RS482_5974, PCI_CHIP_RS482_5974, RES_SHARED_VGA }, + { PCI_CHIP_RS482_5975, PCI_CHIP_RS482_5975, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E48, PCI_CHIP_RV410_5E48, RES_SHARED_VGA }, + { PCI_CHIP_RV410_564A, PCI_CHIP_RV410_564A, RES_SHARED_VGA }, + { PCI_CHIP_RV410_564B, PCI_CHIP_RV410_564B, RES_SHARED_VGA }, + { PCI_CHIP_RV410_564F, PCI_CHIP_RV410_564F, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5652, PCI_CHIP_RV410_5652, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5653, PCI_CHIP_RV410_5653, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E4B, PCI_CHIP_RV410_5E4B, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E4A, PCI_CHIP_RV410_5E4A, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E4D, PCI_CHIP_RV410_5E4D, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E4C, PCI_CHIP_RV410_5E4C, RES_SHARED_VGA }, + { PCI_CHIP_RV410_5E4F, PCI_CHIP_RV410_5E4F, RES_SHARED_VGA }, + { PCI_CHIP_R420_JH, PCI_CHIP_R420_JH, RES_SHARED_VGA }, + { PCI_CHIP_R420_JI, PCI_CHIP_R420_JI, RES_SHARED_VGA }, + { PCI_CHIP_R420_JJ, PCI_CHIP_R420_JJ, RES_SHARED_VGA }, + { PCI_CHIP_R420_JK, PCI_CHIP_R420_JK, RES_SHARED_VGA }, + { PCI_CHIP_R420_JL, PCI_CHIP_R420_JL, RES_SHARED_VGA }, + { PCI_CHIP_R420_JM, PCI_CHIP_R420_JM, RES_SHARED_VGA }, + { PCI_CHIP_R420_JN, PCI_CHIP_R420_JN, RES_SHARED_VGA }, + { PCI_CHIP_R420_JP, PCI_CHIP_R420_JP, RES_SHARED_VGA }, + { PCI_CHIP_R420_4A4F, PCI_CHIP_R420_4A4F, RES_SHARED_VGA }, + { PCI_CHIP_R420_4A54, PCI_CHIP_R420_4A54, RES_SHARED_VGA }, + { PCI_CHIP_R423_UH, PCI_CHIP_R423_UH, RES_SHARED_VGA }, + { PCI_CHIP_R423_UI, PCI_CHIP_R423_UI, RES_SHARED_VGA }, + { PCI_CHIP_R423_UJ, PCI_CHIP_R423_UJ, RES_SHARED_VGA }, + { PCI_CHIP_R423_UK, PCI_CHIP_R423_UK, RES_SHARED_VGA }, + { PCI_CHIP_R423_UQ, PCI_CHIP_R423_UQ, RES_SHARED_VGA }, + { PCI_CHIP_R423_UR, PCI_CHIP_R423_UR, RES_SHARED_VGA }, + { PCI_CHIP_R423_UT, PCI_CHIP_R423_UT, RES_SHARED_VGA }, + { PCI_CHIP_R423_5D57, PCI_CHIP_R423_5D57, RES_SHARED_VGA }, + { PCI_CHIP_R423_5550, PCI_CHIP_R423_5550, RES_SHARED_VGA }, + { PCI_CHIP_R430_5D49, PCI_CHIP_R430_5D49, RES_SHARED_VGA }, + { PCI_CHIP_R430_5D4A, PCI_CHIP_R430_5D4A, RES_SHARED_VGA }, + { PCI_CHIP_R430_5D48, PCI_CHIP_R430_5D48, RES_SHARED_VGA }, + { PCI_CHIP_R430_554F, PCI_CHIP_R430_554F, RES_SHARED_VGA }, + { PCI_CHIP_R430_554D, PCI_CHIP_R430_554D, RES_SHARED_VGA }, + { PCI_CHIP_R430_554E, PCI_CHIP_R430_554E, RES_SHARED_VGA }, + { PCI_CHIP_R430_554C, PCI_CHIP_R430_554C, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D4C, PCI_CHIP_R480_5D4C, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D50, PCI_CHIP_R480_5D50, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D4E, PCI_CHIP_R480_5D4E, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D4F, PCI_CHIP_R480_5D4F, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D52, PCI_CHIP_R480_5D52, RES_SHARED_VGA }, + { PCI_CHIP_R480_5D4D, PCI_CHIP_R480_5D4D, RES_SHARED_VGA }, + { PCI_CHIP_R481_4B4B, PCI_CHIP_R481_4B4B, RES_SHARED_VGA }, + { PCI_CHIP_R481_4B4A, PCI_CHIP_R481_4B4A, RES_SHARED_VGA }, + { PCI_CHIP_R481_4B49, PCI_CHIP_R481_4B49, RES_SHARED_VGA }, + { PCI_CHIP_R481_4B4C, PCI_CHIP_R481_4B4C, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } }; diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h index 92cd8c30a..678ee3776 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h,v 1.18tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h,v 1.19tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -45,6 +45,76 @@ #define _XF86MISC_SERVER_ #include <X11/extensions/xf86misc.h> +typedef enum +{ + DDC_NONE_DETECTED, + DDC_MONID, + DDC_DVI, + DDC_VGA, + DDC_CRT2 +} RADEONDDCType; + +typedef enum +{ + MT_UNKNOWN = -1, + MT_NONE = 0, + MT_CRT = 1, + MT_LCD = 2, + MT_DFP = 3, + MT_CTV = 4, + MT_STV = 5 +} RADEONMonitorType; + +typedef enum +{ + CONNECTOR_NONE, + CONNECTOR_PROPRIETARY, + CONNECTOR_CRT, + CONNECTOR_DVI_I, + CONNECTOR_DVI_D, + CONNECTOR_CTV, + CONNECTOR_STV, + CONNECTOR_UNSUPPORTED +} RADEONConnectorType; + +typedef enum +{ + CONNECTOR_NONE_ATOM, + CONNECTOR_VGA_ATOM, + CONNECTOR_DVI_I_ATOM, + CONNECTOR_DVI_D_ATOM, + CONNECTOR_DVI_A_ATOM, + CONNECTOR_STV_ATOM, + CONNECTOR_CTV_ATOM, + CONNECTOR_LVDS_ATOM, + CONNECTOR_DIGITAL_ATOM, + CONNECTOR_UNSUPPORTED_ATOM +} RADEONConnectorTypeATOM; + +typedef enum +{ + DAC_UNKNOWN = -1, + DAC_PRIMARY = 0, + DAC_TVDAC = 1 +} RADEONDacType; + +typedef enum +{ + TMDS_UNKNOWN = -1, + TMDS_INT = 0, + TMDS_EXT = 1 +} RADEONTmdsType; + +typedef struct +{ + RADEONDDCType DDCType; + RADEONDacType DACType; + RADEONTmdsType TMDSType; + RADEONConnectorType ConnectorType; + RADEONMonitorType MonType; + xf86MonPtr MonInfo; +} RADEONConnector; + typedef struct { Bool HasSecondary; @@ -65,6 +135,7 @@ typedef struct xf86MonPtr MonInfo2; Bool ReversedDAC; /* TVDAC used as primary dac */ Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ + RADEONConnector PortInfo[2]; } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h index ed8de3134..ad4a52bec 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.32 2004/02/19 22:38:12 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.33tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -53,6 +53,22 @@ #ifndef _RADEON_REG_H_ #define _RADEON_REG_H_ +#define ATI_DATATYPE_VQ 0 +#define ATI_DATATYPE_CI4 1 +#define ATI_DATATYPE_CI8 2 +#define ATI_DATATYPE_ARGB1555 3 +#define ATI_DATATYPE_RGB565 4 +#define ATI_DATATYPE_RGB888 5 +#define ATI_DATATYPE_ARGB8888 6 +#define ATI_DATATYPE_RGB332 7 +#define ATI_DATATYPE_Y8 8 +#define ATI_DATATYPE_RGB8 9 +#define ATI_DATATYPE_CI16 10 +#define ATI_DATATYPE_VYUY_422 11 +#define ATI_DATATYPE_YVYU_422 12 +#define ATI_DATATYPE_AYUV_444 14 +#define ATI_DATATYPE_ARGB4444 15 + /* Registers for 2D/Video/Overlay */ #define RADEON_ADAPTER_ID 0x0f2c /* PCI */ #define RADEON_AGP_BASE 0x0170 @@ -65,6 +81,13 @@ # define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) # define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) # define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) +#define RADEON_STATUS_PCI_CONFIG 0x06 +# define RADEON_CAP_LIST 0x100000 +#define RADEON_CAPABILITIES_PTR_PCI_CONFIG 0x34 /* offset in PCI config*/ +# define RADEON_CAP_PTR_MASK 0xfc /* mask off reserved bits of CAP_PTR */ +# define RADEON_CAP_ID_NULL 0x00 /* End of capability list */ +# define RADEON_CAP_ID_AGP 0x02 /* AGP capability ID */ +# define RADEON_CAP_ID_EXP 0x10 /* PCI Express */ #define RADEON_AGP_COMMAND 0x0f60 /* PCI */ #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ # define RADEON_AGP_ENABLE (1<<8) @@ -75,9 +98,9 @@ # define RADEON_AGP_4X_MODE 0x04 # define RADEON_AGP_FW_MODE 0x10 # define RADEON_AGP_MODE_MASK 0x17 -#define RADEON_ATTRDR 0x03c1 /* VGA */ -#define RADEON_ATTRDW 0x03c0 /* VGA */ -#define RADEON_ATTRX 0x03c0 /* VGA */ +# define RADEON_AGPv3_MODE 0x08 +# define RADEON_AGPv3_4X_MODE 0x01 +# define RADEON_AGPv3_8X_MODE 0x02 #define RADEON_AUX_SC_CNTL 0x1660 # define RADEON_AUX1_SC_EN (1 << 0) # define RADEON_AUX1_SC_MODE_OR (0 << 1) @@ -192,16 +215,23 @@ #define RADEON_CACHE_CNTL 0x1724 #define RADEON_CACHE_LINE 0x0f0c /* PCI */ -#define RADEON_CAP0_TRIG_CNTL 0x0950 /* ? */ -#define RADEON_CAP1_TRIG_CNTL 0x09c0 /* ? */ #define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */ #define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ #define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */ +# define RADEON_SCLK_DYN_START_CNTL (1 << 15) #define RADEON_CLOCK_CNTL_DATA 0x000c #define RADEON_CLOCK_CNTL_INDEX 0x0008 # define RADEON_PLL_WR_EN (1 << 7) # define RADEON_PLL_DIV_SEL (3 << 8) # define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8) +#define RADEON_CLK_PWRMGT_CNTL 0x0014 +# define RADEON_ENGIN_DYNCLK_MODE (1 << 12) +# define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) +# define RADEON_ACTIVE_HILO_LAT_SHIFT 13 +# define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12) +# define RADEON_DYN_STOP_MODE_MASK (7 << 21) +#define RADEON_PLL_PWRMGT_CNTL 0x0015 +# define RADEON_TCL_BYPASS_DISABLE (1 << 20) #define RADEON_CLR_CMP_CLR_3D 0x1a24 #define RADEON_CLR_CMP_CLR_DST 0x15c8 #define RADEON_CLR_CMP_CLR_SRC 0x15c4 @@ -219,6 +249,8 @@ #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CONFIG_BONDS 0x00e8 #define RADEON_CONFIG_CNTL 0x00e0 +# define RADEON_CFG_VGA_RAM_EN (1 << 8) +# define RADEON_CFG_VGA_IO_DIS (1 << 9) # define RADEON_CFG_ATI_REV_A11 (0 << 16) # define RADEON_CFG_ATI_REV_A12 (1 << 16) # define RADEON_CFG_ATI_REV_A13 (2 << 16) @@ -274,9 +306,9 @@ # define RADEON_CRTC_DBL_SCAN_EN (1 << 0) # define RADEON_CRTC_INTERLACE_EN (1 << 1) # define RADEON_CRTC_CSYNC_EN (1 << 4) +# define RADEON_CRTC_ICON_EN (1 << 15) # define RADEON_CRTC_CUR_EN (1 << 16) # define RADEON_CRTC_CUR_MODE_MASK (7 << 17) -# define RADEON_CRTC_ICON_EN (1 << 20) # define RADEON_CRTC_EXT_DISP_EN (1 << 24) # define RADEON_CRTC_EN (1 << 25) # define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) @@ -297,8 +329,8 @@ # define RADEON_CRTC2_HSYNC_DIS (1 << 28) # define RADEON_CRTC2_VSYNC_DIS (1 << 29) #define RADEON_CRTC_MORE_CNTL 0x27c -# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) -# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) +# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) +# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) #define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) @@ -324,13 +356,49 @@ # define RADEON_CRTC2_H_TOTAL_SHIFT 0 # define RADEON_CRTC2_H_DISP (0x01ff << 16) # define RADEON_CRTC2_H_DISP_SHIFT 16 + +#define RADEON_CRTC_OFFSET_RIGHT 0x0220 #define RADEON_CRTC_OFFSET 0x0224 +# define RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC_OFFSET__OFFSET_LOCK (1<<31) + #define RADEON_CRTC2_OFFSET 0x0324 +# define RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET (1<<30) +# define RADEON_CRTC2_OFFSET__OFFSET_LOCK (1<<31) #define RADEON_CRTC_OFFSET_CNTL 0x0228 -# define RADEON_CRTC_TILE_EN (1 << 15) +# define RADEON_CRTC_TILE_LINE_SHIFT 0 +# define RADEON_CRTC_TILE_LINE_RIGHT_SHIFT 4 +# define R300_CRTC_X_Y_MODE_EN_RIGHT (1 << 6) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_MASK (3 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_AUTO (0 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_SINGLE (1 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DOUBLE (2 << 7) +# define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DIS (3 << 7) +# define R300_CRTC_X_Y_MODE_EN (1 << 9) +# define R300_CRTC_MICRO_TILE_BUFFER_MASK (3 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_AUTO (0 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_SINGLE (1 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DOUBLE (2 << 10) +# define R300_CRTC_MICRO_TILE_BUFFER_DIS (3 << 10) +# define R300_CRTC_MICRO_TILE_EN_RIGHT (1 << 12) +# define R300_CRTC_MICRO_TILE_EN (1 << 13) +# define R300_CRTC_MACRO_TILE_EN_RIGHT (1 << 14) +# define R300_CRTC_MACRO_TILE_EN (1 << 15) +# define RADEON_CRTC_TILE_EN_RIGHT (1 << 14) +# define RADEON_CRTC_TILE_EN (1 << 15) +# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +# define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) + +#define R300_CRTC_TILE_X0_Y0 0x0350 +#define R300_CRTC2_TILE_X0_Y0 0x0358 + #define RADEON_CRTC2_OFFSET_CNTL 0x0328 +# define RADEON_CRTC2_OFFSET_FLIP_CNTL (1 << 16) # define RADEON_CRTC2_TILE_EN (1 << 15) #define RADEON_CRTC_PITCH 0x022c +# define RADEON_CRTC_PITCH__SHIFT 0 +# define RADEON_CRTC_PITCH__RIGHT_SHIFT 16 + #define RADEON_CRTC2_PITCH 0x032c #define RADEON_CRTC_STATUS 0x005c # define RADEON_CRTC_VBLANK_SAVE (1 << 1) @@ -366,8 +434,6 @@ #define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 #define RADEON_CRTC2_STATUS 0x03fc #define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 -#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ -#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ #define RADEON_CUR_CLR0 0x026c #define RADEON_CUR_CLR1 0x0270 #define RADEON_CUR_HORZ_VERT_OFF 0x0268 @@ -407,10 +473,10 @@ # define RADEON_DAC_PDWN_B (1 << 18) #define RADEON_TV_DAC_CNTL 0x088c # define RADEON_TV_DAC_STD_MASK 0x0300 +# define RADEON_TV_DAC_BGSLEEP (1 << 6) # define RADEON_TV_DAC_RDACPD (1 << 24) # define RADEON_TV_DAC_GDACPD (1 << 25) # define RADEON_TV_DAC_BDACPD (1 << 26) -# define RADEON_TV_DAC_BGSLEEP (1 << 26) #define RADEON_DISP_HW_DEBUG 0x0d14 # define RADEON_CRT2_DISP1_SEL (1 << 5) #define RADEON_DISP_OUTPUT_CNTL 0x0d64 @@ -419,10 +485,6 @@ # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 #define RADEON_DAC_CRC_SIG 0x02cc -#define RADEON_DAC_DATA 0x03c9 /* VGA */ -#define RADEON_DAC_MASK 0x03c6 /* VGA */ -#define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ -#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ #define RADEON_DDA_CONFIG 0x02e0 #define RADEON_DDA_ON_OFF 0x02e4 #define RADEON_DEFAULT_OFFSET 0x16e0 @@ -443,7 +505,7 @@ # define RADEON_DISP_RGB_OFFSET_EN (1<<8) # define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) # define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) -# define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) +# define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) #define RADEON_DISP2_MERGE_CNTL 0x0d68 # define RADEON_DISP2_RGB_OFFSET_EN (1<<8) #define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 @@ -457,6 +519,10 @@ #define RADEON_DP_CNTL 0x16c0 # define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) # define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) +# define RADEON_DP_DST_TILE_LINEAR (0 << 3) +# define RADEON_DP_DST_TILE_MACRO (1 << 3) +# define RADEON_DP_DST_TILE_MICRO (2 << 3) +# define RADEON_DP_DST_TILE_BOTH (3 << 3) #define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 # define RADEON_DST_Y_MAJOR (1 << 2) # define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) @@ -623,10 +689,17 @@ # define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 #define RADEON_FP_GEN_CNTL 0x0284 # define RADEON_FP_FPON (1 << 0) +# define RADEON_FP_BLANK_EN (1 << 1) # define RADEON_FP_TMDS_EN (1 << 2) # define RADEON_FP_PANEL_FORMAT (1 << 3) # define RADEON_FP_EN_TMDS (1 << 7) # define RADEON_FP_DETECT_SENSE (1 << 8) +# define R200_FP_SOURCE_SEL_MASK (3 << 10) +# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP_SOURCE_SEL_RMX (2 << 10) +# define R200_FP_SOURCE_SEL_TRANS (3 << 10) +# define RADEON_FP_SEL_CRTC1 (0 << 13) # define RADEON_FP_SEL_CRTC2 (1 << 13) # define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) # define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) @@ -642,8 +715,10 @@ # define RADEON_FP2_BLANK_EN (1 << 1) # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) -# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10) -# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_MASK (3 << 10) +# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) +# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define R200_FP2_SOURCE_SEL_RMX (2 << 10) # define RADEON_FP2_SRC_SEL_MASK (3 << 13) # define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) # define RADEON_FP2_FP_POL (1 << 16) @@ -653,8 +728,8 @@ # define RADEON_FP2_PAD_FLOP_EN (1 << 22) # define RADEON_FP2_CRC_EN (1 << 23) # define RADEON_FP2_CRC_READ_EN (1 << 24) -# define RADEON_FP2_DV0_EN (1 << 25) -# define RADEON_FP2_DV0_RATE_SEL_SDR (1 << 26) +# define RADEON_FP2_DVO_EN (1 << 25) +# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 #define RADEON_FP_HORZ_STRETCH 0x028c @@ -690,13 +765,6 @@ # define RADEON_VSYNC_INT (1 << 2) # define RADEON_VSYNC2_INT_AK (1 << 6) # define RADEON_VSYNC2_INT (1 << 6) -#define RADEON_GENENB 0x03c3 /* VGA */ -#define RADEON_GENFC_RD 0x03ca /* VGA */ -#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */ -#define RADEON_GENMO_RD 0x03cc /* VGA */ -#define RADEON_GENMO_WT 0x03c2 /* VGA */ -#define RADEON_GENS0 0x03c2 /* VGA */ -#define RADEON_GENS1 0x03da /* VGA, 0x03ba */ #define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */ #define RADEON_GPIO_MONIDB 0x006c #define RADEON_GPIO_CRT2_DDC 0x006c @@ -712,8 +780,6 @@ # define RADEON_GPIO_EN_1 (1 << 17) # define RADEON_GPIO_MASK_0 (1 << 24) /*??*/ # define RADEON_GPIO_MASK_1 (1 << 25) /*??*/ -#define RADEON_GRPH8_DATA 0x03cf /* VGA */ -#define RADEON_GRPH8_IDX 0x03ce /* VGA */ #define RADEON_GUI_SCRATCH_REG0 0x15e0 #define RADEON_GUI_SCRATCH_REG1 0x15e4 #define RADEON_GUI_SCRATCH_REG2 0x15e8 @@ -733,11 +799,19 @@ #define RADEON_HOST_DATA_LAST 0x17e0 #define RADEON_HOST_PATH_CNTL 0x0130 # define RADEON_HDP_SOFT_RESET (1 << 26) +# define RADEON_HDP_APER_CNTL (1 << 23) #define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ #define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ -#define RADEON_I2C_CNTL_1 0x0094 /* ? */ + /* Multimedia I2C bus */ +#define RADEON_I2C_CNTL_0 0x0090 +#define RADEON_I2C_CNTL_1 0x0094 +#define RADEON_I2C_DATA 0x0098 + +#define RADEON_DVI_I2C_CNTL_0 0x02e0 #define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */ +#define RADEON_DVI_I2C_DATA 0x02e8 + #define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ #define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */ #define RADEON_IO_BASE 0x0f14 /* PCI */ @@ -762,10 +836,14 @@ #define RADEON_MAX_LATENCY 0x0f3f /* PCI */ #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 +#define RADEON_MC_STATUS 0x0150 +# define RADEON_MC_IDLE (1 << 2) +# define R300_MC_IDLE (1 << 4) #define RADEON_DISPLAY_BASE_ADDR 0x23c #define RADEON_DISPLAY2_BASE_ADDR 0x33c #define RADEON_OV0_BASE_ADDR 0x43c #define RADEON_NB_TOM 0x15c +#define R300_MC_INIT_MISC_LAT_TIMER 0x180 #define RADEON_MCLK_CNTL 0x0012 /* PLL */ # define RADEON_FORCEON_MCLKA (1 << 16) # define RADEON_FORCEON_MCLKB (1 << 17) @@ -773,6 +851,13 @@ # define RADEON_FORCEON_YCLKB (1 << 19) # define RADEON_FORCEON_MC (1 << 20) # define RADEON_FORCEON_AIC (1 << 21) +# define R300_DISABLE_MC_MCLKA (1 << 21) +# define R300_DISABLE_MC_MCLKB (1 << 21) +#define RADEON_MCLK_MISC 0x001f /* PLL */ +# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12) +# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13) +# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) +# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) #define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_MASK 0x0198 @@ -809,22 +894,42 @@ #define RADEON_N_VIF_COUNT 0x0248 #define RADEON_OV0_AUTO_FLIP_CNTL 0x0470 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM 0x00000007 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD 0x00000008 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 0x00000010 +# define RADEON_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020 +# define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE 0x00000040 +# define RADEON_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT 0x00000300 +# define RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN 0x00010000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN 0x00040000 +# define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN 0x00080000 +# define RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE 0x00800000 + #define RADEON_OV0_COLOUR_CNTL 0x04E0 #define RADEON_OV0_DEINTERLACE_PATTERN 0x0474 #define RADEON_OV0_EXCLUSIVE_HORZ 0x0408 -# define RADEON_EXCL_HORZ_START_MASK 0x000000ff -# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 -# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 -# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 +# define RADEON_EXCL_HORZ_START_MASK 0x000000ff +# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 +# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 +# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 #define RADEON_OV0_EXCLUSIVE_VERT 0x040C -# define RADEON_EXCL_VERT_START_MASK 0x000003ff -# define RADEON_EXCL_VERT_END_MASK 0x03ff0000 +# define RADEON_EXCL_VERT_START_MASK 0x000003ff +# define RADEON_EXCL_VERT_END_MASK 0x03ff0000 #define RADEON_OV0_FILTER_CNTL 0x04A0 +# define RADEON_FILTER_PROGRAMMABLE_COEF 0x0 +# define RADEON_FILTER_HC_COEF_HORZ_Y 0x1 +# define RADEON_FILTER_HC_COEF_HORZ_UV 0x2 +# define RADEON_FILTER_HC_COEF_VERT_Y 0x4 +# define RADEON_FILTER_HC_COEF_VERT_UV 0x8 +# define RADEON_FILTER_HARDCODED_COEF 0xf +# define RADEON_FILTER_COEF_MASK 0xf + #define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0 #define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4 #define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8 #define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC #define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 +#define RADEON_OV0_FLAG_CNTL 0x04DC #define RADEON_OV0_GAMMA_000_00F 0x0d40 #define RADEON_OV0_GAMMA_010_01F 0x0d44 #define RADEON_OV0_GAMMA_020_03F 0x0d48 @@ -847,19 +952,19 @@ #define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 #define RADEON_OV0_H_INC 0x0480 #define RADEON_OV0_KEY_CNTL 0x04F4 -# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L -# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L -# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L -# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L -# define RADEON_VIDEO_KEY_FN_NE 0x00000003L -# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L -# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L -# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L -# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L -# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L -# define RADEON_CMP_MIX_MASK 0x00000100L -# define RADEON_CMP_MIX_OR 0x00000000L -# define RADEON_CMP_MIX_AND 0x00000100L +# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L +# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L +# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L +# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L +# define RADEON_VIDEO_KEY_FN_NE 0x00000003L +# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L +# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L +# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L +# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L +# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L +# define RADEON_CMP_MIX_MASK 0x00000100L +# define RADEON_CMP_MIX_OR 0x00000000L +# define RADEON_CMP_MIX_AND 0x00000100L #define RADEON_OV0_LIN_TRANS_A 0x0d20 #define RADEON_OV0_LIN_TRANS_B 0x0d24 #define RADEON_OV0_LIN_TRANS_C 0x0d28 @@ -867,73 +972,74 @@ #define RADEON_OV0_LIN_TRANS_E 0x0d30 #define RADEON_OV0_LIN_TRANS_F 0x0d34 #define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430 -# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL -# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L +# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL +# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L #define RADEON_OV0_P1_H_ACCUM_INIT 0x0488 #define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 -# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L -# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L +# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L +# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L #define RADEON_OV0_P1_X_START_END 0x0494 #define RADEON_OV0_P2_X_START_END 0x0498 #define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434 -# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL -# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L +# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL +# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L #define RADEON_OV0_P23_H_ACCUM_INIT 0x048C #define RADEON_OV0_P23_V_ACCUM_INIT 0x042C #define RADEON_OV0_P3_X_START_END 0x049C #define RADEON_OV0_REG_LOAD_CNTL 0x0410 -# define RADEON_REG_LD_CTL_LOCK 0x00000001L -# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L -# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L -# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L +# define RADEON_REG_LD_CTL_LOCK 0x00000001L +# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L +# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L +# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L #define RADEON_OV0_SCALE_CNTL 0x0420 -# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L -# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L -# define RADEON_SCALER_SIGNED_UV 0x00000010L -# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L -# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L -# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L -# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L -# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L -# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L -# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L -# define RADEON_SCALER_SOURCE_15BPP 0x00000300L -# define RADEON_SCALER_SOURCE_16BPP 0x00000400L -# define RADEON_SCALER_SOURCE_32BPP 0x00000600L -# define RADEON_SCALER_SOURCE_YUV9 0x00000900L -# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L -# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L -# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L -# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L -# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L -# define RADEON_SCALER_SMART_SWITCH 0x00008000L -# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L -# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L -# define RADEON_SCALER_DIS_LIMIT 0x08000000L -# define RADEON_SCALER_INT_EMU 0x20000000L -# define RADEON_SCALER_ENABLE 0x40000000L -# define RADEON_SCALER_SOFT_RESET 0x80000000L -# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L +# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L +# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L +# define RADEON_SCALER_SIGNED_UV 0x00000010L +# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L +# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L +# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L +# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L +# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L +# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L +# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L +# define RADEON_SCALER_SOURCE_15BPP 0x00000300L +# define RADEON_SCALER_SOURCE_16BPP 0x00000400L +# define RADEON_SCALER_SOURCE_32BPP 0x00000600L +# define RADEON_SCALER_SOURCE_YUV9 0x00000900L +# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L +# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L +# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L +# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L +# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L +# define RADEON_SCALER_CRTC_SEL 0x00004000L +# define RADEON_SCALER_SMART_SWITCH 0x00008000L +# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L +# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L +# define RADEON_SCALER_DIS_LIMIT 0x08000000L +# define RADEON_SCALER_LIN_TRANS_BYPASS 0x10000000L +# define RADEON_SCALER_INT_EMU 0x20000000L +# define RADEON_SCALER_ENABLE 0x40000000L +# define RADEON_SCALER_SOFT_RESET 0x80000000L #define RADEON_OV0_STEP_BY 0x0484 #define RADEON_OV0_TEST 0x04F8 #define RADEON_OV0_V_INC 0x0424 #define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460 #define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464 #define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440 -# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L -# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L -# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L -# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L +# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L #define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444 -# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L -# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L -# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L -# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L +# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L #define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448 -# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L -# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L -# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L -# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L +# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L +# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L +# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L +# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L #define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C #define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450 #define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454 @@ -947,6 +1053,106 @@ #define RADEON_OVR_WID_LEFT_RIGHT 0x0234 #define RADEON_OVR_WID_TOP_BOTTOM 0x0238 +/* first capture unit */ + +#define RADEON_CAP0_BUF0_OFFSET 0x0920 +#define RADEON_CAP0_BUF1_OFFSET 0x0924 +#define RADEON_CAP0_BUF0_EVEN_OFFSET 0x0928 +#define RADEON_CAP0_BUF1_EVEN_OFFSET 0x092C + +#define RADEON_CAP0_BUF_PITCH 0x0930 +#define RADEON_CAP0_V_WINDOW 0x0934 +#define RADEON_CAP0_H_WINDOW 0x0938 +#define RADEON_CAP0_VBI0_OFFSET 0x093C +#define RADEON_CAP0_VBI1_OFFSET 0x0940 +#define RADEON_CAP0_VBI_V_WINDOW 0x0944 +#define RADEON_CAP0_VBI_H_WINDOW 0x0948 +#define RADEON_CAP0_PORT_MODE_CNTL 0x094C +#define RADEON_CAP0_TRIG_CNTL 0x0950 +#define RADEON_CAP0_DEBUG 0x0954 +#define RADEON_CAP0_CONFIG 0x0958 +# define RADEON_CAP0_CONFIG_CONTINUOS 0x00000001 +# define RADEON_CAP0_CONFIG_START_FIELD_EVEN 0x00000002 +# define RADEON_CAP0_CONFIG_START_BUF_GET 0x00000004 +# define RADEON_CAP0_CONFIG_START_BUF_SET 0x00000008 +# define RADEON_CAP0_CONFIG_BUF_TYPE_ALT 0x00000010 +# define RADEON_CAP0_CONFIG_BUF_TYPE_FRAME 0x00000020 +# define RADEON_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040 +# define RADEON_CAP0_CONFIG_BUF_MODE_DOUBLE 0x00000080 +# define RADEON_CAP0_CONFIG_BUF_MODE_TRIPLE 0x00000100 +# define RADEON_CAP0_CONFIG_MIRROR_EN 0x00000200 +# define RADEON_CAP0_CONFIG_ONESHOT_MIRROR_EN 0x00000400 +# define RADEON_CAP0_CONFIG_VIDEO_SIGNED_UV 0x00000800 +# define RADEON_CAP0_CONFIG_ANC_DECODE_EN 0x00001000 +# define RADEON_CAP0_CONFIG_VBI_EN 0x00002000 +# define RADEON_CAP0_CONFIG_SOFT_PULL_DOWN_EN 0x00004000 +# define RADEON_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000 +# define RADEON_CAP0_CONFIG_FAKE_FIELD_EN 0x00010000 +# define RADEON_CAP0_CONFIG_ODD_ONE_MORE_LINE 0x00020000 +# define RADEON_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_2 0x00080000 +# define RADEON_CAP0_CONFIG_HORZ_DIVIDE_4 0x00100000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_2 0x00200000 +# define RADEON_CAP0_CONFIG_VERT_DIVIDE_4 0x00400000 +# define RADEON_CAP0_CONFIG_FORMAT_BROOKTREE 0x00000000 +# define RADEON_CAP0_CONFIG_FORMAT_CCIR656 0x00800000 +# define RADEON_CAP0_CONFIG_FORMAT_ZV 0x01000000 +# define RADEON_CAP0_CONFIG_FORMAT_VIP 0x01800000 +# define RADEON_CAP0_CONFIG_FORMAT_TRANSPORT 0x02000000 +# define RADEON_CAP0_CONFIG_HORZ_DECIMATOR 0x04000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_YVYU422 0x00000000 +# define RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422 0x20000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_2 0x40000000 +# define RADEON_CAP0_CONFIG_VBI_DIVIDE_4 0x80000000 +#define RADEON_CAP0_ANC_ODD_OFFSET 0x095C +#define RADEON_CAP0_ANC_EVEN_OFFSET 0x0960 +#define RADEON_CAP0_ANC_H_WINDOW 0x0964 +#define RADEON_CAP0_VIDEO_SYNC_TEST 0x0968 +#define RADEON_CAP0_ONESHOT_BUF_OFFSET 0x096C +#define RADEON_CAP0_BUF_STATUS 0x0970 +/* #define RADEON_CAP0_DWNSC_XRATIO 0x0978 */ +/* #define RADEON_CAP0_XSHARPNESS 0x097C */ +#define RADEON_CAP0_VBI2_OFFSET 0x0980 +#define RADEON_CAP0_VBI3_OFFSET 0x0984 +#define RADEON_CAP0_ANC2_OFFSET 0x0988 +#define RADEON_CAP0_ANC3_OFFSET 0x098C +#define RADEON_VID_BUFFER_CONTROL 0x0900 + +/* second capture unit */ + +#define RADEON_CAP1_BUF0_OFFSET 0x0990 +#define RADEON_CAP1_BUF1_OFFSET 0x0994 +#define RADEON_CAP1_BUF0_EVEN_OFFSET 0x0998 +#define RADEON_CAP1_BUF1_EVEN_OFFSET 0x099C + +#define RADEON_CAP1_BUF_PITCH 0x09A0 +#define RADEON_CAP1_V_WINDOW 0x09A4 +#define RADEON_CAP1_H_WINDOW 0x09A8 +#define RADEON_CAP1_VBI_ODD_OFFSET 0x09AC +#define RADEON_CAP1_VBI_EVEN_OFFSET 0x09B0 +#define RADEON_CAP1_VBI_V_WINDOW 0x09B4 +#define RADEON_CAP1_VBI_H_WINDOW 0x09B8 +#define RADEON_CAP1_PORT_MODE_CNTL 0x09BC +#define RADEON_CAP1_TRIG_CNTL 0x09C0 +#define RADEON_CAP1_DEBUG 0x09C4 +#define RADEON_CAP1_CONFIG 0x09C8 +#define RADEON_CAP1_ANC_ODD_OFFSET 0x09CC +#define RADEON_CAP1_ANC_EVEN_OFFSET 0x09D0 +#define RADEON_CAP1_ANC_H_WINDOW 0x09D4 +#define RADEON_CAP1_VIDEO_SYNC_TEST 0x09D8 +#define RADEON_CAP1_ONESHOT_BUF_OFFSET 0x09DC +#define RADEON_CAP1_BUF_STATUS 0x09E0 +#define RADEON_CAP1_DWNSC_XRATIO 0x09E8 +#define RADEON_CAP1_XSHARPNESS 0x09EC + +/* misc multimedia registers */ + +#define RADEON_IDCT_RUNS 0x1F80 +#define RADEON_IDCT_LEVELS 0x1F84 +#define RADEON_IDCT_CONTROL 0x1FBC +#define RADEON_IDCT_AUTH_CONTROL 0x1F88 +#define RADEON_IDCT_AUTH 0x1F8C + #define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ # define RADEON_P2PLL_RESET (1 << 0) # define RADEON_P2PLL_SLEEP (1 << 1) @@ -975,8 +1181,19 @@ # define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) # define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) # define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) +# define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9) +# define R300_DVOCLK_ALWAYS_ONb (1 << 10) +# define RADEON_PIXCLK_BLEND_ALWAYS_ONb (1 << 11) +# define RADEON_PIXCLK_GV_ALWAYS_ONb (1 << 12) +# define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13) +# define R300_PIXCLK_DVO_ALWAYS_ONb (1 << 13) # define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) # define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) +# define R300_PIXCLK_TRANS_ALWAYS_ONb (1 << 16) +# define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17) +# define R300_P2G2CLK_ALWAYS_ONb (1 << 18) +# define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19) +# define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) #define RADEON_PLANE_3D_MASK_C 0x1d44 #define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ @@ -1026,6 +1243,28 @@ # define RADEON_RB2D_DC_FLUSH_ALL 0xf # define RADEON_RB2D_DC_BUSY (1 << 31) #define RADEON_RB2D_DSTCACHE_MODE 0x3428 + +#define RADEON_RB3D_DSTCACHE_MODE 0x3258 +# define RADEON_RB3D_DC_CACHE_ENABLE (0) +# define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) +# define RADEON_RB3D_DC_3D_CACHE_DISABLE (2) +# define RADEON_RB3D_DC_CACHE_DISABLE (3) +# define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128 (1 << 2) +# define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128 (2 << 2) +# define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH (1 << 8) +# define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH (2 << 8) +# define R200_RB3D_DC_2D_CACHE_AUTOFREE (1 << 10) +# define R200_RB3D_DC_3D_CACHE_AUTOFREE (2 << 10) +# define RADEON_RB3D_DC_FORCE_RMW (1 << 16) +# define RADEON_RB3D_DC_DISABLE_RI_FILL (1 << 24) +# define RADEON_RB3D_DC_DISABLE_RI_READ (1 << 25) + +#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325C +# define RADEON_RB3D_DC_FLUSH (3 << 0) +# define RADEON_RB3D_DC_FREE (3 << 2) +# define RADEON_RB3D_DC_FLUSH_ALL 0xf +# define RADEON_RB3D_DC_BUSY (1 << 31) + #define RADEON_REG_BASE 0x0f18 /* PCI */ #define RADEON_REGPROG_INF 0x0f09 /* PCI */ #define RADEON_REVISION_ID 0x0f08 /* PCI */ @@ -1041,14 +1280,44 @@ # define RADEON_SC_SIGN_MASK_LO 0x8000 # define RADEON_SC_SIGN_MASK_HI 0x80000000 #define RADEON_SCLK_CNTL 0x000d /* PLL */ +# define RADEON_SCLK_SRC_SEL_MASK 0x0007 # define RADEON_DYN_STOP_LAT_MASK 0x00007ff8 # define RADEON_CP_MAX_DYN_STOP_LAT 0x0008 # define RADEON_SCLK_FORCEON_MASK 0xffff8000 +# define RADEON_SCLK_FORCE_DISP2 (1<<15) +# define RADEON_SCLK_FORCE_CP (1<<16) +# define RADEON_SCLK_FORCE_HDP (1<<17) +# define RADEON_SCLK_FORCE_DISP1 (1<<18) +# define RADEON_SCLK_FORCE_TOP (1<<19) +# define RADEON_SCLK_FORCE_E2 (1<<20) +# define RADEON_SCLK_FORCE_SE (1<<21) +# define RADEON_SCLK_FORCE_IDCT (1<<22) +# define RADEON_SCLK_FORCE_VIP (1<<23) +# define RADEON_SCLK_FORCE_RE (1<<24) +# define RADEON_SCLK_FORCE_PB (1<<25) +# define RADEON_SCLK_FORCE_TAM (1<<26) +# define RADEON_SCLK_FORCE_TDM (1<<27) +# define RADEON_SCLK_FORCE_RB (1<<28) +# define RADEON_SCLK_FORCE_TV_SCLK (1<<29) +# define RADEON_SCLK_FORCE_SUBPIC (1<<30) +# define RADEON_SCLK_FORCE_OV0 (1<<31) +# define R300_SCLK_FORCE_VAP (1<<21) +# define R300_SCLK_FORCE_SR (1<<25) +# define R300_SCLK_FORCE_PX (1<<26) +# define R300_SCLK_FORCE_TX (1<<27) +# define R300_SCLK_FORCE_US (1<<28) +# define R300_SCLK_FORCE_SU (1<<30) +#define R300_SCLK_CNTL2 0x1e /* PLL */ +# define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10) +# define R300_SCLK_GA_MAX_DYN_STOP_LAT (1<<11) +# define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12) +# define R300_SCLK_FORCE_TCL (1<<13) +# define R300_SCLK_FORCE_CBA (1<<14) +# define R300_SCLK_FORCE_GA (1<<15) #define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */ +# define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007 # define RADEON_SCLK_MORE_FORCEON 0x0700 #define RADEON_SDRAM_MODE_REG 0x0158 -#define RADEON_SEQ8_DATA 0x03c5 /* VGA */ -#define RADEON_SEQ8_IDX 0x03c4 /* VGA */ #define RADEON_SNAPSHOT_F_COUNT 0x0244 #define RADEON_SNAPSHOT_VH_COUNTS 0x0240 #define RADEON_SNAPSHOT_VIF_COUNT 0x024c @@ -1072,6 +1341,23 @@ # define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22) # define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23) #define RADEON_SURFACE0_INFO 0x0b0c +# define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) +# define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) +# define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) +# define R200_SURF_TILE_NONE (0 << 16) +# define R200_SURF_TILE_COLOR_MACRO (1 << 16) +# define R200_SURF_TILE_COLOR_MICRO (2 << 16) +# define R200_SURF_TILE_COLOR_BOTH (3 << 16) +# define R200_SURF_TILE_DEPTH_32BPP (4 << 16) +# define R200_SURF_TILE_DEPTH_16BPP (5 << 16) +# define R300_SURF_TILE_NONE (0 << 16) +# define R300_SURF_TILE_COLOR_MACRO (1 << 16) +# define R300_SURF_TILE_DEPTH_32BPP (2 << 16) +# define RADEON_SURF_AP0_SWP_16BPP (1 << 20) +# define RADEON_SURF_AP0_SWP_32BPP (1 << 21) +# define RADEON_SURF_AP1_SWP_16BPP (1 << 22) +# define RADEON_SURF_AP1_SWP_32BPP (1 << 23) #define RADEON_SURFACE0_LOWER_BOUND 0x0b04 #define RADEON_SURFACE0_UPPER_BOUND 0x0b08 #define RADEON_SURFACE1_INFO 0x0b1c @@ -1098,6 +1384,8 @@ #define RADEON_SW_SEMAPHORE 0x013c #define RADEON_TEST_DEBUG_CNTL 0x0120 +#define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 + #define RADEON_TEST_DEBUG_MUX 0x0124 #define RADEON_TEST_DEBUG_OUT 0x012c #define RADEON_TMDS_PLL_CNTL 0x02a8 @@ -1118,13 +1406,43 @@ # define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 # define RADEON_PIXCLK_ALWAYS_ONb (1<<6) # define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) +# define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23) #define RADEON_VENDOR_ID 0x0f00 /* PCI */ #define RADEON_VGA_DDA_CONFIG 0x02e8 #define RADEON_VGA_DDA_ON_OFF 0x02ec #define RADEON_VID_BUFFER_CONTROL 0x0900 #define RADEON_VIDEOMUX_CNTL 0x0190 -#define RADEON_VIPH_CONTROL 0x0c40 /* ? */ + + /* VIP bus */ +#define RADEON_VIPH_CH0_DATA 0x0c00 +#define RADEON_VIPH_CH1_DATA 0x0c04 +#define RADEON_VIPH_CH2_DATA 0x0c08 +#define RADEON_VIPH_CH3_DATA 0x0c0c +#define RADEON_VIPH_CH0_ADDR 0x0c10 +#define RADEON_VIPH_CH1_ADDR 0x0c14 +#define RADEON_VIPH_CH2_ADDR 0x0c18 +#define RADEON_VIPH_CH3_ADDR 0x0c1c +#define RADEON_VIPH_CH0_SBCNT 0x0c20 +#define RADEON_VIPH_CH1_SBCNT 0x0c24 +#define RADEON_VIPH_CH2_SBCNT 0x0c28 +#define RADEON_VIPH_CH3_SBCNT 0x0c2c +#define RADEON_VIPH_CH0_ABCNT 0x0c30 +#define RADEON_VIPH_CH1_ABCNT 0x0c34 +#define RADEON_VIPH_CH2_ABCNT 0x0c38 +#define RADEON_VIPH_CH3_ABCNT 0x0c3c +#define RADEON_VIPH_CONTROL 0x0c40 +#define RADEON_VIPH_DV_LAT 0x0c44 +#define RADEON_VIPH_BM_CHUNK 0x0c48 +#define RADEON_VIPH_DV_INT 0x0c4c +#define RADEON_VIPH_TIMEOUT_STAT 0x0c50 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 + +#define RADEON_VIPH_REG_DATA 0x0084 +#define RADEON_VIPH_REG_ADDR 0x0080 + #define RADEON_WAIT_UNTIL 0x1720 # define RADEON_WAIT_CRTC_PFLIP (1 << 0) @@ -1712,6 +2030,18 @@ # define RADEON_ROUND_PREC_8TH_PIX (1 << 30) # define RADEON_ROUND_PREC_4TH_PIX (2 << 30) # define RADEON_ROUND_PREC_HALF_PIX (3 << 30) +#define R200_RE_CNTL 0x1c50 +# define R200_STIPPLE_ENABLE 0x1 +# define R200_SCISSOR_ENABLE 0x2 +# define R200_PATTERN_ENABLE 0x4 +# define R200_PERSPECTIVE_ENABLE 0x8 +# define R200_POINT_SMOOTH 0x20 +# define R200_VTX_STQ0_D3D 0x00010000 +# define R200_VTX_STQ1_D3D 0x00040000 +# define R200_VTX_STQ2_D3D 0x00100000 +# define R200_VTX_STQ3_D3D 0x00400000 +# define R200_VTX_STQ4_D3D 0x01000000 +# define R200_VTX_STQ5_D3D 0x04000000 #define RADEON_SE_CNTL_STATUS 0x2140 # define RADEON_VC_NO_SWAP (0 << 0) # define RADEON_VC_16BIT_SWAP (1 << 0) @@ -1931,7 +2261,566 @@ #define RADEON_SE_ZBIAS_FACTOR 0x1db0 #define RADEON_SE_ZBIAS_CONSTANT 0x1db4 +#define RADEON_SE_VTX_FMT 0x2080 +# define RADEON_SE_VTX_FMT_XY 0x00000000 +# define RADEON_SE_VTX_FMT_W0 0x00000001 +# define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002 +# define RADEON_SE_VTX_FMT_FPALPHA 0x00000004 +# define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008 +# define RADEON_SE_VTX_FMT_FPSPEC 0x00000010 +# define RADEON_SE_VTX_FMT_FPFOG 0x00000020 +# define RADEON_SE_VTX_FMT_PKSPEC 0x00000040 +# define RADEON_SE_VTX_FMT_ST0 0x00000080 +# define RADEON_SE_VTX_FMT_ST1 0x00000100 +# define RADEON_SE_VTX_FMT_Q1 0x00000200 +# define RADEON_SE_VTX_FMT_ST2 0x00000400 +# define RADEON_SE_VTX_FMT_Q2 0x00000800 +# define RADEON_SE_VTX_FMT_ST3 0x00001000 +# define RADEON_SE_VTX_FMT_Q3 0x00002000 +# define RADEON_SE_VTX_FMT_Q0 0x00004000 +# define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000 +# define RADEON_SE_VTX_FMT_N0 0x00040000 +# define RADEON_SE_VTX_FMT_XY1 0x08000000 +# define RADEON_SE_VTX_FMT_Z1 0x10000000 +# define RADEON_SE_VTX_FMT_W1 0x20000000 +# define RADEON_SE_VTX_FMT_N1 0x40000000 +# define RADEON_SE_VTX_FMT_Z 0x80000000 + +#define RADEON_SE_VF_CNTL 0x2084 +# define RADEON_VF_PRIM_TYPE_POINT_LIST 1 +# define RADEON_VF_PRIM_TYPE_LINE_LIST 2 +# define RADEON_VF_PRIM_TYPE_LINE_STRIP 3 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST 4 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN 5 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP 6 +# define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG 7 +# define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST 8 +# define RADEON_VF_PRIM_TYPE_POINT_LIST_3 9 +# define RADEON_VF_PRIM_TYPE_LINE_LIST_3 10 +# define RADEON_VF_PRIM_TYPE_SPIRIT_LIST 11 +# define RADEON_VF_PRIM_TYPE_LINE_LOOP 12 +# define RADEON_VF_PRIM_TYPE_QUAD_LIST 13 +# define RADEON_VF_PRIM_TYPE_QUAD_STRIP 14 +# define RADEON_VF_PRIM_TYPE_POLYGON 15 +# define RADEON_VF_PRIM_WALK_STATE (0<<4) +# define RADEON_VF_PRIM_WALK_INDEX (1<<4) +# define RADEON_VF_PRIM_WALK_LIST (2<<4) +# define RADEON_VF_PRIM_WALK_DATA (3<<4) +# define RADEON_VF_COLOR_ORDER_RGBA (1<<6) +# define RADEON_VF_RADEON_MODE (1<<8) +# define RADEON_VF_TCL_OUTPUT_CTL_ENA (1<<9) +# define RADEON_VF_PROG_STREAM_ENA (1<<10) +# define RADEON_VF_INDEX_SIZE_SHIFT 11 +# define RADEON_VF_NUM_VERTICES_SHIFT 16 + +#define RADEON_SE_PORT_DATA0 0x2000 + +#define R200_SE_VAP_CNTL 0x2080 +# define R200_VAP_TCL_ENABLE 0x00000001 +# define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 +# define R200_VAP_FORCE_W_TO_ONE 0x00010000 +# define R200_VAP_D3D_TEX_DEFAULT 0x00020000 +# define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 +# define R200_VAP_VF_MAX_VTX_NUM (9 << 18) +# define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 +#define R200_VF_MAX_VTX_INDX 0x210c +#define R200_VF_MIN_VTX_INDX 0x2110 +#define R200_SE_VTE_CNTL 0x20b0 +# define R200_VPORT_X_SCALE_ENA 0x00000001 +# define R200_VPORT_X_OFFSET_ENA 0x00000002 +# define R200_VPORT_Y_SCALE_ENA 0x00000004 +# define R200_VPORT_Y_OFFSET_ENA 0x00000008 +# define R200_VPORT_Z_SCALE_ENA 0x00000010 +# define R200_VPORT_Z_OFFSET_ENA 0x00000020 +# define R200_VTX_XY_FMT 0x00000100 +# define R200_VTX_Z_FMT 0x00000200 +# define R200_VTX_W0_FMT 0x00000400 +# define R200_VTX_W0_NORMALIZE 0x00000800 +# define R200_VTX_ST_DENORMALIZED 0x00001000 +#define R200_SE_VAP_CNTL_STATUS 0x2140 +# define R200_VC_NO_SWAP (0 << 0) +# define R200_VC_16BIT_SWAP (1 << 0) +# define R200_VC_32BIT_SWAP (2 << 0) +#define R200_PP_TXFILTER_0 0x2c00 +#define R200_PP_TXFILTER_1 0x2c20 +#define R200_PP_TXFILTER_2 0x2c40 +#define R200_PP_TXFILTER_3 0x2c60 +#define R200_PP_TXFILTER_4 0x2c80 +#define R200_PP_TXFILTER_5 0x2ca0 +# define R200_MAG_FILTER_NEAREST (0 << 0) +# define R200_MAG_FILTER_LINEAR (1 << 0) +# define R200_MAG_FILTER_MASK (1 << 0) +# define R200_MIN_FILTER_NEAREST (0 << 1) +# define R200_MIN_FILTER_LINEAR (1 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define R200_MIN_FILTER_MASK (15 << 1) +# define R200_MAX_ANISO_1_TO_1 (0 << 5) +# define R200_MAX_ANISO_2_TO_1 (1 << 5) +# define R200_MAX_ANISO_4_TO_1 (2 << 5) +# define R200_MAX_ANISO_8_TO_1 (3 << 5) +# define R200_MAX_ANISO_16_TO_1 (4 << 5) +# define R200_MAX_ANISO_MASK (7 << 5) +# define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define R200_MAX_MIP_LEVEL_SHIFT 16 +# define R200_YUV_TO_RGB (1 << 20) +# define R200_YUV_TEMPERATURE_COOL (0 << 21) +# define R200_YUV_TEMPERATURE_HOT (1 << 21) +# define R200_YUV_TEMPERATURE_MASK (1 << 21) +# define R200_WRAPEN_S (1 << 22) +# define R200_CLAMP_S_WRAP (0 << 23) +# define R200_CLAMP_S_MIRROR (1 << 23) +# define R200_CLAMP_S_CLAMP_LAST (2 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define R200_CLAMP_S_CLAMP_BORDER (4 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define R200_CLAMP_S_CLAMP_GL (6 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define R200_CLAMP_S_MASK (7 << 23) +# define R200_WRAPEN_T (1 << 26) +# define R200_CLAMP_T_WRAP (0 << 27) +# define R200_CLAMP_T_MIRROR (1 << 27) +# define R200_CLAMP_T_CLAMP_LAST (2 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define R200_CLAMP_T_CLAMP_BORDER (4 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define R200_CLAMP_T_CLAMP_GL (6 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define R200_CLAMP_T_MASK (7 << 27) +# define R200_KILL_LT_ZERO (1 << 30) +# define R200_BORDER_MODE_OGL (0 << 31) +# define R200_BORDER_MODE_D3D (1 << 31) +#define R200_PP_TXFORMAT_0 0x2c04 +#define R200_PP_TXFORMAT_1 0x2c24 +#define R200_PP_TXFORMAT_2 0x2c44 +#define R200_PP_TXFORMAT_3 0x2c64 +#define R200_PP_TXFORMAT_4 0x2c84 +#define R200_PP_TXFORMAT_5 0x2ca4 +# define R200_TXFORMAT_I8 (0 << 0) +# define R200_TXFORMAT_AI88 (1 << 0) +# define R200_TXFORMAT_RGB332 (2 << 0) +# define R200_TXFORMAT_ARGB1555 (3 << 0) +# define R200_TXFORMAT_RGB565 (4 << 0) +# define R200_TXFORMAT_ARGB4444 (5 << 0) +# define R200_TXFORMAT_ARGB8888 (6 << 0) +# define R200_TXFORMAT_RGBA8888 (7 << 0) +# define R200_TXFORMAT_Y8 (8 << 0) +# define R200_TXFORMAT_AVYU4444 (9 << 0) +# define R200_TXFORMAT_VYUY422 (10 << 0) +# define R200_TXFORMAT_YVYU422 (11 << 0) +# define R200_TXFORMAT_DXT1 (12 << 0) +# define R200_TXFORMAT_DXT23 (14 << 0) +# define R200_TXFORMAT_DXT45 (15 << 0) +# define R200_TXFORMAT_ABGR8888 (22 << 0) +# define R200_TXFORMAT_FORMAT_MASK (31 << 0) +# define R200_TXFORMAT_FORMAT_SHIFT 0 +# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define R200_TXFORMAT_NON_POWER2 (1 << 7) +# define R200_TXFORMAT_WIDTH_MASK (15 << 8) +# define R200_TXFORMAT_WIDTH_SHIFT 8 +# define R200_TXFORMAT_HEIGHT_MASK (15 << 12) +# define R200_TXFORMAT_HEIGHT_SHIFT 12 +# define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ +# define R200_TXFORMAT_F5_WIDTH_SHIFT 16 +# define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) +# define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) +# define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +# define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +#define R200_PP_TXFORMAT_X_0 0x2c08 +#define R200_PP_TXFORMAT_X_1 0x2c28 +#define R200_PP_TXFORMAT_X_2 0x2c48 +#define R200_PP_TXFORMAT_X_3 0x2c68 +#define R200_PP_TXFORMAT_X_4 0x2c88 +#define R200_PP_TXFORMAT_X_5 0x2ca8 + +#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_PP_TXSIZE_1 0x2c2c /* NPOT only */ +#define R200_PP_TXSIZE_2 0x2c4c /* NPOT only */ +#define R200_PP_TXSIZE_3 0x2c6c /* NPOT only */ +#define R200_PP_TXSIZE_4 0x2c8c /* NPOT only */ +#define R200_PP_TXSIZE_5 0x2cac /* NPOT only */ + +#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_PP_TXPITCH_1 0x2c30 /* NPOT only */ +#define R200_PP_TXPITCH_2 0x2c50 /* NPOT only */ +#define R200_PP_TXPITCH_3 0x2c70 /* NPOT only */ +#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ +#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ + +#define R200_PP_TXOFFSET_0 0x2d00 +# define R200_TXO_ENDIAN_NO_SWAP (0 << 0) +# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R200_TXO_MACRO_LINEAR (0 << 2) +# define R200_TXO_MACRO_TILE (1 << 2) +# define R200_TXO_MICRO_LINEAR (0 << 3) +# define R200_TXO_MICRO_TILE (1 << 3) +# define R200_TXO_OFFSET_MASK 0xffffffe0 +# define R200_TXO_OFFSET_SHIFT 5 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_5 0x2d78 + +#define R200_PP_TFACTOR_0 0x2ee0 +#define R200_PP_TFACTOR_1 0x2ee4 +#define R200_PP_TFACTOR_2 0x2ee8 +#define R200_PP_TFACTOR_3 0x2eec +#define R200_PP_TFACTOR_4 0x2ef0 +#define R200_PP_TFACTOR_5 0x2ef4 + +#define R200_PP_TXCBLEND_0 0x2f00 +# define R200_TXC_ARG_A_ZERO (0) +# define R200_TXC_ARG_A_CURRENT_COLOR (2) +# define R200_TXC_ARG_A_CURRENT_ALPHA (3) +# define R200_TXC_ARG_A_DIFFUSE_COLOR (4) +# define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) +# define R200_TXC_ARG_A_SPECULAR_COLOR (6) +# define R200_TXC_ARG_A_SPECULAR_ALPHA (7) +# define R200_TXC_ARG_A_TFACTOR_COLOR (8) +# define R200_TXC_ARG_A_TFACTOR_ALPHA (9) +# define R200_TXC_ARG_A_R0_COLOR (10) +# define R200_TXC_ARG_A_R0_ALPHA (11) +# define R200_TXC_ARG_A_R1_COLOR (12) +# define R200_TXC_ARG_A_R1_ALPHA (13) +# define R200_TXC_ARG_A_R2_COLOR (14) +# define R200_TXC_ARG_A_R2_ALPHA (15) +# define R200_TXC_ARG_A_R3_COLOR (16) +# define R200_TXC_ARG_A_R3_ALPHA (17) +# define R200_TXC_ARG_A_R4_COLOR (18) +# define R200_TXC_ARG_A_R4_ALPHA (19) +# define R200_TXC_ARG_A_R5_COLOR (20) +# define R200_TXC_ARG_A_R5_ALPHA (21) +# define R200_TXC_ARG_A_TFACTOR1_COLOR (26) +# define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) +# define R200_TXC_ARG_A_MASK (31 << 0) +# define R200_TXC_ARG_A_SHIFT 0 +# define R200_TXC_ARG_B_ZERO (0 << 5) +# define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5) +# define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5) +# define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5) +# define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5) +# define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5) +# define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5) +# define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5) +# define R200_TXC_ARG_B_R0_COLOR (10 << 5) +# define R200_TXC_ARG_B_R0_ALPHA (11 << 5) +# define R200_TXC_ARG_B_R1_COLOR (12 << 5) +# define R200_TXC_ARG_B_R1_ALPHA (13 << 5) +# define R200_TXC_ARG_B_R2_COLOR (14 << 5) +# define R200_TXC_ARG_B_R2_ALPHA (15 << 5) +# define R200_TXC_ARG_B_R3_COLOR (16 << 5) +# define R200_TXC_ARG_B_R3_ALPHA (17 << 5) +# define R200_TXC_ARG_B_R4_COLOR (18 << 5) +# define R200_TXC_ARG_B_R4_ALPHA (19 << 5) +# define R200_TXC_ARG_B_R5_COLOR (20 << 5) +# define R200_TXC_ARG_B_R5_ALPHA (21 << 5) +# define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5) +# define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5) +# define R200_TXC_ARG_B_MASK (31 << 5) +# define R200_TXC_ARG_B_SHIFT 5 +# define R200_TXC_ARG_C_ZERO (0 << 10) +# define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10) +# define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10) +# define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10) +# define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10) +# define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10) +# define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10) +# define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10) +# define R200_TXC_ARG_C_R0_COLOR (10 << 10) +# define R200_TXC_ARG_C_R0_ALPHA (11 << 10) +# define R200_TXC_ARG_C_R1_COLOR (12 << 10) +# define R200_TXC_ARG_C_R1_ALPHA (13 << 10) +# define R200_TXC_ARG_C_R2_COLOR (14 << 10) +# define R200_TXC_ARG_C_R2_ALPHA (15 << 10) +# define R200_TXC_ARG_C_R3_COLOR (16 << 10) +# define R200_TXC_ARG_C_R3_ALPHA (17 << 10) +# define R200_TXC_ARG_C_R4_COLOR (18 << 10) +# define R200_TXC_ARG_C_R4_ALPHA (19 << 10) +# define R200_TXC_ARG_C_R5_COLOR (20 << 10) +# define R200_TXC_ARG_C_R5_ALPHA (21 << 10) +# define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10) +# define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10) +# define R200_TXC_ARG_C_MASK (31 << 10) +# define R200_TXC_ARG_C_SHIFT 10 +# define R200_TXC_COMP_ARG_A (1 << 16) +# define R200_TXC_COMP_ARG_A_SHIFT (16) +# define R200_TXC_BIAS_ARG_A (1 << 17) +# define R200_TXC_SCALE_ARG_A (1 << 18) +# define R200_TXC_NEG_ARG_A (1 << 19) +# define R200_TXC_COMP_ARG_B (1 << 20) +# define R200_TXC_COMP_ARG_B_SHIFT (20) +# define R200_TXC_BIAS_ARG_B (1 << 21) +# define R200_TXC_SCALE_ARG_B (1 << 22) +# define R200_TXC_NEG_ARG_B (1 << 23) +# define R200_TXC_COMP_ARG_C (1 << 24) +# define R200_TXC_COMP_ARG_C_SHIFT (24) +# define R200_TXC_BIAS_ARG_C (1 << 25) +# define R200_TXC_SCALE_ARG_C (1 << 26) +# define R200_TXC_NEG_ARG_C (1 << 27) +# define R200_TXC_OP_MADD (0 << 28) +# define R200_TXC_OP_CND0 (2 << 28) +# define R200_TXC_OP_LERP (3 << 28) +# define R200_TXC_OP_DOT3 (4 << 28) +# define R200_TXC_OP_DOT4 (5 << 28) +# define R200_TXC_OP_CONDITIONAL (6 << 28) +# define R200_TXC_OP_DOT2_ADD (7 << 28) +# define R200_TXC_OP_MASK (7 << 28) +#define R200_PP_TXCBLEND2_0 0x2f04 +# define R200_TXC_TFACTOR_SEL_SHIFT 0 +# define R200_TXC_TFACTOR_SEL_MASK 0x7 +# define R200_TXC_TFACTOR1_SEL_SHIFT 4 +# define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXC_SCALE_SHIFT 8 +# define R200_TXC_SCALE_MASK (7 << 8) +# define R200_TXC_SCALE_1X (0 << 8) +# define R200_TXC_SCALE_2X (1 << 8) +# define R200_TXC_SCALE_4X (2 << 8) +# define R200_TXC_SCALE_8X (3 << 8) +# define R200_TXC_SCALE_INV2 (5 << 8) +# define R200_TXC_SCALE_INV4 (6 << 8) +# define R200_TXC_SCALE_INV8 (7 << 8) +# define R200_TXC_CLAMP_SHIFT 12 +# define R200_TXC_CLAMP_MASK (3 << 12) +# define R200_TXC_CLAMP_WRAP (0 << 12) +# define R200_TXC_CLAMP_0_1 (1 << 12) +# define R200_TXC_CLAMP_8_8 (2 << 12) +# define R200_TXC_OUTPUT_REG_MASK (7 << 16) +# define R200_TXC_OUTPUT_REG_NONE (0 << 16) +# define R200_TXC_OUTPUT_REG_R0 (1 << 16) +# define R200_TXC_OUTPUT_REG_R1 (2 << 16) +# define R200_TXC_OUTPUT_REG_R2 (3 << 16) +# define R200_TXC_OUTPUT_REG_R3 (4 << 16) +# define R200_TXC_OUTPUT_REG_R4 (5 << 16) +# define R200_TXC_OUTPUT_REG_R5 (6 << 16) +# define R200_TXC_OUTPUT_MASK_MASK (7 << 20) +# define R200_TXC_OUTPUT_MASK_RGB (0 << 20) +# define R200_TXC_OUTPUT_MASK_RG (1 << 20) +# define R200_TXC_OUTPUT_MASK_RB (2 << 20) +# define R200_TXC_OUTPUT_MASK_R (3 << 20) +# define R200_TXC_OUTPUT_MASK_GB (4 << 20) +# define R200_TXC_OUTPUT_MASK_G (5 << 20) +# define R200_TXC_OUTPUT_MASK_B (6 << 20) +# define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +# define R200_TXC_REPL_NORMAL 0 +# define R200_TXC_REPL_RED 1 +# define R200_TXC_REPL_GREEN 2 +# define R200_TXC_REPL_BLUE 3 +# define R200_TXC_REPL_ARG_A_SHIFT 26 +# define R200_TXC_REPL_ARG_A_MASK (3 << 26) +# define R200_TXC_REPL_ARG_B_SHIFT 28 +# define R200_TXC_REPL_ARG_B_MASK (3 << 28) +# define R200_TXC_REPL_ARG_C_SHIFT 30 +# define R200_TXC_REPL_ARG_C_MASK (3 << 30) +#define R200_PP_TXABLEND_0 0x2f08 +# define R200_TXA_ARG_A_ZERO (0) +# define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ +# define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ +# define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) +# define R200_TXA_ARG_A_DIFFUSE_BLUE (5) +# define R200_TXA_ARG_A_SPECULAR_ALPHA (6) +# define R200_TXA_ARG_A_SPECULAR_BLUE (7) +# define R200_TXA_ARG_A_TFACTOR_ALPHA (8) +# define R200_TXA_ARG_A_TFACTOR_BLUE (9) +# define R200_TXA_ARG_A_R0_ALPHA (10) +# define R200_TXA_ARG_A_R0_BLUE (11) +# define R200_TXA_ARG_A_R1_ALPHA (12) +# define R200_TXA_ARG_A_R1_BLUE (13) +# define R200_TXA_ARG_A_R2_ALPHA (14) +# define R200_TXA_ARG_A_R2_BLUE (15) +# define R200_TXA_ARG_A_R3_ALPHA (16) +# define R200_TXA_ARG_A_R3_BLUE (17) +# define R200_TXA_ARG_A_R4_ALPHA (18) +# define R200_TXA_ARG_A_R4_BLUE (19) +# define R200_TXA_ARG_A_R5_ALPHA (20) +# define R200_TXA_ARG_A_R5_BLUE (21) +# define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) +# define R200_TXA_ARG_A_TFACTOR1_BLUE (27) +# define R200_TXA_ARG_A_MASK (31 << 0) +# define R200_TXA_ARG_A_SHIFT 0 +# define R200_TXA_ARG_B_ZERO (0 << 5) +# define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */ +# define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */ +# define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5) +# define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5) +# define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5) +# define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5) +# define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5) +# define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5) +# define R200_TXA_ARG_B_R0_ALPHA (10 << 5) +# define R200_TXA_ARG_B_R0_BLUE (11 << 5) +# define R200_TXA_ARG_B_R1_ALPHA (12 << 5) +# define R200_TXA_ARG_B_R1_BLUE (13 << 5) +# define R200_TXA_ARG_B_R2_ALPHA (14 << 5) +# define R200_TXA_ARG_B_R2_BLUE (15 << 5) +# define R200_TXA_ARG_B_R3_ALPHA (16 << 5) +# define R200_TXA_ARG_B_R3_BLUE (17 << 5) +# define R200_TXA_ARG_B_R4_ALPHA (18 << 5) +# define R200_TXA_ARG_B_R4_BLUE (19 << 5) +# define R200_TXA_ARG_B_R5_ALPHA (20 << 5) +# define R200_TXA_ARG_B_R5_BLUE (21 << 5) +# define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5) +# define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5) +# define R200_TXA_ARG_B_MASK (31 << 5) +# define R200_TXA_ARG_B_SHIFT 5 +# define R200_TXA_ARG_C_ZERO (0 << 10) +# define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */ +# define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */ +# define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10) +# define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10) +# define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10) +# define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10) +# define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10) +# define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10) +# define R200_TXA_ARG_C_R0_ALPHA (10 << 10) +# define R200_TXA_ARG_C_R0_BLUE (11 << 10) +# define R200_TXA_ARG_C_R1_ALPHA (12 << 10) +# define R200_TXA_ARG_C_R1_BLUE (13 << 10) +# define R200_TXA_ARG_C_R2_ALPHA (14 << 10) +# define R200_TXA_ARG_C_R2_BLUE (15 << 10) +# define R200_TXA_ARG_C_R3_ALPHA (16 << 10) +# define R200_TXA_ARG_C_R3_BLUE (17 << 10) +# define R200_TXA_ARG_C_R4_ALPHA (18 << 10) +# define R200_TXA_ARG_C_R4_BLUE (19 << 10) +# define R200_TXA_ARG_C_R5_ALPHA (20 << 10) +# define R200_TXA_ARG_C_R5_BLUE (21 << 10) +# define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10) +# define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10) +# define R200_TXA_ARG_C_MASK (31 << 10) +# define R200_TXA_ARG_C_SHIFT 10 +# define R200_TXA_COMP_ARG_A (1 << 16) +# define R200_TXA_COMP_ARG_A_SHIFT (16) +# define R200_TXA_BIAS_ARG_A (1 << 17) +# define R200_TXA_SCALE_ARG_A (1 << 18) +# define R200_TXA_NEG_ARG_A (1 << 19) +# define R200_TXA_COMP_ARG_B (1 << 20) +# define R200_TXA_COMP_ARG_B_SHIFT (20) +# define R200_TXA_BIAS_ARG_B (1 << 21) +# define R200_TXA_SCALE_ARG_B (1 << 22) +# define R200_TXA_NEG_ARG_B (1 << 23) +# define R200_TXA_COMP_ARG_C (1 << 24) +# define R200_TXA_COMP_ARG_C_SHIFT (24) +# define R200_TXA_BIAS_ARG_C (1 << 25) +# define R200_TXA_SCALE_ARG_C (1 << 26) +# define R200_TXA_NEG_ARG_C (1 << 27) +# define R200_TXA_OP_MADD (0 << 28) +# define R200_TXA_OP_CND0 (2 << 28) +# define R200_TXA_OP_LERP (3 << 28) +# define R200_TXA_OP_CONDITIONAL (6 << 28) +# define R200_TXA_OP_MASK (7 << 28) +#define R200_PP_TXABLEND2_0 0x2f0c +# define R200_TXA_TFACTOR_SEL_SHIFT 0 +# define R200_TXA_TFACTOR_SEL_MASK 0x7 +# define R200_TXA_TFACTOR1_SEL_SHIFT 4 +# define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXA_SCALE_SHIFT 8 +# define R200_TXA_SCALE_MASK (7 << 8) +# define R200_TXA_SCALE_1X (0 << 8) +# define R200_TXA_SCALE_2X (1 << 8) +# define R200_TXA_SCALE_4X (2 << 8) +# define R200_TXA_SCALE_8X (3 << 8) +# define R200_TXA_SCALE_INV2 (5 << 8) +# define R200_TXA_SCALE_INV4 (6 << 8) +# define R200_TXA_SCALE_INV8 (7 << 8) +# define R200_TXA_CLAMP_SHIFT 12 +# define R200_TXA_CLAMP_MASK (3 << 12) +# define R200_TXA_CLAMP_WRAP (0 << 12) +# define R200_TXA_CLAMP_0_1 (1 << 12) +# define R200_TXA_CLAMP_8_8 (2 << 12) +# define R200_TXA_OUTPUT_REG_MASK (7 << 16) +# define R200_TXA_OUTPUT_REG_NONE (0 << 16) +# define R200_TXA_OUTPUT_REG_R0 (1 << 16) +# define R200_TXA_OUTPUT_REG_R1 (2 << 16) +# define R200_TXA_OUTPUT_REG_R2 (3 << 16) +# define R200_TXA_OUTPUT_REG_R3 (4 << 16) +# define R200_TXA_OUTPUT_REG_R4 (5 << 16) +# define R200_TXA_OUTPUT_REG_R5 (6 << 16) +# define R200_TXA_DOT_ALPHA (1 << 20) +# define R200_TXA_REPL_NORMAL 0 +# define R200_TXA_REPL_RED 1 +# define R200_TXA_REPL_GREEN 2 +# define R200_TXA_REPL_ARG_A_SHIFT 26 +# define R200_TXA_REPL_ARG_A_MASK (3 << 26) +# define R200_TXA_REPL_ARG_B_SHIFT 28 +# define R200_TXA_REPL_ARG_B_MASK (3 << 28) +# define R200_TXA_REPL_ARG_C_SHIFT 30 +# define R200_TXA_REPL_ARG_C_MASK (3 << 30) + +#define R200_SE_VTX_FMT_0 0x2088 +# define R200_VTX_XY 0 /* always have xy */ +# define R200_VTX_Z0 (1<<0) +# define R200_VTX_W0 (1<<1) +# define R200_VTX_WEIGHT_COUNT_SHIFT (2) +# define R200_VTX_PV_MATRIX_SEL (1<<5) +# define R200_VTX_N0 (1<<6) +# define R200_VTX_POINT_SIZE (1<<7) +# define R200_VTX_DISCRETE_FOG (1<<8) +# define R200_VTX_SHININESS_0 (1<<9) +# define R200_VTX_SHININESS_1 (1<<10) +# define R200_VTX_COLOR_NOT_PRESENT 0 +# define R200_VTX_PK_RGBA 1 +# define R200_VTX_FP_RGB 2 +# define R200_VTX_FP_RGBA 3 +# define R200_VTX_COLOR_MASK 3 +# define R200_VTX_COLOR_0_SHIFT 11 +# define R200_VTX_COLOR_1_SHIFT 13 +# define R200_VTX_COLOR_2_SHIFT 15 +# define R200_VTX_COLOR_3_SHIFT 17 +# define R200_VTX_COLOR_4_SHIFT 19 +# define R200_VTX_COLOR_5_SHIFT 21 +# define R200_VTX_COLOR_6_SHIFT 23 +# define R200_VTX_COLOR_7_SHIFT 25 +# define R200_VTX_XY1 (1<<28) +# define R200_VTX_Z1 (1<<29) +# define R200_VTX_W1 (1<<30) +# define R200_VTX_N1 (1<<31) +#define R200_SE_VTX_FMT_1 0x208c +# define R200_VTX_TEX0_COMP_CNT_SHIFT 0 +# define R200_VTX_TEX1_COMP_CNT_SHIFT 3 +# define R200_VTX_TEX2_COMP_CNT_SHIFT 6 +# define R200_VTX_TEX3_COMP_CNT_SHIFT 9 +# define R200_VTX_TEX4_COMP_CNT_SHIFT 12 +# define R200_VTX_TEX5_COMP_CNT_SHIFT 15 +#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 +#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 +#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 +# define R200_OUTPUT_XYZW (1<<0) +# define R200_OUTPUT_COLOR_0 (1<<8) +# define R200_OUTPUT_COLOR_1 (1<<9) +# define R200_OUTPUT_TEX_0 (1<<16) +# define R200_OUTPUT_TEX_1 (1<<17) +# define R200_OUTPUT_TEX_2 (1<<18) +# define R200_OUTPUT_TEX_3 (1<<19) +# define R200_OUTPUT_TEX_4 (1<<20) +# define R200_OUTPUT_TEX_5 (1<<21) +# define R200_OUTPUT_TEX_MASK (0x3f<<16) +# define R200_OUTPUT_DISCRETE_FOG (1<<24) +# define R200_OUTPUT_PT_SIZE (1<<25) +# define R200_FORCE_INORDER_PROC (1<<31) +#define R200_PP_CNTL_X 0x2cc4 +#define R200_PP_TXMULTI_CTL_0 0x2c1c +#define R200_SE_VTX_STATE_CNTL 0x2180 +# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16) /* Registers for CP and Microcode Engine */ #define RADEON_CP_ME_RAM_ADDR 0x07d4 @@ -2007,6 +2896,7 @@ #define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 #define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 #define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 +#define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500 #define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 #define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 #define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h index db9589086..cddbb757d 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.6 2003/09/28 20:15:57 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.7tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -222,10 +222,11 @@ typedef struct { /* last time texture was uploaded */ unsigned int texAge[RADEON_NR_TEX_HEAPS]; - int ctxOwner; /* last context to upload state */ + drm_context_t ctxOwner; /* last context to upload state */ int pfAllowPageFlip; /* set by the 2d driver, read by the client */ int pfCurrentPage; /* set by kernel, read by others */ int crtc2_base; /* for pageflipping with CloneMode */ + int tiling_enabled; /* set by drm, read by 2d + 3d clients */ } RADEONSAREAPriv, *RADEONSAREAPrivPtr; #endif diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h b/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h index 1241e476b..33758bb5d 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h,v 1.14tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h,v 1.15tsi Exp $ */ /* * Copyright 2000 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -27,6 +27,8 @@ #undef RADEON_NAME #undef RADEON_DRIVER_NAME #undef R200_DRIVER_NAME +#undef R300_DRIVER_NAME + #undef RADEON_VERSION_MAJOR #undef RADEON_VERSION_MINOR #undef RADEON_VERSION_PATCH @@ -38,10 +40,12 @@ #define RADEON_NAME "RADEON" #define RADEON_DRIVER_NAME "radeon" #define R200_DRIVER_NAME "r200" +#define R300_DRIVER_NAME "r300" #define RADEON_VERSION_MAJOR 4 -#define RADEON_VERSION_MINOR 0 -#define RADEON_VERSION_PATCH 1 +#define RADEON_VERSION_MAJOR_TILED 5 +#define RADEON_VERSION_MINOR 1 +#define RADEON_VERSION_PATCH 0 #ifndef RADEON_VERSION_EXTRA #define RADEON_VERSION_EXTRA "" diff --git a/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c b/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c index 2b53b2218..51d741fc4 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c @@ -1,7 +1,8 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.32 2005/10/14 15:16:37 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.33tsi Exp $ */ #include "radeon.h" #include "radeon_macros.h" +#include "radeon_mergedfb.h" #include "radeon_probe.h" #include "radeon_reg.h" @@ -20,8 +21,6 @@ #define TIMER_MASK (OFF_TIMER | FREE_TIMER) -extern int gRADEONEntityIndex; - static void RADEONInitOffscreenImages(ScreenPtr); static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr); @@ -39,13 +38,18 @@ static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) +#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; +static Atom xvGamma, xvColorspace, xvSwitchCRT; +static Atom xvLocationID, xvDeviceID, xvInstanceID; +static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; typedef struct { CARD32 transform_index; + CARD32 gamma; /* gamma value x 1000 */ int brightness; int saturation; int hue; @@ -55,6 +59,13 @@ typedef struct { int blue_intensity; int ecp_div; + /* overlay composition mode */ + int alpha_mode; /* 0 = key mode, 1 = global mode */ + int ov_alpha; + int gr_alpha; + + int overlay_scaler_buffer_width; + Bool doubleBuffer; unsigned char currentBuffer; RegionRec clip; @@ -63,12 +74,15 @@ typedef struct { Time offTime; Time freeTime; Bool autopaint_colorkey; -} RADEONPortPrivRec, *RADEONPortPrivPtr; + Bool crt2; /* 0=CRT1, 1=CRT2 */ + Atom device_id, location_id, instance_id; +} RADEONPortPrivRec, *RADEONPortPrivPtr; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + void RADEONInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -123,15 +137,20 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] = {15, DirectColor}, {16, DirectColor}, {24, DirectColor} }; +#define NUM_ATTRIBUTES 21 -#define NUM_ATTRIBUTES 9+3 - -static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] = { - {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, - {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, - {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"}, - {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, + { XvGettable, 0, ~0, "XV_DEVICE_ID"}, + { XvGettable, 0, ~0, "XV_LOCATION_ID"}, + { XvGettable, 0, ~0, "XV_INSTANCE_ID"}, + {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable | XvGettable, 0, ~0,"XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, + {XvSettable | XvGettable, 0, 255, "XV_OVERLAY_ALPHA"}, + {XvSettable | XvGettable, 0, 255, "XV_GRAPHICS_ALPHA"}, + {XvSettable | XvGettable, 0, 1, "XV_ALPHA_MODE"}, {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, @@ -140,16 +159,110 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, + {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, + {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, + + { 0, 0, 0, NULL} /* just a place holder so I don't have to be fancy with commas */ }; -#define NUM_IMAGES 4 +#define NUM_IMAGES 8 + +/* Note: GUIDs are bogus... - but nothing uses them anyway */ + +#define FOURCC_RGBA32 0x41424752 + +#define XVIMAGE_RGBA32(byte_order) \ + { \ + FOURCC_RGBA32, \ + XvRGB, \ + byte_order, \ + { 'R', 'G', 'B', 'A', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 32, \ + XvPacked, \ + 1, \ + 32, 0x00FF0000, 0x0000FF00, 0x000000FF, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'A', 'R', 'G', 'B', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_RGB24 0x00000000 + +#define XVIMAGE_RGB24(byte_order) \ + { \ + FOURCC_RGB24, \ + XvRGB, \ + byte_order, \ + { 'R', 'G', 'B', 0, \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 24, \ + XvPacked, \ + 1, \ + 24, 0x00FF0000, 0x0000FF00, 0x000000FF, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + { 'R', 'G', 'B', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_RGBT16 0x54424752 + +#define XVIMAGE_RGBT16(byte_order) \ + { \ + FOURCC_RGBT16, \ + XvRGB, \ + byte_order, \ + { 'R', 'G', 'B', 'T', \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 16, 0x00007C00, 0x000003E0, 0x0000001F, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'A', 'R', 'G', 'B', \ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } + +#define FOURCC_RGB16 0x32424752 + +#define XVIMAGE_RGB16(byte_order) \ + { \ + FOURCC_RGB16, \ + XvRGB, \ + byte_order, \ + { 'R', 'G', 'B', 0x00, \ + 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \ + 16, \ + XvPacked, \ + 1, \ + 16, 0x0000F800, 0x000007E0, 0x0000001F, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + {'R', 'G', 'B', \ + 0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \ + XvTopToBottom \ + } static XF86ImageRec Images[NUM_IMAGES] = { - XVIMAGE_YUY2, - XVIMAGE_UYVY, - XVIMAGE_YV12, - XVIMAGE_I420 +#if X_BYTE_ORDER == X_BIG_ENDIAN + XVIMAGE_RGBA32(MSBFirst), + XVIMAGE_RGB24(MSBFirst), + XVIMAGE_RGBT16(MSBFirst), + XVIMAGE_RGB16(MSBFirst), +#else + XVIMAGE_RGBA32(LSBFirst), + XVIMAGE_RGB24(LSBFirst), + XVIMAGE_RGBT16(LSBFirst), + XVIMAGE_RGB16(LSBFirst), +#endif + XVIMAGE_YUY2, + XVIMAGE_UYVY, + XVIMAGE_YV12, + XVIMAGE_I420 }; /* Reference color space transform data */ @@ -172,37 +285,391 @@ static REF_TRANSFORM trans[2] = }; -/* Gamma curve definition */ -typedef struct +/* Gamma curve definition for preset gammas */ +typedef struct tagGAMMA_CURVE_R100 { - unsigned int gammaReg; - unsigned int gammaSlope; - unsigned int gammaOffset; -} GAMMA_SETTINGS; - -/* Recommended gamma curve parameters */ -static GAMMA_SETTINGS def_gamma[18] = + CARD32 GAMMA_0_F_SLOPE; + CARD32 GAMMA_0_F_OFFSET; + CARD32 GAMMA_10_1F_SLOPE; + CARD32 GAMMA_10_1F_OFFSET; + CARD32 GAMMA_20_3F_SLOPE; + CARD32 GAMMA_20_3F_OFFSET; + CARD32 GAMMA_40_7F_SLOPE; + CARD32 GAMMA_40_7F_OFFSET; + CARD32 GAMMA_380_3BF_SLOPE; + CARD32 GAMMA_380_3BF_OFFSET; + CARD32 GAMMA_3C0_3FF_SLOPE; + CARD32 GAMMA_3C0_3FF_OFFSET; + float OvGammaCont; +} GAMMA_CURVE_R100; + +typedef struct tagGAMMA_CURVE_R200 { - {RADEON_OV0_GAMMA_000_00F, 0x100, 0x0000}, - {RADEON_OV0_GAMMA_010_01F, 0x100, 0x0020}, - {RADEON_OV0_GAMMA_020_03F, 0x100, 0x0040}, - {RADEON_OV0_GAMMA_040_07F, 0x100, 0x0080}, - {RADEON_OV0_GAMMA_080_0BF, 0x100, 0x0100}, - {RADEON_OV0_GAMMA_0C0_0FF, 0x100, 0x0100}, - {RADEON_OV0_GAMMA_100_13F, 0x100, 0x0200}, - {RADEON_OV0_GAMMA_140_17F, 0x100, 0x0200}, - {RADEON_OV0_GAMMA_180_1BF, 0x100, 0x0300}, - {RADEON_OV0_GAMMA_1C0_1FF, 0x100, 0x0300}, - {RADEON_OV0_GAMMA_200_23F, 0x100, 0x0400}, - {RADEON_OV0_GAMMA_240_27F, 0x100, 0x0400}, - {RADEON_OV0_GAMMA_280_2BF, 0x100, 0x0500}, - {RADEON_OV0_GAMMA_2C0_2FF, 0x100, 0x0500}, - {RADEON_OV0_GAMMA_300_33F, 0x100, 0x0600}, - {RADEON_OV0_GAMMA_340_37F, 0x100, 0x0600}, - {RADEON_OV0_GAMMA_380_3BF, 0x100, 0x0700}, - {RADEON_OV0_GAMMA_3C0_3FF, 0x100, 0x0700} + CARD32 GAMMA_0_F_SLOPE; + CARD32 GAMMA_0_F_OFFSET; + CARD32 GAMMA_10_1F_SLOPE; + CARD32 GAMMA_10_1F_OFFSET; + CARD32 GAMMA_20_3F_SLOPE; + CARD32 GAMMA_20_3F_OFFSET; + CARD32 GAMMA_40_7F_SLOPE; + CARD32 GAMMA_40_7F_OFFSET; + CARD32 GAMMA_80_BF_SLOPE; + CARD32 GAMMA_80_BF_OFFSET; + CARD32 GAMMA_C0_FF_SLOPE; + CARD32 GAMMA_C0_FF_OFFSET; + CARD32 GAMMA_100_13F_SLOPE; + CARD32 GAMMA_100_13F_OFFSET; + CARD32 GAMMA_140_17F_SLOPE; + CARD32 GAMMA_140_17F_OFFSET; + CARD32 GAMMA_180_1BF_SLOPE; + CARD32 GAMMA_180_1BF_OFFSET; + CARD32 GAMMA_1C0_1FF_SLOPE; + CARD32 GAMMA_1C0_1FF_OFFSET; + CARD32 GAMMA_200_23F_SLOPE; + CARD32 GAMMA_200_23F_OFFSET; + CARD32 GAMMA_240_27F_SLOPE; + CARD32 GAMMA_240_27F_OFFSET; + CARD32 GAMMA_280_2BF_SLOPE; + CARD32 GAMMA_280_2BF_OFFSET; + CARD32 GAMMA_2C0_2FF_SLOPE; + CARD32 GAMMA_2C0_2FF_OFFSET; + CARD32 GAMMA_300_33F_SLOPE; + CARD32 GAMMA_300_33F_OFFSET; + CARD32 GAMMA_340_37F_SLOPE; + CARD32 GAMMA_340_37F_OFFSET; + CARD32 GAMMA_380_3BF_SLOPE; + CARD32 GAMMA_380_3BF_OFFSET; + CARD32 GAMMA_3C0_3FF_SLOPE; + CARD32 GAMMA_3C0_3FF_OFFSET; + float OvGammaCont; +} GAMMA_CURVE_R200; + + +/* Preset gammas */ +static GAMMA_CURVE_R100 gamma_curve_r100[8] = +{ + /* GAMMA 1.0 */ + {0x100, 0x0, + 0x100, 0x20, + 0x100, 0x40, + 0x100, 0x80, + 0x100, 0x100, + 0x100, 0x100, + 1.0}, + /* GAMMA 0.85 */ + {0x75, 0x0, + 0xA2, 0xF, + 0xAC, 0x23, + 0xC6, 0x4E, + 0x129, 0xD6, + 0x12B, 0xD5, + 1.0}, + /* GAMMA 1.1 */ + {0x180, 0x0, + 0x13C, 0x30, + 0x13C, 0x57, + 0x123, 0xA5, + 0xEA, 0x116, + 0xEA, 0x116, + 0.9913}, + /* GAMMA 1.2 */ + {0x21B, 0x0, + 0x16D, 0x43, + 0x172, 0x71, + 0x13D, 0xCD, + 0xD9, 0x128, + 0xD6, 0x12A, + 0.9827}, + /* GAMMA 1.45 */ + {0x404, 0x0, + 0x1B9, 0x81, + 0x1EE, 0xB8, + 0x16A, 0x133, + 0xB7, 0x14B, + 0xB2, 0x14E, + 0.9567}, + /* GAMMA 1.7 */ + {0x658, 0x0, + 0x1B5, 0xCB, + 0x25F, 0x102, + 0x181, 0x199, + 0x9C, 0x165, + 0x98, 0x167, + 0.9394}, + /* GAMMA 2.2 */ + {0x7FF, 0x0, + 0x625, 0x100, + 0x1E4, 0x1C4, + 0x1BD, 0x23D, + 0x79, 0x187, + 0x76, 0x188, + 0.9135}, + /* GAMMA 2.5 */ + {0x7FF, 0x0, + 0x7FF, 0x100, + 0x2AD, 0x200, + 0x1A2, 0x2AB, + 0x6E, 0x194, + 0x67, 0x197, + 0.9135} +}; + +static GAMMA_CURVE_R200 gamma_curve_r200[8] = + { + /* GAMMA 1.0 */ + {0x00000040, 0x00000000, + 0x00000040, 0x00000020, + 0x00000080, 0x00000040, + 0x00000100, 0x00000080, + 0x00000100, 0x00000100, + 0x00000100, 0x00000100, + 0x00000100, 0x00000200, + 0x00000100, 0x00000200, + 0x00000100, 0x00000300, + 0x00000100, 0x00000300, + 0x00000100, 0x00000400, + 0x00000100, 0x00000400, + 0x00000100, 0x00000500, + 0x00000100, 0x00000500, + 0x00000100, 0x00000600, + 0x00000100, 0x00000600, + 0x00000100, 0x00000700, + 0x00000100, 0x00000700, + 1.0}, + /* GAMMA 0.85 */ + {0x0000001D, 0x00000000, + 0x00000028, 0x0000000F, + 0x00000056, 0x00000023, + 0x000000C5, 0x0000004E, + 0x000000DA, 0x000000B0, + 0x000000E6, 0x000000AA, + 0x000000F1, 0x00000190, + 0x000000F9, 0x0000018C, + 0x00000101, 0x00000286, + 0x00000108, 0x00000282, + 0x0000010D, 0x0000038A, + 0x00000113, 0x00000387, + 0x00000118, 0x0000049A, + 0x0000011C, 0x00000498, + 0x00000120, 0x000005B4, + 0x00000124, 0x000005B2, + 0x00000128, 0x000006D6, + 0x0000012C, 0x000006D5, + 1.0}, + /* GAMMA 1.1 */ + {0x00000060, 0x00000000, + 0x0000004F, 0x00000030, + 0x0000009C, 0x00000057, + 0x00000121, 0x000000A5, + 0x00000113, 0x00000136, + 0x0000010B, 0x0000013A, + 0x00000105, 0x00000245, + 0x00000100, 0x00000247, + 0x000000FD, 0x00000348, + 0x000000F9, 0x00000349, + 0x000000F6, 0x00000443, + 0x000000F4, 0x00000444, + 0x000000F2, 0x00000538, + 0x000000F0, 0x00000539, + 0x000000EE, 0x00000629, + 0x000000EC, 0x00000629, + 0x000000EB, 0x00000716, + 0x000000E9, 0x00000717, + 0.9913}, + /* GAMMA 1.2 */ + {0x00000087, 0x00000000, + 0x0000005B, 0x00000043, + 0x000000B7, 0x00000071, + 0x0000013D, 0x000000CD, + 0x00000121, 0x0000016B, + 0x00000113, 0x00000172, + 0x00000107, 0x00000286, + 0x000000FF, 0x0000028A, + 0x000000F8, 0x00000389, + 0x000000F2, 0x0000038B, + 0x000000ED, 0x0000047D, + 0x000000E9, 0x00000480, + 0x000000E5, 0x00000568, + 0x000000E1, 0x0000056A, + 0x000000DE, 0x0000064B, + 0x000000DB, 0x0000064D, + 0x000000D9, 0x00000728, + 0x000000D6, 0x00000729, + 0.9827}, + /* GAMMA 1.45 */ + {0x00000101, 0x00000000, + 0x0000006E, 0x00000081, + 0x000000F7, 0x000000B8, + 0x0000016E, 0x00000133, + 0x00000139, 0x000001EA, + 0x0000011B, 0x000001F9, + 0x00000105, 0x00000314, + 0x000000F6, 0x0000031C, + 0x000000E9, 0x00000411, + 0x000000DF, 0x00000417, + 0x000000D7, 0x000004F6, + 0x000000CF, 0x000004F9, + 0x000000C9, 0x000005C9, + 0x000000C4, 0x000005CC, + 0x000000BF, 0x0000068F, + 0x000000BA, 0x00000691, + 0x000000B6, 0x0000074B, + 0x000000B2, 0x0000074D, + 0.9567}, + /* GAMMA 1.7 */ + {0x00000196, 0x00000000, + 0x0000006D, 0x000000CB, + 0x0000012F, 0x00000102, + 0x00000187, 0x00000199, + 0x00000144, 0x0000025b, + 0x00000118, 0x00000273, + 0x000000FE, 0x0000038B, + 0x000000E9, 0x00000395, + 0x000000DA, 0x0000047E, + 0x000000CE, 0x00000485, + 0x000000C3, 0x00000552, + 0x000000BB, 0x00000556, + 0x000000B3, 0x00000611, + 0x000000AC, 0x00000614, + 0x000000A7, 0x000006C1, + 0x000000A1, 0x000006C3, + 0x0000009D, 0x00000765, + 0x00000098, 0x00000767, + 0.9394}, + /* GAMMA 2.2 */ + {0x000001FF, 0x00000000, + 0x0000018A, 0x00000100, + 0x000000F1, 0x000001C5, + 0x000001D6, 0x0000023D, + 0x00000124, 0x00000328, + 0x00000116, 0x0000032F, + 0x000000E2, 0x00000446, + 0x000000D3, 0x0000044D, + 0x000000BC, 0x00000520, + 0x000000B0, 0x00000526, + 0x000000A4, 0x000005D6, + 0x0000009B, 0x000005DB, + 0x00000092, 0x00000676, + 0x0000008B, 0x00000679, + 0x00000085, 0x00000704, + 0x00000080, 0x00000707, + 0x0000007B, 0x00000787, + 0x00000076, 0x00000789, + 0.9135}, + /* GAMMA 2.5 */ + {0x000001FF, 0x00000000, + 0x000001FF, 0x00000100, + 0x00000159, 0x000001FF, + 0x000001AC, 0x000002AB, + 0x0000012F, 0x00000381, + 0x00000101, 0x00000399, + 0x000000D9, 0x0000049A, + 0x000000C3, 0x000004A5, + 0x000000AF, 0x00000567, + 0x000000A1, 0x0000056E, + 0x00000095, 0x00000610, + 0x0000008C, 0x00000614, + 0x00000084, 0x000006A0, + 0x0000007D, 0x000006A4, + 0x00000077, 0x00000721, + 0x00000071, 0x00000723, + 0x0000006D, 0x00000795, + 0x00000068, 0x00000797, + 0.9135} }; +static void +RADEONSetOverlayGamma(ScrnInfoPtr pScrn, CARD32 GAMMA) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 ov0_scale_cntl; + + /* Set gamma */ + RADEONWaitForIdleMMIO(pScrn); + ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & ~RADEON_SCALER_GAMMA_SEL_MASK; + OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (GAMMA << 0x00000005)); + + /* Load gamma curve adjustments */ + if (info->ChipFamily >= CHIP_FAMILY_R200) { + OUTREG(RADEON_OV0_GAMMA_000_00F, + (gamma_curve_r200[GAMMA].GAMMA_0_F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_0_F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_010_01F, + (gamma_curve_r200[GAMMA].GAMMA_10_1F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_10_1F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_020_03F, + (gamma_curve_r200[GAMMA].GAMMA_20_3F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_20_3F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_040_07F, + (gamma_curve_r200[GAMMA].GAMMA_40_7F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_40_7F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_080_0BF, + (gamma_curve_r200[GAMMA].GAMMA_80_BF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_80_BF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_0C0_0FF, + (gamma_curve_r200[GAMMA].GAMMA_C0_FF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_C0_FF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_100_13F, + (gamma_curve_r200[GAMMA].GAMMA_100_13F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_100_13F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_140_17F, + (gamma_curve_r200[GAMMA].GAMMA_140_17F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_140_17F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_180_1BF, + (gamma_curve_r200[GAMMA].GAMMA_180_1BF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_180_1BF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_1C0_1FF, + (gamma_curve_r200[GAMMA].GAMMA_1C0_1FF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_1C0_1FF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_200_23F, + (gamma_curve_r200[GAMMA].GAMMA_200_23F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_200_23F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_240_27F, + (gamma_curve_r200[GAMMA].GAMMA_240_27F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_240_27F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_280_2BF, + (gamma_curve_r200[GAMMA].GAMMA_280_2BF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_280_2BF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_2C0_2FF, + (gamma_curve_r200[GAMMA].GAMMA_2C0_2FF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_2C0_2FF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_300_33F, + (gamma_curve_r200[GAMMA].GAMMA_300_33F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_300_33F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_340_37F, + (gamma_curve_r200[GAMMA].GAMMA_340_37F_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_340_37F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_380_3BF, + (gamma_curve_r200[GAMMA].GAMMA_380_3BF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_380_3BF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_3C0_3FF, + (gamma_curve_r200[GAMMA].GAMMA_3C0_3FF_OFFSET << 0x00000000) | + (gamma_curve_r200[GAMMA].GAMMA_3C0_3FF_SLOPE << 0x00000010)); + } else { + OUTREG(RADEON_OV0_GAMMA_000_00F, + (gamma_curve_r100[GAMMA].GAMMA_0_F_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_0_F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_010_01F, + (gamma_curve_r100[GAMMA].GAMMA_10_1F_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_10_1F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_020_03F, + (gamma_curve_r100[GAMMA].GAMMA_20_3F_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_20_3F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_040_07F, + (gamma_curve_r100[GAMMA].GAMMA_40_7F_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_40_7F_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_380_3BF, + (gamma_curve_r100[GAMMA].GAMMA_380_3BF_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_380_3BF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_3C0_3FF, + (gamma_curve_r100[GAMMA].GAMMA_3C0_3FF_OFFSET << 0x00000000) | + (gamma_curve_r100[GAMMA].GAMMA_3C0_3FF_SLOPE << 0x00000010)); + } + +} + + /**************************************************************************** * SetTransform * * Function: Calculates and sets color space transform from supplied * @@ -216,6 +683,7 @@ static GAMMA_SETTINGS def_gamma[18] = * green_intensity - intensity of green component * * blue_intensity - intensity of blue component * * ref - index to the table of refernce transforms * + * user_gamma - gamma value x 1000 (e.g., 1200 = gamma of 1.2) * * Outputs: NONE * ****************************************************************************/ @@ -227,7 +695,8 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, float red_intensity, float green_intensity, float blue_intensity, - CARD32 ref) + CARD32 ref, + CARD32 user_gamma) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -248,10 +717,32 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, CARD32 dwOvRCb, dwOvRCr; CARD32 dwOvGCb, dwOvGCr; CARD32 dwOvBCb, dwOvBCr; + CARD32 GAMMA = 0; if (ref >= 2) return; + /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */ + if (user_gamma <= 925) /* 0.85 */ + GAMMA = 1; + else if (user_gamma <= 1050) /* 1.0 */ + GAMMA = 0; + else if (user_gamma <= 1150) /* 1.1 */ + GAMMA = 2; + else if (user_gamma <= 1325) /* 1.2 */ + GAMMA = 3; + else if (user_gamma <= 1575) /* 1.45 */ + GAMMA = 4; + else if (user_gamma <= 1950) /* 1.7 */ + GAMMA = 5; + else if (user_gamma <= 2350) /* 2.2 */ + GAMMA = 6; + else if (user_gamma > 2350) /* 2.5 */ + GAMMA = 7; + + if (GAMMA >= 8) + return; + OvHueSin = sin(hue); OvHueCos = cos(hue); @@ -278,34 +769,34 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, CAdjBCb = 2.01708984375; CAdjBCr = 0; #endif - OvLuma = CAdjLuma; - OvRCb = CAdjRCb; - OvRCr = CAdjRCr; - OvGCb = CAdjGCb; - OvGCr = CAdjGCr; - OvBCb = CAdjBCb; - OvBCr = CAdjBCr; - OvROff = RedAdj + CAdjOff - - OvLuma * Loff - (OvRCb + OvRCr) * Coff; - OvGOff = GreenAdj + CAdjOff - - OvLuma * Loff - (OvGCb + OvGCr) * Coff; - OvBOff = BlueAdj + CAdjOff - - OvLuma * Loff - (OvBCb + OvBCr) * Coff; + + OvLuma = CAdjLuma * gamma_curve_r100[GAMMA].OvGammaCont; + OvRCb = CAdjRCb * gamma_curve_r100[GAMMA].OvGammaCont; + OvRCr = CAdjRCr * gamma_curve_r100[GAMMA].OvGammaCont; + OvGCb = CAdjGCb * gamma_curve_r100[GAMMA].OvGammaCont; + OvGCr = CAdjGCr * gamma_curve_r100[GAMMA].OvGammaCont; + OvBCb = CAdjBCb * gamma_curve_r100[GAMMA].OvGammaCont; + OvBCr = CAdjBCr * gamma_curve_r100[GAMMA].OvGammaCont; + OvROff = CAdjOff * gamma_curve_r100[GAMMA].OvGammaCont - + OvLuma * Loff - (OvRCb + OvRCr) * Coff; + OvGOff = CAdjOff * gamma_curve_r100[GAMMA].OvGammaCont - + OvLuma * Loff - (OvGCb + OvGCr) * Coff; + OvBOff = CAdjOff * gamma_curve_r100[GAMMA].OvGammaCont - + OvLuma * Loff - (OvBCb + OvBCr) * Coff; #if 0 /* default constants */ OvROff = -888.5; OvGOff = 545; OvBOff = -1104; #endif + OvROff = ClipValue(OvROff, -2048.0, 2047.5); + OvGOff = ClipValue(OvGOff, -2048.0, 2047.5); + OvBOff = ClipValue(OvBOff, -2048.0, 2047.5); dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff; dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff; dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff; - /* - * Whatever docs say about R200 having 3.8 format instead of 3.11 - * as in Radeon is a lie - * Or more precisely the location of bit fields is a lie - */ - if(1 || info->ChipFamily < CHIP_FAMILY_R200) + + if(info->ChipFamily == CHIP_FAMILY_RADEON) { dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17; dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1; @@ -317,14 +808,19 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, } else { - dwOvLuma = (((INT32)(OvLuma * 256.0))&0x7ff)<<20; - dwOvRCb = (((INT32)(OvRCb * 256.0))&0x7ff)<<4; - dwOvRCr = (((INT32)(OvRCr * 256.0))&0x7ff)<<20; - dwOvGCb = (((INT32)(OvGCb * 256.0))&0x7ff)<<4; - dwOvGCr = (((INT32)(OvGCr * 256.0))&0x7ff)<<20; - dwOvBCb = (((INT32)(OvBCb * 256.0))&0x7ff)<<4; - dwOvBCr = (((INT32)(OvBCr * 256.0))&0x7ff)<<20; + dwOvLuma = (((INT32)(OvLuma * 256.0))&0xfff)<<20; + dwOvRCb = (((INT32)(OvRCb * 256.0))&0xfff)<<4; + dwOvRCr = (((INT32)(OvRCr * 256.0))&0xfff)<<20; + dwOvGCb = (((INT32)(OvGCb * 256.0))&0xfff)<<4; + dwOvGCr = (((INT32)(OvGCr * 256.0))&0xfff)<<20; + dwOvBCb = (((INT32)(OvBCb * 256.0))&0xfff)<<4; + dwOvBCr = (((INT32)(OvBCr * 256.0))&0xfff)<<20; } + + /* set gamma */ + RADEONSetOverlayGamma(pScrn, GAMMA); + + /* color transforms */ OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma); OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr); OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma); @@ -333,6 +829,58 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr); } +static void RADEONSetOverlayAlpha(ScrnInfoPtr pScrn, int ov_alpha, int gr_alpha, int alpha_mode) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (alpha_mode == 0) { /* key mode */ + OUTREG(RADEON_OV0_KEY_CNTL, + RADEON_GRAPHIC_KEY_FN_EQ | /* what does this do? */ + RADEON_VIDEO_KEY_FN_FALSE | /* what does this do? */ + RADEON_CMP_MIX_OR); + /* crtc 1 */ + OUTREG(RADEON_DISP_MERGE_CNTL, + (RADEON_DISP_ALPHA_MODE_KEY & + RADEON_DISP_ALPHA_MODE_MASK) | + ((gr_alpha << 0x00000010) & + RADEON_DISP_GRPH_ALPHA_MASK) | + ((ov_alpha << 0x00000018) & + RADEON_DISP_OV0_ALPHA_MASK)); + /* crtc 2 */ + OUTREG(RADEON_DISP2_MERGE_CNTL, + (RADEON_DISP_ALPHA_MODE_KEY & + RADEON_DISP_ALPHA_MODE_MASK) | + ((gr_alpha << 0x00000010) & + RADEON_DISP_GRPH_ALPHA_MASK) | + ((ov_alpha << 0x00000018) & + RADEON_DISP_OV0_ALPHA_MASK)); + } else { /* global mode */ + OUTREG(RADEON_OV0_KEY_CNTL, + RADEON_GRAPHIC_KEY_FN_FALSE | /* what does this do? */ + RADEON_VIDEO_KEY_FN_FALSE | /* what does this do? */ + RADEON_CMP_MIX_AND); + /* crtc 2 */ + OUTREG(RADEON_DISP2_MERGE_CNTL, + (RADEON_DISP_ALPHA_MODE_GLOBAL & + RADEON_DISP_ALPHA_MODE_MASK) | + ((gr_alpha << 0x00000010) & + RADEON_DISP_GRPH_ALPHA_MASK) | + ((ov_alpha << 0x00000018) & + RADEON_DISP_OV0_ALPHA_MASK)); + /* crtc 1 */ + OUTREG(RADEON_DISP_MERGE_CNTL, + (RADEON_DISP_ALPHA_MODE_GLOBAL & + RADEON_DISP_ALPHA_MODE_MASK) | + ((gr_alpha << 0x00000010) & + RADEON_DISP_GRPH_ALPHA_MASK) | + ((ov_alpha << 0x00000018) & + RADEON_DISP_OV0_ALPHA_MASK)); + } + /* per-pixel mode - RADEON_DISP_ALPHA_MODE_PER_PIXEL */ + /* not yet supported */ +} + static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 colorKey) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -375,14 +923,52 @@ RADEONResetVideo(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; + char tmp[200]; - if (info->accelOn) info->accel->Sync(pScrn); + /* this function is called from ScreenInit. pScreen is used + by XAA internally, but not valid until ScreenInit finishs. + */ + if (info->accelOn && pScrn->pScreen && info->accel) + (*info->accel->Sync)(pScrn); - RADEONWaitForIdleMMIO(pScrn); - OUTREG(RADEON_OV0_SCALE_CNTL, 0x80000000); + /* this is done here because each time the server is reset these + could change.. Otherwise they remain constant */ + xvInstanceID = MAKE_ATOM("XV_INSTANCE_ID"); + xvDeviceID = MAKE_ATOM("XV_DEVICE_ID"); + xvLocationID = MAKE_ATOM("XV_LOCATION_ID"); + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvColor = MAKE_ATOM("XV_COLOR"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); + xvHue = MAKE_ATOM("XV_HUE"); + xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY"); + xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY"); + xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY"); + xvGamma = MAKE_ATOM("XV_GAMMA"); + xvColorspace = MAKE_ATOM("XV_COLORSPACE"); + + xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); + xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT"); + + xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); + xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); + xvAlphaMode = MAKE_ATOM("XV_ALPHA_MODE"); + + sprintf(tmp, "RXXX:%d.%d.%d", info->PciInfo->vendor, info->PciInfo->chipType, info->PciInfo->chipRev); + pPriv->device_id = MAKE_ATOM(tmp); + sprintf(tmp, "PCI:%02d:%02d.%d", info->PciInfo->bus, info->PciInfo->device, info->PciInfo->func); + pPriv->location_id = MAKE_ATOM(tmp); + sprintf(tmp, "INSTANCE:%d", pScrn->scrnIndex); + pPriv->instance_id = MAKE_ATOM(tmp); + + OUTREG(RADEON_OV0_SCALE_CNTL, RADEON_SCALER_SOFT_RESET); OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0); - OUTREG(RADEON_OV0_FILTER_CNTL, 0x0000000f); + OUTREG(RADEON_OV0_FILTER_CNTL, RADEON_FILTER_PROGRAMMABLE_COEF); OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ | RADEON_VIDEO_KEY_FN_FALSE | RADEON_CMP_MIX_OR); @@ -391,12 +977,16 @@ RADEONResetVideo(ScrnInfoPtr pScrn) OUTREG(RADEON_CAP0_TRIG_CNTL, 0); RADEONSetColorKey(pScrn, pPriv->colorKey); - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || - (info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RADEON)) { - int i; + if (info->ChipFamily == CHIP_FAMILY_RADEON) { + + OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000); + OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e); + OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0); + OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442); + OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040); + OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); + + } else { OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000); OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e); @@ -404,28 +994,17 @@ RADEONResetVideo(ScrnInfoPtr pScrn) OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442); OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046); OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); - + } /* - * Set default Gamma ramp: + * Set default gamma ramp: * * Of 18 segments for gamma curve, all segments in R200 (and * newer) are programmable, while only lower 4 and upper 2 * segments are programmable in the older Radeons. */ - for (i = 0; i < 18; i++) { - OUTREG(def_gamma[i].gammaReg, - (def_gamma[i].gammaSlope<<16) | def_gamma[i].gammaOffset); - } - } else { - OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000); - OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e); - OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0); - OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442); - OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040); - OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); - } -} + RADEONSetOverlayGamma(pScrn, 0); /* gamma = 1.0 */ +} static XF86VideoAdaptorPtr RADEONAllocAdaptor(ScrnInfoPtr pScrn) @@ -433,7 +1012,7 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) XF86VideoAdaptorPtr adapt; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv; - unsigned char *RADEONMMIO = info->MMIO; + CARD32 dot_clock; if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) return NULL; @@ -460,30 +1039,59 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->hue = 0; pPriv->currentBuffer = 0; pPriv->autopaint_colorkey = TRUE; + pPriv->gamma = 1000; + if (info->OverlayOnCRTC2) + pPriv->crt2 = TRUE; + else + pPriv->crt2 = FALSE; + + pPriv->ov_alpha = 255; + pPriv->gr_alpha = 255; + pPriv->alpha_mode = 0; /* * Unlike older Mach64 chips, RADEON has only two ECP settings: * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) * for higher clocks, sure makes life nicer */ - if(info->ModeReg.dot_clock_freq < 17500) + + /* Figure out which head we are on */ + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + dot_clock = info->ModeReg.dot_clock_freq_2; + else + dot_clock = info->ModeReg.dot_clock_freq; + + if(dot_clock < 17500) pPriv->ecp_div = 0; else pPriv->ecp_div = 1; -#if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div); -#endif + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & + 0xfffffCff) | (pPriv->ecp_div << 8)); + + /* I suspect we may need a usleep after writing to the PLL. if you play a video too soon + after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey + on the right edge video output. */ - OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & - 0xfffffCff) | (pPriv->ecp_div << 8)); if ((info->ChipFamily == CHIP_FAMILY_RS100) || (info->ChipFamily == CHIP_FAMILY_RS200) || (info->ChipFamily == CHIP_FAMILY_RS300)) { - /* Force the overlay clock on for integrated chips + /* Force the overlay clock on for integrated chips */ - OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18))); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, + (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18))); + } + + /* overlay scaler line length differs for different revisions + this needs to be maintained by hand */ + switch(info->ChipFamily){ + case CHIP_FAMILY_R200: + case CHIP_FAMILY_R300: + pPriv->overlay_scaler_buffer_width=1920; + break; + default: + pPriv->overlay_scaler_buffer_width=1536; } info->adaptor = adapt; @@ -527,20 +1135,6 @@ RADEONSetupImageVideo(ScreenPtr pScreen) pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr); REGION_NULL(pScreen, &(pPriv->clip)); - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvSaturation = MAKE_ATOM("XV_SATURATION"); - xvColor = MAKE_ATOM("XV_COLOR"); - xvContrast = MAKE_ATOM("XV_CONTRAST"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); - xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); - xvHue = MAKE_ATOM("XV_HUE"); - xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY"); - xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY"); - xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY"); - - xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); - xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); - RADEONResetVideo(pScrn); return adapt; @@ -560,9 +1154,9 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) RADEONWaitForFifo(pScrn, 2); OUTREG(RADEON_OV0_SCALE_CNTL, 0); } - if(info->videoLinear) { - xf86FreeOffscreenLinear(info->videoLinear); - info->videoLinear = NULL; + if (info->videoLinear != NULL) { + xf86FreeOffscreenLinear(info->videoLinear); + info->videoLinear = NULL; } pPriv->videoStatus = 0; } else { @@ -582,15 +1176,16 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; Bool setTransform = FALSE; + Bool setAlpha = FALSE; - info->accel->Sync(pScrn); + if (info->accel) + (*info->accel->Sync)(pScrn); #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) #define RTFBrightness(a) (((a)*1.0)/2000.0) #define RTFIntensity(a) (((a)*1.0)/2000.0) #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) #define RTFHue(a) (((a)*3.1416)/1000.0) -#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) if(attribute == xvAutopaintColorkey) { @@ -606,8 +1201,18 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, pPriv->red_intensity = 0; pPriv->green_intensity = 0; pPriv->blue_intensity = 0; + pPriv->gamma = 1000; + pPriv->transform_index = 0; pPriv->doubleBuffer = FALSE; + pPriv->ov_alpha = 255; + pPriv->gr_alpha = 255; + pPriv->alpha_mode = 0; + + /* It is simpler to call itself */ + RADEONSetPortAttribute(pScrn, xvDoubleBuffer, 1, data); + setTransform = TRUE; + setAlpha = TRUE; } else if(attribute == xvBrightness) { @@ -644,10 +1249,19 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, pPriv->blue_intensity = ClipValue (value, -1000, 1000); setTransform = TRUE; } + else if(attribute == xvGamma) + { + pPriv->gamma = ClipValue (value, 100, 10000); + setTransform = TRUE; + } + else if(attribute == xvColorspace) + { + pPriv->transform_index = ClipValue (value, 0, 1); + setTransform = TRUE; + } else if(attribute == xvDoubleBuffer) { pPriv->doubleBuffer = ClipValue (value, 0, 1); - pPriv->doubleBuffer = value; } else if(attribute == xvColorKey) { @@ -655,6 +1269,30 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } + else if(attribute == xvSwitchCRT) + { + pPriv->crt2 = ClipValue (value, 0, 1); + pPriv->crt2 = value; + if (pPriv->crt2) + info->OverlayOnCRTC2 = TRUE; + else + info->OverlayOnCRTC2 = FALSE; + } + else if(attribute == xvOvAlpha) + { + pPriv->ov_alpha = ClipValue (value, 0, 255); + setAlpha = TRUE; + } + else if(attribute == xvGrAlpha) + { + pPriv->gr_alpha = ClipValue (value, 0, 255); + setAlpha = TRUE; + } + else if(attribute == xvAlphaMode) + { + pPriv->alpha_mode = ClipValue (value, 0, 1); + setAlpha = TRUE; + } else return BadMatch; @@ -668,7 +1306,13 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RTFIntensity(pPriv->red_intensity), RTFIntensity(pPriv->green_intensity), RTFIntensity(pPriv->blue_intensity), - pPriv->transform_index); + pPriv->transform_index, + pPriv->gamma); + } + + if (setAlpha) + { + RADEONSetOverlayAlpha(pScrn, pPriv->ov_alpha, pPriv->gr_alpha, pPriv->alpha_mode); } return Success; @@ -683,7 +1327,8 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; - if (info->accelOn) info->accel->Sync(pScrn); + if (info->accelOn && info->accel) + (*info->accel->Sync)(pScrn); if(attribute == xvAutopaintColorkey) *value = pPriv->autopaint_colorkey; @@ -701,10 +1346,28 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->green_intensity; else if(attribute == xvBlueIntensity) *value = pPriv->blue_intensity; + else if(attribute == xvGamma) + *value = pPriv->gamma; + else if(attribute == xvColorspace) + *value = pPriv->transform_index; else if(attribute == xvDoubleBuffer) *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; + else if(attribute == xvSwitchCRT) + *value = pPriv->crt2 ? 1 : 0; + else if(attribute == xvOvAlpha) + *value = pPriv->ov_alpha; + else if(attribute == xvGrAlpha) + *value = pPriv->gr_alpha; + else if(attribute == xvAlphaMode) + *value = pPriv->alpha_mode; + else if(attribute == xvDeviceID) + *value = pPriv->device_id; + else if(attribute == xvLocationID) + *value = pPriv->location_id; + else if(attribute == xvInstanceID) + *value = pPriv->instance_id; else return BadMatch; @@ -729,115 +1392,421 @@ RADEONQueryBestSize( *p_h = drw_h; } +static struct { + double range; + signed char coeff[5][4]; + } TapCoeffs[]= + { + {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }}, + {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }}, + {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, + {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, + {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }}, + {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }}, + {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }}, + {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, + {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, + {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }}, + {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, + {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, + {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, + {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }}, + {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, + {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, + {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, + {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, + {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }}, + {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }}, + {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }}, + {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, + {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, + {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }}, + {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }}, + {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, + {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, + {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, + {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, + {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }}, + {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }}, + {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, + {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, + {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, + {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }}, + {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}, + {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }} + }; + static void RADEONCopyData( + ScrnInfoPtr pScrn, + unsigned char *src, + unsigned char *dst, + unsigned int srcPitch, + unsigned int dstPitch, + unsigned int h, + unsigned int w, + unsigned int bpp +){ + RADEONInfoPtr info = RADEONPTR(pScrn); +#ifdef XF86DRI + + if ( info->directRenderingEnabled && info->DMAForXv ) + { + CARD8 *buf; + CARD32 bufPitch, dstPitchOff; + int x, y; + unsigned int hpass; + + /* Get the byte-swapping right for big endian systems */ + if ( bpp == 2 ) + { + w *= 2; + bpp = 1; + } + + RADEONHostDataParams( pScrn, dst, dstPitch, bpp, &dstPitchOff, &x, &y ); + + while ( (buf = RADEONHostDataBlit( pScrn, bpp, w, dstPitchOff, &bufPitch, + x, &y, &h, &hpass )) ) + { + RADEONHostDataBlitCopyPass( pScrn, bpp, buf, src, hpass, bufPitch, + srcPitch ); + src += hpass * srcPitch; + } + + FLUSH_RING(); + + return; + } + else +#endif /* XF86DRI */ + { +#if X_BYTE_ORDER == X_BIG_ENDIAN + unsigned char *RADEONMMIO = info->MMIO; + unsigned int swapper = info->ModeReg.surface_cntl & + ~(RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP | + RADEON_NONSURF_AP0_SWP_16BPP | RADEON_NONSURF_AP1_SWP_16BPP); + + switch(bpp) { + case 2: + swapper |= RADEON_NONSURF_AP0_SWP_16BPP + | RADEON_NONSURF_AP1_SWP_16BPP; + break; + case 4: + swapper |= RADEON_NONSURF_AP0_SWP_32BPP + | RADEON_NONSURF_AP1_SWP_32BPP; + break; + } + OUTREG(RADEON_SURFACE_CNTL, swapper); +#endif + w *= bpp; + + while (h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* restore byte swapping */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); +#endif + } +} + +#ifdef XF86DRI +static void RADEON_420_422( + unsigned int *d, + unsigned char *s1, + unsigned char *s2, + unsigned char *s3, + unsigned int n +) +{ + while ( n ) { + *(d++) = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + s1+=2; s2++; s3++; + n--; + } +} +#endif + +static void +RADEONCopyRGB24Data( + ScrnInfoPtr pScrn, unsigned char *src, unsigned char *dst, - int srcPitch, - int dstPitch, - int h, - int w + unsigned int srcPitch, + unsigned int dstPitch, + unsigned int h, + unsigned int w ){ - w <<= 1; - while(h--) { - memcpy(dst, src, w); - src += srcPitch; - dst += dstPitch; + CARD32 *dptr; + CARD8 *sptr = 0; + unsigned int i,j; + RADEONInfoPtr info = RADEONPTR(pScrn); +#ifdef XF86DRI + + if ( info->directRenderingEnabled && info->DMAForXv ) + { + CARD32 bufPitch, dstPitchOff; + int x, y; + unsigned int hpass; + + /* XXX Fix endian flip on R300 */ + + RADEONHostDataParams( pScrn, dst, dstPitch, 4, &dstPitchOff, &x, &y ); + + while ( (dptr = ( CARD32* )RADEONHostDataBlit( pScrn, 4, w, dstPitch, + &bufPitch, x, &y, &h, + &hpass )) ) + { + for( j = 0; j < hpass; j++ ) + { + sptr = src; + + for ( i = 0 ; i < w; i++, sptr += 3 ) + { + *dptr++ = (sptr[0] << 24) | (sptr[1] << 16) | sptr[2]; + } + + src += hpass * srcPitch; + dptr += hpass * bufPitch; + } + } + + FLUSH_RING(); + + return; + } + else +#endif /* XF86DRI */ + { +#if X_BYTE_ORDER == X_BIG_ENDIAN + unsigned char *RADEONMMIO = info->MMIO; + OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl + | RADEON_NONSURF_AP0_SWP_32BPP) + & ~RADEON_NONSURF_AP0_SWP_16BPP); +#endif + + for(j=0;j<h;j++){ + dptr=(CARD32 *)(pointer)(dst+j*dstPitch); + sptr=src+j*srcPitch; + + for(i=w;i>0;i--){ + dptr[0]=((sptr[0])<<24)|((sptr[1])<<16)|(sptr[2]); + dptr++; + sptr+=3; + } + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* restore byte swapping */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); +#endif } } static void RADEONCopyMungedData( + ScrnInfoPtr pScrn, unsigned char *src1, unsigned char *src2, unsigned char *src3, unsigned char *dst1, - int srcPitch, - int srcPitch2, - int dstPitch, - int h, - int w + unsigned int srcPitch, + unsigned int srcPitch2, + unsigned int dstPitch, + unsigned int h, + unsigned int w ){ - CARD32 *dst; - CARD8 *s1, *s2, *s3; - int i, j; - - w >>= 1; - - for(j = 0; j < h; j++) { - dst = (pointer)dst1; - s1 = src1; s2 = src2; s3 = src3; - i = w; - while(i > 4) { - dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); - dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); - dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); - dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); - dst += 4; s2 += 4; s3 += 4; s1 += 8; - i -= 4; - } - while(i--) { - dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); - dst++; s2++; s3++; - s1 += 2; + RADEONInfoPtr info = RADEONPTR(pScrn); +#ifdef XF86DRI + + if ( info->directRenderingEnabled && info->DMAForXv ) + { + CARD8 *buf; + CARD32 y = 0, bufPitch, dstPitchOff; + int blitX, blitY; + unsigned int hpass; + + /* XXX Fix endian flip on R300 */ + + RADEONHostDataParams( pScrn, dst1, dstPitch, 4, &dstPitchOff, &blitX, &blitY ); + + while ( (buf = RADEONHostDataBlit( pScrn, 4, w/2, dstPitchOff, &bufPitch, + blitX, &blitY, &h, &hpass )) ) + { + while ( hpass-- ) + { + RADEON_420_422( (unsigned int *) (pointer) buf, + src1, src2, src3, bufPitch / 4 ); + src1 += srcPitch; + if ( y & 1 ) + { + src2 += srcPitch2; + src3 += srcPitch2; + } + buf += bufPitch; + y++; + } } - dst1 += dstPitch; - src1 += srcPitch; - if(j & 1) { - src2 += srcPitch2; - src3 += srcPitch2; + FLUSH_RING(); + } + else +#endif /* XF86DRI */ + { + CARD32 *dst; + CARD8 *s1, *s2, *s3; + unsigned int i, j; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + unsigned char *RADEONMMIO = info->MMIO; + OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl + | RADEON_NONSURF_AP0_SWP_32BPP) + & ~RADEON_NONSURF_AP0_SWP_16BPP); +#endif + + w /= 2; + + for( j = 0; j < h; j++ ) + { + dst = (pointer)dst1; + s1 = src1; s2 = src2; s3 = src3; + i = w; + while( i > 4 ) + { + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24); + dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24); + dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24); + dst += 4; s2 += 4; s3 += 4; s1 += 8; + i -= 4; + } + while( i-- ) + { + dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24); + dst++; s2++; s3++; + s1 += 2; + } + + dst1 += dstPitch; + src1 += srcPitch; + if( j & 1 ) + { + src2 += srcPitch2; + src3 += srcPitch2; + } } - } +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* restore byte swapping */ + OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl); +#endif + } } - -static FBLinearPtr +/* Allocates memory, either by resizing the allocation pointed to by mem_struct, + * or by freeing mem_struct (if non-NULL) and allocating a new space. The size + * is measured in bytes, and the offset from the beginning of card space is + * returned. + */ +static CARD32 RADEONAllocateMemory( ScrnInfoPtr pScrn, - FBLinearPtr linear, + FBLinearPtr *linear, int size ){ - ScreenPtr pScreen; - FBLinearPtr new_linear; + ScreenPtr pScreen; + RADEONInfoPtr info = RADEONPTR(pScrn); + int offset = 0; + int cpp = info->CurrentLayout.bitsPerPixel / 8; - if(linear) { - if(linear->size >= size) - return linear; + pScreen = screenInfo.screens[pScrn->scrnIndex]; - if(xf86ResizeOffscreenLinear(linear, size)) - return linear; + /* XAA allocates in units of pixels at the screen bpp, so adjust size + * appropriately. + */ + size = (size + cpp - 1) / cpp; - xf86FreeOffscreenLinear(linear); - } + if (*linear) { + if ((*linear)->size >= size) + return (*linear)->offset * cpp; - pScreen = screenInfo.screens[pScrn->scrnIndex]; + if (xf86ResizeOffscreenLinear(*linear, size)) + return (*linear)->offset * cpp; + + xf86FreeOffscreenLinear(*linear); + } - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, - NULL, NULL, NULL); + *linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, NULL, NULL); - if(!new_linear) { + if (!*linear) { int max_size; xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, - PRIORITY_EXTREME); + PRIORITY_EXTREME); - if(max_size < size) - return NULL; + if (max_size < size) + return 0; xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, - NULL, NULL, NULL); - } + *linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + if (!*linear) + return 0; + } + offset = (*linear)->offset * cpp; - return new_linear; + return offset; } static void RADEONDisplayVideo( ScrnInfoPtr pScrn, + RADEONPortPrivPtr pPriv, int id, int offset1, int offset2, + int offset3, int offset4, short width, short height, int pitch, int left, int right, int top, @@ -847,118 +1816,236 @@ RADEONDisplayVideo( ){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int v_inc, h_inc, step_by, tmp; + CARD32 v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp; + double h_inc_d; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init; int ecp_div; int v_inc_shift; int y_mult; int x_off; + int y_off; CARD32 scaler_src; + CARD32 dot_clock; + DisplayModePtr overlay_mode; + int is_rgb; + int i; + CARD32 scale_cntl; + double dsr; + int tap_set; + + is_rgb=0; + switch(id){ + case FOURCC_RGBA32: + case FOURCC_RGB24: + case FOURCC_RGBT16: + case FOURCC_RGB16: + is_rgb=1; + break; + default: + break; + } /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < 175Mhz, and 1 (divide by 2) for higher clocks, sure makes life nicer Here we need to find ecp_div again, as the user may have switched resolutions */ - if(info->ModeReg.dot_clock_freq < 17500) + + /* Figure out which head we are on for dot clock */ + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + dot_clock = info->ModeReg.dot_clock_freq_2; + else + dot_clock = info->ModeReg.dot_clock_freq; + + if (dot_clock < 17500) ecp_div = 0; else ecp_div = 1; - OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8)); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, + (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8)); + + /* I suspect we may need a usleep after writing to the PLL. if you play a video too soon + after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey + on the right edge video output. */ v_inc_shift = 20; - if (pScrn->currentMode->Flags & V_INTERLACE) - v_inc_shift++; - if (pScrn->currentMode->Flags & V_DBLSCAN) - v_inc_shift--; - if (pScrn->currentMode->Flags & RADEON_USE_RMX) { - v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + y_mult = 1; + + if (info->MergedFB) { + if (info->OverlayOnCRTC2) + overlay_mode = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2; + else + overlay_mode = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT1; + if (overlay_mode->Flags & V_INTERLACE) + v_inc_shift++; + if (overlay_mode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + if (overlay_mode->Flags & RADEON_USE_RMX) { + v_inc = ((src_h * overlay_mode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + } else { + v_inc = (src_h << v_inc_shift) / drw_h; + } } else { - v_inc = (src_h << v_inc_shift) / drw_h; + if (pScrn->currentMode->Flags & V_INTERLACE) + v_inc_shift++; + if (pScrn->currentMode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + if (pScrn->currentMode->Flags & RADEON_USE_RMX) { + v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + } else { + v_inc = (src_h << v_inc_shift) / drw_h; + } } - h_inc = ((src_w << (12 + ecp_div)) / drw_w); - step_by = 1; - while(h_inc >= (2 << 12)) { - step_by++; + h_inc = (1 << (12 + ecp_div)); + + step_by_y = 1; + step_by_uv = step_by_y; + + /* if the source width was larger than what would fit in overlay scaler increase step_by values */ + i=src_w; + while(i>pPriv->overlay_scaler_buffer_width){ + step_by_y++; + step_by_uv++; + h_inc >>=1; + i=i/2; + } + + + h_inc_d = src_w; + h_inc_d = h_inc_d/drw_w; + /* we could do a tad better - but why + bother when this concerns downscaling and the code is so much more + hairy */ + while(h_inc*h_inc_d >= (2 << 12)) { + if(!is_rgb && (((h_inc+h_inc/2)*h_inc_d)<(2<<12))){ + step_by_uv = step_by_y+1; + break; + } + step_by_y++; + step_by_uv = step_by_y; h_inc >>= 1; - } + } + h_inc_uv = h_inc>>(step_by_uv-step_by_y); + h_inc = h_inc * h_inc_d; + h_inc_uv = h_inc_uv * h_inc_d; + /* pPriv->overlay_scaler_buffer_width is magic number - maximum line length the overlay scaler can fit + in the buffer for 2 tap filtering */ + /* the only place it is documented in is in ATI source code */ + /* we need twice as much space for 4 tap filtering.. */ + /* under special circumstances turn on 4 tap filtering */ + /* disable this code for now as it has a DISASTROUS effect on image quality when upscaling + at least on rv250 (only as long as the drw_w*2 <=... requirement is still met of course) */ +#if 0 + if(!is_rgb && (step_by_y==1) && (step_by_uv==1) && (h_inc < (1<<12)) && + (drw_w*2 <= pPriv->overlay_scaler_buffer_width)){ + step_by_y=0; + step_by_uv=1; + h_inc_uv = h_inc; + } +#endif /* keep everything in 16.16 */ offset1 += ((left >> 16) & ~7) << 1; offset2 += ((left >> 16) & ~7) << 1; + offset3 += ((left >> 16) & ~7) << 1; + offset4 += ((left >> 16) & ~7) << 1; if (info->IsSecondary) { offset1 += info->FbMapSize; offset2 += info->FbMapSize; + offset3 += info->FbMapSize; + offset4 += info->FbMapSize; } tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); p1_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0xf0000000); - tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); + tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc_uv << 2); p23_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0x70000000); tmp = (top & 0x0000ffff) + 0x00018000; - p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; + p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | ((!is_rgb)?0x03:0x01); left = (left >> 16) & 7; RADEONWaitForFifo(pScrn, 2); - OUTREG(RADEON_OV0_REG_LOAD_CNTL, 1); - if (info->accelOn) info->accel->Sync(pScrn); - while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3))); + OUTREG(RADEON_OV0_REG_LOAD_CNTL, RADEON_REG_LD_CTL_LOCK); + if (info->accelOn && info->accel) + (*info->accel->Sync)(pScrn); + while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_LOCK_READBACK)); - RADEONWaitForFifo(pScrn, 14); - OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); - OUTREG(RADEON_OV0_STEP_BY, step_by | (step_by << 8)); + RADEONWaitForFifo(pScrn, 10); + OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc_uv >> 1) << 16)); + OUTREG(RADEON_OV0_STEP_BY, step_by_y | (step_by_uv << 8)); - y_mult = 1; - if (pScrn->currentMode->Flags & V_DBLSCAN) - y_mult = 2; x_off = 8; + y_off = 0; - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350) || - (info->ChipFamily == CHIP_FAMILY_R200)) + if (IS_R300_VARIANT || + (info->ChipFamily == CHIP_FAMILY_R200)) x_off = 0; + /* needed to make the overlay work on crtc1 in leftof and above modes */ + if (info->MergedFB) { + RADEONScrn2Rel srel = + ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2Position; + overlay_mode = ((RADEONMergedDisplayModePtr)(pointer)info->CurrentLayout.mode->Private)->CRT2; + if (srel == radeonLeftOf) { + x_off -= overlay_mode->CrtcHDisplay; + /* y_off -= pScrn->frameY0; */ + } + if (srel == radeonAbove) { + y_off -= overlay_mode->CrtcVDisplay; + /* x_off -= pScrn->frameX0; */ + } + } + /* Put the hardware overlay on CRTC2: * * Since one hardware overlay can not be displayed on two heads * at the same time, we might need to consider using software * rendering for the second head. */ - if ((info->Clone && info->OverlayOnCRTC2) || info->IsSecondary) { + + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) { x_off = 0; - OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 - + x_off - - info->CloneFrameX0 - + pScrn->frameX0) | - ((dstBox->y1*y_mult - - info->CloneFrameY0 - + pScrn->frameY0) << 16))); - OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 - + x_off - - info->CloneFrameX0 - + pScrn->frameX0) | - ((dstBox->y2*y_mult - - info->CloneFrameY0 - + pScrn->frameY0) << 16))); - scaler_src = (1 << 14); + OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | + ((dstBox->y1*y_mult) << 16))); + OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 + x_off) | + ((dstBox->y2*y_mult) << 16))); + scaler_src = RADEON_SCALER_CRTC_SEL; } else { OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) | - ((dstBox->y1*y_mult) << 16))); + (((dstBox->y1*y_mult) + y_off) << 16))); OUTREG(RADEON_OV0_Y_X_END, ((dstBox->x2 + x_off) | - ((dstBox->y2*y_mult) << 16))); + (((dstBox->y2*y_mult) + y_off) << 16))); scaler_src = 0; } + /* program the tap coefficients for better downscaling quality. + Could do slightly better by using hardcoded coefficients for one axis + in case only the other axis is downscaled (see RADEON_OV0_FILTER_CNTL) */ + dsr=(double)(1<<0xC)/h_inc; + if(dsr<0.25)dsr=0.25; + if(dsr>1.0)dsr=1.0; + tap_set=(int)((dsr-0.25)*100); + for(i=0;i<5;i++){ + OUTREG(RADEON_OV0_FOUR_TAP_COEF_0+i*4, (TapCoeffs[tap_set].coeff[i][0] &0xf) | + ((TapCoeffs[tap_set].coeff[i][1] &0x7f)<<8) | + ((TapCoeffs[tap_set].coeff[i][2] &0x7f)<<16) | + ((TapCoeffs[tap_set].coeff[i][3] &0xf)<<24)); + } + + RADEONWaitForFifo(pScrn, 10); OUTREG(RADEON_OV0_V_INC, v_inc); OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch); @@ -969,38 +2056,41 @@ RADEONDisplayVideo( OUTREG(RADEON_OV0_P3_X_START_END, (src_w + left - 1) | (left << 16)); OUTREG(RADEON_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); OUTREG(RADEON_OV0_VID_BUF1_BASE_ADRS, offset2 & 0xfffffff0); - OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset1 & 0xfffffff0); + OUTREG(RADEON_OV0_VID_BUF2_BASE_ADRS, offset3 & 0xfffffff0); RADEONWaitForFifo(pScrn, 9); - OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset2 & 0xfffffff0); + OUTREG(RADEON_OV0_VID_BUF3_BASE_ADRS, offset4 & 0xfffffff0); OUTREG(RADEON_OV0_VID_BUF4_BASE_ADRS, offset1 & 0xfffffff0); OUTREG(RADEON_OV0_VID_BUF5_BASE_ADRS, offset2 & 0xfffffff0); OUTREG(RADEON_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); OUTREG(RADEON_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); OUTREG(RADEON_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); -#if 0 - if(id == FOURCC_UYVY) - OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008C03); - else - OUTREG(RADEON_OV0_SCALE_CNTL, 0x41008B03); -#endif - - if (id == FOURCC_UYVY) - OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_YVYU422 - | RADEON_SCALER_ADAPTIVE_DEINT - | RADEON_SCALER_SMART_SWITCH - | RADEON_SCALER_DOUBLE_BUFFER - | RADEON_SCALER_ENABLE - | scaler_src)); - else - OUTREG(RADEON_OV0_SCALE_CNTL, (RADEON_SCALER_SOURCE_VYUY422 - | RADEON_SCALER_ADAPTIVE_DEINT - | RADEON_SCALER_SMART_SWITCH - | RADEON_SCALER_DOUBLE_BUFFER - | RADEON_SCALER_ENABLE - | scaler_src)); - + scale_cntl = RADEON_SCALER_ADAPTIVE_DEINT | RADEON_SCALER_DOUBLE_BUFFER + | RADEON_SCALER_ENABLE | RADEON_SCALER_SMART_SWITCH | (0x7f<<16) | scaler_src; + switch(id){ + case FOURCC_UYVY: + scale_cntl |= RADEON_SCALER_SOURCE_YVYU422; + break; + case FOURCC_RGB24: + case FOURCC_RGBA32: + scale_cntl |= RADEON_SCALER_SOURCE_32BPP | RADEON_SCALER_LIN_TRANS_BYPASS; + break; + case FOURCC_RGB16: + scale_cntl |= RADEON_SCALER_SOURCE_16BPP | RADEON_SCALER_LIN_TRANS_BYPASS; + break; + case FOURCC_RGBT16: + scale_cntl |= RADEON_SCALER_SOURCE_15BPP | RADEON_SCALER_LIN_TRANS_BYPASS; + break; + case FOURCC_YUY2: + case FOURCC_YV12: + case FOURCC_I420: + default: + scale_cntl |= RADEON_SCALER_SOURCE_VYUY422 + | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); + break; + } + OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); } @@ -1024,15 +2114,9 @@ RADEONPutImage( int new_size, offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; int top, left, npixels, nlines, bpp; + int video_offset; BoxRec dstBox; CARD32 tmp; -#if X_BYTE_ORDER == X_BIG_ENDIAN - unsigned char *RADEONMMIO = info->MMIO; - CARD32 surface_cntl = INREG(RADEON_SURFACE_CNTL); - - OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | - RADEON_NONSURF_AP0_SWP_32BPP) & ~RADEON_NONSURF_AP0_SWP_16BPP); -#endif /* * s2offset, s3offset - byte offsets into U and V plane of the @@ -1064,22 +2148,44 @@ RADEONPutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; + if (info->MergedFB) + RADEONChooseOverlayCRTC(pScrn, &dstBox); + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; + if (info->MergedFB && info->OverlayOnCRTC2) { + dstBox.x1 -= info->CRT2pScrn->frameX0; + dstBox.x2 -= info->CRT2pScrn->frameX0; + dstBox.y1 -= info->CRT2pScrn->frameY0; + dstBox.y2 -= info->CRT2pScrn->frameY0; + } else { + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + } bpp = pScrn->bitsPerPixel >> 3; switch(id) { + case FOURCC_RGB24: + dstPitch=(width*4+0x0f)&(~0x0f); + srcPitch=width*3; + break; + case FOURCC_RGBA32: + dstPitch=(width*4+0x0f)&(~0x0f); + srcPitch=width*4; + break; + case FOURCC_RGB16: + case FOURCC_RGBT16: + dstPitch=(width*2+0x0f)&(~0x0f); + srcPitch=(width*2+3)&(~0x03); + break; case FOURCC_YV12: case FOURCC_I420: - dstPitch = ((width << 1) + 15) & ~15; - new_size = ((dstPitch * height) + bpp - 1) / bpp; + dstPitch = ((width << 1) + 63) & ~63; srcPitch = (width + 3) & ~3; s2offset = srcPitch * height; srcPitch2 = ((width >> 1) + 3) & ~3; @@ -1088,17 +2194,17 @@ RADEONPutImage( case FOURCC_UYVY: case FOURCC_YUY2: default: - dstPitch = ((width << 1) + 15) & ~15; - new_size = ((dstPitch * height) + bpp - 1) / bpp; + dstPitch = ((width << 1) + 63) & ~63; srcPitch = (width << 1); break; } - if(!(info->videoLinear = RADEONAllocateMemory(pScrn, info->videoLinear, - pPriv->doubleBuffer ? (new_size << 1) : new_size))) - { - return BadAlloc; - } + new_size = dstPitch * height; + video_offset = RADEONAllocateMemory(pScrn, &info->videoLinear, + (pPriv->doubleBuffer ? + (new_size * 2) : new_size)); + if (video_offset == 0) + return BadAlloc; pPriv->currentBuffer ^= 1; @@ -1107,9 +2213,10 @@ RADEONPutImage( left = (xa >> 16) & ~1; npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; - offset = (info->videoLinear->offset * bpp) + (top * dstPitch); + offset = video_offset + (top * dstPitch); + if(pPriv->doubleBuffer) - offset += pPriv->currentBuffer * new_size * bpp; + offset += pPriv->currentBuffer * new_size; dst_start = info->FB + offset; @@ -1127,14 +2234,12 @@ RADEONPutImage( s3offset = tmp; } nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; -#if X_BYTE_ORDER == X_BIG_ENDIAN - OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | RADEON_NONSURF_AP0_SWP_32BPP) - & ~RADEON_NONSURF_AP0_SWP_16BPP); -#endif - RADEONCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset, - buf + s3offset, dst_start, srcPitch, srcPitch2, - dstPitch, nlines, npixels); + RADEONCopyMungedData(pScrn, buf + (top * srcPitch) + left, + buf + s2offset, buf + s3offset, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); break; + case FOURCC_RGBT16: + case FOURCC_RGB16: case FOURCC_UYVY: case FOURCC_YUY2: default: @@ -1142,19 +2247,22 @@ RADEONPutImage( buf += (top * srcPitch) + left; nlines = ((yb + 0xffff) >> 16) - top; dst_start += left; -#if X_BYTE_ORDER == X_BIG_ENDIAN - OUTREG(RADEON_SURFACE_CNTL, surface_cntl & ~(RADEON_NONSURF_AP0_SWP_32BPP - | RADEON_NONSURF_AP0_SWP_16BPP)); -#endif - RADEONCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 2); + break; + case FOURCC_RGBA32: + buf += (top * srcPitch) + left*4; + nlines = ((yb + 0xffff) >> 16) - top; + dst_start += left*4; + RADEONCopyData(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels, 4); + break; + case FOURCC_RGB24: + buf += (top * srcPitch) + left*3; + nlines = ((yb + 0xffff) >> 16) - top; + dst_start += left*4; + RADEONCopyRGB24Data(pScrn, buf, dst_start, srcPitch, dstPitch, nlines, npixels); break; } -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* restore byte swapping */ - OUTREG(RADEON_SURFACE_CNTL, surface_cntl); -#endif - /* update cliplist */ if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { @@ -1164,7 +2272,7 @@ RADEONPutImage( xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, id, offset, offset, width, height, dstPitch, + RADEONDisplayVideo(pScrn, pPriv, id, offset, offset, offset, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); pPriv->videoStatus = CLIENT_VIDEO_ON; @@ -1205,6 +2313,18 @@ RADEONQueryImageAttributes( if(offsets) offsets[2] = size; size += tmp; break; + case FOURCC_RGBA32: + size = *w << 2; + if(pitches) pitches[0] = size; + size *= *h; + break; + case FOURCC_RGB24: + size = *w * 3; + if(pitches) pitches[0] = size; + size *= *h; + break; + case FOURCC_RGBT16: + case FOURCC_RGB16: case FOURCC_UYVY: case FOURCC_YUY2: default: @@ -1233,9 +2353,9 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) } } else { /* FREE_TIMER */ if(pPriv->freeTime < now) { - if(info->videoLinear) { - xf86FreeOffscreenLinear(info->videoLinear); - info->videoLinear = NULL; + if (info->videoLinear != NULL) { + xf86FreeOffscreenLinear(info->videoLinear); + info->videoLinear = NULL; } pPriv->videoStatus = 0; info->VideoTimerCallback = NULL; @@ -1247,7 +2367,7 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) /****************** Offscreen stuff ***************/ typedef struct { - FBLinearPtr linear; + void *surface_memory; Bool isOn; } OffscreenPrivRec, * OffscreenPrivPtr; @@ -1259,46 +2379,46 @@ RADEONAllocateSurface( unsigned short h, XF86SurfacePtr surface ){ - FBLinearPtr linear; - int pitch, size, bpp; + int offset, pitch, size; OffscreenPrivPtr pPriv; + FBLinearPtr surface_memory = NULL; if((w > 1024) || (h > 1024)) return BadAlloc; w = (w + 1) & ~1; pitch = ((w << 1) + 15) & ~15; - bpp = pScrn->bitsPerPixel >> 3; - size = ((pitch * h) + bpp - 1) / bpp; + size = pitch * h; - if(!(linear = RADEONAllocateMemory(pScrn, NULL, size))) + offset = RADEONAllocateMemory(pScrn, &surface_memory, size); + if (offset == 0) return BadAlloc; surface->width = w; surface->height = h; if(!(surface->pitches = xalloc(sizeof(int)))) { - xf86FreeOffscreenLinear(linear); + xf86FreeOffscreenLinear(surface_memory); return BadAlloc; } if(!(surface->offsets = xalloc(sizeof(int)))) { xfree(surface->pitches); - xf86FreeOffscreenLinear(linear); + xf86FreeOffscreenLinear(surface_memory); return BadAlloc; } if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { xfree(surface->pitches); xfree(surface->offsets); - xf86FreeOffscreenLinear(linear); + xf86FreeOffscreenLinear(surface_memory); return BadAlloc; } - pPriv->linear = linear; + pPriv->surface_memory = surface_memory; pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; - surface->offsets[0] = linear->offset * bpp; + surface->offsets[0] = offset; surface->devPrivate.ptr = (pointer)pPriv; return Success; @@ -1328,7 +2448,8 @@ RADEONFreeSurface( if(pPriv->isOn) RADEONStopSurface(surface); - xf86FreeOffscreenLinear(pPriv->linear); + if (pPriv->surface_memory) + xf86FreeOffscreenLinear(pPriv->surface_memory); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); @@ -1390,18 +2511,27 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; + if (info->MergedFB) + RADEONChooseOverlayCRTC(pScrn, &dstBox); + if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, surface->width, surface->height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - - RADEONResetVideo(pScrn); + if (info->MergedFB && info->OverlayOnCRTC2) { + dstBox.x1 -= info->CRT2pScrn->frameX0; + dstBox.x2 -= info->CRT2pScrn->frameX0; + dstBox.y1 -= info->CRT2pScrn->frameY0; + dstBox.y2 -= info->CRT2pScrn->frameY0; + } else { + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + } - RADEONDisplayVideo(pScrn, surface->id, + RADEONDisplayVideo(pScrn, portPriv, surface->id, + surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->width, surface->height, surface->pitches[0], xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); @@ -1443,8 +2573,8 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) offscreenImages[0].stop = RADEONStopSurface; offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute; offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute; - offscreenImages[0].max_width = 1024; - offscreenImages[0].max_height = 1024; + offscreenImages[0].max_width = 2048; + offscreenImages[0].max_height = 2048; offscreenImages[0].num_attributes = NUM_ATTRIBUTES; offscreenImages[0].attributes = Attributes; |