msp3430.c revision 706f2543
1#ifdef HAVE_XORG_CONFIG_H 2#include <xorg-config.h> 3#endif 4 5#include <string.h> 6#include <unistd.h> 7 8#include "xf86.h" 9#include "xf86i2c.h" 10#include "msp3430.h" 11#include "i2c_def.h" 12 13#define CONTROL 0x00 14#define WR_DEM 0x10 15#define RD_DEM 0x11 16#define WR_DSP 0x12 17#define RD_DSP 0x13 18 19 20void InitMSP34xxG(MSP3430Ptr m); 21void InitMSP34x5D(MSP3430Ptr m); 22void CheckModeMSP34x5D(MSP3430Ptr m); 23char *MSP_getProductName (CARD16 product_id); 24void mpause(int milliseconds); 25 26#define __MSPDEBUG__ 0 27 28#if __MSPDEBUG__ > 3 29 30void MSPBeep(MSP3430Ptr m, CARD8 freq); 31#define __MSPBEEP MSPBeep(m,0x14); 32 33#else 34 35#define __MSPBEEP 36#endif 37 38static void SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, CARD8 RegValueLow) 39{ 40 I2CByte data[3]; 41 42 data[0]=RegAddress; 43 data[1]=RegValueHigh; 44 data[2]=RegValueLow; 45 46 I2C_WriteRead(&(m->d),data,3,NULL,0); 47} 48 49static void SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, 50 CARD8 RegValueHigh, CARD8 RegValueLow) 51{ 52 I2CByte data[5]; 53#ifdef MSP_DEBUG 54 if(!m->registers_present[RegSubAddressLow]){ 55 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_ERROR, "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n", 56 RegAddress, RegSubAddressHigh, RegSubAddressLow, RegValueHigh, RegValueLow); 57 } 58#endif 59 60 data[0] = RegAddress; 61 data[1] = RegSubAddressHigh; 62 data[2] = RegSubAddressLow; 63 data[3] = RegValueHigh; 64 data[4] = RegValueLow; 65 66 I2C_WriteRead(&(m->d),data,5,NULL,0); 67} 68 69static void GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, 70 CARD8 *RegValueHigh, CARD8 *RegValueLow) 71{ 72 I2CByte send[3]; 73 I2CByte receive[2]; 74 75 send[0] = RegAddress; 76 send[1] = RegSubAddressHigh; 77 send[2] = RegSubAddressLow; 78 79 I2C_WriteRead(&(m->d), send, 3, receive, 2); 80 81 *RegValueHigh = receive[0]; 82 *RegValueLow = receive[1]; 83} 84 85#if __MSPDEBUG__ > 2 86static void MSP3430DumpStatus(MSP3430Ptr m) 87{ 88CARD8 status_hi, status_lo; 89CARD8 subaddr, data[2]; 90 91GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo); 92xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n", 93 status_hi & 1, (status_lo>>7) & 1, (status_lo>>6)&1, 94 (status_lo>>5)? ( (status_hi>>1)&1? "bad NICAM reception" : "NICAM" ) : 95 ((status_hi>>1)&1 ? "bogus" : "ANALOG FM/AM") , 96 (status_lo>>4)&1, (status_lo>>3)&1,!( (status_lo>>2)&1), !((status_lo>>1)&1)); 97 98GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo); 99xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: standard result=0x%02x%02x\n", 100 status_hi, status_lo); 101subaddr=0x0; 102I2C_WriteRead(&(m->d), &subaddr, 1, data, 2); 103xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n", 104 data[1], data[0]); 105} 106#endif 107 108/* wrapper */ 109void InitMSP3430(MSP3430Ptr m) 110{ 111 #if __MSPDEBUG__ > 1 112 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", 113 m->connector, m->standard, m->chip_family); 114 #endif 115 switch (m->chip_family) { 116 case MSPFAMILY_34x0G: 117 InitMSP34xxG(m); 118 break; 119 case MSPFAMILY_34x5G: 120 InitMSP34xxG(m); 121 break; 122 case MSPFAMILY_34x5D: 123 InitMSP34x5D(m); 124 break; 125 } 126} 127 128/*----------------------------------------------------------------- 129| common functions for all MSP34xx chips 130|----------------------------------------------------------------*/ 131 132MSP3430Ptr DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr) 133{ 134 MSP3430Ptr m; 135 I2CByte a; 136 CARD8 hardware_version, major_revision, product_code, rom_version; 137 Bool supported; 138 139 m = calloc(1,sizeof(MSP3430Rec)); 140 if(m == NULL)return NULL; 141 m->d.DevName = strdup("MSP34xx"); 142 m->d.SlaveAddr = addr; 143 m->d.pI2CBus = b; 144 m->d.NextDev = NULL; 145 m->d.StartTimeout = b->StartTimeout; 146 m->d.BitTimeout = b->BitTimeout; 147 m->d.AcknTimeout = b->AcknTimeout; 148 m->d.ByteTimeout = b->ByteTimeout; 149 150 if(!I2C_WriteRead(&(m->d), NULL, 0, &a, 1)) 151 { 152 free(m->d.DevName); 153 free(m); 154 return NULL; 155 } 156 157 158 m->standard=MSP3430_NTSC; 159 m->connector=MSP3430_CONNECTOR_1; 160 m->mode=MSPMODE_STEREO_A; /*stereo or chanel A if avail. */ 161 m->c_format=MSPFORMAT_UNKNOWN; 162 m->c_standard=MSPSTANDARD_UNKNOWN; 163 m->c_matrix=m->c_fmmatrix=m->c_source=0; 164 m->volume=0; 165 m->recheck=FALSE; 166 167 GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision); 168 GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version); 169 m->hardware_version=hardware_version; 170 m->major_revision=major_revision; 171 m->product_code=product_code; 172 m->rom_version=rom_version; 173 174 m->chip_id=((major_revision << 8) | product_code); 175 176 supported=FALSE; 177 switch (major_revision) { 178 case 4: /* 34xxD */ 179 switch (product_code) { 180 case 0x05: /* 3405D */ 181 case 0x0A: /* 3410D */ 182 case 0x0F: /* 3415D */ 183 m->chip_family=MSPFAMILY_34x5D; 184 m->recheck=TRUE; 185 supported=TRUE; 186 break; 187 default: 188 m->chip_family=MSPFAMILY_34x0D; 189 } 190 break; 191 case 7: /* 34xxG */ 192 switch(product_code){ 193 case 0x00: 194 case 0x0A: 195 case 0x1E: 196 case 0x28: 197 case 0x32: 198 m->chip_family=MSPFAMILY_34x0G; 199 supported=TRUE; 200 break; 201 case 0x0f: 202 case 0x19: 203 case 0x2d: 204 case 0x37: 205 case 0x41: 206 m->chip_family=MSPFAMILY_34x5G; 207 supported=TRUE; 208 #ifdef MSP_DEBUG 209 memset(m->registers_present, 0, 256); 210 #define A(num) m->registers_present[(num)]=1; 211 #define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1); 212 A(0x20) 213 A(0x30) 214 A(0x40) 215 A(0x00) 216 B(0x01, 0x08) 217 B(0x0B, 0x0E) 218 A(0x10) 219 B(0x12,0x14) 220 A(0x16) 221 A(0x29) 222 #undef B 223 #undef A 224 #endif 225 break; 226 default: 227 m->chip_family=MSPFAMILY_UNKNOWN; 228 } 229 break; 230 default: 231 m->chip_family=MSPFAMILY_UNKNOWN; 232 } 233 234 xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n", 235 MSP_getProductName(m->chip_id), supported?"":" (unsupported)", rom_version, m->chip_id); 236 237 if (!supported) { 238 free(m->d.DevName); 239 free(m); 240 return NULL; 241 } 242 if(!I2CDevInit(&(m->d))) 243 { 244 free(m->d.DevName); 245 free(m); 246 return NULL; 247 } 248 249 return m; 250} 251 252void ResetMSP3430(MSP3430Ptr m) 253{ 254 /* Reset the MSP3430 */ 255 SetMSP3430Control(m, 0x00, 0x80, 0x00); 256 /* Set it back to normal operation */ 257 SetMSP3430Control(m, 0x00, 0x00, 0x00); 258 259 m->c_format=MSPFORMAT_UNKNOWN; 260 m->c_standard=MSPSTANDARD_UNKNOWN; 261 m->c_matrix=m->c_fmmatrix=m->c_source=0; 262 m->volume=0; 263} 264 265void MSP3430SetVolume (MSP3430Ptr m, CARD8 value) 266{ 267 CARD8 result; 268#if 0 269 CARD8 old_volume; 270 GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); 271 xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", result); 272#endif 273 /* save an extra Get call */ 274 result=0; 275 276 SetMSP3430Data(m, WR_DSP, 0x00, 0x00, value, result); 277 278 SetMSP3430Data(m, WR_DSP, 0x00, 0x07, value, 0); 279 m->volume=value; 280 281#if __MSPDEBUG__ > 2 282 MSP3430DumpStatus(m); 283 __MSPBEEP 284 GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); 285 xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n",value); 286#endif 287} 288 289 290void MSP3430SetSAP (MSP3430Ptr m, int mode) 291{ 292 xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Put actual code to change SAP here\n"); 293 294 SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); 295} 296 297 298#if 0 299void MSP3430SetSource(MSP3430Ptr m, CARD8 value) 300{ 301 /* Write to DSP, register 0x0008, (loudspeaker channel source/matrix) */ 302 /* This sets the source to the TV tuner, for stereo operation */ 303 SetMSP3430Data(m, WR_DSP, 0x00, 0x08, value, 0x20); 304} 305#endif 306 307 308char *MSP_getProductName (CARD16 product_id) 309{ 310 switch (product_id) { 311 case 0x0400: return "MSP3400D"; 312 case 0x040a: return "MSP3410D"; 313 case 0x0405: return "MSP3405D"; 314 case 0x040f: return "MSP3415D"; 315 case 0x0700: return "MSP3400G"; 316 case 0x070a: return "MSP3410G"; 317 case 0x071e: return "MSP3430G"; 318 case 0x0728: return "MSP3440G"; 319 case 0x0732: return "MSP3450G"; 320 case 0x070f: return "MSP3415G"; 321 case 0x0719: return "MSP3425G"; 322 case 0x072d: return "MSP3445G"; 323 case 0x0737: return "MSP3455G"; 324 case 0x0741: return "MSP3465G"; 325 } 326 return "MSP - unknown type"; 327} 328 329#if __MSPDEBUG__ > 2 330/*puts beep in MSP output 331 freq = 0x01 - 16Hz ... 0x40 - 1kHz ... 0xff - 4kHz 332*/ 333void MSPBeep(MSP3430Ptr m, CARD8 freq) { 334 SetMSP3430Data (m, WR_DSP, 0x00, freq, 0x7f, 0x40); 335 mpause(100); 336 SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x00); 337} 338#endif 339 340void mpause(int milliseconds) { 341 int i,m; 342 m=milliseconds/20; 343 for (i=0;i<m;i++) usleep(20000); 344} 345 346/*----------------------------------------------------------------- 347| specific functions for all MSP34xxG chips 348|----------------------------------------------------------------*/ 349 350void InitMSP34xxG(MSP3430Ptr m) 351{ 352 353 #if __MSPDEBUG__ > 1 354 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", 355 m->connector, m->standard, m->chip_family); 356 #endif 357 /* Reset MSP3430 */ 358 SetMSP3430Control(m, 0x00, 0x80, 0x00); 359 /* Set it back to normal operation */ 360 SetMSP3430Control(m, 0x00, 0x00, 0x00); 361 362 /*set MODUS register */ 363 /* bits: 0 - automatic sound detection */ 364 /* 1 - enable STATUS change */ 365 /* 12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM (does not seem to work ) */ 366 /* 13 - detect 4.5 Mhz carrier as BTSC */ 367 if ( (m->standard & 0xff) == MSP3430_PAL ) 368 { 369 SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03|0x08); /* make O_ pins tristate */ 370 /* PAL standard */ 371 SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */ 372 } else { 373 SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03|0x08); 374 /* standard selection is M-BTSC-Stereo */ 375 SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); 376 } 377 378 switch(m->connector){ 379 case MSP3430_CONNECTOR_1: 380 SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20); 381 break; 382 case MSP3430_CONNECTOR_2: 383 /* this has not been checked yet.. could be bogus */ 384 /* SCART Input Prescale: 0 dB gain */ 385 SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); 386 SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); 387 break; 388 case MSP3430_CONNECTOR_3: 389 default: 390 /* SCART Input Prescale: 0 dB gain */ 391 SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); 392 393 SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); 394 break; 395 } 396 397 switch(m->standard){ 398 case MSP3430_PAL: 399 SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); 400 SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); 401 SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03); 402 /* Set volume to FAST_MUTE. */ 403 SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); 404 break; 405 case MSP3430_PAL_DK1: 406 SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); 407 SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); 408 SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04); 409 /* Set volume to FAST_MUTE. */ 410 SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); 411 break; 412 case MSP3430_SECAM: /* is this right ? */ 413 case MSP3430_NTSC: 414 /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */ 415 SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); 416 417 /* Set volume to FAST_MUTE. */ 418 SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); 419 break; 420 } 421 422} 423 424/*----------------------------------------------------------------- 425| specific functions for all MSP34x5D chips 426|----------------------------------------------------------------*/ 427 428void InitMSP34x5D(MSP3430Ptr m) 429{ 430int count; 431CARD8 high,low; 432CARD16 result,standard; 433CARD16 peak; 434 435 436if (m->c_format==MSPFORMAT_UNKNOWN) ResetMSP3430(m); 437else { 438 /*mute volume*/ 439 SetMSP3430Data (m, WR_DSP, 0x00, 0x00, 0x00, 0x00); 440} 441 442 443 444 switch(m->connector){ 445 case MSP3430_CONNECTOR_2: 446 case MSP3430_CONNECTOR_3: 447 if (m->c_format!=MSPFORMAT_SCART) { 448 /* SCART Input Prescale: 0 dB gain */ 449 SetMSP3430Data (m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); 450 /* this has not been checked yet.. could be bogus */ 451 m->c_format=MSPFORMAT_SCART; /*stereo*/ 452 } 453 break; 454 case MSP3430_CONNECTOR_1: 455 default: 456 457 switch ( m->standard & 0x00ff ) { 458 case MSP3430_PAL: 459 switch( m->standard ) { 460 case MSP3430_PAL_DK1: 461 standard=MSPSTANDARD_FM_DK1; 462 break; 463/* case MSP3430_PAL_DK2: 464 standard=MSPSTANDARD_FM_DK2; 465 break; 466 case MSP3430_PAL_BG: 467 may be FM stereo (Germany) or FM NICAM (Scandinavia,spain) 468 standard=MSPSTANDARD_AUTO; 469 break; 470*/ 471 default: 472 standard=MSPSTANDARD_AUTO; 473 } 474 break; 475 case MSP3430_SECAM: 476 standard=MSPSTANDARD_AUTO; 477 case MSP3430_NTSC: 478 /* Only MSP34x5 supported format - Korean NTSC-M*/ 479 standard=MSPSTANDARD_FM_M; 480 default: 481 standard=MSPSTANDARD_AUTO; 482 } 483 484 /*no NICAM support in MSP3410D - force to autodetect*/ 485 if ((m->chip_id==0x405) && (standard>=MSPSTANDARD_NICAM_BG)) 486 standard=MSPSTANDARD_AUTO; 487 488 if (m->c_standard != standard) { 489 490 SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); 491 if (standard==MSPSTANDARD_AUTO) { 492 count = 50; /* time shouldn't exceed 1s, just in case */ 493 do { 494 usleep(20000); 495 GetMSP3430Data (m, RD_DEM, 0x00, 0x7e, &high, &low); 496 result = ( high << 8 ) | low; 497 --count; 498 } while( result > 0x07ff && count > 0 ); 499 500 if ((result > MSPSTANDARD_AUTO)) 501 standard=result; 502 else standard=MSPSTANDARD_UNKNOWN; 503#if __MSPDEBUG__ > 1 504 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Detected audio standard: %d\n",result); 505#endif 506 /* result = MSPSTANDARD_NICAM_L can be one of: 507 SECAM_L - MSPSTANDARD_NICAM_L 508 D/K1 - MSPSTANDARD_FM_DK1 509 D/K2 - MSPSTANDARD_FM_DK2 510 D/K-NICAM - MSPSTANDARD_NICAM_DK*/ 511 if( standard == MSPSTANDARD_NICAM_L ) { 512 if ((m->standard & 0x00ff)==MSP3430_PAL) { 513 /* force PAL D/K */ 514 standard=MSPSTANDARD_FM_DK1; 515 SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); 516#if __MSPDEBUG__ > 1 517 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO, "Detected 6.5MHz carrier - forced to D/K1 !!!\n" ); 518#endif 519 } 520 } 521 } 522 m->c_standard=standard; 523 } /*end - standard changed*/ 524 else { 525 if (standard<MSPSTANDARD_NICAM_BG) { 526 /* get old value of ident. mode register*/ 527 GetMSP3430Data (m, RD_DSP, 0x00, 0x15, &high, &low); 528 /* reset Ident-Filter */ 529 SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x3F); 530 /* put back old value to ident. mode register*/ 531 SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, low); 532 } 533 } 534 535 if (standard<=MSPSTANDARD_AUTO) { 536 m->c_format=MSPFORMAT_1xFM; 537 } 538 else if (standard<MSPSTANDARD_NICAM_BG) { 539 /* set FM prescale */ 540 SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); 541 /* set FM deemphasis*/ 542 SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, ((standard==MSPSTANDARD_FM_M)?0:1), 0); 543 544 /* check if FM2 carrier is present */ 545 /*turn off FM DC Notch*/ 546 SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x3f); 547 /*matrix source for Quasi-Peak Detector - stereo: ch2->L ch1->R*/ 548 SetMSP3430Data (m, WR_DSP, 0x00, 0x0c, 0x00, 0x20); 549 550 mpause(250); 551 GetMSP3430Data (m, RD_DSP, 0x00, 0x1A, &high, &low); 552 peak = (high << 8) | low; 553#if __MSPDEBUG__ > 1 554 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Second carrier Quasi-Peak detection: %d\n",peak); 555#endif 556 /*turn on FM DC Notch*/ 557 SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x00); 558 559 if (peak<5) { 560 /* if second carrier not detected - only mono from first carrier*/ 561 m->c_format=MSPFORMAT_1xFM; 562 } 563 else { 564 m->c_format=MSPFORMAT_2xFM; 565 /*start of FM identification process - FM_WAIT 566 wait at least 0.5s - used 1s - gives beter resolution*/ 567 mpause(1000); 568 } 569 } 570 else { 571 if (standard==MSPSTANDARD_NICAM_L) { 572 m->c_format=MSPFORMAT_NICAM_AM; 573 /* set AM prescale */ 574 SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x7C, 0); 575 } 576 else { 577 m->c_format=MSPFORMAT_NICAM_FM; 578 /* set FM prescale */ 579 SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); 580 } 581 /* set FM deemphasis*/ 582 SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, 0x00, 0); 583 /* set NICAM prescale to 0dB */ 584 SetMSP3430Data (m, WR_DSP, 0x00, 0x10, 0x20, 0); 585 } 586 587 break; 588 } /*end - case conector*/ 589 590 CheckModeMSP34x5D(m); 591 592 /* Set volume to FAST_MUTE. */ 593 /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);*/ 594 /*set volume*/ 595 MSP3430SetVolume(m,m->volume); 596 597 __MSPBEEP 598 599 600} /* EnableMSP34x5D ()... */ 601 602 603 604 605void CheckModeMSP34x5D(MSP3430Ptr m) { 606 const char stereo_on=25; 607 const char stereo_off=20; 608 const char dual_on=-stereo_on; 609 const char dual_off=-stereo_off; 610 char detect; 611 CARD8 matrix, fmmatrix, source, high, low; 612 613 fmmatrix=0; /*no matrix*/ 614 source=0; /*FM*/ 615 switch (m->c_format) { 616 case MSPFORMAT_NICAM_FM: 617 case MSPFORMAT_NICAM_AM: 618 case MSPFORMAT_SCART: 619 source=( (m->c_format == MSPFORMAT_SCART)?2:1 ); 620 switch (m->mode) { 621 case MSPMODE_MONO: 622 matrix=0x30; /*MONO*/ 623 break; 624 case MSPMODE_A: 625 matrix=0x00; /*A*/ 626 break; 627 case MSPMODE_B: 628 matrix=0x10; /*B*/ 629 break; 630 default: 631 matrix=0x20; /*STEREO*/ 632 break; 633 } 634 break; 635 default: 636 case MSPFORMAT_1xFM: 637 matrix=0x00; /*A*/ 638 break; 639 case MSPFORMAT_2xFM: 640 switch (m->mode) { 641 case MSPMODE_MONO: 642 matrix=0x30; /*MONO*/ 643 break; 644 case MSPMODE_STEREO: 645 matrix=0x20; /*STEREO*/ 646 fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); 647 break; 648 case MSPMODE_AB: 649 matrix=0x20; /*STEREO*/ 650 break; 651 case MSPMODE_A: 652 matrix=0x00; /*A*/ 653 break; 654 case MSPMODE_B: 655 matrix=0x10; /*B*/ 656 break; 657 default: 658 /*FM_IDENT_CHECK*/ 659 GetMSP3430Data (m, RD_DSP, 0x00, 0x18, &high, &low); 660 detect=(char)high; 661#if __MSPDEBUG__ > 1 662 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Stereo Detection Register: %d\n",detect); 663#endif 664 if (detect>=((m->c_mode==MSPMODE_STEREO)?stereo_off:stereo_on)) { 665 m->c_mode=MSPMODE_STEREO; 666 matrix=0x20; /*STEREO*/ 667 fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); 668 } 669 else if (detect<=((m->c_mode==MSPMODE_AB)?dual_off:dual_on)) { 670 m->c_mode=MSPMODE_AB; 671 switch (m->mode) { 672 case MSPMODE_STEREO_AB: matrix=0x20; break; 673 case MSPMODE_STEREO_B: matrix=0x10; break; 674 default: 675 case MSPMODE_A: matrix=0x00; break; 676 } 677 } 678 else { 679 m->c_mode=MSPMODE_MONO; 680 matrix=0x30; /*MONO*/ 681 } 682 break; 683 } /* end - case mode*/ 684 break; 685 } 686 687 if (m->c_fmmatrix != fmmatrix) { 688 GetMSP3430Data (m, RD_DSP, 0x00, 0x0e, &high, &low); 689 SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, high, fmmatrix); 690 m->c_fmmatrix = fmmatrix; 691 } 692 693 if ((m->c_matrix != matrix) || (m->c_source != source)) { 694 /*set chanel source and matrix for loudspeaker*/ 695 SetMSP3430Data (m, WR_DSP, 0x00, 0x08, source, matrix); 696 697 m->c_matrix = matrix; 698 m->c_source = source; 699 } 700 701 if ( ((m->c_format) & 0xF0) == MSPFORMAT_NICAM) 702 SetMSP3430Data (m, WR_DEM, 0x00, 0x21, 0, 1); 703 704#if __MSPDEBUG__ > 0 705 char *msg; 706 switch (matrix) { 707 case 0x30: /*MONO*/ 708 msg="MONO"; 709 break; 710 case 0x00: /*LEFT*/ 711 msg="MONO/CHANNEL_1"; 712 break; 713 case 0x10: /*RIGHT*/ 714 msg="MONO/CHANNEL_2"; 715 break; 716 case 0x20: /*LEFT*/ 717 msg="STEREO"; 718 break; 719 default: 720 msg="unknown"; 721 break; 722 } 723 xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Audio mode set to: %s\n",msg); 724#endif 725} 726 727