~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/pci/echoaudio/layla24_dsp.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /****************************************************************************
  2 
  3    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
  4    All rights reserved
  5    www.echoaudio.com
  6 
  7    This file is part of Echo Digital Audio's generic driver library.
  8 
  9    Echo Digital Audio's generic driver library is free software;
 10    you can redistribute it and/or modify it under the terms of
 11    the GNU General Public License as published by the Free Software Foundation.
 12 
 13    This program is distributed in the hope that it will be useful,
 14    but WITHOUT ANY WARRANTY; without even the implied warranty of
 15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16    GNU General Public License for more details.
 17 
 18    You should have received a copy of the GNU General Public License
 19    along with this program; if not, write to the Free Software
 20    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 21    MA  02111-1307, USA.
 22 
 23    *************************************************************************
 24 
 25  Translation from C++ and adaptation for use in ALSA-Driver
 26  were made by Giuliano Pochini <pochini@shiny.it>
 27 
 28 ****************************************************************************/
 29 
 30 
 31 static int write_control_reg(struct echoaudio *chip, u32 value, char force);
 32 static int set_input_clock(struct echoaudio *chip, u16 clock);
 33 static int set_professional_spdif(struct echoaudio *chip, char prof);
 34 static int set_digital_mode(struct echoaudio *chip, u8 mode);
 35 static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
 36 static int check_asic_status(struct echoaudio *chip);
 37 
 38 
 39 static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
 40 {
 41         int err;
 42 
 43         if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24))
 44                 return -ENODEV;
 45 
 46         if ((err = init_dsp_comm_page(chip))) {
 47                 dev_err(chip->card->dev,
 48                         "init_hw - could not initialize DSP comm page\n");
 49                 return err;
 50         }
 51 
 52         chip->device_id = device_id;
 53         chip->subdevice_id = subdevice_id;
 54         chip->bad_board = true;
 55         chip->has_midi = true;
 56         chip->dsp_code_to_load = FW_LAYLA24_DSP;
 57         chip->input_clock_types =
 58                 ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
 59                 ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT;
 60         chip->digital_modes =
 61                 ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
 62                 ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
 63                 ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
 64 
 65         if ((err = load_firmware(chip)) < 0)
 66                 return err;
 67         chip->bad_board = false;
 68 
 69         if ((err = init_line_levels(chip)) < 0)
 70                 return err;
 71 
 72         return err;
 73 }
 74 
 75 
 76 
 77 static int set_mixer_defaults(struct echoaudio *chip)
 78 {
 79         chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
 80         chip->professional_spdif = false;
 81         chip->digital_in_automute = true;
 82         return init_line_levels(chip);
 83 }
 84 
 85 
 86 
 87 static u32 detect_input_clocks(const struct echoaudio *chip)
 88 {
 89         u32 clocks_from_dsp, clock_bits;
 90 
 91         /* Map the DSP clock detect bits to the generic driver clock detect bits */
 92         clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
 93 
 94         clock_bits = ECHO_CLOCK_BIT_INTERNAL;
 95 
 96         if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
 97                 clock_bits |= ECHO_CLOCK_BIT_SPDIF;
 98 
 99         if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
100                 clock_bits |= ECHO_CLOCK_BIT_ADAT;
101 
102         if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD)
103                 clock_bits |= ECHO_CLOCK_BIT_WORD;
104 
105         return clock_bits;
106 }
107 
108 
109 
110 /* Layla24 has an ASIC on the PCI card and another ASIC in the external box;
111 both need to be loaded. */
112 static int load_asic(struct echoaudio *chip)
113 {
114         int err;
115 
116         if (chip->asic_loaded)
117                 return 1;
118 
119 
120         /* Give the DSP a few milliseconds to settle down */
121         mdelay(10);
122 
123         /* Load the ASIC for the PCI card */
124         err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC,
125                                 FW_LAYLA24_1_ASIC);
126         if (err < 0)
127                 return err;
128 
129         chip->asic_code = FW_LAYLA24_2S_ASIC;
130 
131         /* Now give the new ASIC a little time to set up */
132         mdelay(10);
133 
134         /* Do the external one */
135         err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
136                                 FW_LAYLA24_2S_ASIC);
137         if (err < 0)
138                 return err;
139 
140         /* Now give the external ASIC a little time to set up */
141         mdelay(10);
142 
143         /* See if it worked */
144         err = check_asic_status(chip);
145 
146         /* Set up the control register if the load succeeded -
147            48 kHz, internal clock, S/PDIF RCA mode */
148         if (!err)
149                 err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ,
150                                         true);
151         
152         return err;
153 }
154 
155 
156 
157 static int set_sample_rate(struct echoaudio *chip, u32 rate)
158 {
159         u32 control_reg, clock, base_rate;
160 
161         if (snd_BUG_ON(rate >= 50000 &&
162                        chip->digital_mode == DIGITAL_MODE_ADAT))
163                 return -EINVAL;
164 
165         /* Only set the clock for internal mode. */
166         if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
167                 dev_warn(chip->card->dev,
168                          "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
169                 /* Save the rate anyhow */
170                 chip->comm_page->sample_rate = cpu_to_le32(rate);
171                 chip->sample_rate = rate;
172                 return 0;
173         }
174 
175         /* Get the control register & clear the appropriate bits */
176         control_reg = le32_to_cpu(chip->comm_page->control_register);
177         control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
178 
179         clock = 0;
180 
181         switch (rate) {
182         case 96000:
183                 clock = GML_96KHZ;
184                 break;
185         case 88200:
186                 clock = GML_88KHZ;
187                 break;
188         case 48000:
189                 clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
190                 break;
191         case 44100:
192                 clock = GML_44KHZ;
193                 /* Professional mode */
194                 if (control_reg & GML_SPDIF_PRO_MODE)
195                         clock |= GML_SPDIF_SAMPLE_RATE0;
196                 break;
197         case 32000:
198                 clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
199                         GML_SPDIF_SAMPLE_RATE1;
200                 break;
201         case 22050:
202                 clock = GML_22KHZ;
203                 break;
204         case 16000:
205                 clock = GML_16KHZ;
206                 break;
207         case 11025:
208                 clock = GML_11KHZ;
209                 break;
210         case 8000:
211                 clock = GML_8KHZ;
212                 break;
213         default:
214                 /* If this is a non-standard rate, then the driver needs to
215                 use Layla24's special "continuous frequency" mode */
216                 clock = LAYLA24_CONTINUOUS_CLOCK;
217                 if (rate > 50000) {
218                         base_rate = rate >> 1;
219                         control_reg |= GML_DOUBLE_SPEED_MODE;
220                 } else {
221                         base_rate = rate;
222                 }
223 
224                 if (base_rate < 25000)
225                         base_rate = 25000;
226 
227                 if (wait_handshake(chip))
228                         return -EIO;
229 
230                 chip->comm_page->sample_rate =
231                         cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2);
232 
233                 clear_handshake(chip);
234                 send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG);
235         }
236 
237         control_reg |= clock;
238 
239         chip->comm_page->sample_rate = cpu_to_le32(rate);       /* ignored by the DSP ? */
240         chip->sample_rate = rate;
241         dev_dbg(chip->card->dev,
242                 "set_sample_rate: %d clock %d\n", rate, control_reg);
243 
244         return write_control_reg(chip, control_reg, false);
245 }
246 
247 
248 
249 static int set_input_clock(struct echoaudio *chip, u16 clock)
250 {
251         u32 control_reg, clocks_from_dsp;
252 
253         /* Mask off the clock select bits */
254         control_reg = le32_to_cpu(chip->comm_page->control_register) &
255                 GML_CLOCK_CLEAR_MASK;
256         clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
257 
258         /* Pick the new clock */
259         switch (clock) {
260         case ECHO_CLOCK_INTERNAL:
261                 chip->input_clock = ECHO_CLOCK_INTERNAL;
262                 return set_sample_rate(chip, chip->sample_rate);
263         case ECHO_CLOCK_SPDIF:
264                 if (chip->digital_mode == DIGITAL_MODE_ADAT)
265                         return -EAGAIN;
266                 control_reg |= GML_SPDIF_CLOCK;
267                 /* Layla24 doesn't support 96KHz S/PDIF */
268                 control_reg &= ~GML_DOUBLE_SPEED_MODE;
269                 break;
270         case ECHO_CLOCK_WORD:
271                 control_reg |= GML_WORD_CLOCK;
272                 if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96)
273                         control_reg |= GML_DOUBLE_SPEED_MODE;
274                 else
275                         control_reg &= ~GML_DOUBLE_SPEED_MODE;
276                 break;
277         case ECHO_CLOCK_ADAT:
278                 if (chip->digital_mode != DIGITAL_MODE_ADAT)
279                         return -EAGAIN;
280                 control_reg |= GML_ADAT_CLOCK;
281                 control_reg &= ~GML_DOUBLE_SPEED_MODE;
282                 break;
283         default:
284                 dev_err(chip->card->dev,
285                         "Input clock 0x%x not supported for Layla24\n", clock);
286                 return -EINVAL;
287         }
288 
289         chip->input_clock = clock;
290         return write_control_reg(chip, control_reg, true);
291 }
292 
293 
294 
295 /* Depending on what digital mode you want, Layla24 needs different ASICs
296 loaded.  This function checks the ASIC needed for the new mode and sees
297 if it matches the one already loaded. */
298 static int switch_asic(struct echoaudio *chip, short asic)
299 {
300         s8 *monitors;
301 
302         /*  Check to see if this is already loaded */
303         if (asic != chip->asic_code) {
304                 monitors = kmemdup(chip->comm_page->monitors,
305                                         MONITOR_ARRAY_SIZE, GFP_KERNEL);
306                 if (! monitors)
307                         return -ENOMEM;
308 
309                 memset(chip->comm_page->monitors, ECHOGAIN_MUTED,
310                        MONITOR_ARRAY_SIZE);
311 
312                 /* Load the desired ASIC */
313                 if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC,
314                                       asic) < 0) {
315                         memcpy(chip->comm_page->monitors, monitors,
316                                MONITOR_ARRAY_SIZE);
317                         kfree(monitors);
318                         return -EIO;
319                 }
320                 chip->asic_code = asic;
321                 memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE);
322                 kfree(monitors);
323         }
324 
325         return 0;
326 }
327 
328 
329 
330 static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
331 {
332         u32 control_reg;
333         int err, incompatible_clock;
334         short asic;
335 
336         /* Set clock to "internal" if it's not compatible with the new mode */
337         incompatible_clock = false;
338         switch (mode) {
339         case DIGITAL_MODE_SPDIF_OPTICAL:
340         case DIGITAL_MODE_SPDIF_RCA:
341                 if (chip->input_clock == ECHO_CLOCK_ADAT)
342                         incompatible_clock = true;
343                 asic = FW_LAYLA24_2S_ASIC;
344                 break;
345         case DIGITAL_MODE_ADAT:
346                 if (chip->input_clock == ECHO_CLOCK_SPDIF)
347                         incompatible_clock = true;
348                 asic = FW_LAYLA24_2A_ASIC;
349                 break;
350         default:
351                 dev_err(chip->card->dev,
352                         "Digital mode not supported: %d\n", mode);
353                 return -EINVAL;
354         }
355 
356         if (incompatible_clock) {       /* Switch to 48KHz, internal */
357                 chip->sample_rate = 48000;
358                 spin_lock_irq(&chip->lock);
359                 set_input_clock(chip, ECHO_CLOCK_INTERNAL);
360                 spin_unlock_irq(&chip->lock);
361         }
362 
363         /* switch_asic() can sleep */
364         if (switch_asic(chip, asic) < 0)
365                 return -EIO;
366 
367         spin_lock_irq(&chip->lock);
368 
369         /* Tweak the control register */
370         control_reg = le32_to_cpu(chip->comm_page->control_register);
371         control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
372 
373         switch (mode) {
374         case DIGITAL_MODE_SPDIF_OPTICAL:
375                 control_reg |= GML_SPDIF_OPTICAL_MODE;
376                 break;
377         case DIGITAL_MODE_SPDIF_RCA:
378                 /* GML_SPDIF_OPTICAL_MODE bit cleared */
379                 break;
380         case DIGITAL_MODE_ADAT:
381                 control_reg |= GML_ADAT_MODE;
382                 control_reg &= ~GML_DOUBLE_SPEED_MODE;
383                 break;
384         }
385 
386         err = write_control_reg(chip, control_reg, true);
387         spin_unlock_irq(&chip->lock);
388         if (err < 0)
389                 return err;
390         chip->digital_mode = mode;
391 
392         dev_dbg(chip->card->dev, "set_digital_mode to %d\n", mode);
393         return incompatible_clock;
394 }
395 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp