Skip to content

Commit c58f520

Browse files
harinworkstiwai
authored andcommitted
ALSA: ctxfi: Add support for Onkyo SE-300PCIE (OK0010)
Add support for the Onkyo SE-300PCIE, a Creative X-Fi CA20K2-based sound card with a custom hardware implementation that differs significantly from other CA20K2-based variants. Changes: - PCI quirk entry for OK0010 - Port 0x3 is utilized for dedicated RCA output (configured as I2S) - Modified GPIO pin mappings and states - 4-channel simultaneous ADC input support for line and microphone capture without input switching (similar to SB1270) - Simplified ADC initialization (no manual setup required) Signed-off-by: Harin Lee <me@harin.net> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20251124180501.2760421-7-me@harin.net
1 parent 9b4a227 commit c58f520

4 files changed

Lines changed: 43 additions & 14 deletions

File tree

sound/pci/ctxfi/ctatc.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static const struct snd_pci_quirk subsys_20k2_list[] = {
6363
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000,
6464
PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX",
6565
CTHENDRIX),
66+
SND_PCI_QUIRK(0x160b, 0x0101, "OK0010", CTOK0010),
6667
{ } /* terminator */
6768
};
6869

@@ -78,6 +79,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = {
7879
[CTHENDRIX] = "Hendrix",
7980
[CTSB0880] = "SB0880",
8081
[CTSB1270] = "SB1270",
82+
[CTOK0010] = "OK0010",
8183
[CT20K2_UNKNOWN] = "Unknown",
8284
};
8385

@@ -1535,8 +1537,10 @@ static void atc_connect_resources(struct ct_atc *atc)
15351537
dao->ops->set_right_input(dao, rscs[1]);
15361538
}
15371539

1538-
if (cap.dedicated_rca)
1540+
if (cap.dedicated_rca) {
1541+
/* SE-300PCIE has a dedicated DAC for the RCA. */
15391542
atc_dedicated_rca_select(atc);
1543+
}
15401544

15411545
dai = container_of(atc->daios[LINEIM], struct dai, daio);
15421546
atc_connect_dai(atc->rsc_mgrs[SRC], dai,
@@ -1549,6 +1553,7 @@ static void atc_connect_resources(struct ct_atc *atc)
15491553

15501554
if (cap.dedicated_mic) {
15511555
/* Titanium HD has a dedicated ADC for the Mic. */
1556+
/* SE-300PCIE has a 4-channel ADC. */
15521557
dai = container_of(atc->daios[MIC], struct dai, daio);
15531558
atc_connect_dai(atc->rsc_mgrs[SRC], dai,
15541559
(struct src **)&atc->srcs[4],

sound/pci/ctxfi/ctdaio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ enum DAIOTYP {
3131
LINEIM,
3232
SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */
3333
MIC, /* Dedicated mic on Titanium HD */
34-
RCA,
34+
RCA, /* Dedicated RCA on SE-300PCIE */
3535
SPDIFI1, /* S/PDIF In on internal Drive Bay */
3636
NUM_DAIOTYP
3737
};

sound/pci/ctxfi/cthardware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ enum CTCARDS {
3838
CTHENDRIX,
3939
CTSB0880,
4040
CTSB1270,
41+
CTOK0010,
4142
CT20K2_UNKNOWN,
4243
NUM_CTCARDS /* This should always be the last */
4344
};

sound/pci/ctxfi/cthw20k2.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ static int dao_commit_write(struct hw *hw, unsigned int idx, void *blk)
910910
struct dao_ctrl_blk *ctl = blk;
911911

912912
if (ctl->dirty.bf.atxcsl) {
913-
if (idx < 4) {
913+
if ((idx < 4) && ((hw->model != CTOK0010) || (idx < 3))) {
914914
/* S/PDIF SPOSx */
915915
hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+0x40*idx,
916916
ctl->atxcsl);
@@ -985,11 +985,12 @@ static int daio_mgr_dsb_dao(void *blk, unsigned int idx)
985985
return 0;
986986
}
987987

988-
static int daio_mgr_dao_init(struct hw *hw __maybe_unused, void *blk, unsigned int idx, unsigned int conf)
988+
static int daio_mgr_dao_init(struct hw *hw, void *blk, unsigned int idx, unsigned int conf)
989989
{
990990
struct daio_mgr_ctrl_blk *ctl = blk;
991991

992-
if (idx < 4) {
992+
/* Port 3 is dedicated to RCA on SE-300PCIE */
993+
if ((idx < 4) && ((hw->model != CTOK0010) || (idx < 3))) {
993994
/* S/PDIF output */
994995
switch ((conf & 0xf)) {
995996
case 1:
@@ -1176,14 +1177,19 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
11761177
hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111);
11771178
hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121);
11781179
hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
1180+
} else if ((4 == info->msr) && (hw->model == CTOK0010)) {
1181+
hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21212121);
1182+
hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121);
1183+
hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
11791184
} else {
11801185
dev_alert(hw->card->dev,
11811186
"ERROR!!! Invalid sampling rate!!!\n");
11821187
return -EINVAL;
11831188
}
11841189

11851190
for (i = 0; i < 8; i++) {
1186-
if (i <= 3) {
1191+
/* Port 3 is configured as I2S on SE-300PCIE */
1192+
if ((i < 4) && ((hw->model != CTOK0010) || (i < 3))) {
11871193
/* This comment looks wrong since loop is over 4 */
11881194
/* channels and emu20k2 supports 4 spdif IOs. */
11891195
/* 1st 3 channels are SPDIFs (SB0960) */
@@ -1637,6 +1643,13 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
16371643
hw_write_20kx(hw, GPIO_DATA, data);
16381644
hw_dac_start(hw);
16391645
return 0;
1646+
} else if (hw->model == CTOK0010) {
1647+
hw_dac_stop(hw);
1648+
data = hw_read_20kx(hw, GPIO_DATA);
1649+
data |= 0x1000;
1650+
hw_write_20kx(hw, GPIO_DATA, data);
1651+
hw_dac_start(hw);
1652+
return 0;
16401653
}
16411654

16421655
/* Set DAC reset bit as output */
@@ -1756,9 +1769,11 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
17561769
static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
17571770
{
17581771
u32 data;
1759-
if (hw->model == CTSB1270) {
1772+
if ((hw->model == CTSB1270) || (hw->model == CTOK0010)) {
17601773
/* Titanium HD has two ADC chips, one for line in and one */
1761-
/* for MIC. We don't need to switch the ADC input. */
1774+
/* for MIC. Also, SE-300PCIE has a single ADC chip that */
1775+
/* simultaneously supports 4-channel input. We don't need */
1776+
/* to switch the ADC input. */
17621777
return 1;
17631778
}
17641779
data = hw_read_20kx(hw, GPIO_DATA);
@@ -1846,7 +1861,7 @@ static void hw_adc_start(struct hw *hw)
18461861
msleep(50);
18471862
}
18481863

1849-
static void __maybe_unused hw_adc_reset(struct hw *hw)
1864+
static void hw_adc_reset(struct hw *hw)
18501865
{
18511866
hw_adc_stop(hw);
18521867
hw_adc_start(hw);
@@ -1862,6 +1877,12 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
18621877
data |= (0x1 << 15);
18631878
hw_write_20kx(hw, GPIO_CTRL, data);
18641879

1880+
if (hw->model == CTOK0010) {
1881+
/* Manual ADC setup for SE-300PCIE is not needed. */
1882+
hw_adc_reset(hw);
1883+
return 0;
1884+
}
1885+
18651886
/* Initialize I2C */
18661887
err = hw20k2_i2c_init(hw, 0x1A, 1, 1);
18671888
if (err < 0) {
@@ -1929,8 +1950,8 @@ static struct capabilities hw_capabilities(struct hw *hw)
19291950
struct capabilities cap;
19301951

19311952
cap.digit_io_switch = 0;
1932-
cap.dedicated_mic = hw->model == CTSB1270;
1933-
cap.dedicated_rca = 0;
1953+
cap.dedicated_mic = (hw->model == CTSB1270) || (hw->model == CTOK0010);
1954+
cap.dedicated_rca = hw->model == CTOK0010;
19341955
cap.output_switch = hw->model == CTSB1270;
19351956
cap.mic_source_switch = hw->model == CTSB1270;
19361957

@@ -2167,15 +2188,17 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
21672188
/* Reset all SRC pending interrupts */
21682189
hw_write_20kx(hw, SRC_IP, 0);
21692190

2170-
if (hw->model != CTSB1270) {
2191+
if (hw->model == CTSB1270) {
2192+
hw_write_20kx(hw, GPIO_CTRL, 0x9E5F);
2193+
} else if (hw->model == CTOK0010) {
2194+
hw_write_20kx(hw, GPIO_CTRL, 0x9902);
2195+
} else {
21712196
/* TODO: detect the card ID and configure GPIO accordingly. */
21722197
/* Configures GPIO (0xD802 0x98028) */
21732198
/*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
21742199
/* Configures GPIO (SB0880) */
21752200
/*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
21762201
hw_write_20kx(hw, GPIO_CTRL, 0xD802);
2177-
} else {
2178-
hw_write_20kx(hw, GPIO_CTRL, 0x9E5F);
21792202
}
21802203
/* Enable audio ring */
21812204
hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01);

0 commit comments

Comments
 (0)