1/* 2 * Driver for the i2c/i2s based TA3004 sound chip used 3 * on some Apple hardware. Also known as "snapper". 4 * 5 * Tobias Sargeant <tobias.sargeant@bigpond.com> 6 * Based upon tas3001c.c by Christopher C. Chimelis <chris@debian.org>: 7 * 8 * Input support by Renzo Davoli <renzo@cs.unibo.it> 9 * 10 */ 11 12#include <linux/module.h> 13#include <linux/slab.h> 14#include <linux/proc_fs.h> 15#include <linux/ioport.h> 16#include <linux/sysctl.h> 17#include <linux/types.h> 18#include <linux/i2c.h> 19#include <linux/init.h> 20#include <linux/soundcard.h> 21#include <linux/interrupt.h> 22#include <linux/workqueue.h> 23 24#include <asm/uaccess.h> 25#include <asm/errno.h> 26#include <asm/io.h> 27#include <asm/prom.h> 28 29#include "dmasound.h" 30#include "tas_common.h" 31#include "tas3004.h" 32 33#include "tas_ioctl.h" 34 35/* #define DEBUG_DRCE */ 36 37#define TAS3004_BIQUAD_FILTER_COUNT 7 38#define TAS3004_BIQUAD_CHANNEL_COUNT 2 39 40#define VOL_DEFAULT (100 * 4 / 5) 41#define INPUT_DEFAULT (100 * 4 / 5) 42#define BASS_DEFAULT (100 / 2) 43#define TREBLE_DEFAULT (100 / 2) 44 45struct tas3004_data_t { 46 struct tas_data_t super; 47 int device_id; 48 int output_id; 49 int speaker_id; 50 struct tas_drce_t drce_state; 51 struct work_struct change; 52}; 53 54#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000) 55 56#define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000)) 57 58 59static const union tas_biquad_t tas3004_eq_unity = { 60 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }, 61}; 62 63 64static const struct tas_drce_t tas3004_drce_min = { 65 .enable = 1, 66 .above = { .val = MAKE_RATIO(16,0), .expand = 0 }, 67 .below = { .val = MAKE_RATIO(2,0), .expand = 0 }, 68 .threshold = -0x59a0, 69 .energy = MAKE_TIME(0, 1700), 70 .attack = MAKE_TIME(0, 1700), 71 .decay = MAKE_TIME(0, 1700), 72}; 73 74 75static const struct tas_drce_t tas3004_drce_max = { 76 .enable = 1, 77 .above = { .val = MAKE_RATIO(1,500), .expand = 1 }, 78 .below = { .val = MAKE_RATIO(2,0), .expand = 1 }, 79 .threshold = -0x0, 80 .energy = MAKE_TIME(2,400000), 81 .attack = MAKE_TIME(2,400000), 82 .decay = MAKE_TIME(2,400000), 83}; 84 85 86static const unsigned short time_constants[]={ 87 MAKE_TIME(0, 1700), 88 MAKE_TIME(0, 3500), 89 MAKE_TIME(0, 6700), 90 MAKE_TIME(0, 13000), 91 MAKE_TIME(0, 26000), 92 MAKE_TIME(0, 53000), 93 MAKE_TIME(0,106000), 94 MAKE_TIME(0,212000), 95 MAKE_TIME(0,425000), 96 MAKE_TIME(0,850000), 97 MAKE_TIME(1,700000), 98 MAKE_TIME(2,400000), 99}; 100 101static const unsigned short above_threshold_compression_ratio[]={ 102 MAKE_RATIO( 1, 70), 103 MAKE_RATIO( 1,140), 104 MAKE_RATIO( 1,230), 105 MAKE_RATIO( 1,330), 106 MAKE_RATIO( 1,450), 107 MAKE_RATIO( 1,600), 108 MAKE_RATIO( 1,780), 109 MAKE_RATIO( 2, 0), 110 MAKE_RATIO( 2,290), 111 MAKE_RATIO( 2,670), 112 MAKE_RATIO( 3,200), 113 MAKE_RATIO( 4, 0), 114 MAKE_RATIO( 5,330), 115 MAKE_RATIO( 8, 0), 116 MAKE_RATIO(16, 0), 117}; 118 119static const unsigned short above_threshold_expansion_ratio[]={ 120 MAKE_RATIO(1, 60), 121 MAKE_RATIO(1,130), 122 MAKE_RATIO(1,190), 123 MAKE_RATIO(1,250), 124 MAKE_RATIO(1,310), 125 MAKE_RATIO(1,380), 126 MAKE_RATIO(1,440), 127 MAKE_RATIO(1,500) 128}; 129 130static const unsigned short below_threshold_compression_ratio[]={ 131 MAKE_RATIO(1, 70), 132 MAKE_RATIO(1,140), 133 MAKE_RATIO(1,230), 134 MAKE_RATIO(1,330), 135 MAKE_RATIO(1,450), 136 MAKE_RATIO(1,600), 137 MAKE_RATIO(1,780), 138 MAKE_RATIO(2, 0) 139}; 140 141static const unsigned short below_threshold_expansion_ratio[]={ 142 MAKE_RATIO(1, 60), 143 MAKE_RATIO(1,130), 144 MAKE_RATIO(1,190), 145 MAKE_RATIO(1,250), 146 MAKE_RATIO(1,310), 147 MAKE_RATIO(1,380), 148 MAKE_RATIO(1,440), 149 MAKE_RATIO(1,500), 150 MAKE_RATIO(1,560), 151 MAKE_RATIO(1,630), 152 MAKE_RATIO(1,690), 153 MAKE_RATIO(1,750), 154 MAKE_RATIO(1,810), 155 MAKE_RATIO(1,880), 156 MAKE_RATIO(1,940), 157 MAKE_RATIO(2, 0) 158}; 159 160static inline int 161search( unsigned short val, 162 const unsigned short *arr, 163 const int arrsize) { 164 /* 165 * This could be a binary search, but for small tables, 166 * a linear search is likely to be faster 167 */ 168 169 int i; 170 171 for (i=0; i < arrsize; i++) 172 if (arr[i] >= val) 173 goto _1; 174 return arrsize-1; 175 _1: 176 if (i == 0) 177 return 0; 178 return (arr[i]-val < val-arr[i-1]) ? i : i-1; 179} 180 181#define SEARCH(a, b) search(a, b, ARRAY_SIZE(b)) 182 183static inline int 184time_index(unsigned short time) 185{ 186 return SEARCH(time, time_constants); 187} 188 189 190static inline int 191above_threshold_compression_index(unsigned short ratio) 192{ 193 return SEARCH(ratio, above_threshold_compression_ratio); 194} 195 196 197static inline int 198above_threshold_expansion_index(unsigned short ratio) 199{ 200 return SEARCH(ratio, above_threshold_expansion_ratio); 201} 202 203 204static inline int 205below_threshold_compression_index(unsigned short ratio) 206{ 207 return SEARCH(ratio, below_threshold_compression_ratio); 208} 209 210 211static inline int 212below_threshold_expansion_index(unsigned short ratio) 213{ 214 return SEARCH(ratio, below_threshold_expansion_ratio); 215} 216 217static inline unsigned char db_to_regval(short db) { 218 int r=0; 219 220 r=(db+0x59a0) / 0x60; 221 222 if (r < 0x91) return 0x91; 223 if (r > 0xef) return 0xef; 224 return r; 225} 226 227static inline short quantize_db(short db) 228{ 229 return db_to_regval(db) * 0x60 - 0x59a0; 230} 231 232static inline int 233register_width(enum tas3004_reg_t r) 234{ 235 switch(r) { 236 case TAS3004_REG_MCR: 237 case TAS3004_REG_TREBLE: 238 case TAS3004_REG_BASS: 239 case TAS3004_REG_ANALOG_CTRL: 240 case TAS3004_REG_TEST1: 241 case TAS3004_REG_TEST2: 242 case TAS3004_REG_MCR2: 243 return 1; 244 245 case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN: 246 case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN: 247 return 3; 248 249 case TAS3004_REG_DRC: 250 case TAS3004_REG_VOLUME: 251 return 6; 252 253 case TAS3004_REG_LEFT_MIXER: 254 case TAS3004_REG_RIGHT_MIXER: 255 return 9; 256 257 case TAS3004_REG_TEST: 258 return 10; 259 260 case TAS3004_REG_LEFT_BIQUAD0: 261 case TAS3004_REG_LEFT_BIQUAD1: 262 case TAS3004_REG_LEFT_BIQUAD2: 263 case TAS3004_REG_LEFT_BIQUAD3: 264 case TAS3004_REG_LEFT_BIQUAD4: 265 case TAS3004_REG_LEFT_BIQUAD5: 266 case TAS3004_REG_LEFT_BIQUAD6: 267 268 case TAS3004_REG_RIGHT_BIQUAD0: 269 case TAS3004_REG_RIGHT_BIQUAD1: 270 case TAS3004_REG_RIGHT_BIQUAD2: 271 case TAS3004_REG_RIGHT_BIQUAD3: 272 case TAS3004_REG_RIGHT_BIQUAD4: 273 case TAS3004_REG_RIGHT_BIQUAD5: 274 case TAS3004_REG_RIGHT_BIQUAD6: 275 276 case TAS3004_REG_LEFT_LOUD_BIQUAD: 277 case TAS3004_REG_RIGHT_LOUD_BIQUAD: 278 return 15; 279 280 default: 281 return 0; 282 } 283} 284 285static int 286tas3004_write_register( struct tas3004_data_t *self, 287 enum tas3004_reg_t reg_num, 288 char *data, 289 uint write_mode) 290{ 291 if (reg_num==TAS3004_REG_MCR || 292 reg_num==TAS3004_REG_BASS || 293 reg_num==TAS3004_REG_TREBLE || 294 reg_num==TAS3004_REG_ANALOG_CTRL) { 295 return tas_write_byte_register(&self->super, 296 (uint)reg_num, 297 *data, 298 write_mode); 299 } else { 300 return tas_write_register(&self->super, 301 (uint)reg_num, 302 register_width(reg_num), 303 data, 304 write_mode); 305 } 306} 307 308static int 309tas3004_sync_register( struct tas3004_data_t *self, 310 enum tas3004_reg_t reg_num) 311{ 312 if (reg_num==TAS3004_REG_MCR || 313 reg_num==TAS3004_REG_BASS || 314 reg_num==TAS3004_REG_TREBLE || 315 reg_num==TAS3004_REG_ANALOG_CTRL) { 316 return tas_sync_byte_register(&self->super, 317 (uint)reg_num, 318 register_width(reg_num)); 319 } else { 320 return tas_sync_register(&self->super, 321 (uint)reg_num, 322 register_width(reg_num)); 323 } 324} 325 326static int 327tas3004_read_register( struct tas3004_data_t *self, 328 enum tas3004_reg_t reg_num, 329 char *data, 330 uint write_mode) 331{ 332 return tas_read_register(&self->super, 333 (uint)reg_num, 334 register_width(reg_num), 335 data); 336} 337 338static inline int 339tas3004_fast_load(struct tas3004_data_t *self, int fast) 340{ 341 if (fast) 342 self->super.shadow[TAS3004_REG_MCR][0] |= 0x80; 343 else 344 self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f; 345 return tas3004_sync_register(self,TAS3004_REG_MCR); 346} 347 348static uint 349tas3004_supported_mixers(struct tas3004_data_t *self) 350{ 351 return SOUND_MASK_VOLUME | 352 SOUND_MASK_PCM | 353 SOUND_MASK_ALTPCM | 354 SOUND_MASK_IMIX | 355 SOUND_MASK_TREBLE | 356 SOUND_MASK_BASS | 357 SOUND_MASK_MIC | 358 SOUND_MASK_LINE; 359} 360 361static int 362tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer) 363{ 364 switch(mixer) { 365 case SOUND_MIXER_VOLUME: 366 case SOUND_MIXER_PCM: 367 case SOUND_MIXER_ALTPCM: 368 case SOUND_MIXER_IMIX: 369 return 1; 370 default: 371 return 0; 372 } 373} 374 375static uint 376tas3004_stereo_mixers(struct tas3004_data_t *self) 377{ 378 uint r = tas3004_supported_mixers(self); 379 uint i; 380 381 for (i=1; i<SOUND_MIXER_NRDEVICES; i++) 382 if (r&(1<<i) && !tas3004_mixer_is_stereo(self,i)) 383 r &= ~(1<<i); 384 return r; 385} 386 387static int 388tas3004_get_mixer_level(struct tas3004_data_t *self, int mixer, uint *level) 389{ 390 if (!self) 391 return -1; 392 393 *level = self->super.mixer[mixer]; 394 395 return 0; 396} 397 398static int 399tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level) 400{ 401 int rc; 402 tas_shadow_t *shadow; 403 uint temp; 404 uint offset=0; 405 406 if (!self) 407 return -1; 408 409 shadow = self->super.shadow; 410 411 if (!tas3004_mixer_is_stereo(self,mixer)) 412 level = tas_mono_to_stereo(level); 413 switch(mixer) { 414 case SOUND_MIXER_VOLUME: 415 temp = tas3004_gain.master[level&0xff]; 416 SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp); 417 temp = tas3004_gain.master[(level>>8)&0xff]; 418 SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp); 419 rc = tas3004_sync_register(self,TAS3004_REG_VOLUME); 420 break; 421 case SOUND_MIXER_IMIX: 422 offset += 3; 423 case SOUND_MIXER_ALTPCM: 424 offset += 3; 425 case SOUND_MIXER_PCM: 426 /* 427 * Don't load these in fast mode. The documentation 428 * says it can be done in either mode, but testing it 429 * shows that fast mode produces ugly clicking. 430 */ 431 /* tas3004_fast_load(self,1); */ 432 temp = tas3004_gain.mixer[level&0xff]; 433 SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp); 434 temp = tas3004_gain.mixer[(level>>8)&0xff]; 435 SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp); 436 rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); 437 if (rc == 0) 438 rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); 439 /* tas3004_fast_load(self,0); */ 440 break; 441 case SOUND_MIXER_TREBLE: 442 temp = tas3004_gain.treble[level&0xff]; 443 shadow[TAS3004_REG_TREBLE][0]=temp&0xff; 444 rc = tas3004_sync_register(self,TAS3004_REG_TREBLE); 445 break; 446 case SOUND_MIXER_BASS: 447 temp = tas3004_gain.bass[level&0xff]; 448 shadow[TAS3004_REG_BASS][0]=temp&0xff; 449 rc = tas3004_sync_register(self,TAS3004_REG_BASS); 450 break; 451 case SOUND_MIXER_MIC: 452 if ((level&0xff)>0) { 453 software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff); 454 if (self->super.mixer[mixer] == 0) { 455 self->super.mixer[SOUND_MIXER_LINE] = 0; 456 shadow[TAS3004_REG_ANALOG_CTRL][0]=0xc2; 457 rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL); 458 } else rc=0; 459 } else { 460 self->super.mixer[SOUND_MIXER_LINE] = SW_INPUT_VOLUME_DEFAULT; 461 software_input_volume = SW_INPUT_VOLUME_SCALE * 462 (self->super.mixer[SOUND_MIXER_LINE]&0xff); 463 shadow[TAS3004_REG_ANALOG_CTRL][0]=0x00; 464 rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL); 465 } 466 break; 467 case SOUND_MIXER_LINE: 468 if (self->super.mixer[SOUND_MIXER_MIC] == 0) { 469 software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff); 470 rc=0; 471 } 472 break; 473 default: 474 rc = -1; 475 break; 476 } 477 if (rc < 0) 478 return rc; 479 self->super.mixer[mixer] = level; 480 481 return 0; 482} 483 484static int 485tas3004_leave_sleep(struct tas3004_data_t *self) 486{ 487 unsigned char mcr = (1<<6)+(2<<4)+(2<<2); 488 489 if (!self) 490 return -1; 491 492 /* Make sure something answers on the i2c bus */ 493 if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, 494 WRITE_NORMAL | FORCE_WRITE) < 0) 495 return -1; 496 497 tas3004_fast_load(self, 1); 498 499 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); 500 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); 501 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); 502 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); 503 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); 504 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); 505 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); 506 507 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); 508 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); 509 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); 510 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); 511 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); 512 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); 513 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); 514 515 tas3004_fast_load(self, 0); 516 517 (void)tas3004_sync_register(self,TAS3004_REG_VOLUME); 518 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); 519 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); 520 (void)tas3004_sync_register(self,TAS3004_REG_TREBLE); 521 (void)tas3004_sync_register(self,TAS3004_REG_BASS); 522 (void)tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL); 523 524 return 0; 525} 526 527static int 528tas3004_enter_sleep(struct tas3004_data_t *self) 529{ 530 if (!self) 531 return -1; 532 return 0; 533} 534 535static int 536tas3004_sync_biquad( struct tas3004_data_t *self, 537 u_int channel, 538 u_int filter) 539{ 540 enum tas3004_reg_t reg; 541 542 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || 543 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; 544 545 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; 546 547 return tas3004_sync_register(self,reg); 548} 549 550static int 551tas3004_write_biquad_shadow( struct tas3004_data_t *self, 552 u_int channel, 553 u_int filter, 554 const union tas_biquad_t *biquad) 555{ 556 tas_shadow_t *shadow=self->super.shadow; 557 enum tas3004_reg_t reg; 558 559 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || 560 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; 561 562 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; 563 564 SET_4_20(shadow[reg], 0,biquad->coeff.b0); 565 SET_4_20(shadow[reg], 3,biquad->coeff.b1); 566 SET_4_20(shadow[reg], 6,biquad->coeff.b2); 567 SET_4_20(shadow[reg], 9,biquad->coeff.a1); 568 SET_4_20(shadow[reg],12,biquad->coeff.a2); 569 570 return 0; 571} 572 573static int 574tas3004_write_biquad( struct tas3004_data_t *self, 575 u_int channel, 576 u_int filter, 577 const union tas_biquad_t *biquad) 578{ 579 int rc; 580 581 rc=tas3004_write_biquad_shadow(self, channel, filter, biquad); 582 if (rc < 0) return rc; 583 584 return tas3004_sync_biquad(self, channel, filter); 585} 586 587static int 588tas3004_write_biquad_list( struct tas3004_data_t *self, 589 u_int filter_count, 590 u_int flags, 591 struct tas_biquad_ctrl_t *biquads) 592{ 593 int i; 594 int rc; 595 596 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); 597 598 for (i=0; i<filter_count; i++) { 599 rc=tas3004_write_biquad(self, 600 biquads[i].channel, 601 biquads[i].filter, 602 &biquads[i].data); 603 if (rc < 0) break; 604 } 605 606 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,0); 607 608 return rc; 609} 610 611static int 612tas3004_read_biquad( struct tas3004_data_t *self, 613 u_int channel, 614 u_int filter, 615 union tas_biquad_t *biquad) 616{ 617 tas_shadow_t *shadow=self->super.shadow; 618 enum tas3004_reg_t reg; 619 620 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || 621 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; 622 623 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; 624 625 biquad->coeff.b0=GET_4_20(shadow[reg], 0); 626 biquad->coeff.b1=GET_4_20(shadow[reg], 3); 627 biquad->coeff.b2=GET_4_20(shadow[reg], 6); 628 biquad->coeff.a1=GET_4_20(shadow[reg], 9); 629 biquad->coeff.a2=GET_4_20(shadow[reg],12); 630 631 return 0; 632} 633 634static int 635tas3004_eq_rw( struct tas3004_data_t *self, 636 u_int cmd, 637 u_long arg) 638{ 639 void __user *argp = (void __user *)arg; 640 int rc; 641 struct tas_biquad_ctrl_t biquad; 642 643 if (copy_from_user((void *)&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) { 644 return -EFAULT; 645 } 646 647 if (cmd & SIOC_IN) { 648 rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); 649 if (rc != 0) return rc; 650 } 651 652 if (cmd & SIOC_OUT) { 653 rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); 654 if (rc != 0) return rc; 655 656 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) { 657 return -EFAULT; 658 } 659 660 } 661 return 0; 662} 663 664static int 665tas3004_eq_list_rw( struct tas3004_data_t *self, 666 u_int cmd, 667 u_long arg) 668{ 669 int rc = 0; 670 int filter_count; 671 int flags; 672 int i,j; 673 char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT]; 674 struct tas_biquad_ctrl_t biquad; 675 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg; 676 677 memset(sync_required,0,sizeof(sync_required)); 678 679 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int))) 680 return -EFAULT; 681 682 if (copy_from_user(&flags, &argp->flags, sizeof(int))) 683 return -EFAULT; 684 685 if (cmd & SIOC_IN) { 686 } 687 688 for (i=0; i < filter_count; i++) { 689 if (copy_from_user(&biquad, &argp->biquads[i], 690 sizeof(struct tas_biquad_ctrl_t))) { 691 return -EFAULT; 692 } 693 694 if (cmd & SIOC_IN) { 695 sync_required[biquad.channel][biquad.filter]=1; 696 rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); 697 if (rc != 0) return rc; 698 } 699 700 if (cmd & SIOC_OUT) { 701 rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); 702 if (rc != 0) return rc; 703 704 if (copy_to_user(&argp->biquads[i], &biquad, 705 sizeof(struct tas_biquad_ctrl_t))) { 706 return -EFAULT; 707 } 708 } 709 } 710 711 if (cmd & SIOC_IN) { 712 /* 713 * This is OK for the tas3004. For the 714 * tas3001c, going into fast load mode causes 715 * the treble and bass to be reset to 0dB, and 716 * volume controls to be muted. 717 */ 718 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); 719 for (i=0; i<TAS3004_BIQUAD_CHANNEL_COUNT; i++) { 720 for (j=0; j<TAS3004_BIQUAD_FILTER_COUNT; j++) { 721 if (sync_required[i][j]) { 722 rc=tas3004_sync_biquad(self, i, j); 723 if (rc < 0) goto out; 724 } 725 } 726 } 727 out: 728 if (flags & TAS_BIQUAD_FAST_LOAD) 729 tas3004_fast_load(self,0); 730 } 731 732 return rc; 733} 734 735static int 736tas3004_update_drce( struct tas3004_data_t *self, 737 int flags, 738 struct tas_drce_t *drce) 739{ 740 tas_shadow_t *shadow; 741 int i; 742 shadow=self->super.shadow; 743 744 if (flags & TAS_DRCE_ABOVE_RATIO) { 745 self->drce_state.above.expand = drce->above.expand; 746 if (drce->above.val == (1<<8)) { 747 self->drce_state.above.val = 1<<8; 748 shadow[TAS3004_REG_DRC][0] = 0x02; 749 750 } else if (drce->above.expand) { 751 i=above_threshold_expansion_index(drce->above.val); 752 self->drce_state.above.val=above_threshold_expansion_ratio[i]; 753 shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3); 754 } else { 755 i=above_threshold_compression_index(drce->above.val); 756 self->drce_state.above.val=above_threshold_compression_ratio[i]; 757 shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3); 758 } 759 } 760 761 if (flags & TAS_DRCE_BELOW_RATIO) { 762 self->drce_state.below.expand = drce->below.expand; 763 if (drce->below.val == (1<<8)) { 764 self->drce_state.below.val = 1<<8; 765 shadow[TAS3004_REG_DRC][1] = 0x02; 766 767 } else if (drce->below.expand) { 768 i=below_threshold_expansion_index(drce->below.val); 769 self->drce_state.below.val=below_threshold_expansion_ratio[i]; 770 shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3); 771 } else { 772 i=below_threshold_compression_index(drce->below.val); 773 self->drce_state.below.val=below_threshold_compression_ratio[i]; 774 shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3); 775 } 776 } 777 778 if (flags & TAS_DRCE_THRESHOLD) { 779 self->drce_state.threshold=quantize_db(drce->threshold); 780 shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold); 781 } 782 783 if (flags & TAS_DRCE_ENERGY) { 784 i=time_index(drce->energy); 785 self->drce_state.energy=time_constants[i]; 786 shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4); 787 } 788 789 if (flags & TAS_DRCE_ATTACK) { 790 i=time_index(drce->attack); 791 self->drce_state.attack=time_constants[i]; 792 shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4); 793 } 794 795 if (flags & TAS_DRCE_DECAY) { 796 i=time_index(drce->decay); 797 self->drce_state.decay=time_constants[i]; 798 shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4); 799 } 800 801 if (flags & TAS_DRCE_ENABLE) { 802 self->drce_state.enable = drce->enable; 803 } 804 805 if (!self->drce_state.enable) { 806 shadow[TAS3004_REG_DRC][0] |= 0x01; 807 } 808 809#ifdef DEBUG_DRCE 810 printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", 811 self->drce_state.enable, 812 self->drce_state.above.expand,self->drce_state.above.val, 813 self->drce_state.below.expand,self->drce_state.below.val, 814 self->drce_state.threshold, 815 self->drce_state.energy, 816 self->drce_state.attack, 817 self->drce_state.decay); 818 819 printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n", 820 (unsigned char)shadow[TAS3004_REG_DRC][0], 821 (unsigned char)shadow[TAS3004_REG_DRC][1], 822 (unsigned char)shadow[TAS3004_REG_DRC][2], 823 (unsigned char)shadow[TAS3004_REG_DRC][3], 824 (unsigned char)shadow[TAS3004_REG_DRC][4], 825 (unsigned char)shadow[TAS3004_REG_DRC][5]); 826#endif 827 828 return tas3004_sync_register(self, TAS3004_REG_DRC); 829} 830 831static int 832tas3004_drce_rw( struct tas3004_data_t *self, 833 u_int cmd, 834 u_long arg) 835{ 836 int rc; 837 struct tas_drce_ctrl_t drce_ctrl; 838 void __user *argp = (void __user *)arg; 839 840 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t))) 841 return -EFAULT; 842 843#ifdef DEBUG_DRCE 844 printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", 845 drce_ctrl.flags, 846 drce_ctrl.data.enable, 847 drce_ctrl.data.above.expand,drce_ctrl.data.above.val, 848 drce_ctrl.data.below.expand,drce_ctrl.data.below.val, 849 drce_ctrl.data.threshold, 850 drce_ctrl.data.energy, 851 drce_ctrl.data.attack, 852 drce_ctrl.data.decay); 853#endif 854 855 if (cmd & SIOC_IN) { 856 rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); 857 if (rc < 0) return rc; 858 } 859 860 if (cmd & SIOC_OUT) { 861 if (drce_ctrl.flags & TAS_DRCE_ENABLE) 862 drce_ctrl.data.enable = self->drce_state.enable; 863 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) 864 drce_ctrl.data.above = self->drce_state.above; 865 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) 866 drce_ctrl.data.below = self->drce_state.below; 867 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) 868 drce_ctrl.data.threshold = self->drce_state.threshold; 869 if (drce_ctrl.flags & TAS_DRCE_ENERGY) 870 drce_ctrl.data.energy = self->drce_state.energy; 871 if (drce_ctrl.flags & TAS_DRCE_ATTACK) 872 drce_ctrl.data.attack = self->drce_state.attack; 873 if (drce_ctrl.flags & TAS_DRCE_DECAY) 874 drce_ctrl.data.decay = self->drce_state.decay; 875 876 if (copy_to_user(argp, &drce_ctrl, 877 sizeof(struct tas_drce_ctrl_t))) { 878 return -EFAULT; 879 } 880 } 881 882 return 0; 883} 884 885static void 886tas3004_update_device_parameters(struct tas3004_data_t *self) 887{ 888 char data; 889 int i; 890 891 if (!self) return; 892 893 if (self->output_id == TAS_OUTPUT_HEADPHONES) { 894 /* turn on allPass when headphones are plugged in */ 895 data = 0x02; 896 } else { 897 data = 0x00; 898 } 899 900 tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE); 901 902 for (i=0; tas3004_eq_prefs[i]; i++) { 903 struct tas_eq_pref_t *eq = tas3004_eq_prefs[i]; 904 905 if (eq->device_id == self->device_id && 906 (eq->output_id == 0 || eq->output_id == self->output_id) && 907 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { 908 909 tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce); 910 tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); 911 912 break; 913 } 914 } 915} 916 917static void 918tas3004_device_change_handler(struct work_struct *work) 919{ 920 struct tas3004_data_t *self; 921 self = container_of(work, struct tas3004_data_t, change); 922 tas3004_update_device_parameters(self); 923} 924 925static int 926tas3004_output_device_change( struct tas3004_data_t *self, 927 int device_id, 928 int output_id, 929 int speaker_id) 930{ 931 self->device_id=device_id; 932 self->output_id=output_id; 933 self->speaker_id=speaker_id; 934 935 schedule_work(&self->change); 936 937 return 0; 938} 939 940static int 941tas3004_device_ioctl( struct tas3004_data_t *self, 942 u_int cmd, 943 u_long arg) 944{ 945 uint __user *argp = (void __user *)arg; 946 switch (cmd) { 947 case TAS_READ_EQ: 948 case TAS_WRITE_EQ: 949 return tas3004_eq_rw(self, cmd, arg); 950 951 case TAS_READ_EQ_LIST: 952 case TAS_WRITE_EQ_LIST: 953 return tas3004_eq_list_rw(self, cmd, arg); 954 955 case TAS_READ_EQ_FILTER_COUNT: 956 put_user(TAS3004_BIQUAD_FILTER_COUNT, argp); 957 return 0; 958 959 case TAS_READ_EQ_CHANNEL_COUNT: 960 put_user(TAS3004_BIQUAD_CHANNEL_COUNT, argp); 961 return 0; 962 963 case TAS_READ_DRCE: 964 case TAS_WRITE_DRCE: 965 return tas3004_drce_rw(self, cmd, arg); 966 967 case TAS_READ_DRCE_CAPS: 968 put_user(TAS_DRCE_ENABLE | 969 TAS_DRCE_ABOVE_RATIO | 970 TAS_DRCE_BELOW_RATIO | 971 TAS_DRCE_THRESHOLD | 972 TAS_DRCE_ENERGY | 973 TAS_DRCE_ATTACK | 974 TAS_DRCE_DECAY, 975 argp); 976 return 0; 977 978 case TAS_READ_DRCE_MIN: 979 case TAS_READ_DRCE_MAX: { 980 struct tas_drce_ctrl_t drce_ctrl; 981 const struct tas_drce_t *drce_copy; 982 983 if (copy_from_user(&drce_ctrl, argp, 984 sizeof(struct tas_drce_ctrl_t))) { 985 return -EFAULT; 986 } 987 988 if (cmd == TAS_READ_DRCE_MIN) { 989 drce_copy=&tas3004_drce_min; 990 } else { 991 drce_copy=&tas3004_drce_max; 992 } 993 994 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) { 995 drce_ctrl.data.above=drce_copy->above; 996 } 997 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) { 998 drce_ctrl.data.below=drce_copy->below; 999 } 1000 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { 1001 drce_ctrl.data.threshold=drce_copy->threshold; 1002 } 1003 if (drce_ctrl.flags & TAS_DRCE_ENERGY) { 1004 drce_ctrl.data.energy=drce_copy->energy; 1005 } 1006 if (drce_ctrl.flags & TAS_DRCE_ATTACK) { 1007 drce_ctrl.data.attack=drce_copy->attack; 1008 } 1009 if (drce_ctrl.flags & TAS_DRCE_DECAY) { 1010 drce_ctrl.data.decay=drce_copy->decay; 1011 } 1012 1013 if (copy_to_user(argp, &drce_ctrl, 1014 sizeof(struct tas_drce_ctrl_t))) { 1015 return -EFAULT; 1016 } 1017 } 1018 } 1019 1020 return -EINVAL; 1021} 1022 1023static int 1024tas3004_init_mixer(struct tas3004_data_t *self) 1025{ 1026 unsigned char mcr = (1<<6)+(2<<4)+(2<<2); 1027 1028 /* Make sure something answers on the i2c bus */ 1029 if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, 1030 WRITE_NORMAL | FORCE_WRITE) < 0) 1031 return -1; 1032 1033 tas3004_fast_load(self, 1); 1034 1035 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); 1036 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); 1037 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); 1038 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); 1039 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); 1040 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); 1041 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); 1042 1043 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); 1044 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); 1045 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); 1046 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); 1047 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); 1048 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); 1049 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); 1050 1051 tas3004_sync_register(self, TAS3004_REG_DRC); 1052 1053 tas3004_sync_register(self, TAS3004_REG_MCR2); 1054 1055 tas3004_fast_load(self, 0); 1056 1057 tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); 1058 tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); 1059 tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); 1060 tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); 1061 1062 tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); 1063 tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); 1064 1065 tas3004_set_mixer_level(self, SOUND_MIXER_LINE,SW_INPUT_VOLUME_DEFAULT); 1066 1067 return 0; 1068} 1069 1070static int 1071tas3004_uninit_mixer(struct tas3004_data_t *self) 1072{ 1073 tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); 1074 tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0); 1075 tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); 1076 tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); 1077 1078 tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0); 1079 tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); 1080 1081 tas3004_set_mixer_level(self, SOUND_MIXER_LINE, 0); 1082 1083 return 0; 1084} 1085 1086static int 1087tas3004_init(struct i2c_client *client) 1088{ 1089 struct tas3004_data_t *self; 1090 size_t sz = sizeof(*self) + (TAS3004_REG_MAX*sizeof(tas_shadow_t)); 1091 char drce_init[] = { 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 }; 1092 char mcr2 = 0; 1093 int i, j; 1094 1095 self = kzalloc(sz, GFP_KERNEL); 1096 if (!self) 1097 return -ENOMEM; 1098 1099 self->super.client = client; 1100 self->super.shadow = (tas_shadow_t *)(self+1); 1101 self->output_id = TAS_OUTPUT_HEADPHONES; 1102 1103 dev_set_drvdata(&client->dev, self); 1104 1105 for (i = 0; i < TAS3004_BIQUAD_CHANNEL_COUNT; i++) 1106 for (j = 0; j<TAS3004_BIQUAD_FILTER_COUNT; j++) 1107 tas3004_write_biquad_shadow(self, i, j, 1108 &tas3004_eq_unity); 1109 1110 tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW); 1111 tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW); 1112 1113 INIT_WORK(&self->change, tas3004_device_change_handler); 1114 return 0; 1115} 1116 1117static void 1118tas3004_uninit(struct tas3004_data_t *self) 1119{ 1120 tas3004_uninit_mixer(self); 1121 kfree(self); 1122} 1123 1124 1125struct tas_driver_hooks_t tas3004_hooks = { 1126 .init = (tas_hook_init_t)tas3004_init, 1127 .post_init = (tas_hook_post_init_t)tas3004_init_mixer, 1128 .uninit = (tas_hook_uninit_t)tas3004_uninit, 1129 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3004_get_mixer_level, 1130 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3004_set_mixer_level, 1131 .enter_sleep = (tas_hook_enter_sleep_t)tas3004_enter_sleep, 1132 .leave_sleep = (tas_hook_leave_sleep_t)tas3004_leave_sleep, 1133 .supported_mixers = (tas_hook_supported_mixers_t)tas3004_supported_mixers, 1134 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3004_mixer_is_stereo, 1135 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3004_stereo_mixers, 1136 .output_device_change = (tas_hook_output_device_change_t)tas3004_output_device_change, 1137 .device_ioctl = (tas_hook_device_ioctl_t)tas3004_device_ioctl 1138}; 1139