* 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;
};
/*
}
}
+/*
+ * 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.
*/
*/
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);
+ }
}
/**
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;
/* 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",
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)
*/
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);
+ }
}
/*
*/
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);
}
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);
}
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);
}
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);
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);
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);
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;
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;