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

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
...@@ -774,6 +774,13 @@ struct ca0132_spec { ...@@ -774,6 +774,13 @@ struct ca0132_spec {
* switching, and other unknown commands. * switching, and other unknown commands.
*/ */
void __iomem *mem_base; 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, ...@@ -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. * Set sampling rate of the connection point.
*/ */
...@@ -2631,14 +2674,16 @@ static int dspxfr_image(struct hda_codec *codec, ...@@ -2631,14 +2674,16 @@ static int dspxfr_image(struct hda_codec *codec,
*/ */
static void dspload_post_setup(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"); codec_dbg(codec, "---- dspload_post_setup ------\n");
if (!spec->use_alt_functions) {
/*set DSP speaker to 2.0 configuration*/ /*set DSP speaker to 2.0 configuration*/
chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000); chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
/*update write pointer*/ /*update write pointer*/
chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002); chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
}
} }
/** /**
...@@ -3527,7 +3572,7 @@ static int ca0132_voicefx_set(struct hda_codec *codec, int enable) ...@@ -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) static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
{ {
struct ca0132_spec *spec = codec->spec; struct ca0132_spec *spec = codec->spec;
unsigned int on; unsigned int on, tmp;
int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
int err = 0; int err = 0;
int idx = nid - EFFECT_START_NID; 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) ...@@ -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 */ /* Voice Focus applies to 2-ch Mic, Digital Mic */
if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC)) if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC))
val = 0; 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", 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) ...@@ -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].substreams = 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; 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"); info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
if (!info) if (!info)
return -ENOMEM; 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].substreams = 1;
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1]; info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
}
info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear"); info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear");
if (!info) if (!info)
...@@ -4445,12 +4527,32 @@ static void ca0132_setup_defaults(struct hda_codec *codec) ...@@ -4445,12 +4527,32 @@ static void ca0132_setup_defaults(struct hda_codec *codec)
*/ */
static void ca0132_init_flags(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_IDLE_ENABLE, 0);
chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_COMMON_MODE, 0); chipio_set_control_flag(codec, CONTROL_FLAG_SPDIF2OUT, 0);
chipio_set_control_flag(codec, CONTROL_FLAG_PORT_D_COMMON_MODE, 0); chipio_set_control_flag(codec,
chipio_set_control_flag(codec, CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0); CONTROL_FLAG_PORT_D_10KOHM_LOAD, 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); chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1);
}
} }
/* /*
...@@ -4458,6 +4560,16 @@ static void ca0132_init_flags(struct hda_codec *codec) ...@@ -4458,6 +4560,16 @@ static void ca0132_init_flags(struct hda_codec *codec)
*/ */
static void ca0132_init_params(struct hda_codec *codec) 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_PORTA_160OHM_GAIN, 6);
chipio_set_control_param(codec, CONTROL_PARAM_PORTD_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) ...@@ -4558,7 +4670,8 @@ static void ca0132_download_dsp(struct hda_codec *codec)
spec->dsp_state = DSP_DOWNLOADED; 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); ca0132_set_dsp_msr(codec, true);
} }
...@@ -4605,7 +4718,7 @@ static void ca0132_init_unsol(struct hda_codec *codec) ...@@ -4605,7 +4718,7 @@ static void ca0132_init_unsol(struct hda_codec *codec)
snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
ca0132_process_dsp_response); ca0132_process_dsp_response);
/* Front headphone jack detection */ /* 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, snd_hda_jack_detect_enable_callback(codec,
spec->unsol_tag_front_hp, hp_callback); spec->unsol_tag_front_hp, hp_callback);
} }
...@@ -4798,12 +4911,16 @@ static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir, ...@@ -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) 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 */ /* Mess with GPIO */
sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1); sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1);
sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05); sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05);
sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x01); 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, 0x41, SR_192_000);
chipio_set_conn_rate(codec, 0x91, 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) ...@@ -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, 0x07);
sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06); sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06);
chipio_set_stream_control(codec, 0x0C, 0);
chipio_set_control_param(codec, 0x0D, 0x24); chipio_set_control_param(codec, 0x0D, 0x24);
...@@ -5031,7 +5149,7 @@ static int ca0132_init(struct hda_codec *codec) ...@@ -5031,7 +5149,7 @@ static int ca0132_init(struct hda_codec *codec)
init_input(codec, cfg->dig_in_pin, spec->dig_in); 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_sequence_write(codec, spec->chip_init_verbs);
snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D); VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
...@@ -5116,7 +5234,7 @@ static void ca0132_config(struct hda_codec *codec) ...@@ -5116,7 +5234,7 @@ static void ca0132_config(struct hda_codec *codec)
spec->multiout.dac_nids = spec->dacs; spec->multiout.dac_nids = spec->dacs;
spec->multiout.num_dacs = 3; spec->multiout.num_dacs = 3;
if (spec->quirk == QUIRK_NONE || spec->quirk == QUIRK_ALIENWARE) if (!spec->use_alt_functions)
spec->multiout.max_channels = 2; spec->multiout.max_channels = 2;
else else
spec->multiout.max_channels = 6; spec->multiout.max_channels = 6;
...@@ -5318,10 +5436,22 @@ static int patch_ca0132(struct hda_codec *codec) ...@@ -5318,10 +5436,22 @@ static int patch_ca0132(struct hda_codec *codec)
spec->quirk = QUIRK_NONE; spec->quirk = QUIRK_NONE;
} }
} }
spec->dsp_state = DSP_DOWNLOAD_INIT; spec->dsp_state = DSP_DOWNLOAD_INIT;
spec->num_mixers = 1; spec->num_mixers = 1;
spec->mixers[0] = ca0132_mixer; 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_init_verbs = ca0132_base_init_verbs;
spec->base_exit_verbs = ca0132_base_exit_verbs; spec->base_exit_verbs = ca0132_base_exit_verbs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment