Commit 9b4a2273 authored by Harin Lee's avatar Harin Lee Committed by Takashi Iwai
Browse files

ALSA: ctxfi: Add support for dedicated RCA switching



Add feature to support switching between the dedicated RCA output and
the 7.1ch Front output. This is required for hardware that utilizes
separate DAC circuits for RCA and 7.1ch channels.

Changes:
 - Add dedicated_rca capability flag
 - Add "Analog Playback Route" mixer control
 - Implement logic to swap DAO inputs between RCA and Front ports

Signed-off-by: default avatarHarin Lee <me@harin.net>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20251124180501.2760421-6-me@harin.net
parent a2dbaeb5
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -987,6 +987,24 @@ static struct capabilities atc_capabilities(struct ct_atc *atc)
	return hw->capabilities(hw);
}

static void atc_dedicated_rca_select(struct ct_atc *atc)
{
	struct dao *dao;
	struct ct_mixer *mixer = atc->mixer;
	struct rsc *rscs[2] = {NULL};

	dao = container_of(atc->daios[atc->rca_state ? RCA : LINEO1],
		struct dao, daio);
	dao->ops->clear_left_input(dao);
	dao->ops->clear_right_input(dao);

	mixer->get_output_ports(mixer, MIX_WAVE_FRONT, &rscs[0], &rscs[1]);
	dao = container_of(atc->daios[atc->rca_state ? LINEO1 : RCA],
		struct dao, daio);
	dao->ops->set_left_input(dao, rscs[0]);
	dao->ops->set_right_input(dao, rscs[1]);
}

static int atc_output_switch_get(struct ct_atc *atc)
{
	struct hw *hw = atc->hw;
@@ -1088,6 +1106,11 @@ static int atc_mic_unmute(struct ct_atc *atc, unsigned char state)
	return atc_daio_unmute(atc, state, MIC);
}

static int atc_rca_unmute(struct ct_atc *atc, unsigned char state)
{
	return atc_daio_unmute(atc, state, RCA);
}

static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state)
{
	return atc_daio_unmute(atc, state, SPDIFOO);
@@ -1303,6 +1326,7 @@ static int atc_identify_card(struct ct_atc *atc, unsigned int ssid)
	dev_info(atc->card->dev, "chip %s model %s (%04x:%04x) is found\n",
		   atc->chip_name, atc->model_name,
		   vendor_id, device_id);
	atc->rca_state = 0;
	return 0;
}

@@ -1400,11 +1424,11 @@ static int atc_get_resources(struct ct_atc *atc)
	daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
	da_desc.msr = atc->msr;
	for (i = 0; i < NUM_DAIOTYP; i++) {
		if ((i == MIC) && !cap.dedicated_mic)
		if (((i == MIC) && !cap.dedicated_mic) || ((i == RCA) && !cap.dedicated_rca))
			continue;
		da_desc.type = (atc->model != CTSB073X) ? i :
			     ((i == SPDIFIO) ? SPDIFI1 : i);
		da_desc.output = i < LINEIM;
		da_desc.output = (i < LINEIM) || (i == RCA);
		err = daio_mgr->get_daio(daio_mgr, &da_desc,
					(struct daio **)&atc->daios[i]);
		if (err) {
@@ -1511,6 +1535,9 @@ static void atc_connect_resources(struct ct_atc *atc)
		dao->ops->set_right_input(dao, rscs[1]);
	}

	if (cap.dedicated_rca)
		atc_dedicated_rca_select(atc);

	dai = container_of(atc->daios[LINEIM], struct dai, daio);
	atc_connect_dai(atc->rsc_mgrs[SRC], dai,
			(struct src **)&atc->srcs[2],
@@ -1643,12 +1670,14 @@ static const struct ct_atc atc_preset = {
	.line_rear_unmute = atc_line_rear_unmute,
	.line_in_unmute = atc_line_in_unmute,
	.mic_unmute = atc_mic_unmute,
	.rca_unmute = atc_rca_unmute,
	.spdif_out_unmute = atc_spdif_out_unmute,
	.spdif_in_unmute = atc_spdif_in_unmute,
	.spdif_out_get_status = atc_spdif_out_get_status,
	.spdif_out_set_status = atc_spdif_out_set_status,
	.spdif_out_passthru = atc_spdif_out_passthru,
	.capabilities = atc_capabilities,
	.dedicated_rca_select = atc_dedicated_rca_select,
	.output_switch_get = atc_output_switch_get,
	.output_switch_put = atc_output_switch_put,
	.mic_source_switch_get = atc_mic_source_switch_get,
+4 −0
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@ struct ct_atc {
	const char *chip_name;
	const char *model_name;

	unsigned char rca_state; /* 0 = dedicated RCA, 1 = 7.1ch Front */

	struct ct_vm *vm; /* device virtual memory manager for this card */
	int (*map_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
	void (*unmap_audio_buffer)(struct ct_atc *atc, struct ct_atc_pcm *apcm);
@@ -113,12 +115,14 @@ struct ct_atc {
	int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state);
	int (*line_in_unmute)(struct ct_atc *atc, unsigned char state);
	int (*mic_unmute)(struct ct_atc *atc, unsigned char state);
	int (*rca_unmute)(struct ct_atc *atc, unsigned char state);
	int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state);
	int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state);
	int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status);
	int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status);
	int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state);
	struct capabilities (*capabilities)(struct ct_atc *atc);
	void (*dedicated_rca_select)(struct ct_atc *atc);
	int (*output_switch_get)(struct ct_atc *atc);
	int (*output_switch_put)(struct ct_atc *atc, int position);
	int (*mic_source_switch_get)(struct ct_atc *atc);
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
	[LINEO4] = {.left = 0x70, .right = 0x71},
	[LINEIM] = {.left = 0x45, .right = 0xc5},
	[MIC]	 = {.left = 0x55, .right = 0xd5},
	[RCA]	 = {.left = 0x30, .right = 0x31},
	[SPDIFOO] = {.left = 0x00, .right = 0x01},
	[SPDIFIO] = {.left = 0x05, .right = 0x85},
};
@@ -123,6 +124,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
		case LINEO4:	return 6;
		case LINEIM:	return 4;
		case MIC:	return 5;
		case RCA:	return 3;
		default:	return -EINVAL;
		}
	default:
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ enum DAIOTYP {
	LINEIM,
	SPDIFIO,	/* S/PDIF In (Flexijack/Optical) on the card */
	MIC,		/* Dedicated mic on Titanium HD */
	RCA,
	SPDIFI1,	/* S/PDIF In on internal Drive Bay */
	NUM_DAIOTYP
};
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct card_conf {
struct capabilities {
	unsigned int digit_io_switch:1;
	unsigned int dedicated_mic:1;
	unsigned int dedicated_rca:1;
	unsigned int output_switch:1;
	unsigned int mic_source_switch:1;
};
Loading