xref: /linux/sound/pci/echoaudio/indigodj_dsp.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1dd7b254dSGiuliano Pochini /****************************************************************************
2dd7b254dSGiuliano Pochini 
3dd7b254dSGiuliano Pochini    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
4dd7b254dSGiuliano Pochini    All rights reserved
5dd7b254dSGiuliano Pochini    www.echoaudio.com
6dd7b254dSGiuliano Pochini 
7dd7b254dSGiuliano Pochini    This file is part of Echo Digital Audio's generic driver library.
8dd7b254dSGiuliano Pochini 
9dd7b254dSGiuliano Pochini    Echo Digital Audio's generic driver library is free software;
10dd7b254dSGiuliano Pochini    you can redistribute it and/or modify it under the terms of
11dd7b254dSGiuliano Pochini    the GNU General Public License as published by the Free Software
12dd7b254dSGiuliano Pochini    Foundation.
13dd7b254dSGiuliano Pochini 
14dd7b254dSGiuliano Pochini    This program is distributed in the hope that it will be useful,
15dd7b254dSGiuliano Pochini    but WITHOUT ANY WARRANTY; without even the implied warranty of
16dd7b254dSGiuliano Pochini    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17dd7b254dSGiuliano Pochini    GNU General Public License for more details.
18dd7b254dSGiuliano Pochini 
19dd7b254dSGiuliano Pochini    You should have received a copy of the GNU General Public License
20dd7b254dSGiuliano Pochini    along with this program; if not, write to the Free Software
21dd7b254dSGiuliano Pochini    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22dd7b254dSGiuliano Pochini    MA  02111-1307, USA.
23dd7b254dSGiuliano Pochini 
24dd7b254dSGiuliano Pochini    *************************************************************************
25dd7b254dSGiuliano Pochini 
26dd7b254dSGiuliano Pochini  Translation from C++ and adaptation for use in ALSA-Driver
27dd7b254dSGiuliano Pochini  were made by Giuliano Pochini <pochini@shiny.it>
28dd7b254dSGiuliano Pochini 
29dd7b254dSGiuliano Pochini ****************************************************************************/
30dd7b254dSGiuliano Pochini 
31dd7b254dSGiuliano Pochini 
32dd7b254dSGiuliano Pochini static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
33dd7b254dSGiuliano Pochini 			   int gain);
34dd7b254dSGiuliano Pochini static int update_vmixer_level(struct echoaudio *chip);
35dd7b254dSGiuliano Pochini 
36dd7b254dSGiuliano Pochini 
init_hw(struct echoaudio * chip,u16 device_id,u16 subdevice_id)37dd7b254dSGiuliano Pochini static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
38dd7b254dSGiuliano Pochini {
39dd7b254dSGiuliano Pochini 	int err;
40dd7b254dSGiuliano Pochini 
41da3cec35STakashi Iwai 	if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJ))
42da3cec35STakashi Iwai 		return -ENODEV;
43dd7b254dSGiuliano Pochini 
44*549717fcSTakashi Iwai 	err = init_dsp_comm_page(chip);
45*549717fcSTakashi Iwai 	if (err) {
46b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
47b5b4a41bSSudip Mukherjee 			"init_hw - could not initialize DSP comm page\n");
48dd7b254dSGiuliano Pochini 		return err;
49dd7b254dSGiuliano Pochini 	}
50dd7b254dSGiuliano Pochini 
51dd7b254dSGiuliano Pochini 	chip->device_id = device_id;
52dd7b254dSGiuliano Pochini 	chip->subdevice_id = subdevice_id;
533f6175ecSMark Brown 	chip->bad_board = true;
5419b50063SGiuliano Pochini 	chip->dsp_code_to_load = FW_INDIGO_DJ_DSP;
55dd7b254dSGiuliano Pochini 	/* Since this card has no ASIC, mark it as loaded so everything
56dd7b254dSGiuliano Pochini 	   works OK */
573f6175ecSMark Brown 	chip->asic_loaded = true;
58dd7b254dSGiuliano Pochini 	chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
59dd7b254dSGiuliano Pochini 
60*549717fcSTakashi Iwai 	err = load_firmware(chip);
61*549717fcSTakashi Iwai 	if (err < 0)
62dd7b254dSGiuliano Pochini 		return err;
633f6175ecSMark Brown 	chip->bad_board = false;
64dd7b254dSGiuliano Pochini 
65dd7b254dSGiuliano Pochini 	return err;
66dd7b254dSGiuliano Pochini }
67dd7b254dSGiuliano Pochini 
68dd7b254dSGiuliano Pochini 
69dd7b254dSGiuliano Pochini 
set_mixer_defaults(struct echoaudio * chip)70ad3499f4SGiuliano Pochini static int set_mixer_defaults(struct echoaudio *chip)
71ad3499f4SGiuliano Pochini {
72ad3499f4SGiuliano Pochini 	return init_line_levels(chip);
73ad3499f4SGiuliano Pochini }
74ad3499f4SGiuliano Pochini 
75ad3499f4SGiuliano Pochini 
76ad3499f4SGiuliano Pochini 
detect_input_clocks(const struct echoaudio * chip)77dd7b254dSGiuliano Pochini static u32 detect_input_clocks(const struct echoaudio *chip)
78dd7b254dSGiuliano Pochini {
79dd7b254dSGiuliano Pochini 	return ECHO_CLOCK_BIT_INTERNAL;
80dd7b254dSGiuliano Pochini }
81dd7b254dSGiuliano Pochini 
82dd7b254dSGiuliano Pochini 
83dd7b254dSGiuliano Pochini 
84dd7b254dSGiuliano Pochini /* The IndigoDJ has no ASIC. Just do nothing */
load_asic(struct echoaudio * chip)85dd7b254dSGiuliano Pochini static int load_asic(struct echoaudio *chip)
86dd7b254dSGiuliano Pochini {
87dd7b254dSGiuliano Pochini 	return 0;
88dd7b254dSGiuliano Pochini }
89dd7b254dSGiuliano Pochini 
90dd7b254dSGiuliano Pochini 
91dd7b254dSGiuliano Pochini 
set_sample_rate(struct echoaudio * chip,u32 rate)92dd7b254dSGiuliano Pochini static int set_sample_rate(struct echoaudio *chip, u32 rate)
93dd7b254dSGiuliano Pochini {
94dd7b254dSGiuliano Pochini 	u32 control_reg;
95dd7b254dSGiuliano Pochini 
96dd7b254dSGiuliano Pochini 	switch (rate) {
97dd7b254dSGiuliano Pochini 	case 96000:
98dd7b254dSGiuliano Pochini 		control_reg = MIA_96000;
99dd7b254dSGiuliano Pochini 		break;
100dd7b254dSGiuliano Pochini 	case 88200:
101dd7b254dSGiuliano Pochini 		control_reg = MIA_88200;
102dd7b254dSGiuliano Pochini 		break;
103dd7b254dSGiuliano Pochini 	case 48000:
104dd7b254dSGiuliano Pochini 		control_reg = MIA_48000;
105dd7b254dSGiuliano Pochini 		break;
106dd7b254dSGiuliano Pochini 	case 44100:
107dd7b254dSGiuliano Pochini 		control_reg = MIA_44100;
108dd7b254dSGiuliano Pochini 		break;
109dd7b254dSGiuliano Pochini 	case 32000:
110dd7b254dSGiuliano Pochini 		control_reg = MIA_32000;
111dd7b254dSGiuliano Pochini 		break;
112dd7b254dSGiuliano Pochini 	default:
113b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
114b5b4a41bSSudip Mukherjee 			"set_sample_rate: %d invalid!\n", rate);
115dd7b254dSGiuliano Pochini 		return -EINVAL;
116dd7b254dSGiuliano Pochini 	}
117dd7b254dSGiuliano Pochini 
118dd7b254dSGiuliano Pochini 	/* Set the control register if it has changed */
119dd7b254dSGiuliano Pochini 	if (control_reg != le32_to_cpu(chip->comm_page->control_register)) {
120dd7b254dSGiuliano Pochini 		if (wait_handshake(chip))
121dd7b254dSGiuliano Pochini 			return -EIO;
122dd7b254dSGiuliano Pochini 
123dd7b254dSGiuliano Pochini 		chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP */
124dd7b254dSGiuliano Pochini 		chip->comm_page->control_register = cpu_to_le32(control_reg);
125dd7b254dSGiuliano Pochini 		chip->sample_rate = rate;
126dd7b254dSGiuliano Pochini 
127dd7b254dSGiuliano Pochini 		clear_handshake(chip);
128dd7b254dSGiuliano Pochini 		return send_vector(chip, DSP_VC_UPDATE_CLOCKS);
129dd7b254dSGiuliano Pochini 	}
130dd7b254dSGiuliano Pochini 	return 0;
131dd7b254dSGiuliano Pochini }
132dd7b254dSGiuliano Pochini 
133dd7b254dSGiuliano Pochini 
134dd7b254dSGiuliano Pochini 
135dd7b254dSGiuliano Pochini /* This function routes the sound from a virtual channel to a real output */
set_vmixer_gain(struct echoaudio * chip,u16 output,u16 pipe,int gain)136dd7b254dSGiuliano Pochini static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe,
137dd7b254dSGiuliano Pochini 			   int gain)
138dd7b254dSGiuliano Pochini {
139dd7b254dSGiuliano Pochini 	int index;
140dd7b254dSGiuliano Pochini 
141da3cec35STakashi Iwai 	if (snd_BUG_ON(pipe >= num_pipes_out(chip) ||
142da3cec35STakashi Iwai 		       output >= num_busses_out(chip)))
143da3cec35STakashi Iwai 		return -EINVAL;
144dd7b254dSGiuliano Pochini 
145dd7b254dSGiuliano Pochini 	if (wait_handshake(chip))
146dd7b254dSGiuliano Pochini 		return -EIO;
147dd7b254dSGiuliano Pochini 
148dd7b254dSGiuliano Pochini 	chip->vmixer_gain[output][pipe] = gain;
149dd7b254dSGiuliano Pochini 	index = output * num_pipes_out(chip) + pipe;
150dd7b254dSGiuliano Pochini 	chip->comm_page->vmixer[index] = gain;
151dd7b254dSGiuliano Pochini 
152b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev,
153b5b4a41bSSudip Mukherjee 		"set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain);
154dd7b254dSGiuliano Pochini 	return 0;
155dd7b254dSGiuliano Pochini }
156dd7b254dSGiuliano Pochini 
157dd7b254dSGiuliano Pochini 
158dd7b254dSGiuliano Pochini 
159dd7b254dSGiuliano Pochini /* Tell the DSP to read and update virtual mixer levels in comm page. */
update_vmixer_level(struct echoaudio * chip)160dd7b254dSGiuliano Pochini static int update_vmixer_level(struct echoaudio *chip)
161dd7b254dSGiuliano Pochini {
162dd7b254dSGiuliano Pochini 	if (wait_handshake(chip))
163dd7b254dSGiuliano Pochini 		return -EIO;
164dd7b254dSGiuliano Pochini 	clear_handshake(chip);
165dd7b254dSGiuliano Pochini 	return send_vector(chip, DSP_VC_SET_VMIXER_GAIN);
166dd7b254dSGiuliano Pochini }
167dd7b254dSGiuliano Pochini 
168