@ -1927,6 +1927,31 @@ init_condition_time(struct nvbios *bios, uint16_t offset,
return 3 ;
}
static int
init_ltime ( struct nvbios * bios , uint16_t offset , struct init_exec * iexec )
{
/*
* INIT_LTIME opcode : 0x57 ( ' V ' )
*
* offset ( 8 bit ) : opcode
* offset + 1 ( 16 bit ) : time
*
* Sleep for " time " miliseconds .
*/
unsigned time = ROM16 ( bios - > data [ offset + 1 ] ) ;
if ( ! iexec - > execute )
return 3 ;
BIOSLOG ( bios , " 0x%04X: Sleeping for 0x%04X miliseconds \n " ,
offset , time ) ;
msleep ( time ) ;
return 3 ;
}
static int
init_zm_reg_sequence ( struct nvbios * bios , uint16_t offset ,
struct init_exec * iexec )
@ -1994,6 +2019,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return 3 ;
}
static int
init_i2c_if ( struct nvbios * bios , uint16_t offset , struct init_exec * iexec )
{
/*
* INIT_I2C_IF opcode : 0x5E ( ' ^ ' )
*
* offset ( 8 bit ) : opcode
* offset + 1 ( 8 bit ) : DCB I2C table entry index
* offset + 2 ( 8 bit ) : I2C slave address
* offset + 3 ( 8 bit ) : I2C register
* offset + 4 ( 8 bit ) : mask
* offset + 5 ( 8 bit ) : data
*
* Read the register given by " I2C register " on the device addressed
* by " I2C slave address " on the I2C bus given by " DCB I2C table
* entry index " . Compare the result AND " mask " to " data " .
* If they ' re not equal , skip subsequent opcodes until condition is
* inverted ( INIT_NOT ) , or we hit INIT_RESUME
*/
uint8_t i2c_index = bios - > data [ offset + 1 ] ;
uint8_t i2c_address = bios - > data [ offset + 2 ] > > 1 ;
uint8_t reg = bios - > data [ offset + 3 ] ;
uint8_t mask = bios - > data [ offset + 4 ] ;
uint8_t data = bios - > data [ offset + 5 ] ;
struct nouveau_i2c_chan * chan ;
union i2c_smbus_data val ;
int ret ;
/* no execute check by design */
BIOSLOG ( bios , " 0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X \n " ,
offset , i2c_index , i2c_address ) ;
chan = init_i2c_device_find ( bios - > dev , i2c_index ) ;
if ( ! chan )
return - ENODEV ;
ret = i2c_smbus_xfer ( & chan - > adapter , i2c_address , 0 ,
I2C_SMBUS_READ , reg ,
I2C_SMBUS_BYTE_DATA , & val ) ;
if ( ret < 0 ) {
BIOSLOG ( bios , " 0x%04X: I2CReg: 0x%02X, Value: [no device], "
" Mask: 0x%02X, Data: 0x%02X \n " ,
offset , reg , mask , data ) ;
iexec - > execute = 0 ;
return 6 ;
}
BIOSLOG ( bios , " 0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
" Mask: 0x%02X, Data: 0x%02X \n " ,
offset , reg , val . byte , mask , data ) ;
iexec - > execute = ( ( val . byte & mask ) = = data ) ;
return 6 ;
}
static int
init_copy_nv_reg ( struct nvbios * bios , uint16_t offset , struct init_exec * iexec )
{
@ -2083,9 +2166,10 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t val = 0 ;
if ( off < pci_resource_len ( dev - > pdev , 1 ) ) {
uint32_t __iomem * p = io_mapping_map_atomic_wc ( fb , off , KM_USER0 ) ;
uint32_t __iomem * p =
io_mapping_map_atomic_wc ( fb , off & PAGE_MASK , KM_USER0 ) ;
val = ioread32 ( p ) ;
val = ioread32 ( p + ( off & ~ PAGE_MASK ) ) ;
io_mapping_unmap_atomic ( p , KM_USER0 ) ;
}
@ -2098,9 +2182,10 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t off , uint32_t val )
{
if ( off < pci_resource_len ( dev - > pdev , 1 ) ) {
uint32_t __iomem * p = io_mapping_map_atomic_wc ( fb , off , KM_USER0 ) ;
uint32_t __iomem * p =
io_mapping_map_atomic_wc ( fb , off & PAGE_MASK , KM_USER0 ) ;
iowrite32 ( val , p ) ;
iowrite32 ( val , p + ( off & ~ PAGE_MASK ) ) ;
wmb ( ) ;
io_mapping_unmap_atomic ( p , KM_USER0 ) ;
@ -2165,7 +2250,7 @@ nv04_init_compute_mem(struct nvbios *bios)
NV04_PFB_BOOT_0_RAM_AMOUNT ,
NV04_PFB_BOOT_0_RAM_AMOUNT_4MB ) ;
} else if ( peek_fb ( dev , fb , 0 ) = = patt ) {
} else if ( peek_fb ( dev , fb , 0 ) ! = patt ) {
if ( read_back_fb ( dev , fb , 0x800000 , patt ) )
bios_md32 ( bios , NV04_PFB_BOOT_0 ,
NV04_PFB_BOOT_0_RAM_AMOUNT ,
@ -2593,7 +2678,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset,
/* no iexec->execute check by design */
uint32_t straps = bios_rd32 ( bios , NV_PEXTDEV_BOOT_0 ) ;
uint8_t cr3c = ( ( straps < < 2 ) & 0xf0 ) | ( straps & ( 1 < < 6 ) ) ;
uint8_t cr3c = ( ( straps < < 2 ) & 0xf0 ) | ( straps & 0x40 ) > > 6 ;
if ( bios - > major_version > 2 )
return 0 ;
@ -3140,7 +3225,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
const uint32_t nv50_gpio_ctl [ 2 ] = { 0xe100 , 0xe28c } ;
int i ;
if ( dev_priv - > card_type ! = NV_50 ) {
if ( dev_priv - > card_type < NV_50 ) {
NV_ERROR ( bios - > dev , " INIT_GPIO on unsupported chipset \n " ) ;
return 1 ;
}
@ -3490,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return len ;
}
static int
init_i2c_long_if ( struct nvbios * bios , uint16_t offset , struct init_exec * iexec )
{
/*
* INIT_I2C_LONG_IF opcode : 0x9A ( ' ' )
*
* offset ( 8 bit ) : opcode
* offset + 1 ( 8 bit ) : DCB I2C table entry index
* offset + 2 ( 8 bit ) : I2C slave address
* offset + 3 ( 16 bit ) : I2C register
* offset + 5 ( 8 bit ) : mask
* offset + 6 ( 8 bit ) : data
*
* Read the register given by " I2C register " on the device addressed
* by " I2C slave address " on the I2C bus given by " DCB I2C table
* entry index " . Compare the result AND " mask " to " data " .
* If they ' re not equal , skip subsequent opcodes until condition is
* inverted ( INIT_NOT ) , or we hit INIT_RESUME
*/
uint8_t i2c_index = bios - > data [ offset + 1 ] ;
uint8_t i2c_address = bios - > data [ offset + 2 ] > > 1 ;
uint8_t reglo = bios - > data [ offset + 3 ] ;
uint8_t reghi = bios - > data [ offset + 4 ] ;
uint8_t mask = bios - > data [ offset + 5 ] ;
uint8_t data = bios - > data [ offset + 6 ] ;
struct nouveau_i2c_chan * chan ;
uint8_t buf0 [ 2 ] = { reghi , reglo } ;
uint8_t buf1 [ 1 ] ;
struct i2c_msg msg [ 2 ] = {
{ i2c_address , 0 , 1 , buf0 } ,
{ i2c_address , I2C_M_RD , 1 , buf1 } ,
} ;
int ret ;
/* no execute check by design */
BIOSLOG ( bios , " 0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X \n " ,
offset , i2c_index , i2c_address ) ;
chan = init_i2c_device_find ( bios - > dev , i2c_index ) ;
if ( ! chan )
return - ENODEV ;
ret = i2c_transfer ( & chan - > adapter , msg , 2 ) ;
if ( ret < 0 ) {
BIOSLOG ( bios , " 0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], "
" Mask: 0x%02X, Data: 0x%02X \n " ,
offset , reghi , reglo , mask , data ) ;
iexec - > execute = 0 ;
return 7 ;
}
BIOSLOG ( bios , " 0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, "
" Mask: 0x%02X, Data: 0x%02X \n " ,
offset , reghi , reglo , buf1 [ 0 ] , mask , data ) ;
iexec - > execute = ( ( buf1 [ 0 ] & mask ) = = data ) ;
return 7 ;
}
static struct init_tbl_entry itbl_entry [ ] = {
/* command name , id , length , offset , mult , command handler */
/* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
@ -3516,9 +3664,11 @@ static struct init_tbl_entry itbl_entry[] = {
{ " INIT_ZM_CR " , 0x53 , init_zm_cr } ,
{ " INIT_ZM_CR_GROUP " , 0x54 , init_zm_cr_group } ,
{ " INIT_CONDITION_TIME " , 0x56 , init_condition_time } ,
{ " INIT_LTIME " , 0x57 , init_ltime } ,
{ " INIT_ZM_REG_SEQUENCE " , 0x58 , init_zm_reg_sequence } ,
/* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
{ " INIT_SUB_DIRECT " , 0x5B , init_sub_direct } ,
{ " INIT_I2C_IF " , 0x5E , init_i2c_if } ,
{ " INIT_COPY_NV_REG " , 0x5F , init_copy_nv_reg } ,
{ " INIT_ZM_INDEX_IO " , 0x62 , init_zm_index_io } ,
{ " INIT_COMPUTE_MEM " , 0x63 , init_compute_mem } ,
@ -3552,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = {
{ " INIT_97 " , 0x97 , init_97 } ,
{ " INIT_AUXCH " , 0x98 , init_auxch } ,
{ " INIT_ZM_AUXCH " , 0x99 , init_zm_auxch } ,
{ " INIT_I2C_LONG_IF " , 0x9A , init_i2c_long_if } ,
{ NULL , 0 , NULL }
} ;
@ -4410,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
bios - > display . script_table_ptr ,
table [ 2 ] , table [ 3 ] , table [ 0 ] > = 0x21 ) ;
if ( ! otable ) {
NV_ERROR ( dev , " Couldn't find matching output scrip t table\n " ) ;
NV_DEBUG_KMS ( dev , " failed to match any outpu t table\n " ) ;
return 1 ;
}
@ -4467,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
if ( script )
script = clkcmptable ( bios , script , pxclk ) ;
if ( ! script ) {
NV_ERROR ( dev , " clock script 0 not found \n " ) ;
NV_DEBUG_KMS ( dev , " clock script 0 not found \n " ) ;
return 1 ;
}
@ -4826,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
pll_lim - > min_p = record [ 12 ] ;
pll_lim - > max_p = record [ 13 ] ;
/* where did this go to?? */
if ( limit_match = = 0x00614100 | | limit_match = = 0x0061490 0)
if ( ( entry [ 0 ] & 0xf0 ) = = 0x8 0)
pll_lim - > refclk = 27000 ;
else
pll_lim - > refclk = 100000 ;
@ -5852,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
entry - > i2c_index = i2c ;
entry - > heads = heads ;
entry - > location = DCB_LOC_ON_CHIP ;
/* "or" mostly unused in early gen crt modesetting, 0 is fine */
entry - > or = 1 ;
}
static void fabricate_dvi_i_output ( struct dcb_table * dcb , bool twoHeads )
@ -5980,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
}
break ;
case OUTPUT_TMDS :
entry - > tmdsconf . sor . link = ( conf & 0x00000030 ) > > 4 ;
if ( dcb - > version > = 0x40 )
entry - > tmdsconf . sor . link = ( conf & 0x00000030 ) > > 4 ;
else if ( dcb - > version > = 0x30 )
entry - > tmdsconf . slave_addr = ( conf & 0x00000700 ) > > 8 ;
else if ( dcb - > version > = 0x22 )
entry - > tmdsconf . slave_addr = ( conf & 0x00000070 ) > > 4 ;
break ;
case 0xe :
/* weird g80 mobile type that "nv" treats as a terminator */
@ -6270,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
dcb - > i2c_table = & bios - > data [ i2ctabptr ] ;
if ( dcb - > version > = 0x30 )
dcb - > i2c_default_indices = dcb - > i2c_table [ 4 ] ;
/*
* Parse the " management " I2C bus , used for hardware
* monitoring and some external TMDS transmitters .
*/
if ( dcb - > version > = 0x22 ) {
int idx = ( dcb - > version > = 0x40 ?
dcb - > i2c_default_indices & 0xf :
2 ) ;
read_dcb_i2c_entry ( dev , dcb - > version , dcb - > i2c_table ,
idx , & dcb - > i2c [ idx ] ) ;
}
}
if ( entries > DCB_MAX_NUM_ENTRIES )