Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 009b8f97 authored by Connor McAdams's avatar Connor McAdams Committed by Takashi Iwai
Browse files

ALSA: hda/ca0132: update core functions for sbz + r3di



This patch updates core functions to accommodate the Sound Blaster Z and
Recon3Di by changing which functions they use. It also adds the ability
to enable/disable streams.

Signed-off-by: default avatarConnor McAdams <conmanx360@gmail.com>
Reviewed-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e93ac30a
Loading
Loading
Loading
Loading
+153 −23
Original line number Diff line number Diff line
@@ -774,6 +774,13 @@ struct ca0132_spec {
	 * switching, and other unknown commands.
	 */
	void __iomem *mem_base;

	/*
	 * Whether or not to use the alt functions like alt_select_out,
	 * alt_select_in, etc. Only used on desktop codecs for now, because of
	 * surround sound support.
	 */
	bool use_alt_functions;
};

/*
@@ -1113,6 +1120,42 @@ static void chipio_set_control_param(struct hda_codec *codec,
	}
}

/*
 * Set chip parameters through the chip I/O widget. NO MUTEX.
 */
static void chipio_set_control_param_no_mutex(struct hda_codec *codec,
		enum control_param_id param_id, int param_val)
{
	int val;

	if ((param_id < 32) && (param_val < 8)) {
		val = (param_val << 5) | (param_id);
		snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
				    VENDOR_CHIPIO_PARAM_SET, val);
	} else {
		if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) {
			snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
					    VENDOR_CHIPIO_PARAM_EX_ID_SET,
					    param_id);
			snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
					    VENDOR_CHIPIO_PARAM_EX_VALUE_SET,
					    param_val);
		}
	}
}

/*
 * Enable/Disable audio stream.
 */
static void chipio_set_stream_control(struct hda_codec *codec,
				int streamid, int enable)
{
	chipio_set_control_param_no_mutex(codec,
			CONTROL_PARAM_STREAM_ID, streamid);
	chipio_set_control_param_no_mutex(codec,
			CONTROL_PARAM_STREAM_CONTROL, enable);
}

/*
 * Set sampling rate of the connection point.
 */
@@ -2631,8 +2674,9 @@ static int dspxfr_image(struct hda_codec *codec,
 */
static void dspload_post_setup(struct hda_codec *codec)
{
	struct ca0132_spec *spec = codec->spec;
	codec_dbg(codec, "---- dspload_post_setup ------\n");

	if (!spec->use_alt_functions) {
		/*set DSP speaker to 2.0 configuration*/
		chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
		chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
@@ -2640,6 +2684,7 @@ static void dspload_post_setup(struct hda_codec *codec)
		/*update write pointer*/
		chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
	}
}

/**
 * dspload_image - Download DSP from a DSP Image Fast Load structure.
@@ -3527,7 +3572,7 @@ static int ca0132_voicefx_set(struct hda_codec *codec, int enable)
static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
{
	struct ca0132_spec *spec = codec->spec;
	unsigned int on;
	unsigned int on, tmp;
	int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
	int err = 0;
	int idx = nid - EFFECT_START_NID;
@@ -3551,6 +3596,39 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
		/* Voice Focus applies to 2-ch Mic, Digital Mic */
		if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC))
			val = 0;

		/* If Voice Focus on SBZ, set to two channel. */
		if ((nid == VOICE_FOCUS) && (spec->quirk == QUIRK_SBZ)) {
			if (spec->effects_switch[CRYSTAL_VOICE -
						 EFFECT_START_NID]) {

				if (spec->effects_switch[VOICE_FOCUS -
							 EFFECT_START_NID]) {
					tmp = FLOAT_TWO;
					val = 1;
				} else
					tmp = FLOAT_ONE;

				dspio_set_uint_param(codec, 0x80, 0x00, tmp);
			}
		}
		/*
		 * For SBZ noise reduction, there's an extra command
		 * to module ID 0x47. No clue why.
		 */
		if ((nid == NOISE_REDUCTION) && (spec->quirk == QUIRK_SBZ)) {
			if (spec->effects_switch[CRYSTAL_VOICE -
						 EFFECT_START_NID]) {
				if (spec->effects_switch[NOISE_REDUCTION -
							 EFFECT_START_NID])
					tmp = FLOAT_ONE;
				else
					tmp = FLOAT_ZERO;
			} else
				tmp = FLOAT_ZERO;

			dspio_set_uint_param(codec, 0x47, 0x00, tmp);
		}
	}

	codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n",
@@ -4185,12 +4263,16 @@ static int ca0132_build_pcms(struct hda_codec *codec)
	info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];

	/* With the DSP enabled, desktops don't use this ADC. */
	if (spec->use_alt_functions) {
		info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
		if (!info)
			return -ENOMEM;
	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
		info->stream[SNDRV_PCM_STREAM_CAPTURE] =
			ca0132_pcm_analog_capture;
		info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
	}

	info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear");
	if (!info)
@@ -4445,19 +4527,49 @@ static void ca0132_setup_defaults(struct hda_codec *codec)
 */
static void ca0132_init_flags(struct hda_codec *codec)
{
	struct ca0132_spec *spec = codec->spec;

	if (spec->use_alt_functions) {
		chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1);
		chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1);
		chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1);
		chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, 1);
		chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, 1);
		chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
	chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_COMMON_MODE, 0);
	chipio_set_control_flag(codec, CONTROL_FLAG_PORT_D_COMMON_MODE, 0);
	chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0);
	chipio_set_control_flag(codec, CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
		chipio_set_control_flag(codec, CONTROL_FLAG_SPDIF2OUT, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_A_10KOHM_LOAD, 1);
	} else {
		chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_A_COMMON_MODE, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_D_COMMON_MODE, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0);
		chipio_set_control_flag(codec,
				CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
		chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1);
	}
}

/*
 * Initialization of parameters in chip
 */
static void ca0132_init_params(struct hda_codec *codec)
{
	struct ca0132_spec *spec = codec->spec;

	if (spec->use_alt_functions) {
		chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
		chipio_set_conn_rate(codec, 0x0B, SR_48_000);
		chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0);
		chipio_set_control_param(codec, 0, 0);
		chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
	}

	chipio_set_control_param(codec, CONTROL_PARAM_PORTA_160OHM_GAIN, 6);
	chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6);
}
@@ -4558,7 +4670,8 @@ static void ca0132_download_dsp(struct hda_codec *codec)
			spec->dsp_state = DSP_DOWNLOADED;
	}

	if (spec->dsp_state == DSP_DOWNLOADED)
	/* For codecs using alt functions, this is already done earlier */
	if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions))
		ca0132_set_dsp_msr(codec, true);
}

@@ -4605,7 +4718,7 @@ static void ca0132_init_unsol(struct hda_codec *codec)
	snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
					    ca0132_process_dsp_response);
	/* Front headphone jack detection */
	if (spec->quirk == QUIRK_SBZ || spec->quirk == QUIRK_R3DI)
	if (spec->use_alt_functions)
		snd_hda_jack_detect_enable_callback(codec,
			spec->unsol_tag_front_hp, hp_callback);
}
@@ -4798,12 +4911,16 @@ static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir,

static void sbz_exit_chip(struct hda_codec *codec)
{
	chipio_set_stream_control(codec, 0x03, 0);
	chipio_set_stream_control(codec, 0x04, 0);

	/* Mess with GPIO */
	sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1);
	sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05);
	sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x01);

	chipio_set_stream_control(codec, 0x14, 0);
	chipio_set_stream_control(codec, 0x0C, 0);

	chipio_set_conn_rate(codec, 0x41, SR_192_000);
	chipio_set_conn_rate(codec, 0x91, SR_192_000);
@@ -4814,6 +4931,7 @@ static void sbz_exit_chip(struct hda_codec *codec)
	sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x07);
	sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06);

	chipio_set_stream_control(codec, 0x0C, 0);

	chipio_set_control_param(codec, 0x0D, 0x24);

@@ -5031,7 +5149,7 @@ static int ca0132_init(struct hda_codec *codec)

	init_input(codec, cfg->dig_in_pin, spec->dig_in);

	if (spec->quirk == QUIRK_ALIENWARE || spec->quirk == QUIRK_NONE) {
	if (!spec->use_alt_functions) {
		snd_hda_sequence_write(codec, spec->chip_init_verbs);
		snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
			    VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
@@ -5116,7 +5234,7 @@ static void ca0132_config(struct hda_codec *codec)
	spec->multiout.dac_nids = spec->dacs;
	spec->multiout.num_dacs = 3;

	if (spec->quirk == QUIRK_NONE || spec->quirk == QUIRK_ALIENWARE)
	if (!spec->use_alt_functions)
		spec->multiout.max_channels = 2;
	else
		spec->multiout.max_channels = 6;
@@ -5318,10 +5436,22 @@ static int patch_ca0132(struct hda_codec *codec)
			spec->quirk = QUIRK_NONE;
		}
	}

	spec->dsp_state = DSP_DOWNLOAD_INIT;
	spec->num_mixers = 1;
	spec->mixers[0] = ca0132_mixer;

	/* Setup whether or not to use alt functions */
	switch (spec->quirk) {
	case QUIRK_SBZ:
	case QUIRK_R3DI:
		spec->use_alt_functions = true;
		break;
	default:
		spec->use_alt_functions = false;
		break;
	}

	spec->base_init_verbs = ca0132_base_init_verbs;
	spec->base_exit_verbs = ca0132_base_exit_verbs;