Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
b54fc8dd
Commit
b54fc8dd
authored
Mar 24, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/oxygen' into for-linus
parents
9fb5430c
873591db
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
507 additions
and
116 deletions
+507
-116
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/ALSA-Configuration.txt
+1
-1
sound/pci/Kconfig
sound/pci/Kconfig
+2
-1
sound/pci/oxygen/hifier.c
sound/pci/oxygen/hifier.c
+10
-2
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.c
+88
-26
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen.h
+18
-4
sound/pci/oxygen/oxygen_io.c
sound/pci/oxygen/oxygen_io.c
+31
-0
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_lib.c
+87
-13
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/virtuoso.c
+270
-69
No files found.
Documentation/sound/alsa/ALSA-Configuration.txt
View file @
b54fc8dd
...
@@ -1859,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
...
@@ -1859,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-------------------
-------------------
Module for sound cards based on the Asus AV100/AV200 chips,
Module for sound cards based on the Asus AV100/AV200 chips,
i.e., Xonar D1, DX, D2, D2X
and HDAV1.3 (Deluxe)
.
i.e., Xonar D1, DX, D2, D2X
, HDAV1.3 (Deluxe), and Essence STX
.
This module supports autoprobe and multiple cards.
This module supports autoprobe and multiple cards.
...
...
sound/pci/Kconfig
View file @
b54fc8dd
...
@@ -764,7 +764,8 @@ config SND_VIRTUOSO
...
@@ -764,7 +764,8 @@ config SND_VIRTUOSO
select SND_OXYGEN_LIB
select SND_OXYGEN_LIB
help
help
Say Y here to include support for sound cards based on the
Say Y here to include support for sound cards based on the
Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2 and D2X.
Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, and
Essence STX.
Support for the HDAV1.3 (Deluxe) is very experimental.
Support for the HDAV1.3 (Deluxe) is very experimental.
To compile this driver as a module, choose M here: the module
To compile this driver as a module, choose M here: the module
...
...
sound/pci/oxygen/hifier.c
View file @
b54fc8dd
...
@@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card");
...
@@ -45,6 +45,7 @@ MODULE_PARM_DESC(enable, "enable card");
static
struct
pci_device_id
hifier_ids
[]
__devinitdata
=
{
static
struct
pci_device_id
hifier_ids
[]
__devinitdata
=
{
{
OXYGEN_PCI_SUBID
(
0x14c3
,
0x1710
)
},
{
OXYGEN_PCI_SUBID
(
0x14c3
,
0x1710
)
},
{
OXYGEN_PCI_SUBID
(
0x14c3
,
0x1711
)
},
{
OXYGEN_PCI_SUBID
(
0x14c3
,
0x1711
)
},
{
OXYGEN_PCI_SUBID_BROKEN_EEPROM
},
{
}
{
}
};
};
MODULE_DEVICE_TABLE
(
pci
,
hifier_ids
);
MODULE_DEVICE_TABLE
(
pci
,
hifier_ids
);
...
@@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = {
...
@@ -151,7 +152,6 @@ static const struct oxygen_model model_hifier = {
.
shortname
=
"C-Media CMI8787"
,
.
shortname
=
"C-Media CMI8787"
,
.
longname
=
"C-Media Oxygen HD Audio"
,
.
longname
=
"C-Media Oxygen HD Audio"
,
.
chip
=
"CMI8788"
,
.
chip
=
"CMI8788"
,
.
owner
=
THIS_MODULE
,
.
init
=
hifier_init
,
.
init
=
hifier_init
,
.
control_filter
=
hifier_control_filter
,
.
control_filter
=
hifier_control_filter
,
.
cleanup
=
hifier_cleanup
,
.
cleanup
=
hifier_cleanup
,
...
@@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = {
...
@@ -173,6 +173,13 @@ static const struct oxygen_model model_hifier = {
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
};
};
static
int
__devinit
get_hifier_model
(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
{
chip
->
model
=
model_hifier
;
return
0
;
}
static
int
__devinit
hifier_probe
(
struct
pci_dev
*
pci
,
static
int
__devinit
hifier_probe
(
struct
pci_dev
*
pci
,
const
struct
pci_device_id
*
pci_id
)
const
struct
pci_device_id
*
pci_id
)
{
{
...
@@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci,
...
@@ -185,7 +192,8 @@ static int __devinit hifier_probe(struct pci_dev *pci,
++
dev
;
++
dev
;
return
-
ENOENT
;
return
-
ENOENT
;
}
}
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
&
model_hifier
,
0
);
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
hifier_ids
,
get_hifier_model
);
if
(
err
>=
0
)
if
(
err
>=
0
)
++
dev
;
++
dev
;
return
err
;
return
err
;
...
...
sound/pci/oxygen/oxygen.c
View file @
b54fc8dd
/*
/*
* C-Media CMI8788 driver for C-Media's reference design and
for the X-Meridian
* C-Media CMI8788 driver for C-Media's reference design and
similar models
*
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
*
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
*
*
* GPIO 0 -> DFS0 of AK5385
* GPIO 0 -> DFS0 of AK5385
* GPIO 1 -> DFS1 of AK5385
* GPIO 1 -> DFS1 of AK5385
* GPIO 8 -> enable headphone amplifier on HT-Omega models
*/
*/
#include <linux/delay.h>
#include <linux/delay.h>
...
@@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card");
...
@@ -61,7 +62,8 @@ MODULE_PARM_DESC(enable, "enable card");
enum
{
enum
{
MODEL_CMEDIA_REF
,
/* C-Media's reference design */
MODEL_CMEDIA_REF
,
/* C-Media's reference design */
MODEL_MERIDIAN
,
/* AuzenTech X-Meridian */
MODEL_MERIDIAN
,
/* AuzenTech X-Meridian */
MODEL_HALO
,
/* HT-Omega Claro halo */
MODEL_CLARO
,
/* HT-Omega Claro */
MODEL_CLARO_HALO
,
/* HT-Omega Claro halo */
};
};
static
struct
pci_device_id
oxygen_ids
[]
__devinitdata
=
{
static
struct
pci_device_id
oxygen_ids
[]
__devinitdata
=
{
...
@@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = {
...
@@ -74,8 +76,8 @@ static struct pci_device_id oxygen_ids[] __devinitdata = {
{
OXYGEN_PCI_SUBID
(
0x147a
,
0xa017
),
.
driver_data
=
MODEL_CMEDIA_REF
},
{
OXYGEN_PCI_SUBID
(
0x147a
,
0xa017
),
.
driver_data
=
MODEL_CMEDIA_REF
},
{
OXYGEN_PCI_SUBID
(
0x1a58
,
0x0910
),
.
driver_data
=
MODEL_CMEDIA_REF
},
{
OXYGEN_PCI_SUBID
(
0x1a58
,
0x0910
),
.
driver_data
=
MODEL_CMEDIA_REF
},
{
OXYGEN_PCI_SUBID
(
0x415a
,
0x5431
),
.
driver_data
=
MODEL_MERIDIAN
},
{
OXYGEN_PCI_SUBID
(
0x415a
,
0x5431
),
.
driver_data
=
MODEL_MERIDIAN
},
{
OXYGEN_PCI_SUBID
(
0x7284
,
0x9761
),
.
driver_data
=
MODEL_C
MEDIA_REF
},
{
OXYGEN_PCI_SUBID
(
0x7284
,
0x9761
),
.
driver_data
=
MODEL_C
LARO
},
{
OXYGEN_PCI_SUBID
(
0x7284
,
0x9781
),
.
driver_data
=
MODEL_HALO
},
{
OXYGEN_PCI_SUBID
(
0x7284
,
0x9781
),
.
driver_data
=
MODEL_
CLARO_
HALO
},
{
}
{
}
};
};
MODULE_DEVICE_TABLE
(
pci
,
oxygen_ids
);
MODULE_DEVICE_TABLE
(
pci
,
oxygen_ids
);
...
@@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
...
@@ -86,6 +88,8 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
#define GPIO_AK5385_DFS_DOUBLE 0x0001
#define GPIO_AK5385_DFS_DOUBLE 0x0001
#define GPIO_AK5385_DFS_QUAD 0x0002
#define GPIO_AK5385_DFS_QUAD 0x0002
#define GPIO_CLARO_HP 0x0100
struct
generic_data
{
struct
generic_data
{
u8
ak4396_ctl2
;
u8
ak4396_ctl2
;
u16
saved_wm8785_registers
[
2
];
u16
saved_wm8785_registers
[
2
];
...
@@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip)
...
@@ -196,10 +200,46 @@ static void meridian_init(struct oxygen *chip)
ak5385_init
(
chip
);
ak5385_init
(
chip
);
}
}
static
void
claro_enable_hp
(
struct
oxygen
*
chip
)
{
msleep
(
300
);
oxygen_set_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_CLARO_HP
);
oxygen_set_bits16
(
chip
,
OXYGEN_GPIO_DATA
,
GPIO_CLARO_HP
);
}
static
void
claro_init
(
struct
oxygen
*
chip
)
{
ak4396_init
(
chip
);
wm8785_init
(
chip
);
claro_enable_hp
(
chip
);
}
static
void
claro_halo_init
(
struct
oxygen
*
chip
)
{
ak4396_init
(
chip
);
ak5385_init
(
chip
);
claro_enable_hp
(
chip
);
}
static
void
generic_cleanup
(
struct
oxygen
*
chip
)
static
void
generic_cleanup
(
struct
oxygen
*
chip
)
{
{
}
}
static
void
claro_disable_hp
(
struct
oxygen
*
chip
)
{
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_DATA
,
GPIO_CLARO_HP
);
}
static
void
claro_cleanup
(
struct
oxygen
*
chip
)
{
claro_disable_hp
(
chip
);
}
static
void
claro_suspend
(
struct
oxygen
*
chip
)
{
claro_disable_hp
(
chip
);
}
static
void
generic_resume
(
struct
oxygen
*
chip
)
static
void
generic_resume
(
struct
oxygen
*
chip
)
{
{
ak4396_registers_init
(
chip
);
ak4396_registers_init
(
chip
);
...
@@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip)
...
@@ -211,6 +251,12 @@ static void meridian_resume(struct oxygen *chip)
ak4396_registers_init
(
chip
);
ak4396_registers_init
(
chip
);
}
}
static
void
claro_resume
(
struct
oxygen
*
chip
)
{
ak4396_registers_init
(
chip
);
claro_enable_hp
(
chip
);
}
static
void
set_ak4396_params
(
struct
oxygen
*
chip
,
static
void
set_ak4396_params
(
struct
oxygen
*
chip
,
struct
snd_pcm_hw_params
*
params
)
struct
snd_pcm_hw_params
*
params
)
{
{
...
@@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip,
...
@@ -293,30 +339,10 @@ static void set_ak5385_params(struct oxygen *chip,
static
const
DECLARE_TLV_DB_LINEAR
(
ak4396_db_scale
,
TLV_DB_GAIN_MUTE
,
0
);
static
const
DECLARE_TLV_DB_LINEAR
(
ak4396_db_scale
,
TLV_DB_GAIN_MUTE
,
0
);
static
int
generic_probe
(
struct
oxygen
*
chip
,
unsigned
long
driver_data
)
{
if
(
driver_data
==
MODEL_MERIDIAN
)
{
chip
->
model
.
init
=
meridian_init
;
chip
->
model
.
resume
=
meridian_resume
;
chip
->
model
.
set_adc_params
=
set_ak5385_params
;
chip
->
model
.
device_config
=
PLAYBACK_0_TO_I2S
|
PLAYBACK_1_TO_SPDIF
|
CAPTURE_0_FROM_I2S_2
|
CAPTURE_1_FROM_SPDIF
;
}
if
(
driver_data
==
MODEL_MERIDIAN
||
driver_data
==
MODEL_HALO
)
{
chip
->
model
.
misc_flags
=
OXYGEN_MISC_MIDI
;
chip
->
model
.
device_config
|=
MIDI_OUTPUT
|
MIDI_INPUT
;
}
return
0
;
}
static
const
struct
oxygen_model
model_generic
=
{
static
const
struct
oxygen_model
model_generic
=
{
.
shortname
=
"C-Media CMI8788"
,
.
shortname
=
"C-Media CMI8788"
,
.
longname
=
"C-Media Oxygen HD Audio"
,
.
longname
=
"C-Media Oxygen HD Audio"
,
.
chip
=
"CMI8788"
,
.
chip
=
"CMI8788"
,
.
owner
=
THIS_MODULE
,
.
probe
=
generic_probe
,
.
init
=
generic_init
,
.
init
=
generic_init
,
.
cleanup
=
generic_cleanup
,
.
cleanup
=
generic_cleanup
,
.
resume
=
generic_resume
,
.
resume
=
generic_resume
,
...
@@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = {
...
@@ -341,6 +367,42 @@ static const struct oxygen_model model_generic = {
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
};
};
static
int
__devinit
get_oxygen_model
(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
{
chip
->
model
=
model_generic
;
switch
(
id
->
driver_data
)
{
case
MODEL_MERIDIAN
:
chip
->
model
.
init
=
meridian_init
;
chip
->
model
.
resume
=
meridian_resume
;
chip
->
model
.
set_adc_params
=
set_ak5385_params
;
chip
->
model
.
device_config
=
PLAYBACK_0_TO_I2S
|
PLAYBACK_1_TO_SPDIF
|
CAPTURE_0_FROM_I2S_2
|
CAPTURE_1_FROM_SPDIF
;
break
;
case
MODEL_CLARO
:
chip
->
model
.
init
=
claro_init
;
chip
->
model
.
cleanup
=
claro_cleanup
;
chip
->
model
.
suspend
=
claro_suspend
;
chip
->
model
.
resume
=
claro_resume
;
break
;
case
MODEL_CLARO_HALO
:
chip
->
model
.
init
=
claro_halo_init
;
chip
->
model
.
cleanup
=
claro_cleanup
;
chip
->
model
.
suspend
=
claro_suspend
;
chip
->
model
.
resume
=
claro_resume
;
chip
->
model
.
set_adc_params
=
set_ak5385_params
;
break
;
}
if
(
id
->
driver_data
==
MODEL_MERIDIAN
||
id
->
driver_data
==
MODEL_CLARO_HALO
)
{
chip
->
model
.
misc_flags
=
OXYGEN_MISC_MIDI
;
chip
->
model
.
device_config
|=
MIDI_OUTPUT
|
MIDI_INPUT
;
}
return
0
;
}
static
int
__devinit
generic_oxygen_probe
(
struct
pci_dev
*
pci
,
static
int
__devinit
generic_oxygen_probe
(
struct
pci_dev
*
pci
,
const
struct
pci_device_id
*
pci_id
)
const
struct
pci_device_id
*
pci_id
)
{
{
...
@@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
...
@@ -353,8 +415,8 @@ static int __devinit generic_oxygen_probe(struct pci_dev *pci,
++
dev
;
++
dev
;
return
-
ENOENT
;
return
-
ENOENT
;
}
}
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
&
model_generic
,
pci_id
->
driver_data
);
oxygen_ids
,
get_oxygen_model
);
if
(
err
>=
0
)
if
(
err
>=
0
)
++
dev
;
++
dev
;
return
err
;
return
err
;
...
...
sound/pci/oxygen/oxygen.h
View file @
b54fc8dd
...
@@ -18,6 +18,8 @@
...
@@ -18,6 +18,8 @@
#define OXYGEN_IO_SIZE 0x100
#define OXYGEN_IO_SIZE 0x100
#define OXYGEN_EEPROM_ID 0x434d
/* "CM" */
/* model-specific configuration of outputs/inputs */
/* model-specific configuration of outputs/inputs */
#define PLAYBACK_0_TO_I2S 0x0001
#define PLAYBACK_0_TO_I2S 0x0001
/* PLAYBACK_0_TO_AC97_0 not implemented */
/* PLAYBACK_0_TO_AC97_0 not implemented */
...
@@ -49,7 +51,13 @@ enum {
...
@@ -49,7 +51,13 @@ enum {
.subvendor = sv, \
.subvendor = sv, \
.subdevice = sd
.subdevice = sd
#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1)
#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \
OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \
.driver_data = BROKEN_EEPROM_DRIVER_DATA
struct
pci_dev
;
struct
pci_dev
;
struct
pci_device_id
;
struct
snd_card
;
struct
snd_card
;
struct
snd_pcm_substream
;
struct
snd_pcm_substream
;
struct
snd_pcm_hardware
;
struct
snd_pcm_hardware
;
...
@@ -62,8 +70,6 @@ struct oxygen_model {
...
@@ -62,8 +70,6 @@ struct oxygen_model {
const
char
*
shortname
;
const
char
*
shortname
;
const
char
*
longname
;
const
char
*
longname
;
const
char
*
chip
;
const
char
*
chip
;
struct
module
*
owner
;
int
(
*
probe
)(
struct
oxygen
*
chip
,
unsigned
long
driver_data
);
void
(
*
init
)(
struct
oxygen
*
chip
);
void
(
*
init
)(
struct
oxygen
*
chip
);
int
(
*
control_filter
)(
struct
snd_kcontrol_new
*
template
);
int
(
*
control_filter
)(
struct
snd_kcontrol_new
*
template
);
int
(
*
mixer_init
)(
struct
oxygen
*
chip
);
int
(
*
mixer_init
)(
struct
oxygen
*
chip
);
...
@@ -83,6 +89,7 @@ struct oxygen_model {
...
@@ -83,6 +89,7 @@ struct oxygen_model {
void
(
*
ac97_switch
)(
struct
oxygen
*
chip
,
void
(
*
ac97_switch
)(
struct
oxygen
*
chip
,
unsigned
int
reg
,
unsigned
int
mute
);
unsigned
int
reg
,
unsigned
int
mute
);
const
unsigned
int
*
dac_tlv
;
const
unsigned
int
*
dac_tlv
;
unsigned
long
private_data
;
size_t
model_data_size
;
size_t
model_data_size
;
unsigned
int
device_config
;
unsigned
int
device_config
;
u8
dac_channels
;
u8
dac_channels
;
...
@@ -134,8 +141,12 @@ struct oxygen {
...
@@ -134,8 +141,12 @@ struct oxygen {
/* oxygen_lib.c */
/* oxygen_lib.c */
int
oxygen_pci_probe
(
struct
pci_dev
*
pci
,
int
index
,
char
*
id
,
int
oxygen_pci_probe
(
struct
pci_dev
*
pci
,
int
index
,
char
*
id
,
const
struct
oxygen_model
*
model
,
struct
module
*
owner
,
unsigned
long
driver_data
);
const
struct
pci_device_id
*
ids
,
int
(
*
get_model
)(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
);
void
oxygen_pci_remove
(
struct
pci_dev
*
pci
);
void
oxygen_pci_remove
(
struct
pci_dev
*
pci
);
#ifdef CONFIG_PM
#ifdef CONFIG_PM
int
oxygen_pci_suspend
(
struct
pci_dev
*
pci
,
pm_message_t
state
);
int
oxygen_pci_suspend
(
struct
pci_dev
*
pci
,
pm_message_t
state
);
...
@@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
...
@@ -180,6 +191,9 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data);
void
oxygen_reset_uart
(
struct
oxygen
*
chip
);
void
oxygen_reset_uart
(
struct
oxygen
*
chip
);
void
oxygen_write_uart
(
struct
oxygen
*
chip
,
u8
data
);
void
oxygen_write_uart
(
struct
oxygen
*
chip
,
u8
data
);
u16
oxygen_read_eeprom
(
struct
oxygen
*
chip
,
unsigned
int
index
);
void
oxygen_write_eeprom
(
struct
oxygen
*
chip
,
unsigned
int
index
,
u16
value
);
static
inline
void
oxygen_set_bits8
(
struct
oxygen
*
chip
,
static
inline
void
oxygen_set_bits8
(
struct
oxygen
*
chip
,
unsigned
int
reg
,
u8
value
)
unsigned
int
reg
,
u8
value
)
{
{
...
...
sound/pci/oxygen/oxygen_io.c
View file @
b54fc8dd
...
@@ -254,3 +254,34 @@ void oxygen_write_uart(struct oxygen *chip, u8 data)
...
@@ -254,3 +254,34 @@ void oxygen_write_uart(struct oxygen *chip, u8 data)
_write_uart
(
chip
,
0
,
data
);
_write_uart
(
chip
,
0
,
data
);
}
}
EXPORT_SYMBOL
(
oxygen_write_uart
);
EXPORT_SYMBOL
(
oxygen_write_uart
);
u16
oxygen_read_eeprom
(
struct
oxygen
*
chip
,
unsigned
int
index
)
{
unsigned
int
timeout
;
oxygen_write8
(
chip
,
OXYGEN_EEPROM_CONTROL
,
index
|
OXYGEN_EEPROM_DIR_READ
);
for
(
timeout
=
0
;
timeout
<
100
;
++
timeout
)
{
udelay
(
1
);
if
(
!
(
oxygen_read8
(
chip
,
OXYGEN_EEPROM_STATUS
)
&
OXYGEN_EEPROM_BUSY
))
break
;
}
return
oxygen_read16
(
chip
,
OXYGEN_EEPROM_DATA
);
}
void
oxygen_write_eeprom
(
struct
oxygen
*
chip
,
unsigned
int
index
,
u16
value
)
{
unsigned
int
timeout
;
oxygen_write16
(
chip
,
OXYGEN_EEPROM_DATA
,
value
);
oxygen_write8
(
chip
,
OXYGEN_EEPROM_CONTROL
,
index
|
OXYGEN_EEPROM_DIR_WRITE
);
for
(
timeout
=
0
;
timeout
<
10
;
++
timeout
)
{
msleep
(
1
);
if
(
!
(
oxygen_read8
(
chip
,
OXYGEN_EEPROM_STATUS
)
&
OXYGEN_EEPROM_BUSY
))
return
;
}
snd_printk
(
KERN_ERR
"EEPROM write timeout
\n
"
);
}
sound/pci/oxygen/oxygen_lib.c
View file @
b54fc8dd
...
@@ -34,6 +34,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
...
@@ -34,6 +34,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION
(
"C-Media CMI8788 helper library"
);
MODULE_DESCRIPTION
(
"C-Media CMI8788 helper library"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_LICENSE
(
"GPL v2"
);
#define DRIVER "oxygen"
static
inline
int
oxygen_uart_input_ready
(
struct
oxygen
*
chip
)
static
inline
int
oxygen_uart_input_ready
(
struct
oxygen
*
chip
)
{
{
...
@@ -243,6 +244,62 @@ static void oxygen_proc_init(struct oxygen *chip)
...
@@ -243,6 +244,62 @@ static void oxygen_proc_init(struct oxygen *chip)
#define oxygen_proc_init(chip)
#define oxygen_proc_init(chip)
#endif
#endif
static
const
struct
pci_device_id
*
oxygen_search_pci_id
(
struct
oxygen
*
chip
,
const
struct
pci_device_id
ids
[])
{
u16
subdevice
;
/*
* Make sure the EEPROM pins are available, i.e., not used for SPI.
* (This function is called before we initialize or use SPI.)
*/
oxygen_clear_bits8
(
chip
,
OXYGEN_FUNCTION
,
OXYGEN_FUNCTION_ENABLE_SPI_4_5
);
/*
* Read the subsystem device ID directly from the EEPROM, because the
* chip didn't if the first EEPROM word was overwritten.
*/
subdevice
=
oxygen_read_eeprom
(
chip
,
2
);
/*
* We use only the subsystem device ID for searching because it is
* unique even without the subsystem vendor ID, which may have been
* overwritten in the EEPROM.
*/
for
(;
ids
->
vendor
;
++
ids
)
if
(
ids
->
subdevice
==
subdevice
&&
ids
->
driver_data
!=
BROKEN_EEPROM_DRIVER_DATA
)
return
ids
;
return
NULL
;
}
static
void
oxygen_restore_eeprom
(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
{
if
(
oxygen_read_eeprom
(
chip
,
0
)
!=
OXYGEN_EEPROM_ID
)
{
/*
* This function gets called only when a known card model has
* been detected, i.e., we know there is a valid subsystem
* product ID at index 2 in the EEPROM. Therefore, we have
* been able to deduce the correct subsystem vendor ID, and
* this is enough information to restore the original EEPROM
* contents.
*/
oxygen_write_eeprom
(
chip
,
1
,
id
->
subvendor
);
oxygen_write_eeprom
(
chip
,
0
,
OXYGEN_EEPROM_ID
);
oxygen_set_bits8
(
chip
,
OXYGEN_MISC
,
OXYGEN_MISC_WRITE_PCI_SUBID
);
pci_write_config_word
(
chip
->
pci
,
PCI_SUBSYSTEM_VENDOR_ID
,
id
->
subvendor
);
pci_write_config_word
(
chip
->
pci
,
PCI_SUBSYSTEM_ID
,
id
->
subdevice
);
oxygen_clear_bits8
(
chip
,
OXYGEN_MISC
,
OXYGEN_MISC_WRITE_PCI_SUBID
);
snd_printk
(
KERN_INFO
"EEPROM ID restored
\n
"
);
}
}
static
void
oxygen_init
(
struct
oxygen
*
chip
)
static
void
oxygen_init
(
struct
oxygen
*
chip
)
{
{
unsigned
int
i
;
unsigned
int
i
;
...
@@ -446,21 +503,26 @@ static void oxygen_card_free(struct snd_card *card)
...
@@ -446,21 +503,26 @@ static void oxygen_card_free(struct snd_card *card)
free_irq
(
chip
->
irq
,
chip
);
free_irq
(
chip
->
irq
,
chip
);
flush_scheduled_work
();
flush_scheduled_work
();
chip
->
model
.
cleanup
(
chip
);
chip
->
model
.
cleanup
(
chip
);
kfree
(
chip
->
model_data
);
mutex_destroy
(
&
chip
->
mutex
);
mutex_destroy
(
&
chip
->
mutex
);
pci_release_regions
(
chip
->
pci
);
pci_release_regions
(
chip
->
pci
);
pci_disable_device
(
chip
->
pci
);
pci_disable_device
(
chip
->
pci
);
}
}
int
oxygen_pci_probe
(
struct
pci_dev
*
pci
,
int
index
,
char
*
id
,
int
oxygen_pci_probe
(
struct
pci_dev
*
pci
,
int
index
,
char
*
id
,
const
struct
oxygen_model
*
model
,
struct
module
*
owner
,
unsigned
long
driver_data
)
const
struct
pci_device_id
*
ids
,
int
(
*
get_model
)(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
)
{
{
struct
snd_card
*
card
;
struct
snd_card
*
card
;
struct
oxygen
*
chip
;
struct
oxygen
*
chip
;
const
struct
pci_device_id
*
pci_id
;
int
err
;
int
err
;
err
=
snd_card_create
(
index
,
id
,
model
->
owner
,
err
=
snd_card_create
(
index
,
id
,
owner
,
sizeof
(
*
chip
),
&
card
);
sizeof
(
*
chip
)
+
model
->
model_data_size
,
&
card
);
if
(
err
<
0
)
if
(
err
<
0
)
return
err
;
return
err
;
...
@@ -468,8 +530,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
...
@@ -468,8 +530,6 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
chip
->
card
=
card
;
chip
->
card
=
card
;
chip
->
pci
=
pci
;
chip
->
pci
=
pci
;
chip
->
irq
=
-
1
;
chip
->
irq
=
-
1
;
chip
->
model
=
*
model
;
chip
->
model_data
=
chip
+
1
;
spin_lock_init
(
&
chip
->
reg_lock
);
spin_lock_init
(
&
chip
->
reg_lock
);
mutex_init
(
&
chip
->
mutex
);
mutex_init
(
&
chip
->
mutex
);
INIT_WORK
(
&
chip
->
spdif_input_bits_work
,
INIT_WORK
(
&
chip
->
spdif_input_bits_work
,
...
@@ -481,7 +541,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
...
@@ -481,7 +541,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
if
(
err
<
0
)
if
(
err
<
0
)
goto
err_card
;
goto
err_card
;
err
=
pci_request_regions
(
pci
,
model
->
chip
);
err
=
pci_request_regions
(
pci
,
DRIVER
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
snd_printk
(
KERN_ERR
"cannot reserve PCI resources
\n
"
);
snd_printk
(
KERN_ERR
"cannot reserve PCI resources
\n
"
);
goto
err_pci_enable
;
goto
err_pci_enable
;
...
@@ -495,20 +555,34 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
...
@@ -495,20 +555,34 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
}
}
chip
->
addr
=
pci_resource_start
(
pci
,
0
);
chip
->
addr
=
pci_resource_start
(
pci
,
0
);
pci_id
=
oxygen_search_pci_id
(
chip
,
ids
);
if
(
!
pci_id
)
{
err
=
-
ENODEV
;
goto
err_pci_regions
;
}
oxygen_restore_eeprom
(
chip
,
pci_id
);
err
=
get_model
(
chip
,
pci_id
);
if
(
err
<
0
)
goto
err_pci_regions
;
if
(
chip
->
model
.
model_data_size
)
{
chip
->
model_data
=
kzalloc
(
chip
->
model
.
model_data_size
,
GFP_KERNEL
);
if
(
!
chip
->
model_data
)
{
err
=
-
ENOMEM
;
goto
err_pci_regions
;
}
}
pci_set_master
(
pci
);
pci_set_master
(
pci
);
snd_card_set_dev
(
card
,
&
pci
->
dev
);
snd_card_set_dev
(
card
,
&
pci
->
dev
);
card
->
private_free
=
oxygen_card_free
;
card
->
private_free
=
oxygen_card_free
;
if
(
chip
->
model
.
probe
)
{
err
=
chip
->
model
.
probe
(
chip
,
driver_data
);
if
(
err
<
0
)
goto
err_card
;
}
oxygen_init
(
chip
);
oxygen_init
(
chip
);
chip
->
model
.
init
(
chip
);
chip
->
model
.
init
(
chip
);
err
=
request_irq
(
pci
->
irq
,
oxygen_interrupt
,
IRQF_SHARED
,
err
=
request_irq
(
pci
->
irq
,
oxygen_interrupt
,
IRQF_SHARED
,
chip
->
model
.
chip
,
chip
);
DRIVER
,
chip
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
snd_printk
(
KERN_ERR
"cannot grab interrupt %d
\n
"
,
pci
->
irq
);
snd_printk
(
KERN_ERR
"cannot grab interrupt %d
\n
"
,
pci
->
irq
);
goto
err_card
;
goto
err_card
;
...
...
sound/pci/oxygen/virtuoso.c
View file @
b54fc8dd
...
@@ -112,6 +112,34 @@
...
@@ -112,6 +112,34 @@
* CS4362A: AD0 <- 0
* CS4362A: AD0 <- 0
*/
*/
/*
* Xonar Essence STX
* -----------------
*
* CMI8788:
*
* I²C <-> PCM1792A
*
* GPI 0 <- external power present
*
* GPIO 0 -> enable output to speakers
* GPIO 1 -> route HP to front panel (0) or rear jack (1)
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 7 -> route output to speaker jacks (0) or HP (1)
* GPIO 8 -> route input jack to line-in (0) or mic-in (1)
*
* PCM1792A:
*
* AD0 <- 0
*
* H6 daughterboard
* ----------------
*
* GPIO 4 <- 0
* GPIO 5 <- 0
*/
#include <linux/pci.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
...
@@ -152,6 +180,7 @@ enum {
...
@@ -152,6 +180,7 @@ enum {
MODEL_DX
,
MODEL_DX
,
MODEL_HDAV
,
/* without daughterboard */
MODEL_HDAV
,
/* without daughterboard */
MODEL_HDAV_H6
,
/* with H6 daughterboard */
MODEL_HDAV_H6
,
/* with H6 daughterboard */
MODEL_STX
,
};
};
static
struct
pci_device_id
xonar_ids
[]
__devinitdata
=
{
static
struct
pci_device_id
xonar_ids
[]
__devinitdata
=
{
...
@@ -160,6 +189,8 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
...
@@ -160,6 +189,8 @@ static struct pci_device_id xonar_ids[] __devinitdata = {
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x82b7
),
.
driver_data
=
MODEL_D2X
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x82b7
),
.
driver_data
=
MODEL_D2X
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x8314
),
.
driver_data
=
MODEL_HDAV
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x8314
),
.
driver_data
=
MODEL_HDAV
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x834f
),
.
driver_data
=
MODEL_D1
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x834f
),
.
driver_data
=
MODEL_D1
},
{
OXYGEN_PCI_SUBID
(
0x1043
,
0x835c
),
.
driver_data
=
MODEL_STX
},
{
OXYGEN_PCI_SUBID_BROKEN_EEPROM
},
{
}
{
}
};
};
MODULE_DEVICE_TABLE
(
pci
,
xonar_ids
);
MODULE_DEVICE_TABLE
(
pci
,
xonar_ids
);
...
@@ -183,12 +214,14 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
...
@@ -183,12 +214,14 @@ MODULE_DEVICE_TABLE(pci, xonar_ids);
#define GPIO_HDAV_DB_H6 0x0000
#define GPIO_HDAV_DB_H6 0x0000
#define GPIO_HDAV_DB_XX 0x0020
#define GPIO_HDAV_DB_XX 0x0020
#define GPIO_ST_HP_REAR 0x0002
#define GPIO_ST_HP 0x0080
#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1))
/* 10011, ADx=i, /W=0 */
#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1))
/* 10011, ADx=i, /W=0 */
#define I2C_DEVICE_CS4398 0x9e
/* 10011, AD1=1, AD0=1, /W=0 */
#define I2C_DEVICE_CS4398 0x9e
/* 10011, AD1=1, AD0=1, /W=0 */
#define I2C_DEVICE_CS4362A 0x30
/* 001100, AD0=0, /W=0 */
#define I2C_DEVICE_CS4362A 0x30
/* 001100, AD0=0, /W=0 */
struct
xonar_data
{
struct
xonar_data
{
unsigned
int
model
;
unsigned
int
anti_pop_delay
;
unsigned
int
anti_pop_delay
;
unsigned
int
dacs
;
unsigned
int
dacs
;
u16
output_enable_bit
;
u16
output_enable_bit
;
...
@@ -334,15 +367,9 @@ static void xonar_d2_init(struct oxygen *chip)
...
@@ -334,15 +367,9 @@ static void xonar_d2_init(struct oxygen *chip)
struct
xonar_data
*
data
=
chip
->
model_data
;
struct
xonar_data
*
data
=
chip
->
model_data
;
data
->
anti_pop_delay
=
300
;
data
->
anti_pop_delay
=
300
;
data
->
dacs
=
4
;
data
->
output_enable_bit
=
GPIO_D2_OUTPUT_ENABLE
;
data
->
output_enable_bit
=
GPIO_D2_OUTPUT_ENABLE
;
data
->
pcm1796_oversampling
=
PCM1796_OS_64
;
data
->
pcm1796_oversampling
=
PCM1796_OS_64
;
if
(
data
->
model
==
MODEL_D2X
)
{
data
->
ext_power_reg
=
OXYGEN_GPIO_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPIO_INTERRUPT_MASK
;
data
->
ext_power_bit
=
GPIO_D2X_EXT_POWER
;
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_D2X_EXT_POWER
);
}
pcm1796_init
(
chip
);
pcm1796_init
(
chip
);
...
@@ -355,6 +382,18 @@ static void xonar_d2_init(struct oxygen *chip)
...
@@ -355,6 +382,18 @@ static void xonar_d2_init(struct oxygen *chip)
snd_component_add
(
chip
->
card
,
"CS5381"
);
snd_component_add
(
chip
->
card
,
"CS5381"
);
}
}
static
void
xonar_d2x_init
(
struct
oxygen
*
chip
)
{
struct
xonar_data
*
data
=
chip
->
model_data
;
data
->
ext_power_reg
=
OXYGEN_GPIO_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPIO_INTERRUPT_MASK
;
data
->
ext_power_bit
=
GPIO_D2X_EXT_POWER
;
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_D2X_EXT_POWER
);
xonar_d2_init
(
chip
);
}
static
void
update_cs4362a_volumes
(
struct
oxygen
*
chip
)
static
void
update_cs4362a_volumes
(
struct
oxygen
*
chip
)
{
{
u8
mute
;
u8
mute
;
...
@@ -422,11 +461,6 @@ static void xonar_d1_init(struct oxygen *chip)
...
@@ -422,11 +461,6 @@ static void xonar_d1_init(struct oxygen *chip)
data
->
cs4398_fm
=
CS4398_FM_SINGLE
|
CS4398_DEM_NONE
|
CS4398_DIF_LJUST
;
data
->
cs4398_fm
=
CS4398_FM_SINGLE
|
CS4398_DEM_NONE
|
CS4398_DIF_LJUST
;
data
->
cs4362a_fm
=
CS4362A_FM_SINGLE
|
data
->
cs4362a_fm
=
CS4362A_FM_SINGLE
|
CS4362A_ATAPI_B_R
|
CS4362A_ATAPI_A_L
;
CS4362A_ATAPI_B_R
|
CS4362A_ATAPI_A_L
;
if
(
data
->
model
==
MODEL_DX
)
{
data
->
ext_power_reg
=
OXYGEN_GPI_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPI_INTERRUPT_MASK
;
data
->
ext_power_bit
=
GPI_DX_EXT_POWER
;
}
oxygen_write16
(
chip
,
OXYGEN_2WIRE_BUS_STATUS
,
oxygen_write16
(
chip
,
OXYGEN_2WIRE_BUS_STATUS
,
OXYGEN_2WIRE_LENGTH_8
|
OXYGEN_2WIRE_LENGTH_8
|
...
@@ -447,6 +481,17 @@ static void xonar_d1_init(struct oxygen *chip)
...
@@ -447,6 +481,17 @@ static void xonar_d1_init(struct oxygen *chip)
snd_component_add
(
chip
->
card
,
"CS5361"
);
snd_component_add
(
chip
->
card
,
"CS5361"
);
}
}
static
void
xonar_dx_init
(
struct
oxygen
*
chip
)
{
struct
xonar_data
*
data
=
chip
->
model_data
;
data
->
ext_power_reg
=
OXYGEN_GPI_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPI_INTERRUPT_MASK
;
data
->
ext_power_bit
=
GPI_DX_EXT_POWER
;
xonar_d1_init
(
chip
);
}
static
void
xonar_hdav_init
(
struct
oxygen
*
chip
)
static
void
xonar_hdav_init
(
struct
oxygen
*
chip
)
{
{
struct
xonar_data
*
data
=
chip
->
model_data
;
struct
xonar_data
*
data
=
chip
->
model_data
;
...
@@ -458,6 +503,7 @@ static void xonar_hdav_init(struct oxygen *chip)
...
@@ -458,6 +503,7 @@ static void xonar_hdav_init(struct oxygen *chip)
OXYGEN_2WIRE_SPEED_FAST
);
OXYGEN_2WIRE_SPEED_FAST
);
data
->
anti_pop_delay
=
100
;
data
->
anti_pop_delay
=
100
;
data
->
dacs
=
chip
->
model
.
private_data
==
MODEL_HDAV_H6
?
4
:
1
;
data
->
output_enable_bit
=
GPIO_DX_OUTPUT_ENABLE
;
data
->
output_enable_bit
=
GPIO_DX_OUTPUT_ENABLE
;
data
->
ext_power_reg
=
OXYGEN_GPI_DATA
;
data
->
ext_power_reg
=
OXYGEN_GPI_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPI_INTERRUPT_MASK
;
data
->
ext_power_int_reg
=
OXYGEN_GPI_INTERRUPT_MASK
;
...
@@ -484,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip)
...
@@ -484,6 +530,36 @@ static void xonar_hdav_init(struct oxygen *chip)
snd_component_add
(
chip
->
card
,
"CS5381"
);
snd_component_add
(
chip
->
card
,
"CS5381"
);
}
}
static
void
xonar_stx_init
(
struct
oxygen
*
chip
)
{
struct
xonar_data
*
data
=
chip
->
model_data
;
oxygen_write16
(
chip
,
OXYGEN_2WIRE_BUS_STATUS
,
OXYGEN_2WIRE_LENGTH_8
|
OXYGEN_2WIRE_INTERRUPT_MASK
|
OXYGEN_2WIRE_SPEED_FAST
);
data
->
anti_pop_delay
=
100
;
data
->
dacs
=
1
;
data
->
output_enable_bit
=
GPIO_DX_OUTPUT_ENABLE
;
data
->
ext_power_reg
=
OXYGEN_GPI_DATA
;
data
->
ext_power_int_reg
=
OXYGEN_GPI_INTERRUPT_MASK
;
data
->
ext_power_bit
=
GPI_DX_EXT_POWER
;
data
->
pcm1796_oversampling
=
PCM1796_OS_64
;
pcm1796_init
(
chip
);
oxygen_set_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_DX_INPUT_ROUTE
|
GPIO_ST_HP_REAR
|
GPIO_ST_HP
);
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_DATA
,
GPIO_DX_INPUT_ROUTE
|
GPIO_ST_HP_REAR
|
GPIO_ST_HP
);
xonar_common_init
(
chip
);
snd_component_add
(
chip
->
card
,
"PCM1792A"
);
snd_component_add
(
chip
->
card
,
"CS5381"
);
}
static
void
xonar_disable_output
(
struct
oxygen
*
chip
)
static
void
xonar_disable_output
(
struct
oxygen
*
chip
)
{
{
struct
xonar_data
*
data
=
chip
->
model_data
;
struct
xonar_data
*
data
=
chip
->
model_data
;
...
@@ -511,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip)
...
@@ -511,6 +587,11 @@ static void xonar_hdav_cleanup(struct oxygen *chip)
xonar_disable_output
(
chip
);
xonar_disable_output
(
chip
);
}
}
static
void
xonar_st_cleanup
(
struct
oxygen
*
chip
)
{
xonar_disable_output
(
chip
);
}
static
void
xonar_d2_suspend
(
struct
oxygen
*
chip
)
static
void
xonar_d2_suspend
(
struct
oxygen
*
chip
)
{
{
xonar_d2_cleanup
(
chip
);
xonar_d2_cleanup
(
chip
);
...
@@ -527,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip)
...
@@ -527,6 +608,11 @@ static void xonar_hdav_suspend(struct oxygen *chip)
msleep
(
2
);
msleep
(
2
);
}
}
static
void
xonar_st_suspend
(
struct
oxygen
*
chip
)
{
xonar_st_cleanup
(
chip
);
}
static
void
xonar_d2_resume
(
struct
oxygen
*
chip
)
static
void
xonar_d2_resume
(
struct
oxygen
*
chip
)
{
{
pcm1796_init
(
chip
);
pcm1796_init
(
chip
);
...
@@ -554,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip)
...
@@ -554,6 +640,12 @@ static void xonar_hdav_resume(struct oxygen *chip)
xonar_enable_output
(
chip
);
xonar_enable_output
(
chip
);
}
}
static
void
xonar_st_resume
(
struct
oxygen
*
chip
)
{
pcm1796_init
(
chip
);
xonar_enable_output
(
chip
);
}
static
void
xonar_hdav_pcm_hardware_filter
(
unsigned
int
channel
,
static
void
xonar_hdav_pcm_hardware_filter
(
unsigned
int
channel
,
struct
snd_pcm_hardware
*
hardware
)
struct
snd_pcm_hardware
*
hardware
)
{
{
...
@@ -733,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = {
...
@@ -733,6 +825,72 @@ static const struct snd_kcontrol_new front_panel_switch = {
.
private_value
=
GPIO_DX_FRONT_PANEL
,
.
private_value
=
GPIO_DX_FRONT_PANEL
,
};
};
static
int
st_output_switch_info
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_info
*
info
)
{
static
const
char
*
const
names
[
3
]
=
{
"Speakers"
,
"Headphones"
,
"FP Headphones"
};
info
->
type
=
SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
info
->
count
=
1
;
info
->
value
.
enumerated
.
items
=
3
;
if
(
info
->
value
.
enumerated
.
item
>=
3
)
info
->
value
.
enumerated
.
item
=
2
;
strcpy
(
info
->
value
.
enumerated
.
name
,
names
[
info
->
value
.
enumerated
.
item
]);
return
0
;
}
static
int
st_output_switch_get
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
oxygen
*
chip
=
ctl
->
private_data
;
u16
gpio
;
gpio
=
oxygen_read16
(
chip
,
OXYGEN_GPIO_DATA
);
if
(
!
(
gpio
&
GPIO_ST_HP
))
value
->
value
.
enumerated
.
item
[
0
]
=
0
;
else
if
(
gpio
&
GPIO_ST_HP_REAR
)
value
->
value
.
enumerated
.
item
[
0
]
=
1
;
else
value
->
value
.
enumerated
.
item
[
0
]
=
2
;
return
0
;
}
static
int
st_output_switch_put
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
oxygen
*
chip
=
ctl
->
private_data
;
u16
gpio_old
,
gpio
;
mutex_lock
(
&
chip
->
mutex
);
gpio_old
=
oxygen_read16
(
chip
,
OXYGEN_GPIO_DATA
);
gpio
=
gpio_old
;
switch
(
value
->
value
.
enumerated
.
item
[
0
])
{
case
0
:
gpio
&=
~
(
GPIO_ST_HP
|
GPIO_ST_HP_REAR
);
break
;
case
1
:
gpio
|=
GPIO_ST_HP
|
GPIO_ST_HP_REAR
;
break
;
case
2
:
gpio
=
(
gpio
|
GPIO_ST_HP
)
&
~
GPIO_ST_HP_REAR
;
break
;
}
oxygen_write16
(
chip
,
OXYGEN_GPIO_DATA
,
gpio
);
mutex_unlock
(
&
chip
->
mutex
);
return
gpio
!=
gpio_old
;
}
static
const
struct
snd_kcontrol_new
st_output_switch
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Analog Output"
,
.
info
=
st_output_switch_info
,
.
get
=
st_output_switch_get
,
.
put
=
st_output_switch_put
,
};
static
void
xonar_line_mic_ac97_switch
(
struct
oxygen
*
chip
,
static
void
xonar_line_mic_ac97_switch
(
struct
oxygen
*
chip
,
unsigned
int
reg
,
unsigned
int
mute
)
unsigned
int
reg
,
unsigned
int
mute
)
{
{
...
@@ -745,8 +903,8 @@ static void xonar_line_mic_ac97_switch(struct oxygen *chip,
...
@@ -745,8 +903,8 @@ static void xonar_line_mic_ac97_switch(struct oxygen *chip,
}
}
}
}
static
const
DECLARE_TLV_DB_SCALE
(
pcm1796_db_scale
,
-
12
000
,
50
,
0
);
static
const
DECLARE_TLV_DB_SCALE
(
pcm1796_db_scale
,
-
6
000
,
50
,
0
);
static
const
DECLARE_TLV_DB_SCALE
(
cs4362a_db_scale
,
-
127
00
,
100
,
0
);
static
const
DECLARE_TLV_DB_SCALE
(
cs4362a_db_scale
,
-
60
00
,
100
,
0
);
static
int
xonar_d2_control_filter
(
struct
snd_kcontrol_new
*
template
)
static
int
xonar_d2_control_filter
(
struct
snd_kcontrol_new
*
template
)
{
{
...
@@ -763,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
...
@@ -763,6 +921,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
return
0
;
return
0
;
}
}
static
int
xonar_st_control_filter
(
struct
snd_kcontrol_new
*
template
)
{
if
(
!
strncmp
(
template
->
name
,
"CD Capture "
,
11
))
return
1
;
/* no CD input */
if
(
!
strcmp
(
template
->
name
,
"Stereo Upmixing"
))
return
1
;
/* stereo only - we don't need upmixing */
return
0
;
}
static
int
xonar_d2_mixer_init
(
struct
oxygen
*
chip
)
static
int
xonar_d2_mixer_init
(
struct
oxygen
*
chip
)
{
{
return
snd_ctl_add
(
chip
->
card
,
snd_ctl_new1
(
&
alt_switch
,
chip
));
return
snd_ctl_add
(
chip
->
card
,
snd_ctl_new1
(
&
alt_switch
,
chip
));
...
@@ -773,51 +940,14 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
...
@@ -773,51 +940,14 @@ static int xonar_d1_mixer_init(struct oxygen *chip)
return
snd_ctl_add
(
chip
->
card
,
snd_ctl_new1
(
&
front_panel_switch
,
chip
));
return
snd_ctl_add
(
chip
->
card
,
snd_ctl_new1
(
&
front_panel_switch
,
chip
));
}
}
static
int
xonar_
model_probe
(
struct
oxygen
*
chip
,
unsigned
long
driver_data
)
static
int
xonar_
st_mixer_init
(
struct
oxygen
*
chip
)
{
{
static
const
char
*
const
names
[]
=
{
return
snd_ctl_add
(
chip
->
card
,
snd_ctl_new1
(
&
st_output_switch
,
chip
));
[
MODEL_D1
]
=
"Xonar D1"
,
[
MODEL_DX
]
=
"Xonar DX"
,
[
MODEL_D2
]
=
"Xonar D2"
,
[
MODEL_D2X
]
=
"Xonar D2X"
,
[
MODEL_HDAV
]
=
"Xonar HDAV1.3"
,
[
MODEL_HDAV_H6
]
=
"Xonar HDAV1.3+H6"
,
};
static
const
u8
dacs
[]
=
{
[
MODEL_D1
]
=
2
,
[
MODEL_DX
]
=
2
,
[
MODEL_D2
]
=
4
,
[
MODEL_D2X
]
=
4
,
[
MODEL_HDAV
]
=
1
,
[
MODEL_HDAV_H6
]
=
4
,
};
struct
xonar_data
*
data
=
chip
->
model_data
;
data
->
model
=
driver_data
;
if
(
data
->
model
==
MODEL_HDAV
)
{
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_HDAV_DB_MASK
);
switch
(
oxygen_read16
(
chip
,
OXYGEN_GPIO_DATA
)
&
GPIO_HDAV_DB_MASK
)
{
case
GPIO_HDAV_DB_H6
:
data
->
model
=
MODEL_HDAV_H6
;
break
;
case
GPIO_HDAV_DB_XX
:
snd_printk
(
KERN_ERR
"unknown daughterboard
\n
"
);
return
-
ENODEV
;
}
}
data
->
dacs
=
dacs
[
data
->
model
];
chip
->
model
.
shortname
=
names
[
data
->
model
];
return
0
;
}
}
static
const
struct
oxygen_model
model_xonar_d2
=
{
static
const
struct
oxygen_model
model_xonar_d2
=
{
.
longname
=
"Asus Virtuoso 200"
,
.
longname
=
"Asus Virtuoso 200"
,
.
chip
=
"AV200"
,
.
chip
=
"AV200"
,
.
owner
=
THIS_MODULE
,
.
probe
=
xonar_model_probe
,
.
init
=
xonar_d2_init
,
.
init
=
xonar_d2_init
,
.
control_filter
=
xonar_d2_control_filter
,
.
control_filter
=
xonar_d2_control_filter
,
.
mixer_init
=
xonar_d2_mixer_init
,
.
mixer_init
=
xonar_d2_mixer_init
,
...
@@ -837,8 +967,8 @@ static const struct oxygen_model model_xonar_d2 = {
...
@@ -837,8 +967,8 @@ static const struct oxygen_model model_xonar_d2 = {
MIDI_OUTPUT
|
MIDI_OUTPUT
|
MIDI_INPUT
,
MIDI_INPUT
,
.
dac_channels
=
8
,
.
dac_channels
=
8
,
.
dac_volume_min
=
0x0f
,
.
dac_volume_min
=
255
-
2
*
60
,
.
dac_volume_max
=
0xff
,
.
dac_volume_max
=
255
,
.
misc_flags
=
OXYGEN_MISC_MIDI
,
.
misc_flags
=
OXYGEN_MISC_MIDI
,
.
function_flags
=
OXYGEN_FUNCTION_SPI
|
.
function_flags
=
OXYGEN_FUNCTION_SPI
|
OXYGEN_FUNCTION_ENABLE_SPI_4_5
,
OXYGEN_FUNCTION_ENABLE_SPI_4_5
,
...
@@ -849,8 +979,6 @@ static const struct oxygen_model model_xonar_d2 = {
...
@@ -849,8 +979,6 @@ static const struct oxygen_model model_xonar_d2 = {
static
const
struct
oxygen_model
model_xonar_d1
=
{
static
const
struct
oxygen_model
model_xonar_d1
=
{
.
longname
=
"Asus Virtuoso 100"
,
.
longname
=
"Asus Virtuoso 100"
,
.
chip
=
"AV200"
,
.
chip
=
"AV200"
,
.
owner
=
THIS_MODULE
,
.
probe
=
xonar_model_probe
,
.
init
=
xonar_d1_init
,
.
init
=
xonar_d1_init
,
.
control_filter
=
xonar_d1_control_filter
,
.
control_filter
=
xonar_d1_control_filter
,
.
mixer_init
=
xonar_d1_mixer_init
,
.
mixer_init
=
xonar_d1_mixer_init
,
...
@@ -868,7 +996,7 @@ static const struct oxygen_model model_xonar_d1 = {
...
@@ -868,7 +996,7 @@ static const struct oxygen_model model_xonar_d1 = {
PLAYBACK_1_TO_SPDIF
|
PLAYBACK_1_TO_SPDIF
|
CAPTURE_0_FROM_I2S_2
,
CAPTURE_0_FROM_I2S_2
,
.
dac_channels
=
8
,
.
dac_channels
=
8
,
.
dac_volume_min
=
0
,
.
dac_volume_min
=
127
-
6
0
,
.
dac_volume_max
=
127
,
.
dac_volume_max
=
127
,
.
function_flags
=
OXYGEN_FUNCTION_2WIRE
,
.
function_flags
=
OXYGEN_FUNCTION_2WIRE
,
.
dac_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
dac_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
...
@@ -878,8 +1006,6 @@ static const struct oxygen_model model_xonar_d1 = {
...
@@ -878,8 +1006,6 @@ static const struct oxygen_model model_xonar_d1 = {
static
const
struct
oxygen_model
model_xonar_hdav
=
{
static
const
struct
oxygen_model
model_xonar_hdav
=
{
.
longname
=
"Asus Virtuoso 200"
,
.
longname
=
"Asus Virtuoso 200"
,
.
chip
=
"AV200"
,
.
chip
=
"AV200"
,
.
owner
=
THIS_MODULE
,
.
probe
=
xonar_model_probe
,
.
init
=
xonar_hdav_init
,
.
init
=
xonar_hdav_init
,
.
cleanup
=
xonar_hdav_cleanup
,
.
cleanup
=
xonar_hdav_cleanup
,
.
suspend
=
xonar_hdav_suspend
,
.
suspend
=
xonar_hdav_suspend
,
...
@@ -897,16 +1023,43 @@ static const struct oxygen_model model_xonar_hdav = {
...
@@ -897,16 +1023,43 @@ static const struct oxygen_model model_xonar_hdav = {
PLAYBACK_1_TO_SPDIF
|
PLAYBACK_1_TO_SPDIF
|
CAPTURE_0_FROM_I2S_2
,
CAPTURE_0_FROM_I2S_2
,
.
dac_channels
=
8
,
.
dac_channels
=
8
,
.
dac_volume_min
=
0x0f
,
.
dac_volume_min
=
255
-
2
*
60
,
.
dac_volume_max
=
0xff
,
.
dac_volume_max
=
255
,
.
misc_flags
=
OXYGEN_MISC_MIDI
,
.
misc_flags
=
OXYGEN_MISC_MIDI
,
.
function_flags
=
OXYGEN_FUNCTION_2WIRE
,
.
function_flags
=
OXYGEN_FUNCTION_2WIRE
,
.
dac_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
dac_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
};
};
static
int
__devinit
xonar_probe
(
struct
pci_dev
*
pci
,
static
const
struct
oxygen_model
model_xonar_st
=
{
const
struct
pci_device_id
*
pci_id
)
.
longname
=
"Asus Virtuoso 100"
,
.
chip
=
"AV200"
,
.
init
=
xonar_stx_init
,
.
control_filter
=
xonar_st_control_filter
,
.
mixer_init
=
xonar_st_mixer_init
,
.
cleanup
=
xonar_st_cleanup
,
.
suspend
=
xonar_st_suspend
,
.
resume
=
xonar_st_resume
,
.
set_dac_params
=
set_pcm1796_params
,
.
set_adc_params
=
set_cs53x1_params
,
.
update_dac_volume
=
update_pcm1796_volume
,
.
update_dac_mute
=
update_pcm1796_mute
,
.
ac97_switch
=
xonar_line_mic_ac97_switch
,
.
dac_tlv
=
pcm1796_db_scale
,
.
model_data_size
=
sizeof
(
struct
xonar_data
),
.
device_config
=
PLAYBACK_0_TO_I2S
|
PLAYBACK_1_TO_SPDIF
|
CAPTURE_0_FROM_I2S_2
,
.
dac_channels
=
2
,
.
dac_volume_min
=
255
-
2
*
60
,
.
dac_volume_max
=
255
,
.
function_flags
=
OXYGEN_FUNCTION_2WIRE
,
.
dac_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
.
adc_i2s_format
=
OXYGEN_I2S_FORMAT_LJUST
,
};
static
int
__devinit
get_xonar_model
(
struct
oxygen
*
chip
,
const
struct
pci_device_id
*
id
)
{
{
static
const
struct
oxygen_model
*
const
models
[]
=
{
static
const
struct
oxygen_model
*
const
models
[]
=
{
[
MODEL_D1
]
=
&
model_xonar_d1
,
[
MODEL_D1
]
=
&
model_xonar_d1
,
...
@@ -914,7 +1067,57 @@ static int __devinit xonar_probe(struct pci_dev *pci,
...
@@ -914,7 +1067,57 @@ static int __devinit xonar_probe(struct pci_dev *pci,
[
MODEL_D2
]
=
&
model_xonar_d2
,
[
MODEL_D2
]
=
&
model_xonar_d2
,
[
MODEL_D2X
]
=
&
model_xonar_d2
,
[
MODEL_D2X
]
=
&
model_xonar_d2
,
[
MODEL_HDAV
]
=
&
model_xonar_hdav
,
[
MODEL_HDAV
]
=
&
model_xonar_hdav
,
[
MODEL_STX
]
=
&
model_xonar_st
,
};
};
static
const
char
*
const
names
[]
=
{
[
MODEL_D1
]
=
"Xonar D1"
,
[
MODEL_DX
]
=
"Xonar DX"
,
[
MODEL_D2
]
=
"Xonar D2"
,
[
MODEL_D2X
]
=
"Xonar D2X"
,
[
MODEL_HDAV
]
=
"Xonar HDAV1.3"
,
[
MODEL_HDAV_H6
]
=
"Xonar HDAV1.3+H6"
,
[
MODEL_STX
]
=
"Xonar Essence STX"
,
};
unsigned
int
model
=
id
->
driver_data
;
if
(
model
>=
ARRAY_SIZE
(
models
)
||
!
models
[
model
])
return
-
EINVAL
;
chip
->
model
=
*
models
[
model
];
switch
(
model
)
{
case
MODEL_D2X
:
chip
->
model
.
init
=
xonar_d2x_init
;
break
;
case
MODEL_DX
:
chip
->
model
.
init
=
xonar_dx_init
;
break
;
case
MODEL_HDAV
:
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_HDAV_DB_MASK
);
switch
(
oxygen_read16
(
chip
,
OXYGEN_GPIO_DATA
)
&
GPIO_HDAV_DB_MASK
)
{
case
GPIO_HDAV_DB_H6
:
model
=
MODEL_HDAV_H6
;
break
;
case
GPIO_HDAV_DB_XX
:
snd_printk
(
KERN_ERR
"unknown daughterboard
\n
"
);
return
-
ENODEV
;
}
break
;
case
MODEL_STX
:
oxygen_clear_bits16
(
chip
,
OXYGEN_GPIO_CONTROL
,
GPIO_HDAV_DB_MASK
);
break
;
}
chip
->
model
.
shortname
=
names
[
model
];
chip
->
model
.
private_data
=
model
;
return
0
;
}
static
int
__devinit
xonar_probe
(
struct
pci_dev
*
pci
,
const
struct
pci_device_id
*
pci_id
)
{
static
int
dev
;
static
int
dev
;
int
err
;
int
err
;
...
@@ -924,10 +1127,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
...
@@ -924,10 +1127,8 @@ static int __devinit xonar_probe(struct pci_dev *pci,
++
dev
;
++
dev
;
return
-
ENOENT
;
return
-
ENOENT
;
}
}
BUG_ON
(
pci_id
->
driver_data
>=
ARRAY_SIZE
(
models
));
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
THIS_MODULE
,
err
=
oxygen_pci_probe
(
pci
,
index
[
dev
],
id
[
dev
],
xonar_ids
,
get_xonar_model
);
models
[
pci_id
->
driver_data
],
pci_id
->
driver_data
);
if
(
err
>=
0
)
if
(
err
>=
0
)
++
dev
;
++
dev
;
return
err
;
return
err
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment