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: Connor McAdams <conmanx360@gmail.com> Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
e93ac30a32
commit
009b8f979b
|
@ -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,14 +2674,16 @@ 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);
|
||||
|
||||
/*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);
|
||||
|
||||
/*update write pointer*/
|
||||
chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
|
||||
/*update write pointer*/
|
||||
chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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];
|
||||
|
||||
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].substreams = 1;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
|
||||
/* 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].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,12 +4527,32 @@ static void ca0132_setup_defaults(struct hda_codec *codec)
|
|||
*/
|
||||
static void ca0132_init_flags(struct hda_codec *codec)
|
||||
{
|
||||
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);
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4458,6 +4560,16 @@ static void ca0132_init_flags(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_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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue