2009-06-05 16:42:42 +04:00
/*
* Copyright 2007 - 8 Advanced Micro Devices , Inc .
* Copyright 2008 Red Hat Inc .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*
* Authors : Dave Airlie
* Alex Deucher
*/
# include "drmP.h"
# include "radeon_drm.h"
# include "radeon.h"
# include "atom.h"
# include "atom-bits.h"
/* from radeon_encoder.c */
extern uint32_t
radeon_get_encoder_id ( struct drm_device * dev , uint32_t supported_device ,
uint8_t dac ) ;
extern void radeon_link_encoder_connector ( struct drm_device * dev ) ;
extern void
radeon_add_atom_encoder ( struct drm_device * dev , uint32_t encoder_id ,
uint32_t supported_device ) ;
/* from radeon_connector.c */
extern void
radeon_add_atom_connector ( struct drm_device * dev ,
uint32_t connector_id ,
uint32_t supported_device ,
int connector_type ,
struct radeon_i2c_bus_rec * i2c_bus ,
bool linkb , uint32_t igp_lane_info ) ;
/* from radeon_legacy_encoder.c */
extern void
radeon_add_legacy_encoder ( struct drm_device * dev , uint32_t encoder_id ,
uint32_t supported_device ) ;
union atom_supported_devices {
struct _ATOM_SUPPORTED_DEVICES_INFO info ;
struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2 ;
struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1 ;
} ;
static inline struct radeon_i2c_bus_rec radeon_lookup_gpio ( struct drm_device
* dev , uint8_t id )
{
struct radeon_device * rdev = dev - > dev_private ;
struct atom_context * ctx = rdev - > mode_info . atom_context ;
ATOM_GPIO_I2C_ASSIGMENT gpio ;
struct radeon_i2c_bus_rec i2c ;
int index = GetIndexIntoMasterTable ( DATA , GPIO_I2C_Info ) ;
struct _ATOM_GPIO_I2C_INFO * i2c_info ;
uint16_t data_offset ;
memset ( & i2c , 0 , sizeof ( struct radeon_i2c_bus_rec ) ) ;
i2c . valid = false ;
atom_parse_data_header ( ctx , index , NULL , NULL , NULL , & data_offset ) ;
i2c_info = ( struct _ATOM_GPIO_I2C_INFO * ) ( ctx - > bios + data_offset ) ;
gpio = i2c_info - > asGPIO_Info [ id ] ;
i2c . mask_clk_reg = le16_to_cpu ( gpio . usClkMaskRegisterIndex ) * 4 ;
i2c . mask_data_reg = le16_to_cpu ( gpio . usDataMaskRegisterIndex ) * 4 ;
i2c . put_clk_reg = le16_to_cpu ( gpio . usClkEnRegisterIndex ) * 4 ;
i2c . put_data_reg = le16_to_cpu ( gpio . usDataEnRegisterIndex ) * 4 ;
i2c . get_clk_reg = le16_to_cpu ( gpio . usClkY_RegisterIndex ) * 4 ;
i2c . get_data_reg = le16_to_cpu ( gpio . usDataY_RegisterIndex ) * 4 ;
i2c . a_clk_reg = le16_to_cpu ( gpio . usClkA_RegisterIndex ) * 4 ;
i2c . a_data_reg = le16_to_cpu ( gpio . usDataA_RegisterIndex ) * 4 ;
i2c . mask_clk_mask = ( 1 < < gpio . ucClkMaskShift ) ;
i2c . mask_data_mask = ( 1 < < gpio . ucDataMaskShift ) ;
i2c . put_clk_mask = ( 1 < < gpio . ucClkEnShift ) ;
i2c . put_data_mask = ( 1 < < gpio . ucDataEnShift ) ;
i2c . get_clk_mask = ( 1 < < gpio . ucClkY_Shift ) ;
i2c . get_data_mask = ( 1 < < gpio . ucDataY_Shift ) ;
i2c . a_clk_mask = ( 1 < < gpio . ucClkA_Shift ) ;
i2c . a_data_mask = ( 1 < < gpio . ucDataA_Shift ) ;
i2c . valid = true ;
return i2c ;
}
static bool radeon_atom_apply_quirks ( struct drm_device * dev ,
uint32_t supported_device ,
int * connector_type ,
2009-07-09 00:15:30 +04:00
struct radeon_i2c_bus_rec * i2c_bus ,
uint8_t * line_mux )
2009-06-05 16:42:42 +04:00
{
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
if ( ( dev - > pdev - > device = = 0x791e ) & &
( dev - > pdev - > subsystem_vendor = = 0x1043 ) & &
( dev - > pdev - > subsystem_device = = 0x826d ) ) {
if ( ( * connector_type = = DRM_MODE_CONNECTOR_HDMIA ) & &
( supported_device = = ATOM_DEVICE_DFP3_SUPPORT ) )
* connector_type = DRM_MODE_CONNECTOR_DVID ;
}
/* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */
if ( ( dev - > pdev - > device = = 0x7941 ) & &
( dev - > pdev - > subsystem_vendor = = 0x147b ) & &
( dev - > pdev - > subsystem_device = = 0x2412 ) ) {
if ( * connector_type = = DRM_MODE_CONNECTOR_DVII )
return false ;
}
/* Falcon NW laptop lists vga ddc line for LVDS */
if ( ( dev - > pdev - > device = = 0x5653 ) & &
( dev - > pdev - > subsystem_vendor = = 0x1462 ) & &
( dev - > pdev - > subsystem_device = = 0x0291 ) ) {
2009-07-09 00:15:30 +04:00
if ( * connector_type = = DRM_MODE_CONNECTOR_LVDS ) {
2009-06-05 16:42:42 +04:00
i2c_bus - > valid = false ;
2009-07-09 00:15:30 +04:00
* line_mux = 53 ;
}
2009-06-05 16:42:42 +04:00
}
/* Funky macbooks */
if ( ( dev - > pdev - > device = = 0x71C5 ) & &
( dev - > pdev - > subsystem_vendor = = 0x106b ) & &
( dev - > pdev - > subsystem_device = = 0x0080 ) ) {
if ( ( supported_device = = ATOM_DEVICE_CRT1_SUPPORT ) | |
( supported_device = = ATOM_DEVICE_DFP2_SUPPORT ) )
return false ;
}
/* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */
if ( ( * connector_type = = DRM_MODE_CONNECTOR_HDMIA ) | |
( * connector_type = = DRM_MODE_CONNECTOR_HDMIB ) ) {
if ( supported_device & ( ATOM_DEVICE_CRT_SUPPORT ) ) {
return false ;
}
}
/* ASUS HD 3600 XT board lists the DVI port as HDMI */
if ( ( dev - > pdev - > device = = 0x9598 ) & &
( dev - > pdev - > subsystem_vendor = = 0x1043 ) & &
( dev - > pdev - > subsystem_device = = 0x01da ) ) {
if ( * connector_type = = DRM_MODE_CONNECTOR_HDMIB ) {
* connector_type = DRM_MODE_CONNECTOR_DVID ;
}
}
return true ;
}
const int supported_devices_connector_convert [ ] = {
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_VGA ,
DRM_MODE_CONNECTOR_DVII ,
DRM_MODE_CONNECTOR_DVID ,
DRM_MODE_CONNECTOR_DVIA ,
DRM_MODE_CONNECTOR_SVIDEO ,
DRM_MODE_CONNECTOR_Composite ,
DRM_MODE_CONNECTOR_LVDS ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_HDMIA ,
DRM_MODE_CONNECTOR_HDMIB ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_9PinDIN ,
DRM_MODE_CONNECTOR_DisplayPort
} ;
const int object_connector_convert [ ] = {
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_DVII ,
DRM_MODE_CONNECTOR_DVII ,
DRM_MODE_CONNECTOR_DVID ,
DRM_MODE_CONNECTOR_DVID ,
DRM_MODE_CONNECTOR_VGA ,
DRM_MODE_CONNECTOR_Composite ,
DRM_MODE_CONNECTOR_SVIDEO ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_9PinDIN ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_HDMIA ,
DRM_MODE_CONNECTOR_HDMIB ,
DRM_MODE_CONNECTOR_HDMIB ,
DRM_MODE_CONNECTOR_LVDS ,
DRM_MODE_CONNECTOR_9PinDIN ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_Unknown ,
DRM_MODE_CONNECTOR_DisplayPort
} ;
bool radeon_get_atom_connector_info_from_object_table ( struct drm_device * dev )
{
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
struct atom_context * ctx = mode_info - > atom_context ;
int index = GetIndexIntoMasterTable ( DATA , Object_Header ) ;
uint16_t size , data_offset ;
uint8_t frev , crev , line_mux = 0 ;
ATOM_CONNECTOR_OBJECT_TABLE * con_obj ;
ATOM_DISPLAY_OBJECT_PATH_TABLE * path_obj ;
ATOM_OBJECT_HEADER * obj_header ;
int i , j , path_size , device_support ;
int connector_type ;
uint16_t igp_lane_info ;
bool linkb ;
struct radeon_i2c_bus_rec ddc_bus ;
atom_parse_data_header ( ctx , index , & size , & frev , & crev , & data_offset ) ;
if ( data_offset = = 0 )
return false ;
if ( crev < 2 )
return false ;
obj_header = ( ATOM_OBJECT_HEADER * ) ( ctx - > bios + data_offset ) ;
path_obj = ( ATOM_DISPLAY_OBJECT_PATH_TABLE * )
( ctx - > bios + data_offset +
le16_to_cpu ( obj_header - > usDisplayPathTableOffset ) ) ;
con_obj = ( ATOM_CONNECTOR_OBJECT_TABLE * )
( ctx - > bios + data_offset +
le16_to_cpu ( obj_header - > usConnectorObjectTableOffset ) ) ;
device_support = le16_to_cpu ( obj_header - > usDeviceSupport ) ;
path_size = 0 ;
for ( i = 0 ; i < path_obj - > ucNumOfDispPath ; i + + ) {
uint8_t * addr = ( uint8_t * ) path_obj - > asDispPath ;
ATOM_DISPLAY_OBJECT_PATH * path ;
addr + = path_size ;
path = ( ATOM_DISPLAY_OBJECT_PATH * ) addr ;
path_size + = le16_to_cpu ( path - > usSize ) ;
linkb = false ;
if ( device_support & le16_to_cpu ( path - > usDeviceTag ) ) {
uint8_t con_obj_id , con_obj_num , con_obj_type ;
con_obj_id =
( le16_to_cpu ( path - > usConnObjectId ) & OBJECT_ID_MASK )
> > OBJECT_ID_SHIFT ;
con_obj_num =
( le16_to_cpu ( path - > usConnObjectId ) & ENUM_ID_MASK )
> > ENUM_ID_SHIFT ;
con_obj_type =
( le16_to_cpu ( path - > usConnObjectId ) &
OBJECT_TYPE_MASK ) > > OBJECT_TYPE_SHIFT ;
if ( ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_TV1_SUPPORT )
| | ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_TV2_SUPPORT )
| | ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_CV_SUPPORT ) )
continue ;
if ( ( rdev - > family = = CHIP_RS780 ) & &
( con_obj_id = =
CONNECTOR_OBJECT_ID_PCIE_CONNECTOR ) ) {
uint16_t igp_offset = 0 ;
ATOM_INTEGRATED_SYSTEM_INFO_V2 * igp_obj ;
index =
GetIndexIntoMasterTable ( DATA ,
IntegratedSystemInfo ) ;
atom_parse_data_header ( ctx , index , & size , & frev ,
& crev , & igp_offset ) ;
if ( crev > = 2 ) {
igp_obj =
( ATOM_INTEGRATED_SYSTEM_INFO_V2
* ) ( ctx - > bios + igp_offset ) ;
if ( igp_obj ) {
uint32_t slot_config , ct ;
if ( con_obj_num = = 1 )
slot_config =
igp_obj - >
ulDDISlot1Config ;
else
slot_config =
igp_obj - >
ulDDISlot2Config ;
ct = ( slot_config > > 16 ) & 0xff ;
connector_type =
object_connector_convert
[ ct ] ;
igp_lane_info =
slot_config & 0xffff ;
} else
continue ;
} else
continue ;
} else {
igp_lane_info = 0 ;
connector_type =
object_connector_convert [ con_obj_id ] ;
}
if ( connector_type = = DRM_MODE_CONNECTOR_Unknown )
continue ;
for ( j = 0 ; j < ( ( le16_to_cpu ( path - > usSize ) - 8 ) / 2 ) ;
j + + ) {
uint8_t enc_obj_id , enc_obj_num , enc_obj_type ;
enc_obj_id =
( le16_to_cpu ( path - > usGraphicObjIds [ j ] ) &
OBJECT_ID_MASK ) > > OBJECT_ID_SHIFT ;
enc_obj_num =
( le16_to_cpu ( path - > usGraphicObjIds [ j ] ) &
ENUM_ID_MASK ) > > ENUM_ID_SHIFT ;
enc_obj_type =
( le16_to_cpu ( path - > usGraphicObjIds [ j ] ) &
OBJECT_TYPE_MASK ) > > OBJECT_TYPE_SHIFT ;
/* FIXME: add support for router objects */
if ( enc_obj_type = = GRAPH_OBJECT_TYPE_ENCODER ) {
if ( enc_obj_num = = 2 )
linkb = true ;
else
linkb = false ;
radeon_add_atom_encoder ( dev ,
enc_obj_id ,
le16_to_cpu
( path - >
usDeviceTag ) ) ;
}
}
/* look up gpio for ddc */
if ( ( le16_to_cpu ( path - > usDeviceTag ) &
( ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT ) )
= = 0 ) {
for ( j = 0 ; j < con_obj - > ucNumberOfObjects ; j + + ) {
if ( le16_to_cpu ( path - > usConnObjectId ) = =
le16_to_cpu ( con_obj - > asObjects [ j ] .
usObjectID ) ) {
ATOM_COMMON_RECORD_HEADER
* record =
( ATOM_COMMON_RECORD_HEADER
* )
( ctx - > bios + data_offset +
le16_to_cpu ( con_obj - >
asObjects [ j ] .
usRecordOffset ) ) ;
ATOM_I2C_RECORD * i2c_record ;
while ( record - > ucRecordType > 0
& & record - >
ucRecordType < =
ATOM_MAX_OBJECT_RECORD_NUMBER ) {
DRM_ERROR
( " record type %d \n " ,
record - >
ucRecordType ) ;
switch ( record - >
ucRecordType ) {
case ATOM_I2C_RECORD_TYPE :
i2c_record =
( ATOM_I2C_RECORD
* ) record ;
line_mux =
i2c_record - >
sucI2cId .
bfI2C_LineMux ;
break ;
}
record =
( ATOM_COMMON_RECORD_HEADER
* ) ( ( char * ) record
+
record - >
ucRecordSize ) ;
}
break ;
}
}
} else
line_mux = 0 ;
if ( ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_TV1_SUPPORT )
| | ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_TV2_SUPPORT )
| | ( le16_to_cpu ( path - > usDeviceTag ) = =
ATOM_DEVICE_CV_SUPPORT ) )
ddc_bus . valid = false ;
else
ddc_bus = radeon_lookup_gpio ( dev , line_mux ) ;
radeon_add_atom_connector ( dev ,
le16_to_cpu ( path - >
usConnObjectId ) ,
le16_to_cpu ( path - >
usDeviceTag ) ,
connector_type , & ddc_bus ,
linkb , igp_lane_info ) ;
}
}
radeon_link_encoder_connector ( dev ) ;
return true ;
}
struct bios_connector {
bool valid ;
uint8_t line_mux ;
uint16_t devices ;
int connector_type ;
struct radeon_i2c_bus_rec ddc_bus ;
} ;
bool radeon_get_atom_connector_info_from_supported_devices_table ( struct
drm_device
* dev )
{
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
struct atom_context * ctx = mode_info - > atom_context ;
int index = GetIndexIntoMasterTable ( DATA , SupportedDevicesInfo ) ;
uint16_t size , data_offset ;
uint8_t frev , crev ;
uint16_t device_support ;
uint8_t dac ;
union atom_supported_devices * supported_devices ;
int i , j ;
struct bios_connector bios_connectors [ ATOM_MAX_SUPPORTED_DEVICE ] ;
atom_parse_data_header ( ctx , index , & size , & frev , & crev , & data_offset ) ;
supported_devices =
( union atom_supported_devices * ) ( ctx - > bios + data_offset ) ;
device_support = le16_to_cpu ( supported_devices - > info . usDeviceSupport ) ;
for ( i = 0 ; i < ATOM_MAX_SUPPORTED_DEVICE ; i + + ) {
ATOM_CONNECTOR_INFO_I2C ci =
supported_devices - > info . asConnInfo [ i ] ;
bios_connectors [ i ] . valid = false ;
if ( ! ( device_support & ( 1 < < i ) ) ) {
continue ;
}
if ( i = = ATOM_DEVICE_CV_INDEX ) {
DRM_DEBUG ( " Skipping Component Video \n " ) ;
continue ;
}
if ( i = = ATOM_DEVICE_TV1_INDEX ) {
DRM_DEBUG ( " Skipping TV Out \n " ) ;
continue ;
}
bios_connectors [ i ] . connector_type =
supported_devices_connector_convert [ ci . sucConnectorInfo .
sbfAccess .
bfConnectorType ] ;
if ( bios_connectors [ i ] . connector_type = =
DRM_MODE_CONNECTOR_Unknown )
continue ;
dac = ci . sucConnectorInfo . sbfAccess . bfAssociatedDAC ;
if ( ( rdev - > family = = CHIP_RS690 ) | |
( rdev - > family = = CHIP_RS740 ) ) {
if ( ( i = = ATOM_DEVICE_DFP2_INDEX )
& & ( ci . sucI2cId . sbfAccess . bfI2C_LineMux = = 2 ) )
bios_connectors [ i ] . line_mux =
ci . sucI2cId . sbfAccess . bfI2C_LineMux + 1 ;
else if ( ( i = = ATOM_DEVICE_DFP3_INDEX )
& & ( ci . sucI2cId . sbfAccess . bfI2C_LineMux = = 1 ) )
bios_connectors [ i ] . line_mux =
ci . sucI2cId . sbfAccess . bfI2C_LineMux + 1 ;
else
bios_connectors [ i ] . line_mux =
ci . sucI2cId . sbfAccess . bfI2C_LineMux ;
} else
bios_connectors [ i ] . line_mux =
ci . sucI2cId . sbfAccess . bfI2C_LineMux ;
/* give tv unique connector ids */
if ( i = = ATOM_DEVICE_TV1_INDEX ) {
bios_connectors [ i ] . ddc_bus . valid = false ;
bios_connectors [ i ] . line_mux = 50 ;
} else if ( i = = ATOM_DEVICE_TV2_INDEX ) {
bios_connectors [ i ] . ddc_bus . valid = false ;
bios_connectors [ i ] . line_mux = 51 ;
} else if ( i = = ATOM_DEVICE_CV_INDEX ) {
bios_connectors [ i ] . ddc_bus . valid = false ;
bios_connectors [ i ] . line_mux = 52 ;
} else
bios_connectors [ i ] . ddc_bus =
radeon_lookup_gpio ( dev ,
bios_connectors [ i ] . line_mux ) ;
/* Always set the connector type to VGA for CRT1/CRT2. if they are
* shared with a DVI port , we ' ll pick up the DVI connector when we
* merge the outputs . Some bioses incorrectly list VGA ports as DVI .
*/
if ( i = = ATOM_DEVICE_CRT1_INDEX | | i = = ATOM_DEVICE_CRT2_INDEX )
bios_connectors [ i ] . connector_type =
DRM_MODE_CONNECTOR_VGA ;
if ( ! radeon_atom_apply_quirks
( dev , ( 1 < < i ) , & bios_connectors [ i ] . connector_type ,
2009-07-09 00:15:30 +04:00
& bios_connectors [ i ] . ddc_bus , & bios_connectors [ i ] . line_mux ) )
2009-06-05 16:42:42 +04:00
continue ;
bios_connectors [ i ] . valid = true ;
bios_connectors [ i ] . devices = ( 1 < < i ) ;
if ( ASIC_IS_AVIVO ( rdev ) | | radeon_r4xx_atom )
radeon_add_atom_encoder ( dev ,
radeon_get_encoder_id ( dev ,
( 1 < < i ) ,
dac ) ,
( 1 < < i ) ) ;
else
radeon_add_legacy_encoder ( dev ,
radeon_get_encoder_id ( dev ,
( 1 < <
i ) ,
dac ) ,
( 1 < < i ) ) ;
}
/* combine shared connectors */
for ( i = 0 ; i < ATOM_MAX_SUPPORTED_DEVICE ; i + + ) {
if ( bios_connectors [ i ] . valid ) {
for ( j = 0 ; j < ATOM_MAX_SUPPORTED_DEVICE ; j + + ) {
if ( bios_connectors [ j ] . valid & & ( i ! = j ) ) {
if ( bios_connectors [ i ] . line_mux = =
bios_connectors [ j ] . line_mux ) {
if ( ( ( bios_connectors [ i ] .
devices &
( ATOM_DEVICE_DFP_SUPPORT ) )
& & ( bios_connectors [ j ] .
devices &
( ATOM_DEVICE_CRT_SUPPORT ) ) )
| |
( ( bios_connectors [ j ] .
devices &
( ATOM_DEVICE_DFP_SUPPORT ) )
& & ( bios_connectors [ i ] .
devices &
( ATOM_DEVICE_CRT_SUPPORT ) ) ) ) {
bios_connectors [ i ] .
devices | =
bios_connectors [ j ] .
devices ;
bios_connectors [ i ] .
connector_type =
DRM_MODE_CONNECTOR_DVII ;
bios_connectors [ j ] .
valid = false ;
}
}
}
}
}
}
/* add the connectors */
for ( i = 0 ; i < ATOM_MAX_SUPPORTED_DEVICE ; i + + ) {
if ( bios_connectors [ i ] . valid )
radeon_add_atom_connector ( dev ,
bios_connectors [ i ] . line_mux ,
bios_connectors [ i ] . devices ,
bios_connectors [ i ] .
connector_type ,
& bios_connectors [ i ] . ddc_bus ,
false , 0 ) ;
}
radeon_link_encoder_connector ( dev ) ;
return true ;
}
union firmware_info {
ATOM_FIRMWARE_INFO info ;
ATOM_FIRMWARE_INFO_V1_2 info_12 ;
ATOM_FIRMWARE_INFO_V1_3 info_13 ;
ATOM_FIRMWARE_INFO_V1_4 info_14 ;
} ;
bool radeon_atom_get_clock_info ( struct drm_device * dev )
{
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
int index = GetIndexIntoMasterTable ( DATA , FirmwareInfo ) ;
union firmware_info * firmware_info ;
uint8_t frev , crev ;
struct radeon_pll * p1pll = & rdev - > clock . p1pll ;
struct radeon_pll * p2pll = & rdev - > clock . p2pll ;
struct radeon_pll * spll = & rdev - > clock . spll ;
struct radeon_pll * mpll = & rdev - > clock . mpll ;
uint16_t data_offset ;
atom_parse_data_header ( mode_info - > atom_context , index , NULL , & frev ,
& crev , & data_offset ) ;
firmware_info =
( union firmware_info * ) ( mode_info - > atom_context - > bios +
data_offset ) ;
if ( firmware_info ) {
/* pixel clocks */
p1pll - > reference_freq =
le16_to_cpu ( firmware_info - > info . usReferenceClock ) ;
p1pll - > reference_div = 0 ;
p1pll - > pll_out_min =
le16_to_cpu ( firmware_info - > info . usMinPixelClockPLL_Output ) ;
p1pll - > pll_out_max =
le32_to_cpu ( firmware_info - > info . ulMaxPixelClockPLL_Output ) ;
if ( p1pll - > pll_out_min = = 0 ) {
if ( ASIC_IS_AVIVO ( rdev ) )
p1pll - > pll_out_min = 64800 ;
else
p1pll - > pll_out_min = 20000 ;
}
p1pll - > pll_in_min =
le16_to_cpu ( firmware_info - > info . usMinPixelClockPLL_Input ) ;
p1pll - > pll_in_max =
le16_to_cpu ( firmware_info - > info . usMaxPixelClockPLL_Input ) ;
* p2pll = * p1pll ;
/* system clock */
spll - > reference_freq =
le16_to_cpu ( firmware_info - > info . usReferenceClock ) ;
spll - > reference_div = 0 ;
spll - > pll_out_min =
le16_to_cpu ( firmware_info - > info . usMinEngineClockPLL_Output ) ;
spll - > pll_out_max =
le32_to_cpu ( firmware_info - > info . ulMaxEngineClockPLL_Output ) ;
/* ??? */
if ( spll - > pll_out_min = = 0 ) {
if ( ASIC_IS_AVIVO ( rdev ) )
spll - > pll_out_min = 64800 ;
else
spll - > pll_out_min = 20000 ;
}
spll - > pll_in_min =
le16_to_cpu ( firmware_info - > info . usMinEngineClockPLL_Input ) ;
spll - > pll_in_max =
le16_to_cpu ( firmware_info - > info . usMaxEngineClockPLL_Input ) ;
/* memory clock */
mpll - > reference_freq =
le16_to_cpu ( firmware_info - > info . usReferenceClock ) ;
mpll - > reference_div = 0 ;
mpll - > pll_out_min =
le16_to_cpu ( firmware_info - > info . usMinMemoryClockPLL_Output ) ;
mpll - > pll_out_max =
le32_to_cpu ( firmware_info - > info . ulMaxMemoryClockPLL_Output ) ;
/* ??? */
if ( mpll - > pll_out_min = = 0 ) {
if ( ASIC_IS_AVIVO ( rdev ) )
mpll - > pll_out_min = 64800 ;
else
mpll - > pll_out_min = 20000 ;
}
mpll - > pll_in_min =
le16_to_cpu ( firmware_info - > info . usMinMemoryClockPLL_Input ) ;
mpll - > pll_in_max =
le16_to_cpu ( firmware_info - > info . usMaxMemoryClockPLL_Input ) ;
rdev - > clock . default_sclk =
le32_to_cpu ( firmware_info - > info . ulDefaultEngineClock ) ;
rdev - > clock . default_mclk =
le32_to_cpu ( firmware_info - > info . ulDefaultMemoryClock ) ;
return true ;
}
return false ;
}
struct radeon_encoder_int_tmds * radeon_atombios_get_tmds_info ( struct
radeon_encoder
* encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
int index = GetIndexIntoMasterTable ( DATA , TMDS_Info ) ;
uint16_t data_offset ;
struct _ATOM_TMDS_INFO * tmds_info ;
uint8_t frev , crev ;
uint16_t maxfreq ;
int i ;
struct radeon_encoder_int_tmds * tmds = NULL ;
atom_parse_data_header ( mode_info - > atom_context , index , NULL , & frev ,
& crev , & data_offset ) ;
tmds_info =
( struct _ATOM_TMDS_INFO * ) ( mode_info - > atom_context - > bios +
data_offset ) ;
if ( tmds_info ) {
tmds =
kzalloc ( sizeof ( struct radeon_encoder_int_tmds ) , GFP_KERNEL ) ;
if ( ! tmds )
return NULL ;
maxfreq = le16_to_cpu ( tmds_info - > usMaxFrequency ) ;
for ( i = 0 ; i < 4 ; i + + ) {
tmds - > tmds_pll [ i ] . freq =
le16_to_cpu ( tmds_info - > asMiscInfo [ i ] . usFrequency ) ;
tmds - > tmds_pll [ i ] . value =
tmds_info - > asMiscInfo [ i ] . ucPLL_ChargePump & 0x3f ;
tmds - > tmds_pll [ i ] . value | =
( tmds_info - > asMiscInfo [ i ] .
ucPLL_VCO_Gain & 0x3f ) < < 6 ;
tmds - > tmds_pll [ i ] . value | =
( tmds_info - > asMiscInfo [ i ] .
ucPLL_DutyCycle & 0xf ) < < 12 ;
tmds - > tmds_pll [ i ] . value | =
( tmds_info - > asMiscInfo [ i ] .
ucPLL_VoltageSwing & 0xf ) < < 16 ;
DRM_DEBUG ( " TMDS PLL From ATOMBIOS %u %x \n " ,
tmds - > tmds_pll [ i ] . freq ,
tmds - > tmds_pll [ i ] . value ) ;
if ( maxfreq = = tmds - > tmds_pll [ i ] . freq ) {
tmds - > tmds_pll [ i ] . freq = 0xffffffff ;
break ;
}
}
}
return tmds ;
}
union lvds_info {
struct _ATOM_LVDS_INFO info ;
struct _ATOM_LVDS_INFO_V12 info_12 ;
} ;
struct radeon_encoder_atom_dig * radeon_atombios_get_lvds_info ( struct
radeon_encoder
* encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
int index = GetIndexIntoMasterTable ( DATA , LVDS_Info ) ;
uint16_t data_offset ;
union lvds_info * lvds_info ;
uint8_t frev , crev ;
struct radeon_encoder_atom_dig * lvds = NULL ;
atom_parse_data_header ( mode_info - > atom_context , index , NULL , & frev ,
& crev , & data_offset ) ;
lvds_info =
( union lvds_info * ) ( mode_info - > atom_context - > bios + data_offset ) ;
if ( lvds_info ) {
lvds =
kzalloc ( sizeof ( struct radeon_encoder_atom_dig ) , GFP_KERNEL ) ;
if ( ! lvds )
return NULL ;
lvds - > native_mode . dotclock =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usPixClk ) * 10 ;
lvds - > native_mode . panel_xres =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usHActive ) ;
lvds - > native_mode . panel_yres =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usVActive ) ;
lvds - > native_mode . hblank =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usHBlanking_Time ) ;
lvds - > native_mode . hoverplus =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usHSyncOffset ) ;
lvds - > native_mode . hsync_width =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usHSyncWidth ) ;
lvds - > native_mode . vblank =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usVBlanking_Time ) ;
lvds - > native_mode . voverplus =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usVSyncOffset ) ;
lvds - > native_mode . vsync_width =
le16_to_cpu ( lvds_info - > info . sLCDTiming . usVSyncWidth ) ;
lvds - > panel_pwr_delay =
le16_to_cpu ( lvds_info - > info . usOffDelayInMs ) ;
lvds - > lvds_misc = lvds_info - > info . ucLVDS_Misc ;
encoder - > native_mode = lvds - > native_mode ;
}
return lvds ;
}
2009-06-12 21:26:08 +04:00
struct radeon_encoder_primary_dac *
radeon_atombios_get_primary_dac_info ( struct radeon_encoder * encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
int index = GetIndexIntoMasterTable ( DATA , CompassionateData ) ;
uint16_t data_offset ;
struct _COMPASSIONATE_DATA * dac_info ;
uint8_t frev , crev ;
uint8_t bg , dac ;
struct radeon_encoder_primary_dac * p_dac = NULL ;
atom_parse_data_header ( mode_info - > atom_context , index , NULL , & frev , & crev , & data_offset ) ;
dac_info = ( struct _COMPASSIONATE_DATA * ) ( mode_info - > atom_context - > bios + data_offset ) ;
if ( dac_info ) {
p_dac = kzalloc ( sizeof ( struct radeon_encoder_primary_dac ) , GFP_KERNEL ) ;
if ( ! p_dac )
return NULL ;
bg = dac_info - > ucDAC1_BG_Adjustment ;
dac = dac_info - > ucDAC1_DAC_Adjustment ;
p_dac - > ps2_pdac_adj = ( bg < < 8 ) | ( dac ) ;
}
return p_dac ;
}
struct radeon_encoder_tv_dac *
radeon_atombios_get_tv_dac_info ( struct radeon_encoder * encoder )
{
struct drm_device * dev = encoder - > base . dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_mode_info * mode_info = & rdev - > mode_info ;
int index = GetIndexIntoMasterTable ( DATA , CompassionateData ) ;
uint16_t data_offset ;
struct _COMPASSIONATE_DATA * dac_info ;
uint8_t frev , crev ;
uint8_t bg , dac ;
struct radeon_encoder_tv_dac * tv_dac = NULL ;
atom_parse_data_header ( mode_info - > atom_context , index , NULL , & frev , & crev , & data_offset ) ;
dac_info = ( struct _COMPASSIONATE_DATA * ) ( mode_info - > atom_context - > bios + data_offset ) ;
if ( dac_info ) {
tv_dac = kzalloc ( sizeof ( struct radeon_encoder_tv_dac ) , GFP_KERNEL ) ;
if ( ! tv_dac )
return NULL ;
bg = dac_info - > ucDAC2_CRT2_BG_Adjustment ;
dac = dac_info - > ucDAC2_CRT2_DAC_Adjustment ;
tv_dac - > ps2_tvdac_adj = ( bg < < 16 ) | ( dac < < 20 ) ;
bg = dac_info - > ucDAC2_PAL_BG_Adjustment ;
dac = dac_info - > ucDAC2_PAL_DAC_Adjustment ;
tv_dac - > pal_tvdac_adj = ( bg < < 16 ) | ( dac < < 20 ) ;
bg = dac_info - > ucDAC2_NTSC_BG_Adjustment ;
dac = dac_info - > ucDAC2_NTSC_DAC_Adjustment ;
tv_dac - > ntsc_tvdac_adj = ( bg < < 16 ) | ( dac < < 20 ) ;
}
return tv_dac ;
}
2009-06-05 16:42:42 +04:00
void radeon_atom_set_clock_gating ( struct radeon_device * rdev , int enable )
{
DYNAMIC_CLOCK_GATING_PS_ALLOCATION args ;
int index = GetIndexIntoMasterTable ( COMMAND , DynamicClockGating ) ;
args . ucEnable = enable ;
atom_execute_table ( rdev - > mode_info . atom_context , index , ( uint32_t * ) & args ) ;
}
void radeon_atom_static_pwrmgt_setup ( struct radeon_device * rdev , int enable )
{
ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args ;
int index = GetIndexIntoMasterTable ( COMMAND , EnableASIC_StaticPwrMgt ) ;
args . ucEnable = enable ;
atom_execute_table ( rdev - > mode_info . atom_context , index , ( uint32_t * ) & args ) ;
}
void radeon_atom_set_engine_clock ( struct radeon_device * rdev ,
uint32_t eng_clock )
{
SET_ENGINE_CLOCK_PS_ALLOCATION args ;
int index = GetIndexIntoMasterTable ( COMMAND , SetEngineClock ) ;
args . ulTargetEngineClock = eng_clock ; /* 10 khz */
atom_execute_table ( rdev - > mode_info . atom_context , index , ( uint32_t * ) & args ) ;
}
void radeon_atom_set_memory_clock ( struct radeon_device * rdev ,
uint32_t mem_clock )
{
SET_MEMORY_CLOCK_PS_ALLOCATION args ;
int index = GetIndexIntoMasterTable ( COMMAND , SetMemoryClock ) ;
if ( rdev - > flags & RADEON_IS_IGP )
return ;
args . ulTargetMemoryClock = mem_clock ; /* 10 khz */
atom_execute_table ( rdev - > mode_info . atom_context , index , ( uint32_t * ) & args ) ;
}
void radeon_atom_initialize_bios_scratch_regs ( struct drm_device * dev )
{
struct radeon_device * rdev = dev - > dev_private ;
uint32_t bios_2_scratch , bios_6_scratch ;
if ( rdev - > family > = CHIP_R600 ) {
bios_2_scratch = RREG32 ( R600_BIOS_0_SCRATCH ) ;
bios_6_scratch = RREG32 ( R600_BIOS_6_SCRATCH ) ;
} else {
bios_2_scratch = RREG32 ( RADEON_BIOS_0_SCRATCH ) ;
bios_6_scratch = RREG32 ( RADEON_BIOS_6_SCRATCH ) ;
}
/* let the bios control the backlight */
bios_2_scratch & = ~ ATOM_S2_VRI_BRIGHT_ENABLE ;
/* tell the bios not to handle mode switching */
bios_6_scratch | = ( ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE ) ;
if ( rdev - > family > = CHIP_R600 ) {
WREG32 ( R600_BIOS_2_SCRATCH , bios_2_scratch ) ;
WREG32 ( R600_BIOS_6_SCRATCH , bios_6_scratch ) ;
} else {
WREG32 ( RADEON_BIOS_2_SCRATCH , bios_2_scratch ) ;
WREG32 ( RADEON_BIOS_6_SCRATCH , bios_6_scratch ) ;
}
}
void radeon_atom_output_lock ( struct drm_encoder * encoder , bool lock )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
uint32_t bios_6_scratch ;
if ( rdev - > family > = CHIP_R600 )
bios_6_scratch = RREG32 ( R600_BIOS_6_SCRATCH ) ;
else
bios_6_scratch = RREG32 ( RADEON_BIOS_6_SCRATCH ) ;
if ( lock )
bios_6_scratch | = ATOM_S6_CRITICAL_STATE ;
else
bios_6_scratch & = ~ ATOM_S6_CRITICAL_STATE ;
if ( rdev - > family > = CHIP_R600 )
WREG32 ( R600_BIOS_6_SCRATCH , bios_6_scratch ) ;
else
WREG32 ( RADEON_BIOS_6_SCRATCH , bios_6_scratch ) ;
}
/* at some point we may want to break this out into individual functions */
void
radeon_atombios_connected_scratch_regs ( struct drm_connector * connector ,
struct drm_encoder * encoder ,
bool connected )
{
struct drm_device * dev = connector - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_connector * radeon_connector =
to_radeon_connector ( connector ) ;
struct radeon_encoder * radeon_encoder = to_radeon_encoder ( encoder ) ;
uint32_t bios_0_scratch , bios_3_scratch , bios_6_scratch ;
if ( rdev - > family > = CHIP_R600 ) {
bios_0_scratch = RREG32 ( R600_BIOS_0_SCRATCH ) ;
bios_3_scratch = RREG32 ( R600_BIOS_3_SCRATCH ) ;
bios_6_scratch = RREG32 ( R600_BIOS_6_SCRATCH ) ;
} else {
bios_0_scratch = RREG32 ( RADEON_BIOS_0_SCRATCH ) ;
bios_3_scratch = RREG32 ( RADEON_BIOS_3_SCRATCH ) ;
bios_6_scratch = RREG32 ( RADEON_BIOS_6_SCRATCH ) ;
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_TV1_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_TV1_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " TV1 connected \n " ) ;
bios_3_scratch | = ATOM_S3_TV1_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_TV1 ;
} else {
DRM_DEBUG ( " TV1 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_TV1_MASK ;
bios_3_scratch & = ~ ATOM_S3_TV1_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_TV1 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_CV_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_CV_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " CV connected \n " ) ;
bios_3_scratch | = ATOM_S3_CV_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_CV ;
} else {
DRM_DEBUG ( " CV disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_CV_MASK ;
bios_3_scratch & = ~ ATOM_S3_CV_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_CV ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_LCD1_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_LCD1_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " LCD1 connected \n " ) ;
bios_0_scratch | = ATOM_S0_LCD1 ;
bios_3_scratch | = ATOM_S3_LCD1_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_LCD1 ;
} else {
DRM_DEBUG ( " LCD1 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_LCD1 ;
bios_3_scratch & = ~ ATOM_S3_LCD1_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_LCD1 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_CRT1_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_CRT1_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " CRT1 connected \n " ) ;
bios_0_scratch | = ATOM_S0_CRT1_COLOR ;
bios_3_scratch | = ATOM_S3_CRT1_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_CRT1 ;
} else {
DRM_DEBUG ( " CRT1 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_CRT1_MASK ;
bios_3_scratch & = ~ ATOM_S3_CRT1_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_CRT1 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_CRT2_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_CRT2_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " CRT2 connected \n " ) ;
bios_0_scratch | = ATOM_S0_CRT2_COLOR ;
bios_3_scratch | = ATOM_S3_CRT2_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_CRT2 ;
} else {
DRM_DEBUG ( " CRT2 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_CRT2_MASK ;
bios_3_scratch & = ~ ATOM_S3_CRT2_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_CRT2 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_DFP1_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_DFP1_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " DFP1 connected \n " ) ;
bios_0_scratch | = ATOM_S0_DFP1 ;
bios_3_scratch | = ATOM_S3_DFP1_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_DFP1 ;
} else {
DRM_DEBUG ( " DFP1 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_DFP1 ;
bios_3_scratch & = ~ ATOM_S3_DFP1_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_DFP1 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_DFP2_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_DFP2_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " DFP2 connected \n " ) ;
bios_0_scratch | = ATOM_S0_DFP2 ;
bios_3_scratch | = ATOM_S3_DFP2_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_DFP2 ;
} else {
DRM_DEBUG ( " DFP2 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_DFP2 ;
bios_3_scratch & = ~ ATOM_S3_DFP2_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_DFP2 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_DFP3_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_DFP3_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " DFP3 connected \n " ) ;
bios_0_scratch | = ATOM_S0_DFP3 ;
bios_3_scratch | = ATOM_S3_DFP3_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_DFP3 ;
} else {
DRM_DEBUG ( " DFP3 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_DFP3 ;
bios_3_scratch & = ~ ATOM_S3_DFP3_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_DFP3 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_DFP4_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_DFP4_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " DFP4 connected \n " ) ;
bios_0_scratch | = ATOM_S0_DFP4 ;
bios_3_scratch | = ATOM_S3_DFP4_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_DFP4 ;
} else {
DRM_DEBUG ( " DFP4 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_DFP4 ;
bios_3_scratch & = ~ ATOM_S3_DFP4_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_DFP4 ;
}
}
if ( ( radeon_encoder - > devices & ATOM_DEVICE_DFP5_SUPPORT ) & &
( radeon_connector - > devices & ATOM_DEVICE_DFP5_SUPPORT ) ) {
if ( connected ) {
DRM_DEBUG ( " DFP5 connected \n " ) ;
bios_0_scratch | = ATOM_S0_DFP5 ;
bios_3_scratch | = ATOM_S3_DFP5_ACTIVE ;
bios_6_scratch | = ATOM_S6_ACC_REQ_DFP5 ;
} else {
DRM_DEBUG ( " DFP5 disconnected \n " ) ;
bios_0_scratch & = ~ ATOM_S0_DFP5 ;
bios_3_scratch & = ~ ATOM_S3_DFP5_ACTIVE ;
bios_6_scratch & = ~ ATOM_S6_ACC_REQ_DFP5 ;
}
}
if ( rdev - > family > = CHIP_R600 ) {
WREG32 ( R600_BIOS_0_SCRATCH , bios_0_scratch ) ;
WREG32 ( R600_BIOS_3_SCRATCH , bios_3_scratch ) ;
WREG32 ( R600_BIOS_6_SCRATCH , bios_6_scratch ) ;
} else {
WREG32 ( RADEON_BIOS_0_SCRATCH , bios_0_scratch ) ;
WREG32 ( RADEON_BIOS_3_SCRATCH , bios_3_scratch ) ;
WREG32 ( RADEON_BIOS_6_SCRATCH , bios_6_scratch ) ;
}
}
void
radeon_atombios_encoder_crtc_scratch_regs ( struct drm_encoder * encoder , int crtc )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_encoder * radeon_encoder = to_radeon_encoder ( encoder ) ;
uint32_t bios_3_scratch ;
if ( rdev - > family > = CHIP_R600 )
bios_3_scratch = RREG32 ( R600_BIOS_3_SCRATCH ) ;
else
bios_3_scratch = RREG32 ( RADEON_BIOS_3_SCRATCH ) ;
if ( radeon_encoder - > devices & ATOM_DEVICE_TV1_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_TV1_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 18 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CV_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_CV_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 24 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CRT1_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_CRT1_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 16 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CRT2_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_CRT2_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 20 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_LCD1_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_LCD1_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 17 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP1_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_DFP1_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 19 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP2_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_DFP2_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 23 ) ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP3_SUPPORT ) {
bios_3_scratch & = ~ ATOM_S3_DFP3_CRTC_ACTIVE ;
bios_3_scratch | = ( crtc < < 25 ) ;
}
if ( rdev - > family > = CHIP_R600 )
WREG32 ( R600_BIOS_3_SCRATCH , bios_3_scratch ) ;
else
WREG32 ( RADEON_BIOS_3_SCRATCH , bios_3_scratch ) ;
}
void
radeon_atombios_encoder_dpms_scratch_regs ( struct drm_encoder * encoder , bool on )
{
struct drm_device * dev = encoder - > dev ;
struct radeon_device * rdev = dev - > dev_private ;
struct radeon_encoder * radeon_encoder = to_radeon_encoder ( encoder ) ;
uint32_t bios_2_scratch ;
if ( rdev - > family > = CHIP_R600 )
bios_2_scratch = RREG32 ( R600_BIOS_2_SCRATCH ) ;
else
bios_2_scratch = RREG32 ( RADEON_BIOS_2_SCRATCH ) ;
if ( radeon_encoder - > devices & ATOM_DEVICE_TV1_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_TV1_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_TV1_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CV_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_CV_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_CV_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CRT1_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_CRT1_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_CRT1_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_CRT2_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_CRT2_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_CRT2_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_LCD1_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_LCD1_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_LCD1_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP1_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_DFP1_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_DFP1_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP2_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_DFP2_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_DFP2_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP3_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_DFP3_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_DFP3_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP4_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_DFP4_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_DFP4_DPMS_STATE ;
}
if ( radeon_encoder - > devices & ATOM_DEVICE_DFP5_SUPPORT ) {
if ( on )
bios_2_scratch & = ~ ATOM_S2_DFP5_DPMS_STATE ;
else
bios_2_scratch | = ATOM_S2_DFP5_DPMS_STATE ;
}
if ( rdev - > family > = CHIP_R600 )
WREG32 ( R600_BIOS_2_SCRATCH , bios_2_scratch ) ;
else
WREG32 ( RADEON_BIOS_2_SCRATCH , bios_2_scratch ) ;
}