diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index f9fafd0f725b..c3ae9e4f715b 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1863,6 +1863,18 @@ static void chipio_set_stream_control(struct hda_codec *codec, CONTROL_PARAM_STREAM_CONTROL, enable); } +/* + * Get ChipIO audio stream's status. + */ +static void chipio_get_stream_control(struct hda_codec *codec, + int streamid, unsigned int *enable) +{ + chipio_set_control_param_no_mutex(codec, + CONTROL_PARAM_STREAM_ID, streamid); + *enable = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0, + VENDOR_CHIPIO_PARAM_GET, + CONTROL_PARAM_STREAM_CONTROL); +} /* * Set sampling rate of the connection point. NO MUTEX. @@ -7513,6 +7525,109 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec) } } + +/* If there is an active channel for some reason, find it and free it. */ +static void ca0132_alt_free_active_dma_channels(struct hda_codec *codec) +{ + unsigned int i, tmp; + int status; + + /* Read active DSPDMAC channel register. */ + status = chipio_read(codec, DSPDMAC_CHNLSTART_MODULE_OFFSET, &tmp); + if (status >= 0) { + /* AND against 0xfff to get the active channel bits. */ + tmp = tmp & 0xfff; + + /* If there are no active channels, nothing to free. */ + if (!tmp) + return; + } else { + codec_dbg(codec, "%s: Failed to read active DSP DMA channel register.\n", + __func__); + return; + } + + /* + * Check each DSP DMA channel for activity, and if the channel is + * active, free it. + */ + for (i = 0; i < DSPDMAC_DMA_CFG_CHANNEL_COUNT; i++) { + if (dsp_is_dma_active(codec, i)) { + status = dspio_free_dma_chan(codec, i); + if (status < 0) + codec_dbg(codec, "%s: Failed to free active DSP DMA channel %d.\n", + __func__, i); + } + } +} + +/* + * In the case of CT_EXTENSIONS_ENABLE being set to 1, and the DSP being in + * use, audio is no longer routed directly to the DAC/ADC from the HDA stream. + * Instead, audio is now routed through the DSP's DMA controllers, which + * the DSP is tasked with setting up itself. Through debugging, it seems the + * cause of most of the no-audio on startup issues were due to improperly + * configured DSP DMA channels. + * + * Normally, the DSP configures these the first time an HDA audio stream is + * started post DSP firmware download. That is why creating a 'dummy' stream + * worked in fixing the audio in some cases. This works most of the time, but + * sometimes if a stream is started/stopped before the DSP can setup the DMA + * configuration registers, it ends up in a broken state. Issues can also + * arise if streams are started in an unusual order, i.e the audio output dma + * channel being sandwiched between the mic1 and mic2 dma channels. + * + * The solution to this is to make sure that the DSP has no DMA channels + * in use post DSP firmware download, and then to manually start each default + * DSP stream that uses the DMA channels. These are 0x0c, the audio output + * stream, 0x03, analog mic 1, and 0x04, analog mic 2. + */ +static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) +{ + const unsigned int dsp_dma_stream_ids[] = { 0x0c, 0x03, 0x04 }; + struct ca0132_spec *spec = codec->spec; + unsigned int i, tmp; + + /* + * Check if any of the default streams are active, and if they are, + * stop them. + */ + mutex_lock(&spec->chipio_mutex); + + for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { + chipio_get_stream_control(codec, dsp_dma_stream_ids[i], &tmp); + + if (tmp) { + chipio_set_stream_control(codec, + dsp_dma_stream_ids[i], 0); + } + } + + mutex_unlock(&spec->chipio_mutex); + + /* + * If all DSP streams are inactive, there should be no active DSP DMA + * channels. Check and make sure this is the case, and if it isn't, + * free any active channels. + */ + ca0132_alt_free_active_dma_channels(codec); + + mutex_lock(&spec->chipio_mutex); + + /* Make sure stream 0x0c is six channels. */ + chipio_set_stream_channels(codec, 0x0c, 6); + + for (i = 0; i < ARRAY_SIZE(dsp_dma_stream_ids); i++) { + chipio_set_stream_control(codec, + dsp_dma_stream_ids[i], 1); + + /* Give the DSP some time to setup the DMA channel. */ + msleep(75); + } + + mutex_unlock(&spec->chipio_mutex); +} + /* * The region of ChipIO memory from 0x190000-0x1903fc is a sort of 'audio * router', where each entry represents a 48khz audio channel, with a format @@ -8250,6 +8365,7 @@ static void r3d_setup_defaults(struct hda_codec *codec) ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); /*remove DSP headroom*/ tmp = FLOAT_ZERO; @@ -8300,6 +8416,7 @@ static void sbz_setup_defaults(struct hda_codec *codec) ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); sbz_connect_streams(codec); sbz_chipio_startup_data(codec); @@ -8359,6 +8476,7 @@ static void ae5_setup_defaults(struct hda_codec *codec) ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); chipio_set_stream_control(codec, 0x03, 1); chipio_set_stream_control(codec, 0x04, 1); @@ -8428,6 +8546,7 @@ static void ae7_setup_defaults(struct hda_codec *codec) ca0132_alt_dsp_scp_startup(codec); ca0132_alt_init_analog_mics(codec); + ca0132_alt_start_dsp_audio_streams(codec); ae7_post_dsp_setup_ports(codec); tmp = FLOAT_ZERO; |