ALSA: Echoaudio - Add suspend support #2

This patch adds rearranges parts of the initialization code and adds
suspend and resume callbacks.

This patch adds suspend and resume callbacks.
It also rearranges parts of the initialization code so it can be
used in both the first initialization (when the module is loaded we
also have to load default settings) and the resume callback (where
we have to restore the previous settings).

Signed-off-by: Giuliano Pochini <pochini@shiny.it>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
index 031ef7e..64417a7 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.c
+++ b/sound/pci/echoaudio/echoaudio_dsp.c
@@ -497,9 +497,6 @@
 	if ((box_type = load_asic(chip)) < 0)
 		return box_type;	/* error */
 
-	if ((err = restore_dsp_rettings(chip)) < 0)
-		return err;
-
 	return box_type;
 }
 
@@ -659,25 +656,89 @@
 
 static int restore_dsp_rettings(struct echoaudio *chip)
 {
-	int err;
+	int i, o, err;
 	DE_INIT(("restore_dsp_settings\n"));
 
 	if ((err = check_asic_status(chip)) < 0)
 		return err;
 
-	/* @ Gina20/Darla20 only. Should be harmless for other cards. */
+	/* Gina20/Darla20 only. Should be harmless for other cards. */
 	chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF;
 	chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF;
 	chip->comm_page->handshake = 0xffffffff;
 
-	if ((err = set_sample_rate(chip, chip->sample_rate)) < 0)
+	/* Restore output busses */
+	for (i = 0; i < num_busses_out(chip); i++) {
+		err = set_output_gain(chip, i, chip->output_gain[i]);
+		if (err < 0)
+			return err;
+	}
+
+#ifdef ECHOCARD_HAS_VMIXER
+	for (i = 0; i < num_pipes_out(chip); i++)
+		for (o = 0; o < num_busses_out(chip); o++) {
+			err = set_vmixer_gain(chip, o, i,
+						chip->vmixer_gain[o][i]);
+			if (err < 0)
+				return err;
+		}
+	if (update_vmixer_level(chip) < 0)
+		return -EIO;
+#endif /* ECHOCARD_HAS_VMIXER */
+
+#ifdef ECHOCARD_HAS_MONITOR
+	for (o = 0; o < num_busses_out(chip); o++)
+		for (i = 0; i < num_busses_in(chip); i++) {
+			err = set_monitor_gain(chip, o, i,
+						chip->monitor_gain[o][i]);
+			if (err < 0)
+				return err;
+		}
+#endif /* ECHOCARD_HAS_MONITOR */
+
+#ifdef ECHOCARD_HAS_INPUT_GAIN
+	for (i = 0; i < num_busses_in(chip); i++) {
+		err = set_input_gain(chip, i, chip->input_gain[i]);
+		if (err < 0)
+			return err;
+	}
+#endif /* ECHOCARD_HAS_INPUT_GAIN */
+
+	err = update_output_line_level(chip);
+	if (err < 0)
 		return err;
 
-	if (chip->meters_enabled)
-		if (send_vector(chip, DSP_VC_METERS_ON) < 0)
-			return -EIO;
+	err = update_input_line_level(chip);
+	if (err < 0)
+		return err;
+
+	err = set_sample_rate(chip, chip->sample_rate);
+	if (err < 0)
+		return err;
+
+	if (chip->meters_enabled) {
+		err = send_vector(chip, DSP_VC_METERS_ON);
+		if (err < 0)
+			return err;
+	}
+
+#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH
+	if (set_digital_mode(chip, chip->digital_mode) < 0)
+		return -EIO;
+#endif
+
+#ifdef ECHOCARD_HAS_DIGITAL_IO
+	if (set_professional_spdif(chip, chip->professional_spdif) < 0)
+		return -EIO;
+#endif
+
+#ifdef ECHOCARD_HAS_PHANTOM_POWER
+	if (set_phantom_power(chip, chip->phantom_power) < 0)
+		return -EIO;
+#endif
 
 #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK
+	/* set_input_clock() also restores automute setting */
 	if (set_input_clock(chip, chip->input_clock) < 0)
 		return -EIO;
 #endif
@@ -687,23 +748,14 @@
 		return -EIO;
 #endif
 
-	if (update_output_line_level(chip) < 0)
-		return -EIO;
-
-	if (update_input_line_level(chip) < 0)
-		return -EIO;
-
-#ifdef ECHOCARD_HAS_VMIXER
-	if (update_vmixer_level(chip) < 0)
-		return -EIO;
-#endif
-
 	if (wait_handshake(chip) < 0)
 		return -EIO;
 	clear_handshake(chip);
+	if (send_vector(chip, DSP_VC_UPDATE_FLAGS) < 0)
+		return -EIO;
 
 	DE_INIT(("restore_dsp_rettings done\n"));
-	return send_vector(chip, DSP_VC_UPDATE_FLAGS);
+	return 0;
 }
 
 
@@ -920,9 +972,6 @@
 	chip->card_name = ECHOCARD_NAME;
 	chip->bad_board = TRUE;	/* Set TRUE until DSP loaded */
 	chip->dsp_code = NULL;	/* Current DSP code not loaded */
-	chip->digital_mode = DIGITAL_MODE_NONE;
-	chip->input_clock = ECHO_CLOCK_INTERNAL;
-	chip->output_clock = ECHO_CLOCK_WORD;
 	chip->asic_loaded = FALSE;
 	memset(chip->comm_page, 0, sizeof(struct comm_page));
 
@@ -933,7 +982,6 @@
 	chip->comm_page->midi_out_free_count =
 		cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE);
 	chip->comm_page->sample_rate = cpu_to_le32(44100);
-	chip->sample_rate = 44100;
 
 	/* Set line levels so we don't blast any inputs on startup */
 	memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE);
@@ -944,50 +992,21 @@
 
 
 
-/* This function initializes the several volume controls for busses and pipes.
-This MUST be called after the DSP is up and running ! */
+/* This function initializes the chip structure with default values, ie. all
+ * muted and internal clock source. Then it copies the settings to the DSP.
+ * This MUST be called after the DSP is up and running !
+ */
 static int init_line_levels(struct echoaudio *chip)
 {
-	int st, i, o;
-
 	DE_INIT(("init_line_levels\n"));
-
-	/* Mute output busses */
-	for (i = 0; i < num_busses_out(chip); i++)
-		if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED)))
-			return st;
-	if ((st = update_output_line_level(chip)))
-		return st;
-
-#ifdef ECHOCARD_HAS_VMIXER
-	/* Mute the Vmixer */
-	for (i = 0; i < num_pipes_out(chip); i++)
-		for (o = 0; o < num_busses_out(chip); o++)
-			if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED)))
-				return st;
-	if ((st = update_vmixer_level(chip)))
-		return st;
-#endif /* ECHOCARD_HAS_VMIXER */
-
-#ifdef ECHOCARD_HAS_MONITOR
-	/* Mute the monitor mixer */
-	for (o = 0; o < num_busses_out(chip); o++)
-		for (i = 0; i < num_busses_in(chip); i++)
-			if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED)))
-				return st;
-	if ((st = update_output_line_level(chip)))
-		return st;
-#endif /* ECHOCARD_HAS_MONITOR */
-
-#ifdef ECHOCARD_HAS_INPUT_GAIN
-	for (i = 0; i < num_busses_in(chip); i++)
-		if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED)))
-			return st;
-	if ((st = update_input_line_level(chip)))
-		return st;
-#endif /* ECHOCARD_HAS_INPUT_GAIN */
-
-	return 0;
+	memset(chip->output_gain, ECHOGAIN_MUTED, sizeof(chip->output_gain));
+	memset(chip->input_gain, ECHOGAIN_MUTED, sizeof(chip->input_gain));
+	memset(chip->monitor_gain, ECHOGAIN_MUTED, sizeof(chip->monitor_gain));
+	memset(chip->vmixer_gain, ECHOGAIN_MUTED, sizeof(chip->vmixer_gain));
+	chip->input_clock = ECHO_CLOCK_INTERNAL;
+	chip->output_clock = ECHO_CLOCK_WORD;
+	chip->sample_rate = 44100;
+	return restore_dsp_rettings(chip);
 }