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 * TODO: 9 * ----- 10 * * Enable control over input line 2 (is this connected?) 11 * * Implement sleep support (at least mute everything and 12 * * set gains to minimum during sleep) 13 * * Look into some of Darwin's tweaks regarding the mute 14 * * lines (delays & different behaviour on some HW) 15 * 16 */ 17 18#include <linux/module.h> 19#include <linux/slab.h> 20#include <linux/proc_fs.h> 21#include <linux/ioport.h> 22#include <linux/sysctl.h> 23#include <linux/types.h> 24#include <linux/i2c.h> 25#include <linux/init.h> 26#include <linux/soundcard.h> 27#include <linux/workqueue.h> 28#include <asm/uaccess.h> 29#include <asm/errno.h> 30#include <asm/io.h> 31#include <asm/prom.h> 32 33#include "dmasound.h" 34#include "tas_common.h" 35#include "tas3001c.h" 36 37#include "tas_ioctl.h" 38 39#define TAS3001C_BIQUAD_FILTER_COUNT 6 40#define TAS3001C_BIQUAD_CHANNEL_COUNT 2 41 42#define VOL_DEFAULT (100 * 4 / 5) 43#define INPUT_DEFAULT (100 * 4 / 5) 44#define BASS_DEFAULT (100 / 2) 45#define TREBLE_DEFAULT (100 / 2) 46 47struct tas3001c_data_t { 48 struct tas_data_t super; 49 int device_id; 50 int output_id; 51 int speaker_id; 52 struct tas_drce_t drce_state; 53 struct work_struct change; 54}; 55 56 57static const union tas_biquad_t 58tas3001c_eq_unity={ 59 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } 60}; 61 62 63static inline unsigned char db_to_regval(short db) { 64 int r=0; 65 66 r=(db+0x59a0) / 0x60; 67 68 if (r < 0x91) return 0x91; 69 if (r > 0xef) return 0xef; 70 return r; 71} 72 73static inline short quantize_db(short db) { 74 return db_to_regval(db) * 0x60 - 0x59a0; 75} 76 77 78static inline int 79register_width(enum tas3001c_reg_t r) 80{ 81 switch(r) { 82 case TAS3001C_REG_MCR: 83 case TAS3001C_REG_TREBLE: 84 case TAS3001C_REG_BASS: 85 return 1; 86 87 case TAS3001C_REG_DRC: 88 return 2; 89 90 case TAS3001C_REG_MIXER1: 91 case TAS3001C_REG_MIXER2: 92 return 3; 93 94 case TAS3001C_REG_VOLUME: 95 return 6; 96 97 case TAS3001C_REG_LEFT_BIQUAD0: 98 case TAS3001C_REG_LEFT_BIQUAD1: 99 case TAS3001C_REG_LEFT_BIQUAD2: 100 case TAS3001C_REG_LEFT_BIQUAD3: 101 case TAS3001C_REG_LEFT_BIQUAD4: 102 case TAS3001C_REG_LEFT_BIQUAD5: 103 case TAS3001C_REG_LEFT_BIQUAD6: 104 105 case TAS3001C_REG_RIGHT_BIQUAD0: 106 case TAS3001C_REG_RIGHT_BIQUAD1: 107 case TAS3001C_REG_RIGHT_BIQUAD2: 108 case TAS3001C_REG_RIGHT_BIQUAD3: 109 case TAS3001C_REG_RIGHT_BIQUAD4: 110 case TAS3001C_REG_RIGHT_BIQUAD5: 111 case TAS3001C_REG_RIGHT_BIQUAD6: 112 return 15; 113 114 default: 115 return 0; 116 } 117} 118 119static int 120tas3001c_write_register( struct tas3001c_data_t *self, 121 enum tas3001c_reg_t reg_num, 122 char *data, 123 uint write_mode) 124{ 125 if (reg_num==TAS3001C_REG_MCR || 126 reg_num==TAS3001C_REG_BASS || 127 reg_num==TAS3001C_REG_TREBLE) { 128 return tas_write_byte_register(&self->super, 129 (uint)reg_num, 130 *data, 131 write_mode); 132 } else { 133 return tas_write_register(&self->super, 134 (uint)reg_num, 135 register_width(reg_num), 136 data, 137 write_mode); 138 } 139} 140 141static int 142tas3001c_sync_register( struct tas3001c_data_t *self, 143 enum tas3001c_reg_t reg_num) 144{ 145 if (reg_num==TAS3001C_REG_MCR || 146 reg_num==TAS3001C_REG_BASS || 147 reg_num==TAS3001C_REG_TREBLE) { 148 return tas_sync_byte_register(&self->super, 149 (uint)reg_num, 150 register_width(reg_num)); 151 } else { 152 return tas_sync_register(&self->super, 153 (uint)reg_num, 154 register_width(reg_num)); 155 } 156} 157 158static int 159tas3001c_read_register( struct tas3001c_data_t *self, 160 enum tas3001c_reg_t reg_num, 161 char *data, 162 uint write_mode) 163{ 164 return tas_read_register(&self->super, 165 (uint)reg_num, 166 register_width(reg_num), 167 data); 168} 169 170static inline int 171tas3001c_fast_load(struct tas3001c_data_t *self, int fast) 172{ 173 if (fast) 174 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80; 175 else 176 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f; 177 return tas3001c_sync_register(self,TAS3001C_REG_MCR); 178} 179 180static uint 181tas3001c_supported_mixers(struct tas3001c_data_t *self) 182{ 183 return SOUND_MASK_VOLUME | 184 SOUND_MASK_PCM | 185 SOUND_MASK_ALTPCM | 186 SOUND_MASK_TREBLE | 187 SOUND_MASK_BASS; 188} 189 190static int 191tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer) 192{ 193 switch(mixer) { 194 case SOUND_MIXER_VOLUME: 195 return 1; 196 default: 197 return 0; 198 } 199} 200 201static uint 202tas3001c_stereo_mixers(struct tas3001c_data_t *self) 203{ 204 uint r=tas3001c_supported_mixers(self); 205 uint i; 206 207 for (i=1; i<SOUND_MIXER_NRDEVICES; i++) 208 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i)) 209 r &= ~(1<<i); 210 return r; 211} 212 213static int 214tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level) 215{ 216 if (!self) 217 return -1; 218 219 *level=self->super.mixer[mixer]; 220 221 return 0; 222} 223 224static int 225tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level) 226{ 227 int rc; 228 tas_shadow_t *shadow; 229 230 uint temp; 231 uint offset=0; 232 233 if (!self) 234 return -1; 235 236 shadow=self->super.shadow; 237 238 if (!tas3001c_mixer_is_stereo(self,mixer)) 239 level = tas_mono_to_stereo(level); 240 241 switch(mixer) { 242 case SOUND_MIXER_VOLUME: 243 temp = tas3001c_gain.master[level&0xff]; 244 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff; 245 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff; 246 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff; 247 temp = tas3001c_gain.master[(level>>8)&0xff]; 248 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff; 249 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff; 250 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff; 251 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME); 252 break; 253 case SOUND_MIXER_ALTPCM: 254 /* tas3001c_fast_load(self, 1); */ 255 level = tas_mono_to_stereo(level); 256 temp = tas3001c_gain.mixer[level&0xff]; 257 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff; 258 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff; 259 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff; 260 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2); 261 /* tas3001c_fast_load(self, 0); */ 262 break; 263 case SOUND_MIXER_PCM: 264 /* tas3001c_fast_load(self, 1); */ 265 level = tas_mono_to_stereo(level); 266 temp = tas3001c_gain.mixer[level&0xff]; 267 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff; 268 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff; 269 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff; 270 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1); 271 /* tas3001c_fast_load(self, 0); */ 272 break; 273 case SOUND_MIXER_TREBLE: 274 temp = tas3001c_gain.treble[level&0xff]; 275 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff; 276 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE); 277 break; 278 case SOUND_MIXER_BASS: 279 temp = tas3001c_gain.bass[level&0xff]; 280 shadow[TAS3001C_REG_BASS][0]=temp&0xff; 281 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS); 282 break; 283 default: 284 rc = -1; 285 break; 286 } 287 if (rc < 0) 288 return rc; 289 self->super.mixer[mixer]=level; 290 return 0; 291} 292 293static int 294tas3001c_leave_sleep(struct tas3001c_data_t *self) 295{ 296 unsigned char mcr = (1<<6)+(2<<4)+(2<<2); 297 298 if (!self) 299 return -1; 300 301 /* Make sure something answers on the i2c bus */ 302 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, 303 WRITE_NORMAL|FORCE_WRITE) < 0) 304 return -1; 305 306 tas3001c_fast_load(self, 1); 307 308 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); 309 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); 310 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); 311 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); 312 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); 313 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); 314 315 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); 316 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); 317 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); 318 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); 319 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); 320 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); 321 322 tas3001c_fast_load(self, 0); 323 324 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); 325 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); 326 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); 327 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); 328 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); 329 330 return 0; 331} 332 333static int 334tas3001c_enter_sleep(struct tas3001c_data_t *self) 335{ 336 /* Stub for now, but I have the details on low-power mode */ 337 if (!self) 338 return -1; 339 return 0; 340} 341 342static int 343tas3001c_sync_biquad( struct tas3001c_data_t *self, 344 u_int channel, 345 u_int filter) 346{ 347 enum tas3001c_reg_t reg; 348 349 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || 350 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; 351 352 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; 353 354 return tas3001c_sync_register(self,reg); 355} 356 357static int 358tas3001c_write_biquad_shadow( struct tas3001c_data_t *self, 359 u_int channel, 360 u_int filter, 361 const union tas_biquad_t *biquad) 362{ 363 tas_shadow_t *shadow=self->super.shadow; 364 enum tas3001c_reg_t reg; 365 366 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || 367 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; 368 369 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; 370 371 SET_4_20(shadow[reg], 0,biquad->coeff.b0); 372 SET_4_20(shadow[reg], 3,biquad->coeff.b1); 373 SET_4_20(shadow[reg], 6,biquad->coeff.b2); 374 SET_4_20(shadow[reg], 9,biquad->coeff.a1); 375 SET_4_20(shadow[reg],12,biquad->coeff.a2); 376 377 return 0; 378} 379 380static int 381tas3001c_write_biquad( struct tas3001c_data_t *self, 382 u_int channel, 383 u_int filter, 384 const union tas_biquad_t *biquad) 385{ 386 int rc; 387 388 rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad); 389 if (rc < 0) return rc; 390 391 return tas3001c_sync_biquad(self, channel, filter); 392} 393 394static int 395tas3001c_write_biquad_list( struct tas3001c_data_t *self, 396 u_int filter_count, 397 u_int flags, 398 struct tas_biquad_ctrl_t *biquads) 399{ 400 int i; 401 int rc; 402 403 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); 404 405 for (i=0; i<filter_count; i++) { 406 rc=tas3001c_write_biquad(self, 407 biquads[i].channel, 408 biquads[i].filter, 409 &biquads[i].data); 410 if (rc < 0) break; 411 } 412 413 if (flags & TAS_BIQUAD_FAST_LOAD) { 414 tas3001c_fast_load(self,0); 415 416 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); 417 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); 418 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); 419 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); 420 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); 421 } 422 423 return rc; 424} 425 426static int 427tas3001c_read_biquad( struct tas3001c_data_t *self, 428 u_int channel, 429 u_int filter, 430 union tas_biquad_t *biquad) 431{ 432 tas_shadow_t *shadow=self->super.shadow; 433 enum tas3001c_reg_t reg; 434 435 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || 436 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; 437 438 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; 439 440 biquad->coeff.b0=GET_4_20(shadow[reg], 0); 441 biquad->coeff.b1=GET_4_20(shadow[reg], 3); 442 biquad->coeff.b2=GET_4_20(shadow[reg], 6); 443 biquad->coeff.a1=GET_4_20(shadow[reg], 9); 444 biquad->coeff.a2=GET_4_20(shadow[reg],12); 445 446 return 0; 447} 448 449static int 450tas3001c_eq_rw( struct tas3001c_data_t *self, 451 u_int cmd, 452 u_long arg) 453{ 454 int rc; 455 struct tas_biquad_ctrl_t biquad; 456 void __user *argp = (void __user *)arg; 457 458 if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) { 459 return -EFAULT; 460 } 461 462 if (cmd & SIOC_IN) { 463 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); 464 if (rc != 0) return rc; 465 } 466 467 if (cmd & SIOC_OUT) { 468 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); 469 if (rc != 0) return rc; 470 471 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) { 472 return -EFAULT; 473 } 474 475 } 476 return 0; 477} 478 479static int 480tas3001c_eq_list_rw( struct tas3001c_data_t *self, 481 u_int cmd, 482 u_long arg) 483{ 484 int rc; 485 int filter_count; 486 int flags; 487 int i,j; 488 char sync_required[2][6]; 489 struct tas_biquad_ctrl_t biquad; 490 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg; 491 492 memset(sync_required,0,sizeof(sync_required)); 493 494 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int))) 495 return -EFAULT; 496 497 if (copy_from_user(&flags, &argp->flags, sizeof(int))) 498 return -EFAULT; 499 500 if (cmd & SIOC_IN) { 501 } 502 503 for (i=0; i < filter_count; i++) { 504 if (copy_from_user(&biquad, &argp->biquads[i], 505 sizeof(struct tas_biquad_ctrl_t))) { 506 return -EFAULT; 507 } 508 509 if (cmd & SIOC_IN) { 510 sync_required[biquad.channel][biquad.filter]=1; 511 rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); 512 if (rc != 0) return rc; 513 } 514 515 if (cmd & SIOC_OUT) { 516 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); 517 if (rc != 0) return rc; 518 519 if (copy_to_user(&argp->biquads[i], &biquad, 520 sizeof(struct tas_biquad_ctrl_t))) { 521 return -EFAULT; 522 } 523 } 524 } 525 526 if (cmd & SIOC_IN) { 527 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); 528 for (i=0; i<2; i++) { 529 for (j=0; j<6; j++) { 530 if (sync_required[i][j]) { 531 rc=tas3001c_sync_biquad(self, i, j); 532 if (rc < 0) return rc; 533 } 534 } 535 } 536 if (flags & TAS_BIQUAD_FAST_LOAD) { 537 tas3001c_fast_load(self,0); 538 /* now we need to set up the mixers again, 539 because leaving fast mode resets them. */ 540 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); 541 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); 542 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); 543 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); 544 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); 545 } 546 } 547 548 return 0; 549} 550 551static int 552tas3001c_update_drce( struct tas3001c_data_t *self, 553 int flags, 554 struct tas_drce_t *drce) 555{ 556 tas_shadow_t *shadow; 557 shadow=self->super.shadow; 558 559 shadow[TAS3001C_REG_DRC][1] = 0xc1; 560 561 if (flags & TAS_DRCE_THRESHOLD) { 562 self->drce_state.threshold=quantize_db(drce->threshold); 563 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold); 564 } 565 566 if (flags & TAS_DRCE_ENABLE) { 567 self->drce_state.enable = drce->enable; 568 } 569 570 if (!self->drce_state.enable) { 571 shadow[TAS3001C_REG_DRC][0] = 0xf0; 572 } 573 574#ifdef DEBUG_DRCE 575 printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n", 576 self->drce_state.enable, 577 self->drce_state.threshold); 578 579 printk("DRCE IOCTL: reg [ %02x %02x ]\n", 580 (unsigned char)shadow[TAS3001C_REG_DRC][0], 581 (unsigned char)shadow[TAS3001C_REG_DRC][1]); 582#endif 583 584 return tas3001c_sync_register(self, TAS3001C_REG_DRC); 585} 586 587static int 588tas3001c_drce_rw( struct tas3001c_data_t *self, 589 u_int cmd, 590 u_long arg) 591{ 592 int rc; 593 struct tas_drce_ctrl_t drce_ctrl; 594 void __user *argp = (void __user *)arg; 595 596 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t))) 597 return -EFAULT; 598 599#ifdef DEBUG_DRCE 600 printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n", 601 drce_ctrl.flags, 602 drce_ctrl.data.enable, 603 drce_ctrl.data.threshold); 604#endif 605 606 if (cmd & SIOC_IN) { 607 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); 608 if (rc < 0) 609 return rc; 610 } 611 612 if (cmd & SIOC_OUT) { 613 if (drce_ctrl.flags & TAS_DRCE_ENABLE) 614 drce_ctrl.data.enable = self->drce_state.enable; 615 616 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) 617 drce_ctrl.data.threshold = self->drce_state.threshold; 618 619 if (copy_to_user(argp, &drce_ctrl, 620 sizeof(struct tas_drce_ctrl_t))) { 621 return -EFAULT; 622 } 623 } 624 625 return 0; 626} 627 628static void 629tas3001c_update_device_parameters(struct tas3001c_data_t *self) 630{ 631 int i,j; 632 633 if (!self) return; 634 635 if (self->output_id == TAS_OUTPUT_HEADPHONES) { 636 tas3001c_fast_load(self, 1); 637 638 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) { 639 for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) { 640 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity); 641 } 642 } 643 644 tas3001c_fast_load(self, 0); 645 646 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); 647 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); 648 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); 649 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); 650 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); 651 652 return; 653 } 654 655 for (i=0; tas3001c_eq_prefs[i]; i++) { 656 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i]; 657 658 if (eq->device_id == self->device_id && 659 (eq->output_id == 0 || eq->output_id == self->output_id) && 660 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { 661 662 tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce); 663 tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); 664 665 break; 666 } 667 } 668} 669 670static void 671tas3001c_device_change_handler(struct work_struct *work) 672{ 673 struct tas3001c_data_t *self; 674 self = container_of(work, struct tas3001c_data_t, change); 675 tas3001c_update_device_parameters(self); 676} 677 678static int 679tas3001c_output_device_change( struct tas3001c_data_t *self, 680 int device_id, 681 int output_id, 682 int speaker_id) 683{ 684 self->device_id=device_id; 685 self->output_id=output_id; 686 self->speaker_id=speaker_id; 687 688 schedule_work(&self->change); 689 return 0; 690} 691 692static int 693tas3001c_device_ioctl( struct tas3001c_data_t *self, 694 u_int cmd, 695 u_long arg) 696{ 697 uint __user *argp = (void __user *)arg; 698 switch (cmd) { 699 case TAS_READ_EQ: 700 case TAS_WRITE_EQ: 701 return tas3001c_eq_rw(self, cmd, arg); 702 703 case TAS_READ_EQ_LIST: 704 case TAS_WRITE_EQ_LIST: 705 return tas3001c_eq_list_rw(self, cmd, arg); 706 707 case TAS_READ_EQ_FILTER_COUNT: 708 put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp); 709 return 0; 710 711 case TAS_READ_EQ_CHANNEL_COUNT: 712 put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp); 713 return 0; 714 715 case TAS_READ_DRCE: 716 case TAS_WRITE_DRCE: 717 return tas3001c_drce_rw(self, cmd, arg); 718 719 case TAS_READ_DRCE_CAPS: 720 put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp); 721 return 0; 722 723 case TAS_READ_DRCE_MIN: 724 case TAS_READ_DRCE_MAX: { 725 struct tas_drce_ctrl_t drce_ctrl; 726 727 if (copy_from_user(&drce_ctrl, argp, 728 sizeof(struct tas_drce_ctrl_t))) { 729 return -EFAULT; 730 } 731 732 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { 733 if (cmd == TAS_READ_DRCE_MIN) { 734 drce_ctrl.data.threshold=-36<<8; 735 } else { 736 drce_ctrl.data.threshold=-6<<8; 737 } 738 } 739 740 if (copy_to_user(argp, &drce_ctrl, 741 sizeof(struct tas_drce_ctrl_t))) { 742 return -EFAULT; 743 } 744 } 745 } 746 747 return -EINVAL; 748} 749 750static int 751tas3001c_init_mixer(struct tas3001c_data_t *self) 752{ 753 unsigned char mcr = (1<<6)+(2<<4)+(2<<2); 754 755 /* Make sure something answers on the i2c bus */ 756 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, 757 WRITE_NORMAL|FORCE_WRITE) < 0) 758 return -1; 759 760 tas3001c_fast_load(self, 1); 761 762 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); 763 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); 764 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); 765 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); 766 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); 767 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); 768 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6); 769 770 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); 771 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); 772 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); 773 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); 774 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); 775 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); 776 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6); 777 778 tas3001c_fast_load(self, 0); 779 780 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); 781 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); 782 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); 783 784 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); 785 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); 786 787 return 0; 788} 789 790static int 791tas3001c_uninit_mixer(struct tas3001c_data_t *self) 792{ 793 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); 794 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0); 795 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); 796 797 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0); 798 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); 799 800 return 0; 801} 802 803static int 804tas3001c_init(struct i2c_client *client) 805{ 806 struct tas3001c_data_t *self; 807 size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t)); 808 int i, j; 809 810 self = kzalloc(sz, GFP_KERNEL); 811 if (!self) 812 return -ENOMEM; 813 814 self->super.client = client; 815 self->super.shadow = (tas_shadow_t *)(self+1); 816 self->output_id = TAS_OUTPUT_HEADPHONES; 817 818 dev_set_drvdata(&client->dev, self); 819 820 for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++) 821 for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++) 822 tas3001c_write_biquad_shadow(self, i, j, 823 &tas3001c_eq_unity); 824 825 INIT_WORK(&self->change, tas3001c_device_change_handler); 826 return 0; 827} 828 829static void 830tas3001c_uninit(struct tas3001c_data_t *self) 831{ 832 tas3001c_uninit_mixer(self); 833 kfree(self); 834} 835 836struct tas_driver_hooks_t tas3001c_hooks = { 837 .init = (tas_hook_init_t)tas3001c_init, 838 .post_init = (tas_hook_post_init_t)tas3001c_init_mixer, 839 .uninit = (tas_hook_uninit_t)tas3001c_uninit, 840 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level, 841 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level, 842 .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep, 843 .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep, 844 .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers, 845 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo, 846 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers, 847 .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change, 848 .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl 849}; 850