2005-04-16 15:20:36 -07:00
/* r128_state.c -- State support for r128 -*- linux-c -*-
* Created : Thu Jan 27 02 : 53 : 43 2000 by gareth @ valinux . com
2006-01-02 17:18:39 +11:00
*/
2006-12-19 17:56:14 +11:00
/*
* Copyright 2000 VA Linux Systems , Inc . , Sunnyvale , California .
2005-04-16 15:20:36 -07:00
* All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* PRECISION INSIGHT AND / OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*
* Authors :
* Gareth Hughes < gareth @ valinux . com >
*/
# include "drmP.h"
# include "drm.h"
# include "r128_drm.h"
# include "r128_drv.h"
/* ================================================================
* CCE hardware state programming functions
*/
2005-09-25 14:28:13 +10:00
static void r128_emit_clip_rects ( drm_r128_private_t * dev_priv ,
drm_clip_rect_t * boxes , int count )
2005-04-16 15:20:36 -07:00
{
u32 aux_sc_cntl = 0x00000000 ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( ( count < 3 ? count : 3 ) * 5 + 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( count > = 1 ) {
OUT_RING ( CCE_PACKET0 ( R128_AUX1_SC_LEFT , 3 ) ) ;
OUT_RING ( boxes [ 0 ] . x1 ) ;
OUT_RING ( boxes [ 0 ] . x2 - 1 ) ;
OUT_RING ( boxes [ 0 ] . y1 ) ;
OUT_RING ( boxes [ 0 ] . y2 - 1 ) ;
2005-04-16 15:20:36 -07:00
aux_sc_cntl | = ( R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR ) ;
}
2005-09-25 14:28:13 +10:00
if ( count > = 2 ) {
OUT_RING ( CCE_PACKET0 ( R128_AUX2_SC_LEFT , 3 ) ) ;
OUT_RING ( boxes [ 1 ] . x1 ) ;
OUT_RING ( boxes [ 1 ] . x2 - 1 ) ;
OUT_RING ( boxes [ 1 ] . y1 ) ;
OUT_RING ( boxes [ 1 ] . y2 - 1 ) ;
2005-04-16 15:20:36 -07:00
aux_sc_cntl | = ( R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR ) ;
}
2005-09-25 14:28:13 +10:00
if ( count > = 3 ) {
OUT_RING ( CCE_PACKET0 ( R128_AUX3_SC_LEFT , 3 ) ) ;
OUT_RING ( boxes [ 2 ] . x1 ) ;
OUT_RING ( boxes [ 2 ] . x2 - 1 ) ;
OUT_RING ( boxes [ 2 ] . y1 ) ;
OUT_RING ( boxes [ 2 ] . y2 - 1 ) ;
2005-04-16 15:20:36 -07:00
aux_sc_cntl | = ( R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR ) ;
}
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_AUX_SC_CNTL , 0 ) ) ;
OUT_RING ( aux_sc_cntl ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_core ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_SCALE_3D_CNTL , 0 ) ) ;
OUT_RING ( ctx - > scale_3d_cntl ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_context ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
BEGIN_RING ( 13 ) ;
OUT_RING ( CCE_PACKET0 ( R128_DST_PITCH_OFFSET_C , 11 ) ) ;
OUT_RING ( ctx - > dst_pitch_offset_c ) ;
OUT_RING ( ctx - > dp_gui_master_cntl_c ) ;
OUT_RING ( ctx - > sc_top_left_c ) ;
OUT_RING ( ctx - > sc_bottom_right_c ) ;
OUT_RING ( ctx - > z_offset_c ) ;
OUT_RING ( ctx - > z_pitch_c ) ;
OUT_RING ( ctx - > z_sten_cntl_c ) ;
OUT_RING ( ctx - > tex_cntl_c ) ;
OUT_RING ( ctx - > misc_3d_state_cntl_reg ) ;
OUT_RING ( ctx - > texture_clr_cmp_clr_c ) ;
OUT_RING ( ctx - > texture_clr_cmp_msk_c ) ;
OUT_RING ( ctx - > fog_color_c ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_setup ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 3 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET1 ( R128_SETUP_CNTL , R128_PM4_VC_FPU_SETUP ) ) ;
OUT_RING ( ctx - > setup_cntl ) ;
OUT_RING ( ctx - > pm4_vc_fpu_setup ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_masks ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 5 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_DP_WRITE_MASK , 0 ) ) ;
OUT_RING ( ctx - > dp_write_mask ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_STEN_REF_MASK_C , 1 ) ) ;
OUT_RING ( ctx - > sten_ref_mask_c ) ;
OUT_RING ( ctx - > plane_3d_mask_c ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_window ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_WINDOW_XY_OFFSET , 0 ) ) ;
OUT_RING ( ctx - > window_xy_offset ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_tex0 ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_context_regs_t * ctx = & sarea_priv - > context_state ;
drm_r128_texture_regs_t * tex = & sarea_priv - > tex_state [ 0 ] ;
int i ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 7 + R128_MAX_TEXTURE_LEVELS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_PRIM_TEX_CNTL_C ,
2 + R128_MAX_TEXTURE_LEVELS ) ) ;
OUT_RING ( tex - > tex_cntl ) ;
OUT_RING ( tex - > tex_combine_cntl ) ;
OUT_RING ( ctx - > tex_size_pitch_c ) ;
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i + + ) {
OUT_RING ( tex - > tex_offset [ i ] ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_CONSTANT_COLOR_C , 1 ) ) ;
OUT_RING ( ctx - > constant_color_c ) ;
OUT_RING ( tex - > tex_border_color ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static __inline__ void r128_emit_tex1 ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_texture_regs_t * tex = & sarea_priv - > tex_state [ 1 ] ;
int i ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 5 + R128_MAX_TEXTURE_LEVELS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_SEC_TEX_CNTL_C , 1 + R128_MAX_TEXTURE_LEVELS ) ) ;
OUT_RING ( tex - > tex_cntl ) ;
OUT_RING ( tex - > tex_combine_cntl ) ;
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i + + ) {
OUT_RING ( tex - > tex_offset [ i ] ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_SEC_TEXTURE_BORDER_COLOR_C , 0 ) ) ;
OUT_RING ( tex - > tex_border_color ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2006-01-14 13:20:43 -08:00
static void r128_emit_state ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
unsigned int dirty = sarea_priv - > dirty ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s: dirty=0x%08x \n " , __FUNCTION__ , dirty ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_CORE ) {
r128_emit_core ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_CORE ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_CONTEXT ) {
r128_emit_context ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_CONTEXT ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_SETUP ) {
r128_emit_setup ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_SETUP ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_MASKS ) {
r128_emit_masks ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_MASKS ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_WINDOW ) {
r128_emit_window ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_WINDOW ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_TEX0 ) {
r128_emit_tex0 ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_TEX0 ;
}
2005-09-25 14:28:13 +10:00
if ( dirty & R128_UPLOAD_TEX1 ) {
r128_emit_tex1 ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
sarea_priv - > dirty & = ~ R128_UPLOAD_TEX1 ;
}
/* Turn off the texture cache flushing */
sarea_priv - > context_state . tex_cntl_c & = ~ R128_TEX_CACHE_FLUSH ;
sarea_priv - > dirty & = ~ R128_REQUIRE_QUIESCENCE ;
}
# if R128_PERFORMANCE_BOXES
/* ================================================================
* Performance monitoring functions
*/
2005-09-25 14:28:13 +10:00
static void r128_clear_box ( drm_r128_private_t * dev_priv ,
int x , int y , int w , int h , int r , int g , int b )
2005-04-16 15:20:36 -07:00
{
u32 pitch , offset ;
u32 fb_bpp , color ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
switch ( dev_priv - > fb_bpp ) {
2005-04-16 15:20:36 -07:00
case 16 :
fb_bpp = R128_GMC_DST_16BPP ;
color = ( ( ( r & 0xf8 ) < < 8 ) |
2005-09-25 14:28:13 +10:00
( ( g & 0xfc ) < < 3 ) | ( ( b & 0xf8 ) > > 3 ) ) ;
2005-04-16 15:20:36 -07:00
break ;
case 24 :
fb_bpp = R128_GMC_DST_24BPP ;
color = ( ( r < < 16 ) | ( g < < 8 ) | b ) ;
break ;
case 32 :
fb_bpp = R128_GMC_DST_32BPP ;
2005-09-25 14:28:13 +10:00
color = ( ( ( 0xff ) < < 24 ) | ( r < < 16 ) | ( g < < 8 ) | b ) ;
2005-04-16 15:20:36 -07:00
break ;
default :
return ;
}
offset = dev_priv - > back_offset ;
pitch = dev_priv - > back_pitch > > 3 ;
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
fb_bpp |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( pitch < < 21 ) | ( offset > > 5 ) ) ;
OUT_RING ( color ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( w < < 16 ) | h ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static void r128_cce_performance_boxes ( drm_r128_private_t * dev_priv )
2005-04-16 15:20:36 -07:00
{
2005-09-25 14:28:13 +10:00
if ( atomic_read ( & dev_priv - > idle_count ) = = 0 ) {
r128_clear_box ( dev_priv , 64 , 4 , 8 , 8 , 0 , 255 , 0 ) ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-25 14:28:13 +10:00
atomic_set ( & dev_priv - > idle_count , 0 ) ;
2005-04-16 15:20:36 -07:00
}
}
# endif
/* ================================================================
* CCE command dispatch functions
*/
2005-09-25 14:28:13 +10:00
static void r128_print_dirty ( const char * msg , unsigned int flags )
2005-04-16 15:20:36 -07:00
{
2005-09-25 14:28:13 +10:00
DRM_INFO ( " %s: (0x%x) %s%s%s%s%s%s%s%s%s \n " ,
msg ,
flags ,
( flags & R128_UPLOAD_CORE ) ? " core, " : " " ,
( flags & R128_UPLOAD_CONTEXT ) ? " context, " : " " ,
( flags & R128_UPLOAD_SETUP ) ? " setup, " : " " ,
( flags & R128_UPLOAD_TEX0 ) ? " tex0, " : " " ,
( flags & R128_UPLOAD_TEX1 ) ? " tex1, " : " " ,
( flags & R128_UPLOAD_MASKS ) ? " masks, " : " " ,
( flags & R128_UPLOAD_WINDOW ) ? " window, " : " " ,
( flags & R128_UPLOAD_CLIPRECTS ) ? " cliprects, " : " " ,
( flags & R128_REQUIRE_QUIESCENCE ) ? " quiescence, " : " " ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_clear ( drm_device_t * dev ,
drm_r128_clear_t * clear )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
int nbox = sarea_priv - > nbox ;
drm_clip_rect_t * pbox = sarea_priv - > boxes ;
unsigned int flags = clear - > flags ;
int i ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( dev_priv - > page_flipping & & dev_priv - > current_page = = 1 ) {
2005-04-16 15:20:36 -07:00
unsigned int tmp = flags ;
flags & = ~ ( R128_FRONT | R128_BACK ) ;
2005-09-25 14:28:13 +10:00
if ( tmp & R128_FRONT )
flags | = R128_BACK ;
if ( tmp & R128_BACK )
flags | = R128_FRONT ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < nbox ; i + + ) {
2005-04-16 15:20:36 -07:00
int x = pbox [ i ] . x1 ;
int y = pbox [ i ] . y1 ;
int w = pbox [ i ] . x2 - x ;
int h = pbox [ i ] . y2 - y ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " dispatch clear %d,%d-%d,%d flags 0x%x \n " ,
pbox [ i ] . x1 , pbox [ i ] . y1 , pbox [ i ] . x2 ,
pbox [ i ] . y2 , flags ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( flags & ( R128_FRONT | R128_BACK ) ) {
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_DP_WRITE_MASK , 0 ) ) ;
OUT_RING ( clear - > color_mask ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
if ( flags & R128_FRONT ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > color_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > front_pitch_offset_c ) ;
OUT_RING ( clear - > clear_color ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( w < < 16 ) | h ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
if ( flags & R128_BACK ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > color_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > back_pitch_offset_c ) ;
OUT_RING ( clear - > clear_color ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( w < < 16 ) | h ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
if ( flags & R128_DEPTH ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( clear - > clear_depth ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( w < < 16 ) | h ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
}
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_swap ( drm_device_t * dev )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
int nbox = sarea_priv - > nbox ;
drm_clip_rect_t * pbox = sarea_priv - > boxes ;
int i ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
# if R128_PERFORMANCE_BOXES
/* Do some trivial performance monitoring...
*/
2005-09-25 14:28:13 +10:00
r128_cce_performance_boxes ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
# endif
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < nbox ; i + + ) {
2005-04-16 15:20:36 -07:00
int x = pbox [ i ] . x1 ;
int y = pbox [ i ] . y1 ;
int w = pbox [ i ] . x2 - x ;
int h = pbox [ i ] . y2 - y ;
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 7 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_BITBLT_MULTI , 5 ) ) ;
OUT_RING ( R128_GMC_SRC_PITCH_OFFSET_CNTL |
R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_NONE |
( dev_priv - > color_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_S |
R128_DP_SRC_SOURCE_MEMORY |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
/* Make this work even if front & back are flipped:
*/
if ( dev_priv - > current_page = = 0 ) {
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > back_pitch_offset_c ) ;
OUT_RING ( dev_priv - > front_pitch_offset_c ) ;
} else {
OUT_RING ( dev_priv - > front_pitch_offset_c ) ;
OUT_RING ( dev_priv - > back_pitch_offset_c ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( w < < 16 ) | h ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
/* Increment the frame counter. The client-side 3D driver must
* throttle the framerate by waiting for this value before
* performing the swapbuffer ioctl .
*/
dev_priv - > sarea_priv - > last_frame + + ;
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_LAST_FRAME_REG , 0 ) ) ;
OUT_RING ( dev_priv - > sarea_priv - > last_frame ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_flip ( drm_device_t * dev )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s: page=%d pfCurrentPage=%d \n " ,
__FUNCTION__ ,
dev_priv - > current_page , dev_priv - > sarea_priv - > pfCurrentPage ) ;
2005-04-16 15:20:36 -07:00
# if R128_PERFORMANCE_BOXES
/* Do some trivial performance monitoring...
*/
2005-09-25 14:28:13 +10:00
r128_cce_performance_boxes ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
# endif
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 4 ) ;
2005-04-16 15:20:36 -07:00
R128_WAIT_UNTIL_PAGE_FLIPPED ( ) ;
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_CRTC_OFFSET , 0 ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( dev_priv - > current_page = = 0 ) {
OUT_RING ( dev_priv - > back_offset ) ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > front_offset ) ;
2005-04-16 15:20:36 -07:00
}
ADVANCE_RING ( ) ;
/* Increment the frame counter. The client-side 3D driver must
* throttle the framerate by waiting for this value before
* performing the swapbuffer ioctl .
*/
dev_priv - > sarea_priv - > last_frame + + ;
dev_priv - > sarea_priv - > pfCurrentPage = dev_priv - > current_page =
2005-09-25 14:28:13 +10:00
1 - dev_priv - > current_page ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_LAST_FRAME_REG , 0 ) ) ;
OUT_RING ( dev_priv - > sarea_priv - > last_frame ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_vertex ( drm_device_t * dev , drm_buf_t * buf )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_buf_priv_t * buf_priv = buf - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
int format = sarea_priv - > vc_format ;
int offset = buf - > bus_address ;
int size = buf - > used ;
int prim = buf_priv - > prim ;
int i = 0 ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " buf=%d nbox=%d \n " , buf - > idx , sarea_priv - > nbox ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( 0 )
r128_print_dirty ( " dispatch_vertex " , sarea_priv - > dirty ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( buf - > used ) {
2005-04-16 15:20:36 -07:00
buf_priv - > dispatched = 1 ;
2005-09-25 14:28:13 +10:00
if ( sarea_priv - > dirty & ~ R128_UPLOAD_CLIPRECTS ) {
r128_emit_state ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
}
do {
/* Emit the next set of up to three cliprects */
2005-09-25 14:28:13 +10:00
if ( i < sarea_priv - > nbox ) {
r128_emit_clip_rects ( dev_priv ,
& sarea_priv - > boxes [ i ] ,
sarea_priv - > nbox - i ) ;
2005-04-16 15:20:36 -07:00
}
/* Emit the vertex buffer rendering commands */
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 5 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_3D_RNDR_GEN_INDX_PRIM , 3 ) ) ;
OUT_RING ( offset ) ;
OUT_RING ( size ) ;
OUT_RING ( format ) ;
OUT_RING ( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
( size < < R128_CCE_VC_CNTL_NUM_SHIFT ) ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
i + = 3 ;
2005-09-25 14:28:13 +10:00
} while ( i < sarea_priv - > nbox ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
if ( buf_priv - > discard ) {
2005-04-16 15:20:36 -07:00
buf_priv - > age = dev_priv - > sarea_priv - > last_dispatch ;
/* Emit the vertex buffer age */
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_LAST_DISPATCH_REG , 0 ) ) ;
OUT_RING ( buf_priv - > age ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
buf - > pending = 1 ;
buf - > used = 0 ;
/* FIXME: Check dispatched field */
buf_priv - > dispatched = 0 ;
}
dev_priv - > sarea_priv - > last_dispatch + + ;
sarea_priv - > dirty & = ~ R128_UPLOAD_CLIPRECTS ;
sarea_priv - > nbox = 0 ;
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_indirect ( drm_device_t * dev ,
drm_buf_t * buf , int start , int end )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_buf_priv_t * buf_priv = buf - > dev_private ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " indirect: buf=%d s=0x%x e=0x%x \n " , buf - > idx , start , end ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( start ! = end ) {
2005-04-16 15:20:36 -07:00
int offset = buf - > bus_address + start ;
int dwords = ( end - start + 3 ) / sizeof ( u32 ) ;
/* Indirect buffer data must be an even number of
* dwords , so if we ' ve been given an odd number we must
* pad the data with a Type - 2 CCE packet .
*/
2005-09-25 14:28:13 +10:00
if ( dwords & 1 ) {
2005-04-16 15:20:36 -07:00
u32 * data = ( u32 * )
2005-09-25 14:28:13 +10:00
( ( char * ) dev - > agp_buffer_map - > handle
+ buf - > offset + start ) ;
data [ dwords + + ] = cpu_to_le32 ( R128_CCE_PACKET2 ) ;
2005-04-16 15:20:36 -07:00
}
buf_priv - > dispatched = 1 ;
/* Fire off the indirect buffer */
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 3 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_PM4_IW_INDOFF , 1 ) ) ;
OUT_RING ( offset ) ;
OUT_RING ( dwords ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
if ( buf_priv - > discard ) {
2005-04-16 15:20:36 -07:00
buf_priv - > age = dev_priv - > sarea_priv - > last_dispatch ;
/* Emit the indirect buffer age */
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_LAST_DISPATCH_REG , 0 ) ) ;
OUT_RING ( buf_priv - > age ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
buf - > pending = 1 ;
buf - > used = 0 ;
/* FIXME: Check dispatched field */
buf_priv - > dispatched = 0 ;
}
dev_priv - > sarea_priv - > last_dispatch + + ;
}
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_indices ( drm_device_t * dev ,
drm_buf_t * buf ,
int start , int end , int count )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_buf_priv_t * buf_priv = buf - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
int format = sarea_priv - > vc_format ;
int offset = dev - > agp_buffer_map - > offset - dev_priv - > cce_buffers_offset ;
int prim = buf_priv - > prim ;
u32 * data ;
int dwords ;
int i = 0 ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " indices: s=%d e=%d c=%d \n " , start , end , count ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( 0 )
r128_print_dirty ( " dispatch_indices " , sarea_priv - > dirty ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( start ! = end ) {
2005-04-16 15:20:36 -07:00
buf_priv - > dispatched = 1 ;
2005-09-25 14:28:13 +10:00
if ( sarea_priv - > dirty & ~ R128_UPLOAD_CLIPRECTS ) {
r128_emit_state ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
}
dwords = ( end - start + 3 ) / sizeof ( u32 ) ;
2005-09-25 14:28:13 +10:00
data = ( u32 * ) ( ( char * ) dev - > agp_buffer_map - > handle
+ buf - > offset + start ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
data [ 0 ] = cpu_to_le32 ( CCE_PACKET3 ( R128_3D_RNDR_GEN_INDX_PRIM ,
dwords - 2 ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
data [ 1 ] = cpu_to_le32 ( offset ) ;
data [ 2 ] = cpu_to_le32 ( R128_MAX_VB_VERTS ) ;
data [ 3 ] = cpu_to_le32 ( format ) ;
data [ 4 ] = cpu_to_le32 ( ( prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
( count < < 16 ) ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( count & 0x1 ) {
2005-04-16 15:20:36 -07:00
# ifdef __LITTLE_ENDIAN
2005-09-25 14:28:13 +10:00
data [ dwords - 1 ] & = 0x0000ffff ;
2005-04-16 15:20:36 -07:00
# else
2005-09-25 14:28:13 +10:00
data [ dwords - 1 ] & = 0xffff0000 ;
2005-04-16 15:20:36 -07:00
# endif
}
do {
/* Emit the next set of up to three cliprects */
2005-09-25 14:28:13 +10:00
if ( i < sarea_priv - > nbox ) {
r128_emit_clip_rects ( dev_priv ,
& sarea_priv - > boxes [ i ] ,
sarea_priv - > nbox - i ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_indirect ( dev , buf , start , end ) ;
2005-04-16 15:20:36 -07:00
i + = 3 ;
2005-09-25 14:28:13 +10:00
} while ( i < sarea_priv - > nbox ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
if ( buf_priv - > discard ) {
2005-04-16 15:20:36 -07:00
buf_priv - > age = dev_priv - > sarea_priv - > last_dispatch ;
/* Emit the vertex buffer age */
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_LAST_DISPATCH_REG , 0 ) ) ;
OUT_RING ( buf_priv - > age ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
buf - > pending = 1 ;
/* FIXME: Check dispatched field */
buf_priv - > dispatched = 0 ;
}
dev_priv - > sarea_priv - > last_dispatch + + ;
sarea_priv - > dirty & = ~ R128_UPLOAD_CLIPRECTS ;
sarea_priv - > nbox = 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_dispatch_blit ( DRMFILE filp ,
drm_device_t * dev , drm_r128_blit_t * blit )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_device_dma_t * dma = dev - > dma ;
drm_buf_t * buf ;
drm_r128_buf_priv_t * buf_priv ;
u32 * data ;
int dword_shift , dwords ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
/* The compiler won't optimize away a division by a variable,
* even if the only legal values are powers of two . Thus , we ' ll
* use a shift instead .
*/
2005-09-25 14:28:13 +10:00
switch ( blit - > format ) {
2005-04-16 15:20:36 -07:00
case R128_DATATYPE_ARGB8888 :
dword_shift = 0 ;
break ;
case R128_DATATYPE_ARGB1555 :
case R128_DATATYPE_RGB565 :
case R128_DATATYPE_ARGB4444 :
case R128_DATATYPE_YVYU422 :
case R128_DATATYPE_VYUY422 :
dword_shift = 1 ;
break ;
case R128_DATATYPE_CI8 :
case R128_DATATYPE_RGB8 :
dword_shift = 2 ;
break ;
default :
2005-09-25 14:28:13 +10:00
DRM_ERROR ( " invalid blit format %d \n " , blit - > format ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
/* Flush the pixel cache, and mark the contents as Read Invalid.
* This ensures no pixel data gets mixed up with the texture
* data from the host data blit , otherwise part of the texture
* image may be corrupted .
*/
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_PC_GUI_CTLSTAT , 0 ) ) ;
OUT_RING ( R128_PC_RI_GUI | R128_PC_FLUSH_GUI ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
/* Dispatch the indirect buffer.
*/
buf = dma - > buflist [ blit - > idx ] ;
buf_priv = buf - > dev_private ;
2005-09-25 14:28:13 +10:00
if ( buf - > filp ! = filp ) {
DRM_ERROR ( " process %d using buffer owned by %p \n " ,
DRM_CURRENTPID , buf - > filp ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( buf - > pending ) {
DRM_ERROR ( " sending pending buffer %d \n " , blit - > idx ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
buf_priv - > discard = 1 ;
dwords = ( blit - > width * blit - > height ) > > dword_shift ;
2005-09-25 14:28:13 +10:00
data = ( u32 * ) ( ( char * ) dev - > agp_buffer_map - > handle + buf - > offset ) ;
data [ 0 ] = cpu_to_le32 ( CCE_PACKET3 ( R128_CNTL_HOSTDATA_BLT , dwords + 6 ) ) ;
data [ 1 ] = cpu_to_le32 ( ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_NONE |
( blit - > format < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_S |
R128_DP_SRC_SOURCE_HOST_DATA |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ) ) ;
data [ 2 ] = cpu_to_le32 ( ( blit - > pitch < < 21 ) | ( blit - > offset > > 5 ) ) ;
data [ 3 ] = cpu_to_le32 ( 0xffffffff ) ;
data [ 4 ] = cpu_to_le32 ( 0xffffffff ) ;
data [ 5 ] = cpu_to_le32 ( ( blit - > y < < 16 ) | blit - > x ) ;
data [ 6 ] = cpu_to_le32 ( ( blit - > height < < 16 ) | blit - > width ) ;
data [ 7 ] = cpu_to_le32 ( dwords ) ;
2005-04-16 15:20:36 -07:00
buf - > used = ( dwords + 8 ) * sizeof ( u32 ) ;
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_indirect ( dev , buf , 0 , buf - > used ) ;
2005-04-16 15:20:36 -07:00
/* Flush the pixel cache after the blit completes. This ensures
* the texture data is written out to memory before rendering
* continues .
*/
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_PC_GUI_CTLSTAT , 0 ) ) ;
OUT_RING ( R128_PC_FLUSH_GUI ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
return 0 ;
}
/* ================================================================
* Tiled depth buffer management
*
* FIXME : These should all set the destination write mask for when we
* have hardware stencil support .
*/
2005-09-25 14:28:13 +10:00
static int r128_cce_dispatch_write_span ( drm_device_t * dev ,
drm_r128_depth_t * depth )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
int count , x , y ;
u32 * buffer ;
u8 * mask ;
int i , buffer_size , mask_size ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
count = depth - > n ;
if ( count > 4096 | | count < = 0 )
return DRM_ERR ( EMSGSIZE ) ;
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( & x , depth - > x , sizeof ( x ) ) ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( & y , depth - > y , sizeof ( y ) ) ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
buffer_size = depth - > n * sizeof ( u32 ) ;
2005-09-25 14:28:13 +10:00
buffer = drm_alloc ( buffer_size , DRM_MEM_BUFS ) ;
if ( buffer = = NULL )
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( buffer , depth - > buffer , buffer_size ) ) {
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
mask_size = depth - > n * sizeof ( u8 ) ;
2005-09-25 14:28:13 +10:00
if ( depth - > mask ) {
mask = drm_alloc ( mask_size , DRM_MEM_BUFS ) ;
if ( mask = = NULL ) {
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( mask , depth - > mask , mask_size ) ) {
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
drm_free ( mask , mask_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < count ; i + + , x + + ) {
if ( mask [ i ] ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( buffer [ i ] ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( 1 < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
}
2005-09-25 14:28:13 +10:00
drm_free ( mask , mask_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < count ; i + + , x + + ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( buffer [ i ] ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( 1 < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
}
2005-09-25 14:28:13 +10:00
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_dispatch_write_pixels ( drm_device_t * dev ,
drm_r128_depth_t * depth )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
int count , * x , * y ;
u32 * buffer ;
u8 * mask ;
int i , xbuf_size , ybuf_size , buffer_size , mask_size ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
count = depth - > n ;
if ( count > 4096 | | count < = 0 )
return DRM_ERR ( EMSGSIZE ) ;
xbuf_size = count * sizeof ( * x ) ;
ybuf_size = count * sizeof ( * y ) ;
2005-09-25 14:28:13 +10:00
x = drm_alloc ( xbuf_size , DRM_MEM_BUFS ) ;
if ( x = = NULL ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
y = drm_alloc ( ybuf_size , DRM_MEM_BUFS ) ;
if ( y = = NULL ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( x , depth - > x , xbuf_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( y , depth - > y , xbuf_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
buffer_size = depth - > n * sizeof ( u32 ) ;
2005-09-25 14:28:13 +10:00
buffer = drm_alloc ( buffer_size , DRM_MEM_BUFS ) ;
if ( buffer = = NULL ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( buffer , depth - > buffer , buffer_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
if ( depth - > mask ) {
2005-04-16 15:20:36 -07:00
mask_size = depth - > n * sizeof ( u8 ) ;
2005-09-25 14:28:13 +10:00
mask = drm_alloc ( mask_size , DRM_MEM_BUFS ) ;
if ( mask = = NULL ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( mask , depth - > mask , mask_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
drm_free ( mask , mask_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < count ; i + + ) {
if ( mask [ i ] ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( buffer [ i ] ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x [ i ] < < 16 ) | y [ i ] ) ;
OUT_RING ( ( 1 < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
}
2005-09-25 14:28:13 +10:00
drm_free ( mask , mask_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
} else {
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < count ; i + + ) {
BEGIN_RING ( 6 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_PAINT_MULTI , 4 ) ) ;
OUT_RING ( R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_SOLID_COLOR |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_P |
R128_GMC_CLR_CMP_CNTL_DIS |
R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( buffer [ i ] ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x [ i ] < < 16 ) | y [ i ] ) ;
OUT_RING ( ( 1 < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
}
2005-09-25 14:28:13 +10:00
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
drm_free ( buffer , buffer_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_dispatch_read_span ( drm_device_t * dev ,
drm_r128_depth_t * depth )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
int count , x , y ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
count = depth - > n ;
if ( count > 4096 | | count < = 0 )
return DRM_ERR ( EMSGSIZE ) ;
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( & x , depth - > x , sizeof ( x ) ) ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( & y , depth - > y , sizeof ( y ) ) ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 7 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_BITBLT_MULTI , 5 ) ) ;
OUT_RING ( R128_GMC_SRC_PITCH_OFFSET_CNTL |
R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_NONE |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_S |
R128_DP_SRC_SOURCE_MEMORY |
R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( dev_priv - > span_pitch_offset_c ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x < < 16 ) | y ) ;
OUT_RING ( ( 0 < < 16 ) | 0 ) ;
OUT_RING ( ( count < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_dispatch_read_pixels ( drm_device_t * dev ,
drm_r128_depth_t * depth )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
int count , * x , * y ;
int i , xbuf_size , ybuf_size ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
count = depth - > n ;
if ( count > 4096 | | count < = 0 )
return DRM_ERR ( EMSGSIZE ) ;
2005-09-25 14:28:13 +10:00
if ( count > dev_priv - > depth_pitch ) {
2005-04-16 15:20:36 -07:00
count = dev_priv - > depth_pitch ;
}
xbuf_size = count * sizeof ( * x ) ;
ybuf_size = count * sizeof ( * y ) ;
2005-09-25 14:28:13 +10:00
x = drm_alloc ( xbuf_size , DRM_MEM_BUFS ) ;
if ( x = = NULL ) {
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
y = drm_alloc ( ybuf_size , DRM_MEM_BUFS ) ;
if ( y = = NULL ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( ENOMEM ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( x , depth - > x , xbuf_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( y , depth - > y , ybuf_size ) ) {
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
for ( i = 0 ; i < count ; i + + ) {
BEGIN_RING ( 7 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET3 ( R128_CNTL_BITBLT_MULTI , 5 ) ) ;
OUT_RING ( R128_GMC_SRC_PITCH_OFFSET_CNTL |
R128_GMC_DST_PITCH_OFFSET_CNTL |
R128_GMC_BRUSH_NONE |
( dev_priv - > depth_fmt < < 8 ) |
R128_GMC_SRC_DATATYPE_COLOR |
R128_ROP3_S |
R128_DP_SRC_SOURCE_MEMORY |
R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( dev_priv - > depth_pitch_offset_c ) ;
OUT_RING ( dev_priv - > span_pitch_offset_c ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( ( x [ i ] < < 16 ) | y [ i ] ) ;
OUT_RING ( ( i < < 16 ) | 0 ) ;
OUT_RING ( ( 1 < < 16 ) | 1 ) ;
2005-04-16 15:20:36 -07:00
ADVANCE_RING ( ) ;
}
2005-09-25 14:28:13 +10:00
drm_free ( x , xbuf_size , DRM_MEM_BUFS ) ;
drm_free ( y , ybuf_size , DRM_MEM_BUFS ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
/* ================================================================
* Polygon stipple
*/
2005-09-25 14:28:13 +10:00
static void r128_cce_dispatch_stipple ( drm_device_t * dev , u32 * stipple )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
int i ;
RING_LOCALS ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 33 ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
OUT_RING ( CCE_PACKET0 ( R128_BRUSH_DATA0 , 31 ) ) ;
for ( i = 0 ; i < 32 ; i + + ) {
OUT_RING ( stipple [ i ] ) ;
2005-04-16 15:20:36 -07:00
}
ADVANCE_RING ( ) ;
}
/* ================================================================
* IOCTL functions
*/
2005-09-25 14:28:13 +10:00
static int r128_cce_clear ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
drm_r128_clear_t clear ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( clear , ( drm_r128_clear_t __user * ) data ,
sizeof ( clear ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( sarea_priv - > nbox > R128_NR_SAREA_CLIPRECTS )
2005-04-16 15:20:36 -07:00
sarea_priv - > nbox = R128_NR_SAREA_CLIPRECTS ;
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_clear ( dev , & clear ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
/* Make sure we restore the 3D state next time.
*/
dev_priv - > sarea_priv - > dirty | = R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_do_init_pageflip ( drm_device_t * dev )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
dev_priv - > crtc_offset = R128_READ ( R128_CRTC_OFFSET ) ;
dev_priv - > crtc_offset_cntl = R128_READ ( R128_CRTC_OFFSET_CNTL ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
R128_WRITE ( R128_CRTC_OFFSET , dev_priv - > front_offset ) ;
R128_WRITE ( R128_CRTC_OFFSET_CNTL ,
dev_priv - > crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL ) ;
2005-04-16 15:20:36 -07:00
dev_priv - > page_flipping = 1 ;
dev_priv - > current_page = 0 ;
dev_priv - > sarea_priv - > pfCurrentPage = dev_priv - > current_page ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_do_cleanup_pageflip ( drm_device_t * dev )
2005-04-16 15:20:36 -07:00
{
drm_r128_private_t * dev_priv = dev - > dev_private ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " \n " ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
R128_WRITE ( R128_CRTC_OFFSET , dev_priv - > crtc_offset ) ;
R128_WRITE ( R128_CRTC_OFFSET_CNTL , dev_priv - > crtc_offset_cntl ) ;
2005-04-16 15:20:36 -07:00
if ( dev_priv - > current_page ! = 0 ) {
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_flip ( dev ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
}
dev_priv - > page_flipping = 0 ;
return 0 ;
}
/* Swapping and flipping are different operations, need different ioctls.
2005-09-25 14:28:13 +10:00
* They can & should be intermixed to support multiple 3 d windows .
2005-04-16 15:20:36 -07:00
*/
2005-09-25 14:28:13 +10:00
static int r128_cce_flip ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( ! dev_priv - > page_flipping )
r128_do_init_pageflip ( dev ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_flip ( dev ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_swap ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_sarea_t * sarea_priv = dev_priv - > sarea_priv ;
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " %s \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( sarea_priv - > nbox > R128_NR_SAREA_CLIPRECTS )
2005-04-16 15:20:36 -07:00
sarea_priv - > nbox = R128_NR_SAREA_CLIPRECTS ;
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_swap ( dev ) ;
2005-04-16 15:20:36 -07:00
dev_priv - > sarea_priv - > dirty | = ( R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS ) ;
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_vertex ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_device_dma_t * dma = dev - > dma ;
drm_buf_t * buf ;
drm_r128_buf_priv_t * buf_priv ;
drm_r128_vertex_t vertex ;
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( ! dev_priv ) {
DRM_ERROR ( " %s called with no initialization \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( vertex , ( drm_r128_vertex_t __user * ) data ,
sizeof ( vertex ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " pid=%d index=%d count=%d discard=%d \n " ,
DRM_CURRENTPID , vertex . idx , vertex . count , vertex . discard ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( vertex . idx < 0 | | vertex . idx > = dma - > buf_count ) {
DRM_ERROR ( " buffer index %d (of %d max) \n " ,
vertex . idx , dma - > buf_count - 1 ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( vertex . prim < 0 | |
vertex . prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
DRM_ERROR ( " buffer prim %d \n " , vertex . prim ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
VB_AGE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
buf = dma - > buflist [ vertex . idx ] ;
buf_priv = buf - > dev_private ;
2005-09-25 14:28:13 +10:00
if ( buf - > filp ! = filp ) {
DRM_ERROR ( " process %d using buffer owned by %p \n " ,
DRM_CURRENTPID , buf - > filp ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( buf - > pending ) {
DRM_ERROR ( " sending pending buffer %d \n " , vertex . idx ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
buf - > used = vertex . count ;
buf_priv - > prim = vertex . prim ;
buf_priv - > discard = vertex . discard ;
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_vertex ( dev , buf ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_indices ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_device_dma_t * dma = dev - > dma ;
drm_buf_t * buf ;
drm_r128_buf_priv_t * buf_priv ;
drm_r128_indices_t elts ;
int count ;
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( ! dev_priv ) {
DRM_ERROR ( " %s called with no initialization \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( elts , ( drm_r128_indices_t __user * ) data ,
sizeof ( elts ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " pid=%d buf=%d s=%d e=%d d=%d \n " , DRM_CURRENTPID ,
elts . idx , elts . start , elts . end , elts . discard ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( elts . idx < 0 | | elts . idx > = dma - > buf_count ) {
DRM_ERROR ( " buffer index %d (of %d max) \n " ,
elts . idx , dma - > buf_count - 1 ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( elts . prim < 0 | | elts . prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
DRM_ERROR ( " buffer prim %d \n " , elts . prim ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
VB_AGE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
buf = dma - > buflist [ elts . idx ] ;
buf_priv = buf - > dev_private ;
2005-09-25 14:28:13 +10:00
if ( buf - > filp ! = filp ) {
DRM_ERROR ( " process %d using buffer owned by %p \n " ,
DRM_CURRENTPID , buf - > filp ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( buf - > pending ) {
DRM_ERROR ( " sending pending buffer %d \n " , elts . idx ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
count = ( elts . end - elts . start ) / sizeof ( u16 ) ;
elts . start - = R128_INDEX_PRIM_OFFSET ;
2005-09-25 14:28:13 +10:00
if ( elts . start & 0x7 ) {
DRM_ERROR ( " misaligned buffer 0x%x \n " , elts . start ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( elts . start < buf - > used ) {
DRM_ERROR ( " no header 0x%x - 0x%x \n " , elts . start , buf - > used ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
buf - > used = elts . end ;
buf_priv - > prim = elts . prim ;
buf_priv - > discard = elts . discard ;
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_indices ( dev , buf , elts . start , elts . end , count ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_blit ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_device_dma_t * dma = dev - > dma ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_blit_t blit ;
int ret ;
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( blit , ( drm_r128_blit_t __user * ) data ,
sizeof ( blit ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " pid=%d index=%d \n " , DRM_CURRENTPID , blit . idx ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( blit . idx < 0 | | blit . idx > = dma - > buf_count ) {
DRM_ERROR ( " buffer index %d (of %d max) \n " ,
blit . idx , dma - > buf_count - 1 ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
VB_AGE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
ret = r128_cce_dispatch_blit ( filp , dev , & blit ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return ret ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_depth ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_depth_t depth ;
int ret ;
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( depth , ( drm_r128_depth_t __user * ) data ,
sizeof ( depth ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
ret = DRM_ERR ( EINVAL ) ;
2005-09-25 14:28:13 +10:00
switch ( depth . func ) {
2005-04-16 15:20:36 -07:00
case R128_WRITE_SPAN :
2005-09-25 14:28:13 +10:00
ret = r128_cce_dispatch_write_span ( dev , & depth ) ;
2005-04-16 15:24:04 -07:00
break ;
2005-04-16 15:20:36 -07:00
case R128_WRITE_PIXELS :
2005-09-25 14:28:13 +10:00
ret = r128_cce_dispatch_write_pixels ( dev , & depth ) ;
2005-04-16 15:24:04 -07:00
break ;
2005-04-16 15:20:36 -07:00
case R128_READ_SPAN :
2005-09-25 14:28:13 +10:00
ret = r128_cce_dispatch_read_span ( dev , & depth ) ;
2005-04-16 15:24:04 -07:00
break ;
2005-04-16 15:20:36 -07:00
case R128_READ_PIXELS :
2005-09-25 14:28:13 +10:00
ret = r128_cce_dispatch_read_pixels ( dev , & depth ) ;
2005-04-16 15:24:04 -07:00
break ;
2005-04-16 15:20:36 -07:00
}
COMMIT_RING ( ) ;
return ret ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_stipple ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_stipple_t stipple ;
u32 mask [ 32 ] ;
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( stipple , ( drm_r128_stipple_t __user * ) data ,
sizeof ( stipple ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_FROM_USER ( & mask , stipple . mask , 32 * sizeof ( u32 ) ) )
return DRM_ERR ( EFAULT ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_stipple ( dev , mask ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_cce_indirect ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_device_dma_t * dma = dev - > dma ;
drm_buf_t * buf ;
drm_r128_buf_priv_t * buf_priv ;
drm_r128_indirect_t indirect ;
#if 0
RING_LOCALS ;
# endif
2005-09-25 14:28:13 +10:00
LOCK_TEST_WITH_RETURN ( dev , filp ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( ! dev_priv ) {
DRM_ERROR ( " %s called with no initialization \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( indirect , ( drm_r128_indirect_t __user * ) data ,
sizeof ( indirect ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " indirect: idx=%d s=%d e=%d d=%d \n " ,
indirect . idx , indirect . start , indirect . end , indirect . discard ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
if ( indirect . idx < 0 | | indirect . idx > = dma - > buf_count ) {
DRM_ERROR ( " buffer index %d (of %d max) \n " ,
indirect . idx , dma - > buf_count - 1 ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
buf = dma - > buflist [ indirect . idx ] ;
buf_priv = buf - > dev_private ;
2005-09-25 14:28:13 +10:00
if ( buf - > filp ! = filp ) {
DRM_ERROR ( " process %d using buffer owned by %p \n " ,
DRM_CURRENTPID , buf - > filp ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( buf - > pending ) {
DRM_ERROR ( " sending pending buffer %d \n " , indirect . idx ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( indirect . start < buf - > used ) {
DRM_ERROR ( " reusing indirect: start=0x%x actual=0x%x \n " ,
indirect . start , buf - > used ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
RING_SPACE_TEST_WITH_RETURN ( dev_priv ) ;
VB_AGE_TEST_WITH_RETURN ( dev_priv ) ;
2005-04-16 15:20:36 -07:00
buf - > used = indirect . end ;
buf_priv - > discard = indirect . discard ;
#if 0
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2 D acceleration commands is processed .
*/
2005-09-25 14:28:13 +10:00
BEGIN_RING ( 2 ) ;
2005-04-16 15:20:36 -07:00
RADEON_WAIT_UNTIL_3D_IDLE ( ) ;
ADVANCE_RING ( ) ;
# endif
/* Dispatch the indirect buffer full of commands from the
* X server . This is insecure and is thus only available to
* privileged clients .
*/
2005-09-25 14:28:13 +10:00
r128_cce_dispatch_indirect ( dev , buf , indirect . start , indirect . end ) ;
2005-04-16 15:20:36 -07:00
COMMIT_RING ( ) ;
return 0 ;
}
2005-09-25 14:28:13 +10:00
static int r128_getparam ( DRM_IOCTL_ARGS )
2005-04-16 15:20:36 -07:00
{
DRM_DEVICE ;
drm_r128_private_t * dev_priv = dev - > dev_private ;
drm_r128_getparam_t param ;
int value ;
2005-09-25 14:28:13 +10:00
if ( ! dev_priv ) {
DRM_ERROR ( " %s called with no initialization \n " , __FUNCTION__ ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
DRM_COPY_FROM_USER_IOCTL ( param , ( drm_r128_getparam_t __user * ) data ,
sizeof ( param ) ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
DRM_DEBUG ( " pid=%d \n " , DRM_CURRENTPID ) ;
2005-04-16 15:20:36 -07:00
2005-09-25 14:28:13 +10:00
switch ( param . param ) {
2005-04-16 15:20:36 -07:00
case R128_PARAM_IRQ_NR :
value = dev - > irq ;
break ;
default :
return DRM_ERR ( EINVAL ) ;
}
2005-09-25 14:28:13 +10:00
if ( DRM_COPY_TO_USER ( param . value , & value , sizeof ( int ) ) ) {
DRM_ERROR ( " copy_to_user \n " ) ;
2005-04-16 15:20:36 -07:00
return DRM_ERR ( EFAULT ) ;
}
2005-09-25 14:28:13 +10:00
2005-04-16 15:20:36 -07:00
return 0 ;
}
2005-11-10 22:16:34 +11:00
void r128_driver_preclose ( drm_device_t * dev , DRMFILE filp )
2005-04-16 15:20:36 -07:00
{
2005-09-25 14:28:13 +10:00
if ( dev - > dev_private ) {
2005-04-16 15:20:36 -07:00
drm_r128_private_t * dev_priv = dev - > dev_private ;
2005-09-25 14:28:13 +10:00
if ( dev_priv - > page_flipping ) {
r128_do_cleanup_pageflip ( dev ) ;
2005-04-16 15:20:36 -07:00
}
2005-09-25 14:28:13 +10:00
}
2005-04-16 15:20:36 -07:00
}
2005-11-10 22:16:34 +11:00
void r128_driver_lastclose ( drm_device_t * dev )
2005-04-16 15:20:36 -07:00
{
2005-09-25 14:28:13 +10:00
r128_do_cleanup_cce ( dev ) ;
2005-04-16 15:20:36 -07:00
}
drm_ioctl_desc_t r128_ioctls [ ] = {
2006-01-02 13:54:04 +11:00
[ DRM_IOCTL_NR ( DRM_R128_INIT ) ] = { r128_cce_init , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY } ,
[ DRM_IOCTL_NR ( DRM_R128_CCE_START ) ] = { r128_cce_start , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY } ,
[ DRM_IOCTL_NR ( DRM_R128_CCE_STOP ) ] = { r128_cce_stop , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY } ,
[ DRM_IOCTL_NR ( DRM_R128_CCE_RESET ) ] = { r128_cce_reset , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY } ,
[ DRM_IOCTL_NR ( DRM_R128_CCE_IDLE ) ] = { r128_cce_idle , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_RESET ) ] = { r128_engine_reset , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_FULLSCREEN ) ] = { r128_fullscreen , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_SWAP ) ] = { r128_cce_swap , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_FLIP ) ] = { r128_cce_flip , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_CLEAR ) ] = { r128_cce_clear , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_VERTEX ) ] = { r128_cce_vertex , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_INDICES ) ] = { r128_cce_indices , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_BLIT ) ] = { r128_cce_blit , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_DEPTH ) ] = { r128_cce_depth , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_STIPPLE ) ] = { r128_cce_stipple , DRM_AUTH } ,
[ DRM_IOCTL_NR ( DRM_R128_INDIRECT ) ] = { r128_cce_indirect , DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY } ,
[ DRM_IOCTL_NR ( DRM_R128_GETPARAM ) ] = { r128_getparam , DRM_AUTH } ,
2005-04-16 15:20:36 -07:00
} ;
int r128_max_ioctl = DRM_ARRAY_SIZE ( r128_ioctls ) ;