File Index
Files and directories
Sign in
FILE

ctmixer.c

File preview with syntax highlighting.

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