1/** 2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 3 * 4 * This source file is released under GPL v2 license (no other versions). 5 * See the COPYING file included in the main directory of this source 6 * distribution for the license terms and conditions. 7 * 8 * @File ctmixer.c 9 * 10 * @Brief 11 * This file contains the implementation of alsa mixer device functions. 12 * 13 * @Author Liu Chun 14 * @Date May 28 2008 15 * 16 */ 17 18 19#include "ctmixer.h" 20#include "ctamixer.h" 21#include <linux/slab.h> 22#include <sound/core.h> 23#include <sound/control.h> 24#include <sound/asoundef.h> 25#include <sound/pcm.h> 26#include <sound/tlv.h> 27 28enum CT_SUM_CTL { 29 SUM_IN_F, 30 SUM_IN_R, 31 SUM_IN_C, 32 SUM_IN_S, 33 SUM_IN_F_C, 34 35 NUM_CT_SUMS 36}; 37 38enum CT_AMIXER_CTL { 39 /* volume control mixers */ 40 AMIXER_MASTER_F, 41 AMIXER_MASTER_R, 42 AMIXER_MASTER_C, 43 AMIXER_MASTER_S, 44 AMIXER_PCM_F, 45 AMIXER_PCM_R, 46 AMIXER_PCM_C, 47 AMIXER_PCM_S, 48 AMIXER_SPDIFI, 49 AMIXER_LINEIN, 50 AMIXER_MIC, 51 AMIXER_SPDIFO, 52 AMIXER_WAVE_F, 53 AMIXER_WAVE_R, 54 AMIXER_WAVE_C, 55 AMIXER_WAVE_S, 56 AMIXER_MASTER_F_C, 57 AMIXER_PCM_F_C, 58 AMIXER_SPDIFI_C, 59 AMIXER_LINEIN_C, 60 AMIXER_MIC_C, 61 62 /* this should always be the last one */ 63 NUM_CT_AMIXERS 64}; 65 66enum CTALSA_MIXER_CTL { 67 /* volume control mixers */ 68 MIXER_MASTER_P, 69 MIXER_PCM_P, 70 MIXER_LINEIN_P, 71 MIXER_MIC_P, 72 MIXER_SPDIFI_P, 73 MIXER_SPDIFO_P, 74 MIXER_WAVEF_P, 75 MIXER_WAVER_P, 76 MIXER_WAVEC_P, 77 MIXER_WAVES_P, 78 MIXER_MASTER_C, 79 MIXER_PCM_C, 80 MIXER_LINEIN_C, 81 MIXER_MIC_C, 82 MIXER_SPDIFI_C, 83 84 /* switch control mixers */ 85 MIXER_PCM_C_S, 86 MIXER_LINEIN_C_S, 87 MIXER_MIC_C_S, 88 MIXER_SPDIFI_C_S, 89 MIXER_LINEIN_P_S, 90 MIXER_SPDIFO_P_S, 91 MIXER_SPDIFI_P_S, 92 MIXER_WAVEF_P_S, 93 MIXER_WAVER_P_S, 94 MIXER_WAVEC_P_S, 95 MIXER_WAVES_P_S, 96 MIXER_DIGITAL_IO_S, 97 MIXER_IEC958_MASK, 98 MIXER_IEC958_DEFAULT, 99 MIXER_IEC958_STREAM, 100 101 /* this should always be the last one */ 102 NUM_CTALSA_MIXERS 103}; 104 105#define VOL_MIXER_START MIXER_MASTER_P 106#define VOL_MIXER_END MIXER_SPDIFI_C 107#define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1) 108#define SWH_MIXER_START MIXER_PCM_C_S 109#define SWH_MIXER_END MIXER_DIGITAL_IO_S 110#define SWH_CAPTURE_START MIXER_PCM_C_S 111#define SWH_CAPTURE_END MIXER_SPDIFI_C_S 112 113#define CHN_NUM 2 114 115struct ct_kcontrol_init { 116 unsigned char ctl; 117 char *name; 118}; 119 120static struct ct_kcontrol_init 121ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { 122 [MIXER_MASTER_P] = { 123 .ctl = 1, 124 .name = "Master Playback Volume", 125 }, 126 [MIXER_MASTER_C] = { 127 .ctl = 1, 128 .name = "Master Capture Volume", 129 }, 130 [MIXER_PCM_P] = { 131 .ctl = 1, 132 .name = "PCM Playback Volume", 133 }, 134 [MIXER_PCM_C] = { 135 .ctl = 1, 136 .name = "PCM Capture Volume", 137 }, 138 [MIXER_LINEIN_P] = { 139 .ctl = 1, 140 .name = "Line-in Playback Volume", 141 }, 142 [MIXER_LINEIN_C] = { 143 .ctl = 1, 144 .name = "Line-in Capture Volume", 145 }, 146 [MIXER_MIC_P] = { 147 .ctl = 1, 148 .name = "Mic Playback Volume", 149 }, 150 [MIXER_MIC_C] = { 151 .ctl = 1, 152 .name = "Mic Capture Volume", 153 }, 154 [MIXER_SPDIFI_P] = { 155 .ctl = 1, 156 .name = "S/PDIF-in Playback Volume", 157 }, 158 [MIXER_SPDIFI_C] = { 159 .ctl = 1, 160 .name = "S/PDIF-in Capture Volume", 161 }, 162 [MIXER_SPDIFO_P] = { 163 .ctl = 1, 164 .name = "S/PDIF-out Playback Volume", 165 }, 166 [MIXER_WAVEF_P] = { 167 .ctl = 1, 168 .name = "Front Playback Volume", 169 }, 170 [MIXER_WAVES_P] = { 171 .ctl = 1, 172 .name = "Side Playback Volume", 173 }, 174 [MIXER_WAVEC_P] = { 175 .ctl = 1, 176 .name = "Center/LFE Playback Volume", 177 }, 178 [MIXER_WAVER_P] = { 179 .ctl = 1, 180 .name = "Surround Playback Volume", 181 }, 182 183 [MIXER_PCM_C_S] = { 184 .ctl = 1, 185 .name = "PCM Capture Switch", 186 }, 187 [MIXER_LINEIN_C_S] = { 188 .ctl = 1, 189 .name = "Line-in Capture Switch", 190 }, 191 [MIXER_MIC_C_S] = { 192 .ctl = 1, 193 .name = "Mic Capture Switch", 194 }, 195 [MIXER_SPDIFI_C_S] = { 196 .ctl = 1, 197 .name = "S/PDIF-in Capture Switch", 198 }, 199 [MIXER_LINEIN_P_S] = { 200 .ctl = 1, 201 .name = "Line-in Playback Switch", 202 }, 203 [MIXER_SPDIFO_P_S] = { 204 .ctl = 1, 205 .name = "S/PDIF-out Playback Switch", 206 }, 207 [MIXER_SPDIFI_P_S] = { 208 .ctl = 1, 209 .name = "S/PDIF-in Playback Switch", 210 }, 211 [MIXER_WAVEF_P_S] = { 212 .ctl = 1, 213 .name = "Front Playback Switch", 214 }, 215 [MIXER_WAVES_P_S] = { 216 .ctl = 1, 217 .name = "Side Playback Switch", 218 }, 219 [MIXER_WAVEC_P_S] = { 220 .ctl = 1, 221 .name = "Center/LFE Playback Switch", 222 }, 223 [MIXER_WAVER_P_S] = { 224 .ctl = 1, 225 .name = "Surround Playback Switch", 226 }, 227 [MIXER_DIGITAL_IO_S] = { 228 .ctl = 0, 229 .name = "Digit-IO Playback Switch", 230 }, 231}; 232 233static void 234ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); 235 236static void 237ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); 238 239static struct snd_kcontrol *kctls[2] = {NULL}; 240 241static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) 242{ 243 switch (alsa_index) { 244 case MIXER_MASTER_P: return AMIXER_MASTER_F; 245 case MIXER_MASTER_C: return AMIXER_MASTER_F_C; 246 case MIXER_PCM_P: return AMIXER_PCM_F; 247 case MIXER_PCM_C: 248 case MIXER_PCM_C_S: return AMIXER_PCM_F_C; 249 case MIXER_LINEIN_P: return AMIXER_LINEIN; 250 case MIXER_LINEIN_C: 251 case MIXER_LINEIN_C_S: return AMIXER_LINEIN_C; 252 case MIXER_MIC_P: return AMIXER_MIC; 253 case MIXER_MIC_C: 254 case MIXER_MIC_C_S: return AMIXER_MIC_C; 255 case MIXER_SPDIFI_P: return AMIXER_SPDIFI; 256 case MIXER_SPDIFI_C: 257 case MIXER_SPDIFI_C_S: return AMIXER_SPDIFI_C; 258 case MIXER_SPDIFO_P: return AMIXER_SPDIFO; 259 case MIXER_WAVEF_P: return AMIXER_WAVE_F; 260 case MIXER_WAVES_P: return AMIXER_WAVE_S; 261 case MIXER_WAVEC_P: return AMIXER_WAVE_C; 262 case MIXER_WAVER_P: return AMIXER_WAVE_R; 263 default: return NUM_CT_AMIXERS; 264 } 265} 266 267static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index) 268{ 269 switch (index) { 270 case AMIXER_MASTER_F: return AMIXER_MASTER_F_C; 271 case AMIXER_PCM_F: return AMIXER_PCM_F_C; 272 case AMIXER_SPDIFI: return AMIXER_SPDIFI_C; 273 case AMIXER_LINEIN: return AMIXER_LINEIN_C; 274 case AMIXER_MIC: return AMIXER_MIC_C; 275 default: return NUM_CT_AMIXERS; 276 } 277} 278 279static unsigned char 280get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type) 281{ 282 return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START))) 283 ? 1 : 0; 284} 285 286static void 287set_switch_state(struct ct_mixer *mixer, 288 enum CTALSA_MIXER_CTL type, unsigned char state) 289{ 290 if (state) 291 mixer->switch_state |= (0x1 << (type - SWH_MIXER_START)); 292 else 293 mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START)); 294} 295 296 297#define VOL_SCALE 0x1c 298#define VOL_MAX 0x100 299 300static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1); 301 302static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol, 303 struct snd_ctl_elem_info *uinfo) 304{ 305 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 306 uinfo->count = 2; 307 uinfo->value.integer.min = 0; 308 uinfo->value.integer.max = VOL_MAX; 309 310 return 0; 311} 312 313static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol, 314 struct snd_ctl_elem_value *ucontrol) 315{ 316 struct ct_atc *atc = snd_kcontrol_chip(kcontrol); 317 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value); 318 struct amixer *amixer; 319 int i, val; 320 321 for (i = 0; i < 2; i++) { 322 amixer = ((struct ct_mixer *)atc->mixer)-> 323 amixers[type*CHN_NUM+i]; 324 val = amixer->ops->get_scale(amixer) / VOL_SCALE; 325 if (val < 0) 326 val = 0; 327 else if (val > VOL_MAX) 328 val = VOL_MAX; 329 ucontrol->value.integer.value[i] = val; 330 } 331 332 return 0; 333} 334 335static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol, 336 struct snd_ctl_elem_value *ucontrol) 337{ 338 struct ct_atc *atc = snd_kcontrol_chip(kcontrol); 339 struct ct_mixer *mixer = atc->mixer; 340 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value); 341 struct amixer *amixer; 342 int i, j, val, oval, change = 0; 343 344 for (i = 0; i < 2; i++) { 345 val = ucontrol->value.integer.value[i]; 346 if (val < 0) 347 val = 0; 348 else if (val > VOL_MAX) 349 val = VOL_MAX; 350 val *= VOL_SCALE; 351 amixer = mixer->amixers[type*CHN_NUM+i]; 352 oval = amixer->ops->get_scale(amixer); 353 if (val != oval) { 354 amixer->ops->set_scale(amixer, val); 355 amixer->ops->commit_write(amixer); 356 change = 1; 357 /* Synchronize Master/PCM playback AMIXERs. */ 358 if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) { 359 for (j = 1; j < 4; j++) { 360 amixer = mixer-> 361 amixers[(type+j)*CHN_NUM+i]; 362 amixer->ops->set_scale(amixer, val); 363 amixer->ops->commit_write(amixer); 364 } 365 } 366 } 367 } 368 369 return change; 370} 371 372static struct snd_kcontrol_new vol_ctl = { 373 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 374 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 375 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 376 .info = ct_alsa_mix_volume_info, 377 .get = ct_alsa_mix_volume_get, 378 .put = ct_alsa_mix_volume_put, 379 .tlv = { .p = ct_vol_db_scale }, 380}; 381 382static void 383do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) 384{ 385 386 if (MIXER_LINEIN_C_S == type) { 387 atc->select_line_in(atc); 388 set_switch_state(atc->mixer, MIXER_MIC_C_S, 0); 389 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, 390 &kctls[1]->id); 391 } else if (MIXER_MIC_C_S == type) { 392 atc->select_mic_in(atc); 393 set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0); 394 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, 395 &kctls[0]->id); 396 } 397} 398 399static void 400do_digit_io_switch(struct ct_atc *atc, int state) 401{ 402 struct ct_mixer *mixer = atc->mixer; 403 404 if (state) { 405 atc->select_digit_io(atc); 406 atc->spdif_out_unmute(atc, 407 get_switch_state(mixer, MIXER_SPDIFO_P_S)); 408 atc->spdif_in_unmute(atc, 1); 409 atc->line_in_unmute(atc, 0); 410 return; 411 } 412 413 if (get_switch_state(mixer, MIXER_LINEIN_C_S)) 414 atc->select_line_in(atc); 415 else if (get_switch_state(mixer, MIXER_MIC_C_S)) 416 atc->select_mic_in(atc); 417 418 atc->spdif_out_unmute(atc, 0); 419 atc->spdif_in_unmute(atc, 0); 420 atc->line_in_unmute(atc, 1); 421 return; 422} 423 424static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) 425{ 426 struct ct_mixer *mixer = atc->mixer; 427 428 /* Do changes in mixer. */ 429 if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { 430 if (state) { 431 ct_mixer_recording_select(mixer, 432 get_amixer_index(type)); 433 } else { 434 ct_mixer_recording_unselect(mixer, 435 get_amixer_index(type)); 436 } 437 } 438 /* Do changes out of mixer. */ 439 if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) 440 do_line_mic_switch(atc, type); 441 else if (MIXER_WAVEF_P_S == type) 442 atc->line_front_unmute(atc, state); 443 else if (MIXER_WAVES_P_S == type) 444 atc->line_surround_unmute(atc, state); 445 else if (MIXER_WAVEC_P_S == type) 446 atc->line_clfe_unmute(atc, state); 447 else if (MIXER_WAVER_P_S == type) 448 atc->line_rear_unmute(atc, state); 449 else if (MIXER_LINEIN_P_S == type) 450 atc->line_in_unmute(atc, state); 451 else if (MIXER_SPDIFO_P_S == type) 452 atc->spdif_out_unmute(atc, state); 453 else if (MIXER_SPDIFI_P_S == type) 454 atc->spdif_in_unmute(atc, state); 455 else if (MIXER_DIGITAL_IO_S == type) 456 do_digit_io_switch(atc, state); 457 458 return; 459} 460 461static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol, 462 struct snd_ctl_elem_info *uinfo) 463{ 464 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 465 uinfo->count = 1; 466 uinfo->value.integer.min = 0; 467 uinfo->value.integer.max = 1; 468 uinfo->value.integer.step = 1; 469 470 return 0; 471} 472 473static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol, 474 struct snd_ctl_elem_value *ucontrol) 475{ 476 struct ct_mixer *mixer = 477 ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer; 478 enum CTALSA_MIXER_CTL type = kcontrol->private_value; 479 480 ucontrol->value.integer.value[0] = get_switch_state(mixer, type); 481 return 0; 482} 483 484static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol, 485 struct snd_ctl_elem_value *ucontrol) 486{ 487 struct ct_atc *atc = snd_kcontrol_chip(kcontrol); 488 struct ct_mixer *mixer = atc->mixer; 489 enum CTALSA_MIXER_CTL type = kcontrol->private_value; 490 int state; 491 492 state = ucontrol->value.integer.value[0]; 493 if (get_switch_state(mixer, type) == state) 494 return 0; 495 496 set_switch_state(mixer, type, state); 497 do_switch(atc, type, state); 498 499 return 1; 500} 501 502static struct snd_kcontrol_new swh_ctl = { 503 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 504 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 505 .info = ct_alsa_mix_switch_info, 506 .get = ct_alsa_mix_switch_get, 507 .put = ct_alsa_mix_switch_put 508}; 509 510static int ct_spdif_info(struct snd_kcontrol *kcontrol, 511 struct snd_ctl_elem_info *uinfo) 512{ 513 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 514 uinfo->count = 1; 515 return 0; 516} 517 518static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol, 519 struct snd_ctl_elem_value *ucontrol) 520{ 521 ucontrol->value.iec958.status[0] = 0xff; 522 ucontrol->value.iec958.status[1] = 0xff; 523 ucontrol->value.iec958.status[2] = 0xff; 524 ucontrol->value.iec958.status[3] = 0xff; 525 return 0; 526} 527 528static int ct_spdif_default_get(struct snd_kcontrol *kcontrol, 529 struct snd_ctl_elem_value *ucontrol) 530{ 531 unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF; 532 533 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; 534 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; 535 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; 536 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; 537 538 return 0; 539} 540 541static int ct_spdif_get(struct snd_kcontrol *kcontrol, 542 struct snd_ctl_elem_value *ucontrol) 543{ 544 struct ct_atc *atc = snd_kcontrol_chip(kcontrol); 545 unsigned int status; 546 547 atc->spdif_out_get_status(atc, &status); 548 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; 549 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; 550 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; 551 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; 552 553 return 0; 554} 555 556static int ct_spdif_put(struct snd_kcontrol *kcontrol, 557 struct snd_ctl_elem_value *ucontrol) 558{ 559 struct ct_atc *atc = snd_kcontrol_chip(kcontrol); 560 int change; 561 unsigned int status, old_status; 562 563 status = (ucontrol->value.iec958.status[0] << 0) | 564 (ucontrol->value.iec958.status[1] << 8) | 565 (ucontrol->value.iec958.status[2] << 16) | 566 (ucontrol->value.iec958.status[3] << 24); 567 568 atc->spdif_out_get_status(atc, &old_status); 569 change = (old_status != status); 570 if (change) 571 atc->spdif_out_set_status(atc, status); 572 573 return change; 574} 575 576static struct snd_kcontrol_new iec958_mask_ctl = { 577 .access = SNDRV_CTL_ELEM_ACCESS_READ, 578 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 579 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), 580 .count = 1, 581 .info = ct_spdif_info, 582 .get = ct_spdif_get_mask, 583 .private_value = MIXER_IEC958_MASK 584}; 585 586static struct snd_kcontrol_new iec958_default_ctl = { 587 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 588 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), 589 .count = 1, 590 .info = ct_spdif_info, 591 .get = ct_spdif_default_get, 592 .put = ct_spdif_put, 593 .private_value = MIXER_IEC958_DEFAULT 594}; 595 596static struct snd_kcontrol_new iec958_ctl = { 597 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 598 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 599 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), 600 .count = 1, 601 .info = ct_spdif_info, 602 .get = ct_spdif_get, 603 .put = ct_spdif_put, 604 .private_value = MIXER_IEC958_STREAM 605}; 606 607#define NUM_IEC958_CTL 3 608 609static int 610ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new) 611{ 612 struct snd_kcontrol *kctl; 613 int err; 614 615 kctl = snd_ctl_new1(new, mixer->atc); 616 if (!kctl) 617 return -ENOMEM; 618 619 if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface) 620 kctl->id.device = IEC958; 621 622 err = snd_ctl_add(mixer->atc->card, kctl); 623 if (err) 624 return err; 625 626 switch (new->private_value) { 627 case MIXER_LINEIN_C_S: 628 kctls[0] = kctl; break; 629 case MIXER_MIC_C_S: 630 kctls[1] = kctl; break; 631 default: 632 break; 633 } 634 635 return 0; 636} 637 638static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) 639{ 640 enum CTALSA_MIXER_CTL type; 641 struct ct_atc *atc = mixer->atc; 642 int err; 643 644 /* Create snd kcontrol instances on demand */ 645 for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) { 646 if (ct_kcontrol_init_table[type].ctl) { 647 vol_ctl.name = ct_kcontrol_init_table[type].name; 648 vol_ctl.private_value = (unsigned long)type; 649 err = ct_mixer_kcontrol_new(mixer, &vol_ctl); 650 if (err) 651 return err; 652 } 653 } 654 655 ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = 656 atc->have_digit_io_switch(atc); 657 for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { 658 if (ct_kcontrol_init_table[type].ctl) { 659 swh_ctl.name = ct_kcontrol_init_table[type].name; 660 swh_ctl.private_value = (unsigned long)type; 661 err = ct_mixer_kcontrol_new(mixer, &swh_ctl); 662 if (err) 663 return err; 664 } 665 } 666 667 err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl); 668 if (err) 669 return err; 670 671 err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl); 672 if (err) 673 return err; 674 675 err = ct_mixer_kcontrol_new(mixer, &iec958_ctl); 676 if (err) 677 return err; 678 679 atc->line_front_unmute(atc, 1); 680 set_switch_state(mixer, MIXER_WAVEF_P_S, 1); 681 atc->line_surround_unmute(atc, 0); 682 set_switch_state(mixer, MIXER_WAVES_P_S, 0); 683 atc->line_clfe_unmute(atc, 0); 684 set_switch_state(mixer, MIXER_WAVEC_P_S, 0); 685 atc->line_rear_unmute(atc, 0); 686 set_switch_state(mixer, MIXER_WAVER_P_S, 0); 687 atc->spdif_out_unmute(atc, 0); 688 set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); 689 atc->line_in_unmute(atc, 0); 690 set_switch_state(mixer, MIXER_LINEIN_P_S, 0); 691 atc->spdif_in_unmute(atc, 0); 692 set_switch_state(mixer, MIXER_SPDIFI_P_S, 0); 693 694 set_switch_state(mixer, MIXER_PCM_C_S, 1); 695 set_switch_state(mixer, MIXER_LINEIN_C_S, 1); 696 set_switch_state(mixer, MIXER_SPDIFI_C_S, 1); 697 698 return 0; 699} 700 701static void 702ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type) 703{ 704 struct amixer *amix_d; 705 struct sum *sum_c; 706 int i; 707 708 for (i = 0; i < 2; i++) { 709 amix_d = mixer->amixers[type*CHN_NUM+i]; 710 sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i]; 711 amix_d->ops->set_sum(amix_d, sum_c); 712 amix_d->ops->commit_write(amix_d); 713 } 714} 715 716static void 717ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type) 718{ 719 struct amixer *amix_d; 720 int i; 721 722 for (i = 0; i < 2; i++) { 723 amix_d = mixer->amixers[type*CHN_NUM+i]; 724 amix_d->ops->set_sum(amix_d, NULL); 725 amix_d->ops->commit_write(amix_d); 726 } 727} 728 729static int ct_mixer_get_resources(struct ct_mixer *mixer) 730{ 731 struct sum_mgr *sum_mgr; 732 struct sum *sum; 733 struct sum_desc sum_desc = {0}; 734 struct amixer_mgr *amixer_mgr; 735 struct amixer *amixer; 736 struct amixer_desc am_desc = {0}; 737 int err; 738 int i; 739 740 /* Allocate sum resources for mixer obj */ 741 sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; 742 sum_desc.msr = mixer->atc->msr; 743 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { 744 err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum); 745 if (err) { 746 printk(KERN_ERR "ctxfi:Failed to get sum resources for " 747 "front output!\n"); 748 break; 749 } 750 mixer->sums[i] = sum; 751 } 752 if (err) 753 goto error1; 754 755 /* Allocate amixer resources for mixer obj */ 756 amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER]; 757 am_desc.msr = mixer->atc->msr; 758 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { 759 err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer); 760 if (err) { 761 printk(KERN_ERR "ctxfi:Failed to get amixer resources " 762 "for mixer obj!\n"); 763 break; 764 } 765 mixer->amixers[i] = amixer; 766 } 767 if (err) 768 goto error2; 769 770 return 0; 771 772error2: 773 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { 774 if (NULL != mixer->amixers[i]) { 775 amixer = mixer->amixers[i]; 776 amixer_mgr->put_amixer(amixer_mgr, amixer); 777 mixer->amixers[i] = NULL; 778 } 779 } 780error1: 781 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { 782 if (NULL != mixer->sums[i]) { 783 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]); 784 mixer->sums[i] = NULL; 785 } 786 } 787 788 return err; 789} 790 791static int ct_mixer_get_mem(struct ct_mixer **rmixer) 792{ 793 struct ct_mixer *mixer; 794 int err; 795 796 *rmixer = NULL; 797 /* Allocate mem for mixer obj */ 798 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); 799 if (!mixer) 800 return -ENOMEM; 801 802 mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM), 803 GFP_KERNEL); 804 if (!mixer->amixers) { 805 err = -ENOMEM; 806 goto error1; 807 } 808 mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL); 809 if (!mixer->sums) { 810 err = -ENOMEM; 811 goto error2; 812 } 813 814 *rmixer = mixer; 815 return 0; 816 817error2: 818 kfree(mixer->amixers); 819error1: 820 kfree(mixer); 821 return err; 822} 823 824static int ct_mixer_topology_build(struct ct_mixer *mixer) 825{ 826 struct sum *sum; 827 struct amixer *amix_d, *amix_s; 828 enum CT_AMIXER_CTL i, j; 829 830 /* Build topology from destination to source */ 831 832 /* Set up Master mixer */ 833 for (i = AMIXER_MASTER_F, j = SUM_IN_F; 834 i <= AMIXER_MASTER_S; i++, j++) { 835 amix_d = mixer->amixers[i*CHN_NUM]; 836 sum = mixer->sums[j*CHN_NUM]; 837 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); 838 amix_d = mixer->amixers[i*CHN_NUM+1]; 839 sum = mixer->sums[j*CHN_NUM+1]; 840 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); 841 } 842 843 /* Set up Wave-out mixer */ 844 for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F; 845 i <= AMIXER_WAVE_S; i++, j++) { 846 amix_d = mixer->amixers[i*CHN_NUM]; 847 amix_s = mixer->amixers[j*CHN_NUM]; 848 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); 849 amix_d = mixer->amixers[i*CHN_NUM+1]; 850 amix_s = mixer->amixers[j*CHN_NUM+1]; 851 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); 852 } 853 854 /* Set up S/PDIF-out mixer */ 855 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM]; 856 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM]; 857 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); 858 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1]; 859 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1]; 860 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL); 861 862 /* Set up PCM-in mixer */ 863 for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) { 864 amix_d = mixer->amixers[i*CHN_NUM]; 865 sum = mixer->sums[j*CHN_NUM]; 866 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 867 amix_d = mixer->amixers[i*CHN_NUM+1]; 868 sum = mixer->sums[j*CHN_NUM+1]; 869 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 870 } 871 872 /* Set up Line-in mixer */ 873 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM]; 874 sum = mixer->sums[SUM_IN_F*CHN_NUM]; 875 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 876 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1]; 877 sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; 878 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 879 880 /* Set up Mic-in mixer */ 881 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM]; 882 sum = mixer->sums[SUM_IN_F*CHN_NUM]; 883 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 884 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1]; 885 sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; 886 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 887 888 /* Set up S/PDIF-in mixer */ 889 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM]; 890 sum = mixer->sums[SUM_IN_F*CHN_NUM]; 891 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 892 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1]; 893 sum = mixer->sums[SUM_IN_F*CHN_NUM+1]; 894 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 895 896 /* Set up Master recording mixer */ 897 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM]; 898 sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; 899 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); 900 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1]; 901 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; 902 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL); 903 904 /* Set up PCM-in recording mixer */ 905 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM]; 906 sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; 907 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 908 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1]; 909 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; 910 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 911 912 /* Set up Line-in recording mixer */ 913 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM]; 914 sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; 915 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 916 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1]; 917 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; 918 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 919 920 /* Set up Mic-in recording mixer */ 921 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM]; 922 sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; 923 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 924 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1]; 925 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; 926 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 927 928 /* Set up S/PDIF-in recording mixer */ 929 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM]; 930 sum = mixer->sums[SUM_IN_F_C*CHN_NUM]; 931 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 932 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1]; 933 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1]; 934 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum); 935 936 return 0; 937} 938 939static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc) 940{ 941 amixer->ops->set_input(amixer, rsc); 942 amixer->ops->commit_write(amixer); 943 944 return 0; 945} 946 947static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type) 948{ 949 switch (type) { 950 case MIX_WAVE_FRONT: return AMIXER_WAVE_F; 951 case MIX_WAVE_SURROUND: return AMIXER_WAVE_S; 952 case MIX_WAVE_CENTLFE: return AMIXER_WAVE_C; 953 case MIX_WAVE_REAR: return AMIXER_WAVE_R; 954 case MIX_PCMO_FRONT: return AMIXER_MASTER_F_C; 955 case MIX_SPDIF_OUT: return AMIXER_SPDIFO; 956 case MIX_LINE_IN: return AMIXER_LINEIN; 957 case MIX_MIC_IN: return AMIXER_MIC; 958 case MIX_SPDIF_IN: return AMIXER_SPDIFI; 959 case MIX_PCMI_FRONT: return AMIXER_PCM_F; 960 case MIX_PCMI_SURROUND: return AMIXER_PCM_S; 961 case MIX_PCMI_CENTLFE: return AMIXER_PCM_C; 962 case MIX_PCMI_REAR: return AMIXER_PCM_R; 963 default: return 0; 964 } 965} 966 967static int mixer_get_output_ports(struct ct_mixer *mixer, 968 enum MIXER_PORT_T type, 969 struct rsc **rleft, struct rsc **rright) 970{ 971 enum CT_AMIXER_CTL amix = port_to_amixer(type); 972 973 if (NULL != rleft) 974 *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc; 975 976 if (NULL != rright) 977 *rright = 978 &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc; 979 980 return 0; 981} 982 983static int mixer_set_input_left(struct ct_mixer *mixer, 984 enum MIXER_PORT_T type, struct rsc *rsc) 985{ 986 enum CT_AMIXER_CTL amix = port_to_amixer(type); 987 988 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc); 989 amix = get_recording_amixer(amix); 990 if (amix < NUM_CT_AMIXERS) 991 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc); 992 993 return 0; 994} 995 996static int 997mixer_set_input_right(struct ct_mixer *mixer, 998 enum MIXER_PORT_T type, struct rsc *rsc) 999{ 1000 enum CT_AMIXER_CTL amix = port_to_amixer(type); 1001 1002 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc); 1003 amix = get_recording_amixer(amix); 1004 if (amix < NUM_CT_AMIXERS) 1005 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc); 1006 1007 return 0; 1008} 1009 1010#ifdef CONFIG_PM 1011static int mixer_resume(struct ct_mixer *mixer) 1012{ 1013 int i, state; 1014 struct amixer *amixer; 1015 1016 /* resume topology and volume gain. */ 1017 for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) { 1018 amixer = mixer->amixers[i]; 1019 amixer->ops->commit_write(amixer); 1020 } 1021 1022 /* resume switch state. */ 1023 for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) { 1024 state = get_switch_state(mixer, i); 1025 do_switch(mixer->atc, i, state); 1026 } 1027 1028 return 0; 1029} 1030#endif 1031 1032int ct_mixer_destroy(struct ct_mixer *mixer) 1033{ 1034 struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; 1035 struct amixer_mgr *amixer_mgr = 1036 (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER]; 1037 struct amixer *amixer; 1038 int i = 0; 1039 1040 /* Release amixer resources */ 1041 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) { 1042 if (NULL != mixer->amixers[i]) { 1043 amixer = mixer->amixers[i]; 1044 amixer_mgr->put_amixer(amixer_mgr, amixer); 1045 } 1046 } 1047 1048 /* Release sum resources */ 1049 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) { 1050 if (NULL != mixer->sums[i]) 1051 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]); 1052 } 1053 1054 /* Release mem assigned to mixer object */ 1055 kfree(mixer->sums); 1056 kfree(mixer->amixers); 1057 kfree(mixer); 1058 1059 return 0; 1060} 1061 1062int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer) 1063{ 1064 struct ct_mixer *mixer; 1065 int err; 1066 1067 *rmixer = NULL; 1068 1069 /* Allocate mem for mixer obj */ 1070 err = ct_mixer_get_mem(&mixer); 1071 if (err) 1072 return err; 1073 1074 mixer->switch_state = 0; 1075 mixer->atc = atc; 1076 /* Set operations */ 1077 mixer->get_output_ports = mixer_get_output_ports; 1078 mixer->set_input_left = mixer_set_input_left; 1079 mixer->set_input_right = mixer_set_input_right; 1080#ifdef CONFIG_PM 1081 mixer->resume = mixer_resume; 1082#endif 1083 1084 /* Allocate chip resources for mixer obj */ 1085 err = ct_mixer_get_resources(mixer); 1086 if (err) 1087 goto error; 1088 1089 /* Build internal mixer topology */ 1090 ct_mixer_topology_build(mixer); 1091 1092 *rmixer = mixer; 1093 1094 return 0; 1095 1096error: 1097 ct_mixer_destroy(mixer); 1098 return err; 1099} 1100 1101int ct_alsa_mix_create(struct ct_atc *atc, 1102 enum CTALSADEVS device, 1103 const char *device_name) 1104{ 1105 int err; 1106 1107 /* Create snd kcontrol instances on demand */ 1108 /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */ 1109 err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer); 1110 if (err) 1111 return err; 1112 1113 strcpy(atc->card->mixername, device_name); 1114 1115 return 0; 1116} 1117