Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Harin Lee and committed by
Takashi Iwai
c58f520e 9b4a2273

+43 -14
+6 -1
sound/pci/ctxfi/ctatc.c
··· 63 63 SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 64 64 PCI_SUBDEVICE_ID_CREATIVE_HENDRIX, "HENDRIX", 65 65 CTHENDRIX), 66 + SND_PCI_QUIRK(0x160b, 0x0101, "OK0010", CTOK0010), 66 67 { } /* terminator */ 67 68 }; 68 69 ··· 79 78 [CTHENDRIX] = "Hendrix", 80 79 [CTSB0880] = "SB0880", 81 80 [CTSB1270] = "SB1270", 81 + [CTOK0010] = "OK0010", 82 82 [CT20K2_UNKNOWN] = "Unknown", 83 83 }; 84 84 ··· 1537 1535 dao->ops->set_right_input(dao, rscs[1]); 1538 1536 } 1539 1537 1540 - if (cap.dedicated_rca) 1538 + if (cap.dedicated_rca) { 1539 + /* SE-300PCIE has a dedicated DAC for the RCA. */ 1541 1540 atc_dedicated_rca_select(atc); 1541 + } 1542 1542 1543 1543 dai = container_of(atc->daios[LINEIM], struct dai, daio); 1544 1544 atc_connect_dai(atc->rsc_mgrs[SRC], dai, ··· 1553 1549 1554 1550 if (cap.dedicated_mic) { 1555 1551 /* Titanium HD has a dedicated ADC for the Mic. */ 1552 + /* SE-300PCIE has a 4-channel ADC. */ 1556 1553 dai = container_of(atc->daios[MIC], struct dai, daio); 1557 1554 atc_connect_dai(atc->rsc_mgrs[SRC], dai, 1558 1555 (struct src **)&atc->srcs[4],
+1 -1
sound/pci/ctxfi/ctdaio.h
··· 31 31 LINEIM, 32 32 SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ 33 33 MIC, /* Dedicated mic on Titanium HD */ 34 - RCA, 34 + RCA, /* Dedicated RCA on SE-300PCIE */ 35 35 SPDIFI1, /* S/PDIF In on internal Drive Bay */ 36 36 NUM_DAIOTYP 37 37 };
+1
sound/pci/ctxfi/cthardware.h
··· 38 38 CTHENDRIX, 39 39 CTSB0880, 40 40 CTSB1270, 41 + CTOK0010, 41 42 CT20K2_UNKNOWN, 42 43 NUM_CTCARDS /* This should always be the last */ 43 44 };
+35 -12
sound/pci/ctxfi/cthw20k2.c
··· 910 910 struct dao_ctrl_blk *ctl = blk; 911 911 912 912 if (ctl->dirty.bf.atxcsl) { 913 - if (idx < 4) { 913 + if ((idx < 4) && ((hw->model != CTOK0010) || (idx < 3))) { 914 914 /* S/PDIF SPOSx */ 915 915 hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_L+0x40*idx, 916 916 ctl->atxcsl); ··· 985 985 return 0; 986 986 } 987 987 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) 989 989 { 990 990 struct daio_mgr_ctrl_blk *ctl = blk; 991 991 992 - if (idx < 4) { 992 + /* Port 3 is dedicated to RCA on SE-300PCIE */ 993 + if ((idx < 4) && ((hw->model != CTOK0010) || (idx < 3))) { 993 994 /* S/PDIF output */ 994 995 switch ((conf & 0xf)) { 995 996 case 1: ··· 1177 1176 hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); 1178 1177 hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); 1179 1178 hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); 1179 + } else if ((4 == info->msr) && (hw->model == CTOK0010)) { 1180 + hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21212121); 1181 + hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); 1182 + hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); 1180 1183 } else { 1181 1184 dev_alert(hw->card->dev, 1182 1185 "ERROR!!! Invalid sampling rate!!!\n"); ··· 1188 1183 } 1189 1184 1190 1185 for (i = 0; i < 8; i++) { 1191 - if (i <= 3) { 1186 + /* Port 3 is configured as I2S on SE-300PCIE */ 1187 + if ((i < 4) && ((hw->model != CTOK0010) || (i < 3))) { 1192 1188 /* This comment looks wrong since loop is over 4 */ 1193 1189 /* channels and emu20k2 supports 4 spdif IOs. */ 1194 1190 /* 1st 3 channels are SPDIFs (SB0960) */ ··· 1643 1637 hw_write_20kx(hw, GPIO_DATA, data); 1644 1638 hw_dac_start(hw); 1645 1639 return 0; 1640 + } else if (hw->model == CTOK0010) { 1641 + hw_dac_stop(hw); 1642 + data = hw_read_20kx(hw, GPIO_DATA); 1643 + data |= 0x1000; 1644 + hw_write_20kx(hw, GPIO_DATA, data); 1645 + hw_dac_start(hw); 1646 + return 0; 1646 1647 } 1647 1648 1648 1649 /* Set DAC reset bit as output */ ··· 1769 1756 static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) 1770 1757 { 1771 1758 u32 data; 1772 - if (hw->model == CTSB1270) { 1759 + if ((hw->model == CTSB1270) || (hw->model == CTOK0010)) { 1773 1760 /* Titanium HD has two ADC chips, one for line in and one */ 1774 - /* for MIC. We don't need to switch the ADC input. */ 1761 + /* for MIC. Also, SE-300PCIE has a single ADC chip that */ 1762 + /* simultaneously supports 4-channel input. We don't need */ 1763 + /* to switch the ADC input. */ 1775 1764 return 1; 1776 1765 } 1777 1766 data = hw_read_20kx(hw, GPIO_DATA); ··· 1861 1846 msleep(50); 1862 1847 } 1863 1848 1864 - static void __maybe_unused hw_adc_reset(struct hw *hw) 1849 + static void hw_adc_reset(struct hw *hw) 1865 1850 { 1866 1851 hw_adc_stop(hw); 1867 1852 hw_adc_start(hw); ··· 1876 1861 data = hw_read_20kx(hw, GPIO_CTRL); 1877 1862 data |= (0x1 << 15); 1878 1863 hw_write_20kx(hw, GPIO_CTRL, data); 1864 + 1865 + if (hw->model == CTOK0010) { 1866 + /* Manual ADC setup for SE-300PCIE is not needed. */ 1867 + hw_adc_reset(hw); 1868 + return 0; 1869 + } 1879 1870 1880 1871 /* Initialize I2C */ 1881 1872 err = hw20k2_i2c_init(hw, 0x1A, 1, 1); ··· 1950 1929 struct capabilities cap; 1951 1930 1952 1931 cap.digit_io_switch = 0; 1953 - cap.dedicated_mic = hw->model == CTSB1270; 1954 - cap.dedicated_rca = 0; 1932 + cap.dedicated_mic = (hw->model == CTSB1270) || (hw->model == CTOK0010); 1933 + cap.dedicated_rca = hw->model == CTOK0010; 1955 1934 cap.output_switch = hw->model == CTSB1270; 1956 1935 cap.mic_source_switch = hw->model == CTSB1270; 1957 1936 ··· 2188 2167 /* Reset all SRC pending interrupts */ 2189 2168 hw_write_20kx(hw, SRC_IP, 0); 2190 2169 2191 - if (hw->model != CTSB1270) { 2170 + if (hw->model == CTSB1270) { 2171 + hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); 2172 + } else if (hw->model == CTOK0010) { 2173 + hw_write_20kx(hw, GPIO_CTRL, 0x9902); 2174 + } else { 2192 2175 /* TODO: detect the card ID and configure GPIO accordingly. */ 2193 2176 /* Configures GPIO (0xD802 0x98028) */ 2194 2177 /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ 2195 2178 /* Configures GPIO (SB0880) */ 2196 2179 /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ 2197 2180 hw_write_20kx(hw, GPIO_CTRL, 0xD802); 2198 - } else { 2199 - hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); 2200 2181 } 2201 2182 /* Enable audio ring */ 2202 2183 hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01);