mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
[ALSA] Add echoaudio sound drivers
From: Giuliano Pochini <pochini@shiny.it>Add echoaudio sound drivers (darla20, darla24, echo3g, gina20, gina24, indigo, indigodj, indigoio, layla20, lala24, mia, mona) Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
This commit is contained in:
committed by
Jaroslav Kysela
parent
cb9d24e434
commit
dd7b254d8d
@@ -472,6 +472,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-darla20
|
||||
------------------
|
||||
|
||||
Module for Echoaudio Darla20
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-darla24
|
||||
------------------
|
||||
|
||||
Module for Echoaudio Darla24
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-dt019x
|
||||
-----------------
|
||||
|
||||
@@ -499,6 +515,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-echo3g
|
||||
-----------------
|
||||
|
||||
Module for Echoaudio 3G cards (Gina3G/Layla3G)
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-emu10k1
|
||||
------------------
|
||||
|
||||
@@ -657,6 +681,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-gina20
|
||||
-----------------
|
||||
|
||||
Module for Echoaudio Gina20
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-gina24
|
||||
-----------------
|
||||
|
||||
Module for Echoaudio Gina24
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-gusclassic
|
||||
---------------------
|
||||
|
||||
@@ -937,6 +977,30 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
driver isn't configured properly or you want to try another
|
||||
type for testing.
|
||||
|
||||
Module snd-indigo
|
||||
-----------------
|
||||
|
||||
Module for Echoaudio Indigo
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-indigodj
|
||||
-------------------
|
||||
|
||||
Module for Echoaudio Indigo DJ
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-indigoio
|
||||
-------------------
|
||||
|
||||
Module for Echoaudio Indigo IO
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-intel8x0
|
||||
-------------------
|
||||
|
||||
@@ -1036,6 +1100,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-layla20
|
||||
------------------
|
||||
|
||||
Module for Echoaudio Layla20
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-layla24
|
||||
------------------
|
||||
|
||||
Module for Echoaudio Layla24
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-maestro3
|
||||
-------------------
|
||||
|
||||
@@ -1056,6 +1136,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-mia
|
||||
---------------
|
||||
|
||||
Module for Echoaudio Mia
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-miro
|
||||
---------------
|
||||
|
||||
@@ -1088,6 +1176,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
When no hotplug fw loader is available, you need to load the
|
||||
firmware via mixartloader utility in alsa-tools package.
|
||||
|
||||
Module snd-mona
|
||||
---------------
|
||||
|
||||
Module for Echoaudio Mona
|
||||
|
||||
This module supports multiple cards.
|
||||
The driver requires the firmware loader support on kernel.
|
||||
|
||||
Module snd-mpu401
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -233,6 +233,143 @@ config SND_CS5535AUDIO
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-cs5535audio.
|
||||
|
||||
config SND_DARLA20
|
||||
tristate "(Echoaudio) Darla20"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Darla.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-darla20
|
||||
|
||||
config SND_GINA20
|
||||
tristate "(Echoaudio) Gina20"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Gina.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-gina20
|
||||
|
||||
config SND_LAYLA20
|
||||
tristate "(Echoaudio) Layla20"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Layla.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-layla20
|
||||
|
||||
config SND_DARLA24
|
||||
tristate "(Echoaudio) Darla24"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Darla24.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-darla24
|
||||
|
||||
config SND_GINA24
|
||||
tristate "(Echoaudio) Gina24"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Gina24.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-gina24
|
||||
|
||||
config SND_LAYLA24
|
||||
tristate "(Echoaudio) Layla24"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Layla24.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-layla24
|
||||
|
||||
config SND_MONA
|
||||
tristate "(Echoaudio) Mona"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Mona.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-mona
|
||||
|
||||
config SND_MIA
|
||||
tristate "(Echoaudio) Mia"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Mia and Mia-midi.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-mia
|
||||
|
||||
config SND_ECHO3G
|
||||
tristate "(Echoaudio) 3G cards"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Gina3G and Layla3G.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-echo3g
|
||||
|
||||
config SND_INDIGO
|
||||
tristate "(Echoaudio) Indigo"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Indigo.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-indigo
|
||||
|
||||
config SND_INDIGOIO
|
||||
tristate "(Echoaudio) Indigo IO"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Indigo IO.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-indigoio
|
||||
|
||||
config SND_INDIGODJ
|
||||
tristate "(Echoaudio) Indigo DJ"
|
||||
depends on SND
|
||||
depends on FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for Echoaudio Indigo DJ.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-indigodj
|
||||
|
||||
config SND_EMU10K1
|
||||
tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
|
||||
depends on SND
|
||||
|
||||
@@ -57,6 +57,7 @@ obj-$(CONFIG_SND) += \
|
||||
ca0106/ \
|
||||
cs46xx/ \
|
||||
cs5535audio/ \
|
||||
echoaudio/ \
|
||||
emu10k1/ \
|
||||
hda/ \
|
||||
ice1712/ \
|
||||
|
||||
17
sound/pci/echoaudio/Makefile
Normal file
17
sound/pci/echoaudio/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Makefile for ALSA Echoaudio soundcard drivers
|
||||
# Copyright (c) 2003 by Giuliano Pochini <pochini@shiny.it>
|
||||
#
|
||||
|
||||
snd-darla20-objs := darla20.o
|
||||
snd-gina20-objs := gina20.o
|
||||
snd-layla20-objs := layla20.o
|
||||
snd-darla24-objs := darla24.o
|
||||
snd-gina24-objs := gina24.o
|
||||
snd-layla24-objs := layla24.o
|
||||
snd-mona-objs := mona.o
|
||||
snd-mia-objs := mia.o
|
||||
snd-echo3g-objs := echo3g.o
|
||||
snd-indigo-objs := indigo.o
|
||||
snd-indigoio-objs := indigoio.o
|
||||
snd-indigodj-objs := indigodj.o
|
||||
99
sound/pci/echoaudio/darla20.c
Normal file
99
sound/pci/echoaudio/darla20.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* ALSA driver for Echoaudio soundcards.
|
||||
* Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define ECHOGALS_FAMILY
|
||||
#define ECHOCARD_DARLA20
|
||||
#define ECHOCARD_NAME "Darla20"
|
||||
#define ECHOCARD_HAS_MONITOR
|
||||
|
||||
/* Pipe indexes */
|
||||
#define PX_ANALOG_OUT 0 /* 8 */
|
||||
#define PX_DIGITAL_OUT 8 /* 0 */
|
||||
#define PX_ANALOG_IN 8 /* 2 */
|
||||
#define PX_DIGITAL_IN 10 /* 0 */
|
||||
#define PX_NUM 10
|
||||
|
||||
/* Bus indexes */
|
||||
#define BX_ANALOG_OUT 0 /* 8 */
|
||||
#define BX_DIGITAL_OUT 8 /* 0 */
|
||||
#define BX_ANALOG_IN 8 /* 2 */
|
||||
#define BX_DIGITAL_IN 10 /* 0 */
|
||||
#define BX_NUM 10
|
||||
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/asoundef.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "echoaudio.h"
|
||||
|
||||
#define FW_DARLA20_DSP 0
|
||||
|
||||
static const struct firmware card_fw[] = {
|
||||
{0, "darla20_dsp.fw"}
|
||||
};
|
||||
|
||||
static struct pci_device_id snd_echo_ids[] = {
|
||||
{0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */
|
||||
{0,}
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware pcm_hardware_skel = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_SYNC_START,
|
||||
.formats = SNDRV_PCM_FMTBIT_U8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_BE,
|
||||
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 262144,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 131072,
|
||||
.periods_min = 2,
|
||||
.periods_max = 220,
|
||||
/* One page (4k) contains 512 instructions. I don't know if the hw
|
||||
supports lists longer than this. In this case periods_max=220 is a
|
||||
safe limit to make sure the list never exceeds 512 instructions. */
|
||||
};
|
||||
|
||||
|
||||
#include "darla20_dsp.c"
|
||||
#include "echoaudio_dsp.c"
|
||||
#include "echoaudio.c"
|
||||
125
sound/pci/echoaudio/darla20_dsp.c
Normal file
125
sound/pci/echoaudio/darla20_dsp.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/***************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
DE_INIT(("init_hw() - Darla20\n"));
|
||||
snd_assert((subdevice_id & 0xfff0) == DARLA20, return -ENODEV);
|
||||
|
||||
if ((err = init_dsp_comm_page(chip))) {
|
||||
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->device_id = device_id;
|
||||
chip->subdevice_id = subdevice_id;
|
||||
chip->bad_board = TRUE;
|
||||
chip->dsp_code_to_load = &card_fw[FW_DARLA20_DSP];
|
||||
chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
|
||||
chip->clock_state = GD_CLOCK_UNDEF;
|
||||
/* Since this card has no ASIC, mark it as loaded so everything
|
||||
works OK */
|
||||
chip->asic_loaded = TRUE;
|
||||
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL;
|
||||
|
||||
if ((err = load_firmware(chip)) < 0)
|
||||
return err;
|
||||
chip->bad_board = FALSE;
|
||||
|
||||
if ((err = init_line_levels(chip)) < 0)
|
||||
return err;
|
||||
|
||||
DE_INIT(("init_hw done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The Darla20 has no external clock sources */
|
||||
static u32 detect_input_clocks(const struct echoaudio *chip)
|
||||
{
|
||||
return ECHO_CLOCK_BIT_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The Darla20 has no ASIC. Just do nothing */
|
||||
static int load_asic(struct echoaudio *chip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate)
|
||||
{
|
||||
u8 clock_state, spdif_status;
|
||||
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
switch (rate) {
|
||||
case 44100:
|
||||
clock_state = GD_CLOCK_44;
|
||||
spdif_status = GD_SPDIF_STATUS_44;
|
||||
break;
|
||||
case 48000:
|
||||
clock_state = GD_CLOCK_48;
|
||||
spdif_status = GD_SPDIF_STATUS_48;
|
||||
break;
|
||||
default:
|
||||
clock_state = GD_CLOCK_NOCHANGE;
|
||||
spdif_status = GD_SPDIF_STATUS_NOCHANGE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chip->clock_state == clock_state)
|
||||
clock_state = GD_CLOCK_NOCHANGE;
|
||||
if (spdif_status == chip->spdif_status)
|
||||
spdif_status = GD_SPDIF_STATUS_NOCHANGE;
|
||||
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate);
|
||||
chip->comm_page->gd_clock_state = clock_state;
|
||||
chip->comm_page->gd_spdif_status = spdif_status;
|
||||
chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */
|
||||
|
||||
/* Save the new audio state if it changed */
|
||||
if (clock_state != GD_CLOCK_NOCHANGE)
|
||||
chip->clock_state = clock_state;
|
||||
if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
|
||||
chip->spdif_status = spdif_status;
|
||||
chip->sample_rate = rate;
|
||||
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
|
||||
}
|
||||
106
sound/pci/echoaudio/darla24.c
Normal file
106
sound/pci/echoaudio/darla24.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* ALSA driver for Echoaudio soundcards.
|
||||
* Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define ECHOGALS_FAMILY
|
||||
#define ECHOCARD_DARLA24
|
||||
#define ECHOCARD_NAME "Darla24"
|
||||
#define ECHOCARD_HAS_MONITOR
|
||||
#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_EXTERNAL_CLOCK
|
||||
#define ECHOCARD_HAS_SUPER_INTERLEAVE
|
||||
|
||||
/* Pipe indexes */
|
||||
#define PX_ANALOG_OUT 0 /* 8 */
|
||||
#define PX_DIGITAL_OUT 8 /* 0 */
|
||||
#define PX_ANALOG_IN 8 /* 2 */
|
||||
#define PX_DIGITAL_IN 10 /* 0 */
|
||||
#define PX_NUM 10
|
||||
|
||||
/* Bus indexes */
|
||||
#define BX_ANALOG_OUT 0 /* 8 */
|
||||
#define BX_DIGITAL_OUT 8 /* 0 */
|
||||
#define BX_ANALOG_IN 8 /* 2 */
|
||||
#define BX_DIGITAL_IN 10 /* 0 */
|
||||
#define BX_NUM 10
|
||||
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/asoundef.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "echoaudio.h"
|
||||
|
||||
#define FW_DARLA24_DSP 0
|
||||
|
||||
static const struct firmware card_fw[] = {
|
||||
{0, "darla24_dsp.fw"}
|
||||
};
|
||||
|
||||
static struct pci_device_id snd_echo_ids[] = {
|
||||
{0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */
|
||||
{0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */
|
||||
{0,}
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware pcm_hardware_skel = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_SYNC_START,
|
||||
.formats = SNDRV_PCM_FMTBIT_U8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_BE,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.buffer_bytes_max = 262144,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 131072,
|
||||
.periods_min = 2,
|
||||
.periods_max = 220,
|
||||
/* One page (4k) contains 512 instructions. I don't know if the hw
|
||||
supports lists longer than this. In this case periods_max=220 is a
|
||||
safe limit to make sure the list never exceeds 512 instructions. */
|
||||
};
|
||||
|
||||
|
||||
#include "darla24_dsp.c"
|
||||
#include "echoaudio_dsp.c"
|
||||
#include "echoaudio.c"
|
||||
156
sound/pci/echoaudio/darla24_dsp.c
Normal file
156
sound/pci/echoaudio/darla24_dsp.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/***************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
DE_INIT(("init_hw() - Darla24\n"));
|
||||
snd_assert((subdevice_id & 0xfff0) == DARLA24, return -ENODEV);
|
||||
|
||||
if ((err = init_dsp_comm_page(chip))) {
|
||||
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->device_id = device_id;
|
||||
chip->subdevice_id = subdevice_id;
|
||||
chip->bad_board = TRUE;
|
||||
chip->dsp_code_to_load = &card_fw[FW_DARLA24_DSP];
|
||||
/* Since this card has no ASIC, mark it as loaded so everything
|
||||
works OK */
|
||||
chip->asic_loaded = TRUE;
|
||||
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
|
||||
ECHO_CLOCK_BIT_ESYNC;
|
||||
|
||||
if ((err = load_firmware(chip)) < 0)
|
||||
return err;
|
||||
chip->bad_board = FALSE;
|
||||
|
||||
if ((err = init_line_levels(chip)) < 0)
|
||||
return err;
|
||||
|
||||
DE_INIT(("init_hw done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 detect_input_clocks(const struct echoaudio *chip)
|
||||
{
|
||||
u32 clocks_from_dsp, clock_bits;
|
||||
|
||||
/* Map the DSP clock detect bits to the generic driver clock
|
||||
detect bits */
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
|
||||
|
||||
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_ESYNC)
|
||||
clock_bits |= ECHO_CLOCK_BIT_ESYNC;
|
||||
|
||||
return clock_bits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The Darla24 has no ASIC. Just do nothing */
|
||||
static int load_asic(struct echoaudio *chip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate)
|
||||
{
|
||||
u8 clock;
|
||||
|
||||
switch (rate) {
|
||||
case 96000:
|
||||
clock = GD24_96000;
|
||||
break;
|
||||
case 88200:
|
||||
clock = GD24_88200;
|
||||
break;
|
||||
case 48000:
|
||||
clock = GD24_48000;
|
||||
break;
|
||||
case 44100:
|
||||
clock = GD24_44100;
|
||||
break;
|
||||
case 32000:
|
||||
clock = GD24_32000;
|
||||
break;
|
||||
case 22050:
|
||||
clock = GD24_22050;
|
||||
break;
|
||||
case 16000:
|
||||
clock = GD24_16000;
|
||||
break;
|
||||
case 11025:
|
||||
clock = GD24_11025;
|
||||
break;
|
||||
case 8000:
|
||||
clock = GD24_8000;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("set_sample_rate: Error, invalid sample rate %d\n",
|
||||
rate));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));
|
||||
chip->sample_rate = rate;
|
||||
|
||||
/* Override the sample rate if this card is set to Echo sync. */
|
||||
if (chip->input_clock == ECHO_CLOCK_ESYNC)
|
||||
clock = GD24_EXT_SYNC;
|
||||
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */
|
||||
chip->comm_page->gd_clock_state = clock;
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock)
|
||||
{
|
||||
snd_assert(clock == ECHO_CLOCK_INTERNAL ||
|
||||
clock == ECHO_CLOCK_ESYNC, return -EINVAL);
|
||||
chip->input_clock = clock;
|
||||
return set_sample_rate(chip, chip->sample_rate);
|
||||
}
|
||||
|
||||
118
sound/pci/echoaudio/echo3g.c
Normal file
118
sound/pci/echoaudio/echo3g.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* ALSA driver for Echoaudio soundcards.
|
||||
* Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define ECHO3G_FAMILY
|
||||
#define ECHOCARD_ECHO3G
|
||||
#define ECHOCARD_NAME "Echo3G"
|
||||
#define ECHOCARD_HAS_MONITOR
|
||||
#define ECHOCARD_HAS_ASIC
|
||||
#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_SUPER_INTERLEAVE
|
||||
#define ECHOCARD_HAS_DIGITAL_IO
|
||||
#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
|
||||
#define ECHOCARD_HAS_ADAT 6
|
||||
#define ECHOCARD_HAS_EXTERNAL_CLOCK
|
||||
#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
|
||||
#define ECHOCARD_HAS_MIDI
|
||||
#define ECHOCARD_HAS_PHANTOM_POWER
|
||||
|
||||
/* Pipe indexes */
|
||||
#define PX_ANALOG_OUT 0
|
||||
#define PX_DIGITAL_OUT chip->px_digital_out
|
||||
#define PX_ANALOG_IN chip->px_analog_in
|
||||
#define PX_DIGITAL_IN chip->px_digital_in
|
||||
#define PX_NUM chip->px_num
|
||||
|
||||
/* Bus indexes */
|
||||
#define BX_ANALOG_OUT 0
|
||||
#define BX_DIGITAL_OUT chip->bx_digital_out
|
||||
#define BX_ANALOG_IN chip->bx_analog_in
|
||||
#define BX_DIGITAL_IN chip->bx_digital_in
|
||||
#define BX_NUM chip->bx_num
|
||||
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/asoundef.h>
|
||||
#include <sound/initval.h>
|
||||
#include <sound/rawmidi.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "echoaudio.h"
|
||||
|
||||
#define FW_361_LOADER 0
|
||||
#define FW_ECHO3G_DSP 1
|
||||
#define FW_3G_ASIC 2
|
||||
|
||||
static const struct firmware card_fw[] = {
|
||||
{0, "loader_dsp.fw"},
|
||||
{0, "echo3g_dsp.fw"},
|
||||
{0, "3g_asic.fw"}
|
||||
};
|
||||
|
||||
static struct pci_device_id snd_echo_ids[] = {
|
||||
{0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */
|
||||
{0,}
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware pcm_hardware_skel = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_SYNC_START,
|
||||
.formats = SNDRV_PCM_FMTBIT_U8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_BE,
|
||||
.rates = SNDRV_PCM_RATE_32000 |
|
||||
SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000 |
|
||||
SNDRV_PCM_RATE_CONTINUOUS,
|
||||
.rate_min = 32000,
|
||||
.rate_max = 100000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.buffer_bytes_max = 262144,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 131072,
|
||||
.periods_min = 2,
|
||||
.periods_max = 220,
|
||||
};
|
||||
|
||||
#include "echo3g_dsp.c"
|
||||
#include "echoaudio_dsp.c"
|
||||
#include "echoaudio_3g.c"
|
||||
#include "echoaudio.c"
|
||||
#include "midi.c"
|
||||
131
sound/pci/echoaudio/echo3g_dsp.c
Normal file
131
sound/pci/echoaudio/echo3g_dsp.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/****************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
static int load_asic(struct echoaudio *chip);
|
||||
static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode);
|
||||
static int set_digital_mode(struct echoaudio *chip, u8 mode);
|
||||
static int check_asic_status(struct echoaudio *chip);
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate);
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock);
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof);
|
||||
static int set_phantom_power(struct echoaudio *chip, char on);
|
||||
static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
|
||||
char force);
|
||||
|
||||
#include <linux/irq.h>
|
||||
|
||||
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
local_irq_enable();
|
||||
DE_INIT(("init_hw() - Echo3G\n"));
|
||||
snd_assert((subdevice_id & 0xfff0) == ECHO3G, return -ENODEV);
|
||||
|
||||
if ((err = init_dsp_comm_page(chip))) {
|
||||
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->comm_page->e3g_frq_register =
|
||||
__constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2);
|
||||
chip->device_id = device_id;
|
||||
chip->subdevice_id = subdevice_id;
|
||||
chip->bad_board = TRUE;
|
||||
chip->has_midi = TRUE;
|
||||
chip->dsp_code_to_load = &card_fw[FW_ECHO3G_DSP];
|
||||
|
||||
/* Load the DSP code and the ASIC on the PCI card and get
|
||||
what type of external box is attached */
|
||||
err = load_firmware(chip);
|
||||
|
||||
if (err < 0) {
|
||||
return err;
|
||||
} else if (err == E3G_GINA3G_BOX_TYPE) {
|
||||
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
|
||||
ECHO_CLOCK_BIT_SPDIF |
|
||||
ECHO_CLOCK_BIT_ADAT;
|
||||
chip->card_name = "Gina3G";
|
||||
chip->px_digital_out = chip->bx_digital_out = 6;
|
||||
chip->px_analog_in = chip->bx_analog_in = 14;
|
||||
chip->px_digital_in = chip->bx_digital_in = 16;
|
||||
chip->px_num = chip->bx_num = 24;
|
||||
chip->has_phantom_power = TRUE;
|
||||
chip->hasnt_input_nominal_level = TRUE;
|
||||
} else if (err == E3G_LAYLA3G_BOX_TYPE) {
|
||||
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
|
||||
ECHO_CLOCK_BIT_SPDIF |
|
||||
ECHO_CLOCK_BIT_ADAT |
|
||||
ECHO_CLOCK_BIT_WORD;
|
||||
chip->card_name = "Layla3G";
|
||||
chip->px_digital_out = chip->bx_digital_out = 8;
|
||||
chip->px_analog_in = chip->bx_analog_in = 16;
|
||||
chip->px_digital_in = chip->bx_digital_in = 24;
|
||||
chip->px_num = chip->bx_num = 32;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
|
||||
chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
|
||||
chip->professional_spdif = FALSE;
|
||||
chip->non_audio_spdif = FALSE;
|
||||
chip->bad_board = FALSE;
|
||||
|
||||
if ((err = init_line_levels(chip)) < 0)
|
||||
return err;
|
||||
err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
|
||||
snd_assert(err >= 0, return err);
|
||||
err = set_phantom_power(chip, 0);
|
||||
snd_assert(err >= 0, return err);
|
||||
err = set_professional_spdif(chip, TRUE);
|
||||
|
||||
DE_INIT(("init_hw done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_phantom_power(struct echoaudio *chip, char on)
|
||||
{
|
||||
u32 control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
|
||||
if (on)
|
||||
control_reg |= E3G_PHANTOM_POWER;
|
||||
else
|
||||
control_reg &= ~E3G_PHANTOM_POWER;
|
||||
|
||||
chip->phantom_power = on;
|
||||
return write_control_reg(chip, control_reg,
|
||||
le32_to_cpu(chip->comm_page->e3g_frq_register),
|
||||
0);
|
||||
}
|
||||
2197
sound/pci/echoaudio/echoaudio.c
Normal file
2197
sound/pci/echoaudio/echoaudio.c
Normal file
File diff suppressed because it is too large
Load Diff
590
sound/pci/echoaudio/echoaudio.h
Normal file
590
sound/pci/echoaudio/echoaudio.h
Normal file
File diff suppressed because it is too large
Load Diff
431
sound/pci/echoaudio/echoaudio_3g.c
Normal file
431
sound/pci/echoaudio/echoaudio_3g.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/****************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* These functions are common for all "3G" cards */
|
||||
|
||||
|
||||
static int check_asic_status(struct echoaudio *chip)
|
||||
{
|
||||
u32 box_status;
|
||||
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
chip->comm_page->ext_box_status =
|
||||
__constant_cpu_to_le32(E3G_ASIC_NOT_LOADED);
|
||||
chip->asic_loaded = FALSE;
|
||||
clear_handshake(chip);
|
||||
send_vector(chip, DSP_VC_TEST_ASIC);
|
||||
|
||||
if (wait_handshake(chip)) {
|
||||
chip->dsp_code = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
box_status = le32_to_cpu(chip->comm_page->ext_box_status);
|
||||
DE_INIT(("box_status=%x\n", box_status));
|
||||
if (box_status == E3G_ASIC_NOT_LOADED)
|
||||
return -ENODEV;
|
||||
|
||||
chip->asic_loaded = TRUE;
|
||||
return box_status & E3G_BOX_TYPE_MASK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline u32 get_frq_reg(struct echoaudio *chip)
|
||||
{
|
||||
return le32_to_cpu(chip->comm_page->e3g_frq_register);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Most configuration of 3G cards is accomplished by writing the control
|
||||
register. write_control_reg sends the new control register value to the DSP. */
|
||||
static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
|
||||
char force)
|
||||
{
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
DE_ACT(("WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq));
|
||||
|
||||
ctl = cpu_to_le32(ctl);
|
||||
frq = cpu_to_le32(frq);
|
||||
|
||||
if (ctl != chip->comm_page->control_register ||
|
||||
frq != chip->comm_page->e3g_frq_register || force) {
|
||||
chip->comm_page->e3g_frq_register = frq;
|
||||
chip->comm_page->control_register = ctl;
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
|
||||
}
|
||||
|
||||
DE_ACT(("WriteControlReg: not written, no change\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */
|
||||
static int set_digital_mode(struct echoaudio *chip, u8 mode)
|
||||
{
|
||||
u8 previous_mode;
|
||||
int err, i, o;
|
||||
|
||||
/* All audio channels must be closed before changing the digital mode */
|
||||
snd_assert(!chip->pipe_alloc_mask, return -EAGAIN);
|
||||
|
||||
snd_assert(chip->digital_modes & (1 << mode), return -EINVAL);
|
||||
|
||||
previous_mode = chip->digital_mode;
|
||||
err = dsp_set_digital_mode(chip, mode);
|
||||
|
||||
/* If we successfully changed the digital mode from or to ADAT,
|
||||
* then make sure all output, input and monitor levels are
|
||||
* updated by the DSP comm object. */
|
||||
if (err >= 0 && previous_mode != mode &&
|
||||
(previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
|
||||
spin_lock_irq(&chip->lock);
|
||||
for (o = 0; o < num_busses_out(chip); o++)
|
||||
for (i = 0; i < num_busses_in(chip); i++)
|
||||
set_monitor_gain(chip, o, i,
|
||||
chip->monitor_gain[o][i]);
|
||||
|
||||
#ifdef ECHOCARD_HAS_INPUT_GAIN
|
||||
for (i = 0; i < num_busses_in(chip); i++)
|
||||
set_input_gain(chip, i, chip->input_gain[i]);
|
||||
update_input_line_level(chip);
|
||||
#endif
|
||||
|
||||
for (o = 0; o < num_busses_out(chip); o++)
|
||||
set_output_gain(chip, o, chip->output_gain[o]);
|
||||
update_output_line_level(chip);
|
||||
spin_unlock_irq(&chip->lock);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate)
|
||||
{
|
||||
control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK;
|
||||
|
||||
switch (rate) {
|
||||
case 32000 :
|
||||
control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
case 44100 :
|
||||
if (chip->professional_spdif)
|
||||
control_reg |= E3G_SPDIF_SAMPLE_RATE0;
|
||||
break;
|
||||
case 48000 :
|
||||
control_reg |= E3G_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chip->professional_spdif)
|
||||
control_reg |= E3G_SPDIF_PRO_MODE;
|
||||
|
||||
if (chip->non_audio_spdif)
|
||||
control_reg |= E3G_SPDIF_NOT_AUDIO;
|
||||
|
||||
control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL |
|
||||
E3G_SPDIF_COPY_PERMIT;
|
||||
|
||||
return control_reg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the S/PDIF output format */
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof)
|
||||
{
|
||||
u32 control_reg;
|
||||
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
chip->professional_spdif = prof;
|
||||
control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate);
|
||||
return write_control_reg(chip, control_reg, get_frq_reg(chip), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* detect_input_clocks() returns a bitmask consisting of all the input clocks
|
||||
currently connected to the hardware; this changes as the user connects and
|
||||
disconnects clock inputs. You should use this information to determine which
|
||||
clocks the user is allowed to select. */
|
||||
static u32 detect_input_clocks(const struct echoaudio *chip)
|
||||
{
|
||||
u32 clocks_from_dsp, clock_bits;
|
||||
|
||||
/* Map the DSP clock detect bits to the generic driver clock
|
||||
* detect bits */
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
|
||||
|
||||
if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD)
|
||||
clock_bits |= ECHO_CLOCK_BIT_WORD;
|
||||
|
||||
switch(chip->digital_mode) {
|
||||
case DIGITAL_MODE_SPDIF_RCA:
|
||||
case DIGITAL_MODE_SPDIF_OPTICAL:
|
||||
if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF)
|
||||
clock_bits |= ECHO_CLOCK_BIT_SPDIF;
|
||||
break;
|
||||
case DIGITAL_MODE_ADAT:
|
||||
if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT)
|
||||
clock_bits |= ECHO_CLOCK_BIT_ADAT;
|
||||
break;
|
||||
}
|
||||
|
||||
return clock_bits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int load_asic(struct echoaudio *chip)
|
||||
{
|
||||
int box_type, err;
|
||||
|
||||
if (chip->asic_loaded)
|
||||
return 0;
|
||||
|
||||
/* Give the DSP a few milliseconds to settle down */
|
||||
mdelay(2);
|
||||
|
||||
err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC,
|
||||
&card_fw[FW_3G_ASIC]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
chip->asic_code = &card_fw[FW_3G_ASIC];
|
||||
|
||||
/* Now give the new ASIC a little time to set up */
|
||||
mdelay(2);
|
||||
/* See if it worked */
|
||||
box_type = check_asic_status(chip);
|
||||
|
||||
/* Set up the control register if the load succeeded -
|
||||
* 48 kHz, internal clock, S/PDIF RCA mode */
|
||||
if (box_type >= 0) {
|
||||
err = write_control_reg(chip, E3G_48KHZ,
|
||||
E3G_FREQ_REG_DEFAULT, TRUE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return box_type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate)
|
||||
{
|
||||
u32 control_reg, clock, base_rate, frq_reg;
|
||||
|
||||
/* Only set the clock for internal mode. */
|
||||
if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
|
||||
DE_ACT(("set_sample_rate: Cannot set sample rate - "
|
||||
"clock not set to CLK_CLOCKININTERNAL\n"));
|
||||
/* Save the rate anyhow */
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate);
|
||||
chip->sample_rate = rate;
|
||||
set_input_clock(chip, chip->input_clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT,
|
||||
return -EINVAL);
|
||||
|
||||
clock = 0;
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
control_reg &= E3G_CLOCK_CLEAR_MASK;
|
||||
|
||||
switch (rate) {
|
||||
case 96000:
|
||||
clock = E3G_96KHZ;
|
||||
break;
|
||||
case 88200:
|
||||
clock = E3G_88KHZ;
|
||||
break;
|
||||
case 48000:
|
||||
clock = E3G_48KHZ;
|
||||
break;
|
||||
case 44100:
|
||||
clock = E3G_44KHZ;
|
||||
break;
|
||||
case 32000:
|
||||
clock = E3G_32KHZ;
|
||||
break;
|
||||
default:
|
||||
clock = E3G_CONTINUOUS_CLOCK;
|
||||
if (rate > 50000)
|
||||
clock |= E3G_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
control_reg |= clock;
|
||||
control_reg = set_spdif_bits(chip, control_reg, rate);
|
||||
|
||||
base_rate = rate;
|
||||
if (base_rate > 50000)
|
||||
base_rate /= 2;
|
||||
if (base_rate < 32000)
|
||||
base_rate = 32000;
|
||||
|
||||
frq_reg = E3G_MAGIC_NUMBER / base_rate - 2;
|
||||
if (frq_reg > E3G_FREQ_REG_MAX)
|
||||
frq_reg = E3G_FREQ_REG_MAX;
|
||||
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */
|
||||
chip->sample_rate = rate;
|
||||
DE_ACT(("SetSampleRate: %d clock %x\n", rate, control_reg));
|
||||
|
||||
/* Tell the DSP about it - DSP reads both control reg & freq reg */
|
||||
return write_control_reg(chip, control_reg, frq_reg, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the sample clock source to internal, S/PDIF, ADAT */
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock)
|
||||
{
|
||||
u32 control_reg, clocks_from_dsp;
|
||||
|
||||
DE_ACT(("set_input_clock:\n"));
|
||||
|
||||
/* Mask off the clock select bits */
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register) &
|
||||
E3G_CLOCK_CLEAR_MASK;
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
switch (clock) {
|
||||
case ECHO_CLOCK_INTERNAL:
|
||||
DE_ACT(("Set Echo3G clock to INTERNAL\n"));
|
||||
chip->input_clock = ECHO_CLOCK_INTERNAL;
|
||||
return set_sample_rate(chip, chip->sample_rate);
|
||||
case ECHO_CLOCK_SPDIF:
|
||||
if (chip->digital_mode == DIGITAL_MODE_ADAT)
|
||||
return -EAGAIN;
|
||||
DE_ACT(("Set Echo3G clock to SPDIF\n"));
|
||||
control_reg |= E3G_SPDIF_CLOCK;
|
||||
if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96)
|
||||
control_reg |= E3G_DOUBLE_SPEED_MODE;
|
||||
else
|
||||
control_reg &= ~E3G_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
case ECHO_CLOCK_ADAT:
|
||||
if (chip->digital_mode != DIGITAL_MODE_ADAT)
|
||||
return -EAGAIN;
|
||||
DE_ACT(("Set Echo3G clock to ADAT\n"));
|
||||
control_reg |= E3G_ADAT_CLOCK;
|
||||
control_reg &= ~E3G_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
case ECHO_CLOCK_WORD:
|
||||
DE_ACT(("Set Echo3G clock to WORD\n"));
|
||||
control_reg |= E3G_WORD_CLOCK;
|
||||
if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96)
|
||||
control_reg |= E3G_DOUBLE_SPEED_MODE;
|
||||
else
|
||||
control_reg &= ~E3G_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("Input clock 0x%x not supported for Echo3G\n", clock));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip->input_clock = clock;
|
||||
return write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
|
||||
{
|
||||
u32 control_reg;
|
||||
int err, incompatible_clock;
|
||||
|
||||
/* Set clock to "internal" if it's not compatible with the new mode */
|
||||
incompatible_clock = FALSE;
|
||||
switch (mode) {
|
||||
case DIGITAL_MODE_SPDIF_OPTICAL:
|
||||
case DIGITAL_MODE_SPDIF_RCA:
|
||||
if (chip->input_clock == ECHO_CLOCK_ADAT)
|
||||
incompatible_clock = TRUE;
|
||||
break;
|
||||
case DIGITAL_MODE_ADAT:
|
||||
if (chip->input_clock == ECHO_CLOCK_SPDIF)
|
||||
incompatible_clock = TRUE;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("Digital mode not supported: %d\n", mode));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irq(&chip->lock);
|
||||
|
||||
if (incompatible_clock) {
|
||||
chip->sample_rate = 48000;
|
||||
set_input_clock(chip, ECHO_CLOCK_INTERNAL);
|
||||
}
|
||||
|
||||
/* Clear the current digital mode */
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK;
|
||||
|
||||
/* Tweak the control reg */
|
||||
switch (mode) {
|
||||
case DIGITAL_MODE_SPDIF_OPTICAL:
|
||||
control_reg |= E3G_SPDIF_OPTICAL_MODE;
|
||||
break;
|
||||
case DIGITAL_MODE_SPDIF_RCA:
|
||||
/* E3G_SPDIF_OPTICAL_MODE bit cleared */
|
||||
break;
|
||||
case DIGITAL_MODE_ADAT:
|
||||
control_reg |= E3G_ADAT_MODE;
|
||||
control_reg &= ~E3G_DOUBLE_SPEED_MODE; /* @@ useless */
|
||||
break;
|
||||
}
|
||||
|
||||
err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1);
|
||||
spin_unlock_irq(&chip->lock);
|
||||
if (err < 0)
|
||||
return err;
|
||||
chip->digital_mode = mode;
|
||||
|
||||
DE_ACT(("set_digital_mode(%d)\n", chip->digital_mode));
|
||||
return incompatible_clock;
|
||||
}
|
||||
1125
sound/pci/echoaudio/echoaudio_dsp.c
Normal file
1125
sound/pci/echoaudio/echoaudio_dsp.c
Normal file
File diff suppressed because it is too large
Load Diff
694
sound/pci/echoaudio/echoaudio_dsp.h
Normal file
694
sound/pci/echoaudio/echoaudio_dsp.h
Normal file
File diff suppressed because it is too large
Load Diff
198
sound/pci/echoaudio/echoaudio_gml.c
Normal file
198
sound/pci/echoaudio/echoaudio_gml.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/* These functions are common for Gina24, Layla24 and Mona cards */
|
||||
|
||||
|
||||
/* ASIC status check - some cards have one or two ASICs that need to be
|
||||
loaded. Once that load is complete, this function is called to see if
|
||||
the load was successful.
|
||||
If this load fails, it does not necessarily mean that the hardware is
|
||||
defective - the external box may be disconnected or turned off. */
|
||||
static int check_asic_status(struct echoaudio *chip)
|
||||
{
|
||||
u32 asic_status;
|
||||
|
||||
send_vector(chip, DSP_VC_TEST_ASIC);
|
||||
|
||||
/* The DSP will return a value to indicate whether or not the
|
||||
ASIC is currently loaded */
|
||||
if (read_dsp(chip, &asic_status) < 0) {
|
||||
DE_INIT(("check_asic_status: failed on read_dsp\n"));
|
||||
chip->asic_loaded = FALSE;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED);
|
||||
return chip->asic_loaded ? 0 : -EIO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing
|
||||
the control register. write_control_reg sends the new control register
|
||||
value to the DSP. */
|
||||
static int write_control_reg(struct echoaudio *chip, u32 value, char force)
|
||||
{
|
||||
/* Handle the digital input auto-mute */
|
||||
if (chip->digital_in_automute)
|
||||
value |= GML_DIGITAL_IN_AUTO_MUTE;
|
||||
else
|
||||
value &= ~GML_DIGITAL_IN_AUTO_MUTE;
|
||||
|
||||
DE_ACT(("write_control_reg: 0x%x\n", value));
|
||||
|
||||
/* Write the control register */
|
||||
value = cpu_to_le32(value);
|
||||
if (value != chip->comm_page->control_register || force) {
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
chip->comm_page->control_register = value;
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_WRITE_CONTROL_REG);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital
|
||||
input auto-mute is enabled, the DSP will only enable the digital inputs if
|
||||
the card is syncing to a valid clock on the ADAT or S/PDIF inputs.
|
||||
If the auto-mute is disabled, the digital inputs are enabled regardless of
|
||||
what the input clock is set or what is connected. */
|
||||
static int set_input_auto_mute(struct echoaudio *chip, int automute)
|
||||
{
|
||||
DE_ACT(("set_input_auto_mute %d\n", automute));
|
||||
|
||||
chip->digital_in_automute = automute;
|
||||
|
||||
/* Re-set the input clock to the current value - indirectly causes
|
||||
the auto-mute flag to be sent to the DSP */
|
||||
return set_input_clock(chip, chip->input_clock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* S/PDIF coax / S/PDIF optical / ADAT - switch */
|
||||
static int set_digital_mode(struct echoaudio *chip, u8 mode)
|
||||
{
|
||||
u8 previous_mode;
|
||||
int err, i, o;
|
||||
|
||||
if (chip->bad_board)
|
||||
return -EIO;
|
||||
|
||||
/* All audio channels must be closed before changing the digital mode */
|
||||
snd_assert(!chip->pipe_alloc_mask, return -EAGAIN);
|
||||
|
||||
snd_assert(chip->digital_modes & (1 << mode), return -EINVAL);
|
||||
|
||||
previous_mode = chip->digital_mode;
|
||||
err = dsp_set_digital_mode(chip, mode);
|
||||
|
||||
/* If we successfully changed the digital mode from or to ADAT,
|
||||
then make sure all output, input and monitor levels are
|
||||
updated by the DSP comm object. */
|
||||
if (err >= 0 && previous_mode != mode &&
|
||||
(previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) {
|
||||
spin_lock_irq(&chip->lock);
|
||||
for (o = 0; o < num_busses_out(chip); o++)
|
||||
for (i = 0; i < num_busses_in(chip); i++)
|
||||
set_monitor_gain(chip, o, i,
|
||||
chip->monitor_gain[o][i]);
|
||||
|
||||
#ifdef ECHOCARD_HAS_INPUT_GAIN
|
||||
for (i = 0; i < num_busses_in(chip); i++)
|
||||
set_input_gain(chip, i, chip->input_gain[i]);
|
||||
update_input_line_level(chip);
|
||||
#endif
|
||||
|
||||
for (o = 0; o < num_busses_out(chip); o++)
|
||||
set_output_gain(chip, o, chip->output_gain[o]);
|
||||
update_output_line_level(chip);
|
||||
spin_unlock_irq(&chip->lock);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set the S/PDIF output format */
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof)
|
||||
{
|
||||
u32 control_reg;
|
||||
int err;
|
||||
|
||||
/* Clear the current S/PDIF flags */
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK;
|
||||
|
||||
/* Set the new S/PDIF flags depending on the mode */
|
||||
control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT |
|
||||
GML_SPDIF_COPY_PERMIT;
|
||||
if (prof) {
|
||||
/* Professional mode */
|
||||
control_reg |= GML_SPDIF_PRO_MODE;
|
||||
|
||||
switch (chip->sample_rate) {
|
||||
case 32000:
|
||||
control_reg |= GML_SPDIF_SAMPLE_RATE0 |
|
||||
GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
case 44100:
|
||||
control_reg |= GML_SPDIF_SAMPLE_RATE0;
|
||||
break;
|
||||
case 48000:
|
||||
control_reg |= GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Consumer mode */
|
||||
switch (chip->sample_rate) {
|
||||
case 32000:
|
||||
control_reg |= GML_SPDIF_SAMPLE_RATE0 |
|
||||
GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
case 48000:
|
||||
control_reg |= GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = write_control_reg(chip, control_reg, FALSE)))
|
||||
return err;
|
||||
chip->professional_spdif = prof;
|
||||
DE_ACT(("set_professional_spdif to %s\n",
|
||||
prof ? "Professional" : "Consumer"));
|
||||
return 0;
|
||||
}
|
||||
103
sound/pci/echoaudio/gina20.c
Normal file
103
sound/pci/echoaudio/gina20.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* ALSA driver for Echoaudio soundcards.
|
||||
* Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define ECHOGALS_FAMILY
|
||||
#define ECHOCARD_GINA20
|
||||
#define ECHOCARD_NAME "Gina20"
|
||||
#define ECHOCARD_HAS_MONITOR
|
||||
#define ECHOCARD_HAS_INPUT_GAIN
|
||||
#define ECHOCARD_HAS_DIGITAL_IO
|
||||
#define ECHOCARD_HAS_EXTERNAL_CLOCK
|
||||
#define ECHOCARD_HAS_ADAT FALSE
|
||||
|
||||
/* Pipe indexes */
|
||||
#define PX_ANALOG_OUT 0 /* 8 */
|
||||
#define PX_DIGITAL_OUT 8 /* 2 */
|
||||
#define PX_ANALOG_IN 10 /* 2 */
|
||||
#define PX_DIGITAL_IN 12 /* 2 */
|
||||
#define PX_NUM 14
|
||||
|
||||
/* Bus indexes */
|
||||
#define BX_ANALOG_OUT 0 /* 8 */
|
||||
#define BX_DIGITAL_OUT 8 /* 2 */
|
||||
#define BX_ANALOG_IN 10 /* 2 */
|
||||
#define BX_DIGITAL_IN 12 /* 2 */
|
||||
#define BX_NUM 14
|
||||
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/asoundef.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "echoaudio.h"
|
||||
|
||||
#define FW_GINA20_DSP 0
|
||||
|
||||
static const struct firmware card_fw[] = {
|
||||
{0, "gina20_dsp.fw"}
|
||||
};
|
||||
|
||||
static struct pci_device_id snd_echo_ids[] = {
|
||||
{0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */
|
||||
{0,}
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware pcm_hardware_skel = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_SYNC_START,
|
||||
.formats = SNDRV_PCM_FMTBIT_U8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_BE,
|
||||
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 262144,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 131072,
|
||||
.periods_min = 2,
|
||||
.periods_max = 220,
|
||||
/* One page (4k) contains 512 instructions. I don't know if the hw
|
||||
supports lists longer than this. In this case periods_max=220 is a
|
||||
safe limit to make sure the list never exceeds 512 instructions. */
|
||||
};
|
||||
|
||||
|
||||
#include "gina20_dsp.c"
|
||||
#include "echoaudio_dsp.c"
|
||||
#include "echoaudio.c"
|
||||
215
sound/pci/echoaudio/gina20_dsp.c
Normal file
215
sound/pci/echoaudio/gina20_dsp.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/****************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof);
|
||||
static int update_flags(struct echoaudio *chip);
|
||||
|
||||
|
||||
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
DE_INIT(("init_hw() - Gina20\n"));
|
||||
snd_assert((subdevice_id & 0xfff0) == GINA20, return -ENODEV);
|
||||
|
||||
if ((err = init_dsp_comm_page(chip))) {
|
||||
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->device_id = device_id;
|
||||
chip->subdevice_id = subdevice_id;
|
||||
chip->bad_board = TRUE;
|
||||
chip->dsp_code_to_load = &card_fw[FW_GINA20_DSP];
|
||||
chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
|
||||
chip->clock_state = GD_CLOCK_UNDEF;
|
||||
/* Since this card has no ASIC, mark it as loaded so everything
|
||||
works OK */
|
||||
chip->asic_loaded = TRUE;
|
||||
chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL |
|
||||
ECHO_CLOCK_BIT_SPDIF;
|
||||
|
||||
if ((err = load_firmware(chip)) < 0)
|
||||
return err;
|
||||
chip->bad_board = FALSE;
|
||||
|
||||
if ((err = init_line_levels(chip)) < 0)
|
||||
return err;
|
||||
|
||||
err = set_professional_spdif(chip, TRUE);
|
||||
|
||||
DE_INIT(("init_hw done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 detect_input_clocks(const struct echoaudio *chip)
|
||||
{
|
||||
u32 clocks_from_dsp, clock_bits;
|
||||
|
||||
/* Map the DSP clock detect bits to the generic driver clock
|
||||
detect bits */
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
|
||||
|
||||
if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF)
|
||||
clock_bits |= ECHO_CLOCK_BIT_SPDIF;
|
||||
|
||||
return clock_bits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The Gina20 has no ASIC. Just do nothing */
|
||||
static int load_asic(struct echoaudio *chip)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate)
|
||||
{
|
||||
u8 clock_state, spdif_status;
|
||||
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
switch (rate) {
|
||||
case 44100:
|
||||
clock_state = GD_CLOCK_44;
|
||||
spdif_status = GD_SPDIF_STATUS_44;
|
||||
break;
|
||||
case 48000:
|
||||
clock_state = GD_CLOCK_48;
|
||||
spdif_status = GD_SPDIF_STATUS_48;
|
||||
break;
|
||||
default:
|
||||
clock_state = GD_CLOCK_NOCHANGE;
|
||||
spdif_status = GD_SPDIF_STATUS_NOCHANGE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chip->clock_state == clock_state)
|
||||
clock_state = GD_CLOCK_NOCHANGE;
|
||||
if (spdif_status == chip->spdif_status)
|
||||
spdif_status = GD_SPDIF_STATUS_NOCHANGE;
|
||||
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate);
|
||||
chip->comm_page->gd_clock_state = clock_state;
|
||||
chip->comm_page->gd_spdif_status = spdif_status;
|
||||
chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */
|
||||
|
||||
/* Save the new audio state if it changed */
|
||||
if (clock_state != GD_CLOCK_NOCHANGE)
|
||||
chip->clock_state = clock_state;
|
||||
if (spdif_status != GD_SPDIF_STATUS_NOCHANGE)
|
||||
chip->spdif_status = spdif_status;
|
||||
chip->sample_rate = rate;
|
||||
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock)
|
||||
{
|
||||
DE_ACT(("set_input_clock:\n"));
|
||||
|
||||
switch (clock) {
|
||||
case ECHO_CLOCK_INTERNAL:
|
||||
/* Reset the audio state to unknown (just in case) */
|
||||
chip->clock_state = GD_CLOCK_UNDEF;
|
||||
chip->spdif_status = GD_SPDIF_STATUS_UNDEF;
|
||||
set_sample_rate(chip, chip->sample_rate);
|
||||
chip->input_clock = clock;
|
||||
DE_ACT(("Set Gina clock to INTERNAL\n"));
|
||||
break;
|
||||
case ECHO_CLOCK_SPDIF:
|
||||
chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN;
|
||||
chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE;
|
||||
clear_handshake(chip);
|
||||
send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE);
|
||||
chip->clock_state = GD_CLOCK_SPDIFIN;
|
||||
DE_ACT(("Set Gina20 clock to SPDIF\n"));
|
||||
chip->input_clock = clock;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Set input bus gain (one unit is 0.5dB !) */
|
||||
static int set_input_gain(struct echoaudio *chip, u16 input, int gain)
|
||||
{
|
||||
snd_assert(input < num_busses_in(chip), return -EINVAL);
|
||||
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
|
||||
chip->input_gain[input] = gain;
|
||||
gain += GL20_INPUT_GAIN_MAGIC_NUMBER;
|
||||
chip->comm_page->line_in_level[input] = gain;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Tell the DSP to reread the flags from the comm page */
|
||||
static int update_flags(struct echoaudio *chip)
|
||||
{
|
||||
if (wait_handshake(chip))
|
||||
return -EIO;
|
||||
clear_handshake(chip);
|
||||
return send_vector(chip, DSP_VC_UPDATE_FLAGS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof)
|
||||
{
|
||||
DE_ACT(("set_professional_spdif %d\n", prof));
|
||||
if (prof)
|
||||
chip->comm_page->flags |=
|
||||
__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
|
||||
else
|
||||
chip->comm_page->flags &=
|
||||
~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF);
|
||||
chip->professional_spdif = prof;
|
||||
return update_flags(chip);
|
||||
}
|
||||
123
sound/pci/echoaudio/gina24.c
Normal file
123
sound/pci/echoaudio/gina24.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* ALSA driver for Echoaudio soundcards.
|
||||
* Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define ECHO24_FAMILY
|
||||
#define ECHOCARD_GINA24
|
||||
#define ECHOCARD_NAME "Gina24"
|
||||
#define ECHOCARD_HAS_MONITOR
|
||||
#define ECHOCARD_HAS_ASIC
|
||||
#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL
|
||||
#define ECHOCARD_HAS_SUPER_INTERLEAVE
|
||||
#define ECHOCARD_HAS_DIGITAL_IO
|
||||
#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE
|
||||
#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH
|
||||
#define ECHOCARD_HAS_EXTERNAL_CLOCK
|
||||
#define ECHOCARD_HAS_ADAT 6
|
||||
#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
|
||||
|
||||
/* Pipe indexes */
|
||||
#define PX_ANALOG_OUT 0 /* 8 */
|
||||
#define PX_DIGITAL_OUT 8 /* 8 */
|
||||
#define PX_ANALOG_IN 16 /* 2 */
|
||||
#define PX_DIGITAL_IN 18 /* 8 */
|
||||
#define PX_NUM 26
|
||||
|
||||
/* Bus indexes */
|
||||
#define BX_ANALOG_OUT 0 /* 8 */
|
||||
#define BX_DIGITAL_OUT 8 /* 8 */
|
||||
#define BX_ANALOG_IN 16 /* 2 */
|
||||
#define BX_DIGITAL_IN 18 /* 8 */
|
||||
#define BX_NUM 26
|
||||
|
||||
|
||||
#include <sound/driver.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/asoundef.h>
|
||||
#include <sound/initval.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "echoaudio.h"
|
||||
|
||||
#define FW_361_LOADER 0
|
||||
#define FW_GINA24_301_DSP 1
|
||||
#define FW_GINA24_361_DSP 2
|
||||
#define FW_GINA24_301_ASIC 3
|
||||
#define FW_GINA24_361_ASIC 4
|
||||
|
||||
static const struct firmware card_fw[] = {
|
||||
{0, "loader_dsp.fw"},
|
||||
{0, "gina24_301_dsp.fw"},
|
||||
{0, "gina24_361_dsp.fw"},
|
||||
{0, "gina24_301_asic.fw"},
|
||||
{0, "gina24_361_asic.fw"}
|
||||
};
|
||||
|
||||
static struct pci_device_id snd_echo_ids[] = {
|
||||
{0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */
|
||||
{0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */
|
||||
{0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */
|
||||
{0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */
|
||||
{0,}
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware pcm_hardware_skel = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_PAUSE |
|
||||
SNDRV_PCM_INFO_SYNC_START,
|
||||
.formats = SNDRV_PCM_FMTBIT_U8 |
|
||||
SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_3LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_BE,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 96000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.buffer_bytes_max = 262144,
|
||||
.period_bytes_min = 32,
|
||||
.period_bytes_max = 131072,
|
||||
.periods_min = 2,
|
||||
.periods_max = 220,
|
||||
/* One page (4k) contains 512 instructions. I don't know if the hw
|
||||
supports lists longer than this. In this case periods_max=220 is a
|
||||
safe limit to make sure the list never exceeds 512 instructions.
|
||||
220 ~= (512 - 1 - (BUFFER_BYTES_MAX / PAGE_SIZE)) / 2 */
|
||||
};
|
||||
|
||||
#include "gina24_dsp.c"
|
||||
#include "echoaudio_dsp.c"
|
||||
#include "echoaudio_gml.c"
|
||||
#include "echoaudio.c"
|
||||
346
sound/pci/echoaudio/gina24_dsp.c
Normal file
346
sound/pci/echoaudio/gina24_dsp.c
Normal file
@@ -0,0 +1,346 @@
|
||||
/****************************************************************************
|
||||
|
||||
Copyright Echo Digital Audio Corporation (c) 1998 - 2004
|
||||
All rights reserved
|
||||
www.echoaudio.com
|
||||
|
||||
This file is part of Echo Digital Audio's generic driver library.
|
||||
|
||||
Echo Digital Audio's generic driver library is free software;
|
||||
you can redistribute it and/or modify it under the terms of
|
||||
the GNU General Public License as published by the Free Software
|
||||
Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA.
|
||||
|
||||
*************************************************************************
|
||||
|
||||
Translation from C++ and adaptation for use in ALSA-Driver
|
||||
were made by Giuliano Pochini <pochini@shiny.it>
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
static int write_control_reg(struct echoaudio *chip, u32 value, char force);
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock);
|
||||
static int set_professional_spdif(struct echoaudio *chip, char prof);
|
||||
static int set_digital_mode(struct echoaudio *chip, u8 mode);
|
||||
static int load_asic_generic(struct echoaudio *chip, u32 cmd,
|
||||
const struct firmware *asic);
|
||||
static int check_asic_status(struct echoaudio *chip);
|
||||
|
||||
|
||||
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
|
||||
{
|
||||
int err;
|
||||
|
||||
DE_INIT(("init_hw() - Gina24\n"));
|
||||
snd_assert((subdevice_id & 0xfff0) == GINA24, return -ENODEV);
|
||||
|
||||
if ((err = init_dsp_comm_page(chip))) {
|
||||
DE_INIT(("init_hw - could not initialize DSP comm page\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
chip->device_id = device_id;
|
||||
chip->subdevice_id = subdevice_id;
|
||||
chip->bad_board = TRUE;
|
||||
chip->input_clock_types =
|
||||
ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
|
||||
ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 |
|
||||
ECHO_CLOCK_BIT_ADAT;
|
||||
chip->professional_spdif = FALSE;
|
||||
chip->digital_in_automute = TRUE;
|
||||
chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
|
||||
|
||||
/* Gina24 comes in both '301 and '361 flavors */
|
||||
if (chip->device_id == DEVICE_ID_56361) {
|
||||
chip->dsp_code_to_load = &card_fw[FW_GINA24_361_DSP];
|
||||
chip->digital_modes =
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
|
||||
} else {
|
||||
chip->dsp_code_to_load = &card_fw[FW_GINA24_301_DSP];
|
||||
chip->digital_modes =
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_ADAT |
|
||||
ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM;
|
||||
}
|
||||
|
||||
if ((err = load_firmware(chip)) < 0)
|
||||
return err;
|
||||
chip->bad_board = FALSE;
|
||||
|
||||
if ((err = init_line_levels(chip)) < 0)
|
||||
return err;
|
||||
err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA);
|
||||
snd_assert(err >= 0, return err);
|
||||
err = set_professional_spdif(chip, TRUE);
|
||||
|
||||
DE_INIT(("init_hw done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 detect_input_clocks(const struct echoaudio *chip)
|
||||
{
|
||||
u32 clocks_from_dsp, clock_bits;
|
||||
|
||||
/* Map the DSP clock detect bits to the generic driver clock
|
||||
detect bits */
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
clock_bits = ECHO_CLOCK_BIT_INTERNAL;
|
||||
|
||||
if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
|
||||
clock_bits |= ECHO_CLOCK_BIT_SPDIF;
|
||||
|
||||
if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
|
||||
clock_bits |= ECHO_CLOCK_BIT_ADAT;
|
||||
|
||||
if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC)
|
||||
clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
|
||||
|
||||
return clock_bits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Gina24 has an ASIC on the PCI card which must be loaded for anything
|
||||
interesting to happen. */
|
||||
static int load_asic(struct echoaudio *chip)
|
||||
{
|
||||
u32 control_reg;
|
||||
int err;
|
||||
const struct firmware *fw;
|
||||
|
||||
if (chip->asic_loaded)
|
||||
return 1;
|
||||
|
||||
/* Give the DSP a few milliseconds to settle down */
|
||||
mdelay(10);
|
||||
|
||||
/* Pick the correct ASIC for '301 or '361 Gina24 */
|
||||
if (chip->device_id == DEVICE_ID_56361)
|
||||
fw = &card_fw[FW_GINA24_361_ASIC];
|
||||
else
|
||||
fw = &card_fw[FW_GINA24_301_ASIC];
|
||||
|
||||
if ((err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, fw)) < 0)
|
||||
return err;
|
||||
|
||||
chip->asic_code = fw;
|
||||
|
||||
/* Now give the new ASIC a little time to set up */
|
||||
mdelay(10);
|
||||
/* See if it worked */
|
||||
err = check_asic_status(chip);
|
||||
|
||||
/* Set up the control register if the load succeeded -
|
||||
48 kHz, internal clock, S/PDIF RCA mode */
|
||||
if (!err) {
|
||||
control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;
|
||||
err = write_control_reg(chip, control_reg, TRUE);
|
||||
}
|
||||
DE_INIT(("load_asic() done\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_sample_rate(struct echoaudio *chip, u32 rate)
|
||||
{
|
||||
u32 control_reg, clock;
|
||||
|
||||
snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT,
|
||||
return -EINVAL);
|
||||
|
||||
/* Only set the clock for internal mode. */
|
||||
if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
|
||||
DE_ACT(("set_sample_rate: Cannot set sample rate - "
|
||||
"clock not set to CLK_CLOCKININTERNAL\n"));
|
||||
/* Save the rate anyhow */
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate);
|
||||
chip->sample_rate = rate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clock = 0;
|
||||
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
|
||||
|
||||
switch (rate) {
|
||||
case 96000:
|
||||
clock = GML_96KHZ;
|
||||
break;
|
||||
case 88200:
|
||||
clock = GML_88KHZ;
|
||||
break;
|
||||
case 48000:
|
||||
clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
case 44100:
|
||||
clock = GML_44KHZ;
|
||||
/* Professional mode ? */
|
||||
if (control_reg & GML_SPDIF_PRO_MODE)
|
||||
clock |= GML_SPDIF_SAMPLE_RATE0;
|
||||
break;
|
||||
case 32000:
|
||||
clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
|
||||
GML_SPDIF_SAMPLE_RATE1;
|
||||
break;
|
||||
case 22050:
|
||||
clock = GML_22KHZ;
|
||||
break;
|
||||
case 16000:
|
||||
clock = GML_16KHZ;
|
||||
break;
|
||||
case 11025:
|
||||
clock = GML_11KHZ;
|
||||
break;
|
||||
case 8000:
|
||||
clock = GML_8KHZ;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("set_sample_rate: %d invalid!\n", rate));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
control_reg |= clock;
|
||||
|
||||
chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */
|
||||
chip->sample_rate = rate;
|
||||
DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock));
|
||||
|
||||
return write_control_reg(chip, control_reg, FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int set_input_clock(struct echoaudio *chip, u16 clock)
|
||||
{
|
||||
u32 control_reg, clocks_from_dsp;
|
||||
|
||||
DE_ACT(("set_input_clock:\n"));
|
||||
|
||||
/* Mask off the clock select bits */
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register) &
|
||||
GML_CLOCK_CLEAR_MASK;
|
||||
clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
|
||||
|
||||
switch (clock) {
|
||||
case ECHO_CLOCK_INTERNAL:
|
||||
DE_ACT(("Set Gina24 clock to INTERNAL\n"));
|
||||
chip->input_clock = ECHO_CLOCK_INTERNAL;
|
||||
return set_sample_rate(chip, chip->sample_rate);
|
||||
case ECHO_CLOCK_SPDIF:
|
||||
if (chip->digital_mode == DIGITAL_MODE_ADAT)
|
||||
return -EAGAIN;
|
||||
DE_ACT(("Set Gina24 clock to SPDIF\n"));
|
||||
control_reg |= GML_SPDIF_CLOCK;
|
||||
if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)
|
||||
control_reg |= GML_DOUBLE_SPEED_MODE;
|
||||
else
|
||||
control_reg &= ~GML_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
case ECHO_CLOCK_ADAT:
|
||||
if (chip->digital_mode != DIGITAL_MODE_ADAT)
|
||||
return -EAGAIN;
|
||||
DE_ACT(("Set Gina24 clock to ADAT\n"));
|
||||
control_reg |= GML_ADAT_CLOCK;
|
||||
control_reg &= ~GML_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
case ECHO_CLOCK_ESYNC:
|
||||
DE_ACT(("Set Gina24 clock to ESYNC\n"));
|
||||
control_reg |= GML_ESYNC_CLOCK;
|
||||
control_reg &= ~GML_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
case ECHO_CLOCK_ESYNC96:
|
||||
DE_ACT(("Set Gina24 clock to ESYNC96\n"));
|
||||
control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip->input_clock = clock;
|
||||
return write_control_reg(chip, control_reg, TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
|
||||
{
|
||||
u32 control_reg;
|
||||
int err, incompatible_clock;
|
||||
|
||||
/* Set clock to "internal" if it's not compatible with the new mode */
|
||||
incompatible_clock = FALSE;
|
||||
switch (mode) {
|
||||
case DIGITAL_MODE_SPDIF_OPTICAL:
|
||||
case DIGITAL_MODE_SPDIF_CDROM:
|
||||
case DIGITAL_MODE_SPDIF_RCA:
|
||||
if (chip->input_clock == ECHO_CLOCK_ADAT)
|
||||
incompatible_clock = TRUE;
|
||||
break;
|
||||
case DIGITAL_MODE_ADAT:
|
||||
if (chip->input_clock == ECHO_CLOCK_SPDIF)
|
||||
incompatible_clock = TRUE;
|
||||
break;
|
||||
default:
|
||||
DE_ACT(("Digital mode not supported: %d\n", mode));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irq(&chip->lock);
|
||||
|
||||
if (incompatible_clock) { /* Switch to 48KHz, internal */
|
||||
chip->sample_rate = 48000;
|
||||
set_input_clock(chip, ECHO_CLOCK_INTERNAL);
|
||||
}
|
||||
|
||||
/* Clear the current digital mode */
|
||||
control_reg = le32_to_cpu(chip->comm_page->control_register);
|
||||
control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
|
||||
|
||||
/* Tweak the control reg */
|
||||
switch (mode) {
|
||||
case DIGITAL_MODE_SPDIF_OPTICAL:
|
||||
control_reg |= GML_SPDIF_OPTICAL_MODE;
|
||||
break;
|
||||
case DIGITAL_MODE_SPDIF_CDROM:
|
||||
/* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */
|
||||
if (chip->device_id == DEVICE_ID_56301)
|
||||
control_reg |= GML_SPDIF_CDROM_MODE;
|
||||
break;
|
||||
case DIGITAL_MODE_SPDIF_RCA:
|
||||
/* GML_SPDIF_OPTICAL_MODE bit cleared */
|
||||
break;
|
||||
case DIGITAL_MODE_ADAT:
|
||||
control_reg |= GML_ADAT_MODE;
|
||||
control_reg &= ~GML_DOUBLE_SPEED_MODE;
|
||||
break;
|
||||
}
|
||||
|
||||
err = write_control_reg(chip, control_reg, TRUE);
|
||||
spin_unlock_irq(&chip->lock);
|
||||
if (err < 0)
|
||||
return err;
|
||||
chip->digital_mode = mode;
|
||||
|
||||
DE_ACT(("set_digital_mode to %d\n", chip->digital_mode));
|
||||
return incompatible_clock;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user