1 /* 2 Copyright (c) 2002-05, Thomas Kurschel 3 4 5 Part of Radeon accelerant 6 7 Access to VIP 8 9 This code must be in kernel because we need for FIFO to become empty 10 during VIP access (which in turn requires locking the card, and locking 11 is a dangerous thing in user mode as the app can suddenly die, taking 12 the lock with it) 13 */ 14 15 #include "radeon_driver.h" 16 #include "mmio.h" 17 #include "vip_regs.h" 18 #include "bios_regs.h" 19 #include "theatre_regs.h" 20 21 22 // moved to bottom to avoid inlining 23 static bool Radeon_VIPWaitForIdle( device_info *di ); 24 25 26 // read data from VIP 27 // CP lock must be hold 28 static bool do_VIPRead( 29 device_info *di, uint channel, uint address, uint32 *data ) 30 { 31 vuint8 *regs = di->regs; 32 33 Radeon_WaitForFifo( di, 2 ); 34 // the 0x2000 is the nameless "register-read" flag 35 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x2000 ); 36 37 if( !Radeon_VIPWaitForIdle( di )) 38 return false; 39 40 // enable VIP register cycle reads 41 Radeon_WaitForFifo( di, 2 ); 42 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 0, 43 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 44 //Radeon_WaitForIdle( di, false, false ); 45 46 // this read starts a register cycle; the returned value has no meaning 47 INREG( regs, RADEON_VIPH_REG_DATA ); 48 49 if( !Radeon_VIPWaitForIdle( di )) 50 return false; 51 52 //Radeon_WaitForIdle( di, false, false ); 53 54 // register cycle is done, so disable any further cycle 55 Radeon_WaitForFifo( di, 2 ); 56 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 57 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 58 //Radeon_WaitForIdle( di, false, false ); 59 60 // get the data 61 *data = INREG( regs, RADEON_VIPH_REG_DATA ); 62 63 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data ); 64 65 if( !Radeon_VIPWaitForIdle( di )) 66 return false; 67 68 // disable register cycle again (according to sample code) 69 // IMHO, this is not necessary as it has been done before 70 Radeon_WaitForFifo( di, 2 ); 71 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 72 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS ); 73 74 return true; 75 } 76 77 // public function: read data from VIP 78 bool Radeon_VIPRead( 79 device_info *di, uint channel, uint address, uint32 *data, bool lock ) 80 { 81 bool res; 82 83 if( lock ) 84 ACQUIRE_BEN( di->si->cp.lock ); 85 86 res = do_VIPRead( di, channel, address, data ); 87 88 if( lock ) 89 RELEASE_BEN( di->si->cp.lock ); 90 91 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock ); 92 93 return res; 94 } 95 96 // write data to VIP 97 // CP must be hold 98 static bool do_VIPWrite( 99 device_info *di, uint8 channel, uint address, uint32 data ) 100 { 101 vuint8 *regs = di->regs; 102 bool res; 103 104 Radeon_WaitForFifo( di, 2 ); 105 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) ); 106 107 if( !Radeon_VIPWaitForIdle( di )) 108 return false; 109 110 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data ); 111 112 Radeon_WaitForFifo( di, 2 ); 113 OUTREG( regs, RADEON_VIPH_REG_DATA, data ); 114 115 res = Radeon_VIPWaitForIdle( di ); 116 117 return res; 118 } 119 120 // public function: write data to VIP 121 bool Radeon_VIPWrite( 122 device_info *di, uint8 channel, uint address, uint32 data, bool lock ) 123 { 124 bool res; 125 126 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock ); 127 128 if( lock ) 129 ACQUIRE_BEN( di->si->cp.lock ); 130 131 res = do_VIPWrite( di, channel, address, data ); 132 133 if( lock ) 134 RELEASE_BEN( di->si->cp.lock ); 135 136 return res; 137 } 138 139 140 // reset VIP 141 static void VIPReset( 142 device_info *di, bool lock ) 143 { 144 vuint8 *regs = di->regs; 145 146 if( lock ) 147 ACQUIRE_BEN( di->si->cp.lock ); 148 149 Radeon_WaitForFifo( di, 5 ); 150 OUTREG( regs, RADEON_VIPH_CONTROL, 151 4 | 152 (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) | 153 RADEON_VIPH_CONTROL_VIPH_DMA_MODE | 154 RADEON_VIPH_CONTROL_VIPH_EN ); 155 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS, 156 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS); 157 OUTREG( regs, RADEON_VIPH_DV_LAT, 158 0xff | 159 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) | 160 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) | 161 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) | 162 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); 163 OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 164 1 | 165 (1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH1_CHUNK_SHIFT) | 166 (1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH2_CHUNK_SHIFT) | 167 (1 << RADEON_VIPH_DMA_CHUNK_VIPH_CH3_CHUNK_SHIFT)); 168 OUTREGP( regs, RADEON_TEST_DEBUG_CNTL, 0, ~RADEON_TEST_DEBUG_CNTL_OUT_EN ); 169 170 if( lock ) 171 RELEASE_BEN( di->si->cp.lock ); 172 } 173 174 175 // check whether VIP host is idle 176 // lock must be hold 177 static status_t Radeon_VIPIdle( 178 device_info *di ) 179 { 180 vuint8 *regs = di->regs; 181 uint32 timeout; 182 183 //Radeon_WaitForIdle( di, false, false ); 184 185 // if there is a stuck transaction, acknowledge that 186 timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT ); 187 if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 ) { 188 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 189 RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK, 190 ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK & ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK ); 191 if( (INREG( regs, RADEON_VIPH_CONTROL) & RADEON_VIPH_CONTROL_VIPH_REG_RDY) != 0 ) 192 return B_BUSY; 193 else 194 return B_ERROR; 195 } 196 197 //Radeon_WaitForIdle( di, false, false ); 198 199 if( (INREG( regs, RADEON_VIPH_CONTROL) & RADEON_VIPH_CONTROL_VIPH_REG_RDY) != 0 ) 200 return B_BUSY; 201 else 202 return B_OK; 203 } 204 205 206 // wait until VIP host is idle 207 // lock must be hold 208 static bool Radeon_VIPWaitForIdle( 209 device_info *di ) 210 { 211 int i; 212 213 // wait 100x 1ms before giving up 214 for( i = 0; i < 100; ++i ) { 215 status_t res; 216 217 res = Radeon_VIPIdle( di ); 218 if( res != B_BUSY ) { 219 if( res == B_OK ) 220 return true; 221 else 222 return false; 223 } 224 225 snooze( 1000 ); 226 } 227 228 return false; 229 } 230 231 232 // find VIP channel of a device 233 // return: >= 0 channel of device 234 // < 0 no device found 235 int Radeon_FindVIPDevice( 236 device_info *di, uint32 device_id ) 237 { 238 uint channel; 239 uint32 cur_device_id; 240 241 // if card has no VIP port, let hardware detection fail; 242 // in this case, noone will bother us again 243 if( !di->has_vip ) 244 return -1; 245 246 ACQUIRE_BEN( di->si->cp.lock ); 247 248 VIPReset( di, false ); 249 250 // there are up to 4 devices, connected to one of 4 channels 251 for( channel = 0; channel < 4; ++channel ) { 252 // read device id 253 if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false )) 254 continue; 255 256 // compare device id directly 257 if( cur_device_id == device_id ) { 258 RELEASE_BEN( di->si->cp.lock ); 259 260 return channel; 261 } 262 } 263 264 RELEASE_BEN( di->si->cp.lock ); 265 266 // couldn't find device 267 return -1; 268 } 269