diff options
Diffstat (limited to 'sound/pci/ctxfi/cthw20k2.c')
-rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 337 |
1 files changed, 240 insertions, 97 deletions
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 5364164674e..d6c54b524bf 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * @File cthw20k2.c | 8 | * @File cthw20k2.c |
9 | * | 9 | * |
10 | * @Brief | 10 | * @Brief |
11 | * This file contains the implementation of hardware access methord for 20k2. | 11 | * This file contains the implementation of hardware access method for 20k2. |
12 | * | 12 | * |
13 | * @Author Liu Chun | 13 | * @Author Liu Chun |
14 | * @Date May 14 2008 | 14 | * @Date May 14 2008 |
@@ -38,6 +38,8 @@ struct hw20k2 { | |||
38 | unsigned char dev_id; | 38 | unsigned char dev_id; |
39 | unsigned char addr_size; | 39 | unsigned char addr_size; |
40 | unsigned char data_size; | 40 | unsigned char data_size; |
41 | |||
42 | int mic_source; | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | static u32 hw_read_20kx(struct hw *hw, u32 reg); | 45 | static u32 hw_read_20kx(struct hw *hw, u32 reg); |
@@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1163 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); | 1165 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); |
1164 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1166 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1165 | } else if (2 == info->msr) { | 1167 | } else if (2 == info->msr) { |
1166 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | 1168 | if (hw->model != CTSB1270) { |
1169 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); | ||
1170 | } else { | ||
1171 | /* PCM4220 on Titanium HD is different. */ | ||
1172 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); | ||
1173 | } | ||
1167 | /* Specify all playing 96khz | 1174 | /* Specify all playing 96khz |
1168 | * EA [0] - Enabled | 1175 | * EA [0] - Enabled |
1169 | * RTA [4:5] - 96kHz | 1176 | * RTA [4:5] - 96kHz |
@@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1175 | * RTD [28:29] - 96kHz */ | 1182 | * RTD [28:29] - 96kHz */ |
1176 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); | 1183 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); |
1177 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | 1184 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); |
1185 | } else if ((4 == info->msr) && (hw->model == CTSB1270)) { | ||
1186 | hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); | ||
1187 | hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); | ||
1188 | hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); | ||
1178 | } else { | 1189 | } else { |
1179 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); | 1190 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); |
1180 | return -EINVAL; | 1191 | return -EINVAL; |
@@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1182 | 1193 | ||
1183 | for (i = 0; i < 8; i++) { | 1194 | for (i = 0; i < 8; i++) { |
1184 | if (i <= 3) { | 1195 | if (i <= 3) { |
1196 | /* This comment looks wrong since loop is over 4 */ | ||
1197 | /* channels and emu20k2 supports 4 spdif IOs. */ | ||
1185 | /* 1st 3 channels are SPDIFs (SB0960) */ | 1198 | /* 1st 3 channels are SPDIFs (SB0960) */ |
1186 | if (i == 3) | 1199 | if (i == 3) |
1187 | data = 0x1001001; | 1200 | data = 0x1001001; |
@@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) | |||
1206 | 1219 | ||
1207 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); | 1220 | hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); |
1208 | } else { | 1221 | } else { |
1222 | /* Again, loop is over 4 channels not 5. */ | ||
1209 | /* Next 5 channels are I2S (SB0960) */ | 1223 | /* Next 5 channels are I2S (SB0960) */ |
1210 | data = 0x11; | 1224 | data = 0x11; |
1211 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); | 1225 | hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); |
1212 | if (2 == info->msr) { | 1226 | if (2 == info->msr) { |
1213 | /* Four channels per sample period */ | 1227 | /* Four channels per sample period */ |
1214 | data |= 0x1000; | 1228 | data |= 0x1000; |
1229 | } else if (4 == info->msr) { | ||
1230 | /* FIXME: check this against the chip spec */ | ||
1231 | data |= 0x2000; | ||
1215 | } | 1232 | } |
1216 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); | 1233 | hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); |
1217 | } | 1234 | } |
@@ -1299,21 +1316,18 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1299 | 1316 | ||
1300 | pllenb = 0xB; | 1317 | pllenb = 0xB; |
1301 | hw_write_20kx(hw, PLL_ENB, pllenb); | 1318 | hw_write_20kx(hw, PLL_ENB, pllenb); |
1302 | pllctl = 0x20D00000; | 1319 | pllctl = 0x20C00000; |
1303 | set_field(&pllctl, PLLCTL_FD, 16 - 4); | 1320 | set_field(&pllctl, PLLCTL_B, 0); |
1321 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 4 : 147 - 4); | ||
1322 | set_field(&pllctl, PLLCTL_RD, 48000 == rsr ? 1 - 1 : 10 - 1); | ||
1304 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1323 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1305 | mdelay(40); | 1324 | mdelay(40); |
1325 | |||
1306 | pllctl = hw_read_20kx(hw, PLL_CTL); | 1326 | pllctl = hw_read_20kx(hw, PLL_CTL); |
1307 | set_field(&pllctl, PLLCTL_B, 0); | 1327 | set_field(&pllctl, PLLCTL_FD, 48000 == rsr ? 16 - 2 : 147 - 2); |
1308 | if (48000 == rsr) { | ||
1309 | set_field(&pllctl, PLLCTL_FD, 16 - 2); | ||
1310 | set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */ | ||
1311 | } else { /* 44100 */ | ||
1312 | set_field(&pllctl, PLLCTL_FD, 147 - 2); | ||
1313 | set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */ | ||
1314 | } | ||
1315 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1328 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1316 | mdelay(40); | 1329 | mdelay(40); |
1330 | |||
1317 | for (i = 0; i < 1000; i++) { | 1331 | for (i = 0; i < 1000; i++) { |
1318 | pllstat = hw_read_20kx(hw, PLL_STAT); | 1332 | pllstat = hw_read_20kx(hw, PLL_STAT); |
1319 | if (get_field(pllstat, PLLSTAT_PD)) | 1333 | if (get_field(pllstat, PLLSTAT_PD)) |
@@ -1557,7 +1571,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1557 | 1571 | ||
1558 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); | 1572 | hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); |
1559 | hw20k2_i2c_wait_data_ready(hw); | 1573 | hw20k2_i2c_wait_data_ready(hw); |
1560 | /* Dummy write to trigger the write oprtation */ | 1574 | /* Dummy write to trigger the write operation */ |
1561 | hw_write_20kx(hw, I2C_IF_WDATA, 0); | 1575 | hw_write_20kx(hw, I2C_IF_WDATA, 0); |
1562 | hw20k2_i2c_wait_data_ready(hw); | 1576 | hw20k2_i2c_wait_data_ready(hw); |
1563 | 1577 | ||
@@ -1568,6 +1582,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) | |||
1568 | return 0; | 1582 | return 0; |
1569 | } | 1583 | } |
1570 | 1584 | ||
1585 | static void hw_dac_stop(struct hw *hw) | ||
1586 | { | ||
1587 | u32 data; | ||
1588 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1589 | data &= 0xFFFFFFFD; | ||
1590 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1591 | mdelay(10); | ||
1592 | } | ||
1593 | |||
1594 | static void hw_dac_start(struct hw *hw) | ||
1595 | { | ||
1596 | u32 data; | ||
1597 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1598 | data |= 0x2; | ||
1599 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1600 | mdelay(50); | ||
1601 | } | ||
1602 | |||
1603 | static void hw_dac_reset(struct hw *hw) | ||
1604 | { | ||
1605 | hw_dac_stop(hw); | ||
1606 | hw_dac_start(hw); | ||
1607 | } | ||
1608 | |||
1571 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | 1609 | static int hw_dac_init(struct hw *hw, const struct dac_conf *info) |
1572 | { | 1610 | { |
1573 | int err; | 1611 | int err; |
@@ -1594,6 +1632,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1594 | 0x00000000 /* Vol Control B4 */ | 1632 | 0x00000000 /* Vol Control B4 */ |
1595 | }; | 1633 | }; |
1596 | 1634 | ||
1635 | if (hw->model == CTSB1270) { | ||
1636 | hw_dac_stop(hw); | ||
1637 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1638 | data &= ~0x0600; | ||
1639 | if (1 == info->msr) | ||
1640 | data |= 0x0000; /* Single Speed Mode 0-50kHz */ | ||
1641 | else if (2 == info->msr) | ||
1642 | data |= 0x0200; /* Double Speed Mode 50-100kHz */ | ||
1643 | else | ||
1644 | data |= 0x0600; /* Quad Speed Mode 100-200kHz */ | ||
1645 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1646 | hw_dac_start(hw); | ||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1597 | /* Set DAC reset bit as output */ | 1650 | /* Set DAC reset bit as output */ |
1598 | data = hw_read_20kx(hw, GPIO_CTRL); | 1651 | data = hw_read_20kx(hw, GPIO_CTRL); |
1599 | data |= 0x02; | 1652 | data |= 0x02; |
@@ -1606,22 +1659,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) | |||
1606 | for (i = 0; i < 2; i++) { | 1659 | for (i = 0; i < 2; i++) { |
1607 | /* Reset DAC twice just in-case the chip | 1660 | /* Reset DAC twice just in-case the chip |
1608 | * didn't initialized properly */ | 1661 | * didn't initialized properly */ |
1609 | data = hw_read_20kx(hw, GPIO_DATA); | 1662 | hw_dac_reset(hw); |
1610 | /* GPIO data bit 1 */ | 1663 | hw_dac_reset(hw); |
1611 | data &= 0xFFFFFFFD; | ||
1612 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1613 | mdelay(10); | ||
1614 | data |= 0x2; | ||
1615 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1616 | mdelay(50); | ||
1617 | |||
1618 | /* Reset the 2nd time */ | ||
1619 | data &= 0xFFFFFFFD; | ||
1620 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1621 | mdelay(10); | ||
1622 | data |= 0x2; | ||
1623 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1624 | mdelay(50); | ||
1625 | 1664 | ||
1626 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) | 1665 | if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) |
1627 | continue; | 1666 | continue; |
@@ -1725,7 +1764,11 @@ End: | |||
1725 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | 1764 | static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) |
1726 | { | 1765 | { |
1727 | u32 data; | 1766 | u32 data; |
1728 | 1767 | if (hw->model == CTSB1270) { | |
1768 | /* Titanium HD has two ADC chips, one for line in and one */ | ||
1769 | /* for MIC. We don't need to switch the ADC input. */ | ||
1770 | return 1; | ||
1771 | } | ||
1729 | data = hw_read_20kx(hw, GPIO_DATA); | 1772 | data = hw_read_20kx(hw, GPIO_DATA); |
1730 | switch (type) { | 1773 | switch (type) { |
1731 | case ADC_MICIN: | 1774 | case ADC_MICIN: |
@@ -1742,35 +1785,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | |||
1742 | 1785 | ||
1743 | #define MIC_BOOST_0DB 0xCF | 1786 | #define MIC_BOOST_0DB 0xCF |
1744 | #define MIC_BOOST_STEPS_PER_DB 2 | 1787 | #define MIC_BOOST_STEPS_PER_DB 2 |
1745 | #define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB) | 1788 | |
1789 | static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) | ||
1790 | { | ||
1791 | u32 adcmc, gain; | ||
1792 | |||
1793 | if (input > 3) | ||
1794 | input = 3; | ||
1795 | |||
1796 | adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ | ||
1797 | |||
1798 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), | ||
1799 | MAKE_WM8775_DATA(adcmc)); | ||
1800 | |||
1801 | if (gain_in_db < -103) | ||
1802 | gain_in_db = -103; | ||
1803 | if (gain_in_db > 24) | ||
1804 | gain_in_db = 24; | ||
1805 | |||
1806 | gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; | ||
1807 | |||
1808 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), | ||
1809 | MAKE_WM8775_DATA(gain)); | ||
1810 | /* ...so there should be no need for the following. */ | ||
1811 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), | ||
1812 | MAKE_WM8775_DATA(gain)); | ||
1813 | } | ||
1746 | 1814 | ||
1747 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | 1815 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) |
1748 | { | 1816 | { |
1749 | u32 data; | 1817 | u32 data; |
1750 | |||
1751 | data = hw_read_20kx(hw, GPIO_DATA); | 1818 | data = hw_read_20kx(hw, GPIO_DATA); |
1752 | switch (type) { | 1819 | switch (type) { |
1753 | case ADC_MICIN: | 1820 | case ADC_MICIN: |
1754 | data |= (0x1 << 14); | 1821 | data |= (0x1 << 14); |
1755 | hw_write_20kx(hw, GPIO_DATA, data); | 1822 | hw_write_20kx(hw, GPIO_DATA, data); |
1756 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | 1823 | hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ |
1757 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1758 | hw20k2_i2c_write(hw, | ||
1759 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1760 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1761 | hw20k2_i2c_write(hw, | ||
1762 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1763 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1764 | break; | 1824 | break; |
1765 | case ADC_LINEIN: | 1825 | case ADC_LINEIN: |
1766 | data &= ~(0x1 << 14); | 1826 | data &= ~(0x1 << 14); |
1767 | hw_write_20kx(hw, GPIO_DATA, data); | 1827 | hw_write_20kx(hw, GPIO_DATA, data); |
1768 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | 1828 | hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ |
1769 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1770 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1771 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1772 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1773 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1774 | break; | 1829 | break; |
1775 | default: | 1830 | default: |
1776 | break; | 1831 | break; |
@@ -1782,7 +1837,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | |||
1782 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | 1837 | static int hw_adc_init(struct hw *hw, const struct adc_conf *info) |
1783 | { | 1838 | { |
1784 | int err; | 1839 | int err; |
1785 | u32 mux = 2, data, ctl; | 1840 | u32 data, ctl; |
1786 | 1841 | ||
1787 | /* Set ADC reset bit as output */ | 1842 | /* Set ADC reset bit as output */ |
1788 | data = hw_read_20kx(hw, GPIO_CTRL); | 1843 | data = hw_read_20kx(hw, GPIO_CTRL); |
@@ -1796,19 +1851,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1796 | goto error; | 1851 | goto error; |
1797 | } | 1852 | } |
1798 | 1853 | ||
1799 | /* Make ADC in normal operation */ | 1854 | /* Reset the ADC (reset is active low). */ |
1800 | data = hw_read_20kx(hw, GPIO_DATA); | 1855 | data = hw_read_20kx(hw, GPIO_DATA); |
1801 | data &= ~(0x1 << 15); | 1856 | data &= ~(0x1 << 15); |
1857 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1858 | |||
1859 | if (hw->model == CTSB1270) { | ||
1860 | /* Set up the PCM4220 ADC on Titanium HD */ | ||
1861 | data &= ~0x0C; | ||
1862 | if (1 == info->msr) | ||
1863 | data |= 0x00; /* Single Speed Mode 32-50kHz */ | ||
1864 | else if (2 == info->msr) | ||
1865 | data |= 0x08; /* Double Speed Mode 50-108kHz */ | ||
1866 | else | ||
1867 | data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ | ||
1868 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1869 | } | ||
1870 | |||
1802 | mdelay(10); | 1871 | mdelay(10); |
1872 | /* Return the ADC to normal operation. */ | ||
1803 | data |= (0x1 << 15); | 1873 | data |= (0x1 << 15); |
1804 | hw_write_20kx(hw, GPIO_DATA, data); | 1874 | hw_write_20kx(hw, GPIO_DATA, data); |
1805 | mdelay(50); | 1875 | mdelay(50); |
1806 | 1876 | ||
1877 | /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ | ||
1878 | /* invert bit, interface format to I2S, word length to 24-bit, */ | ||
1879 | /* enable ADC high pass filter. Fixes bug 5323? */ | ||
1880 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), | ||
1881 | MAKE_WM8775_DATA(0x26)); | ||
1882 | |||
1807 | /* Set the master mode (256fs) */ | 1883 | /* Set the master mode (256fs) */ |
1808 | if (1 == info->msr) { | 1884 | if (1 == info->msr) { |
1885 | /* slave mode, 128x oversampling 256fs */ | ||
1809 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), | 1886 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), |
1810 | MAKE_WM8775_DATA(0x02)); | 1887 | MAKE_WM8775_DATA(0x02)); |
1811 | } else if (2 == info->msr) { | 1888 | } else if ((2 == info->msr) || (4 == info->msr)) { |
1889 | /* slave mode, 64x oversampling, 256fs */ | ||
1812 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), | 1890 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), |
1813 | MAKE_WM8775_DATA(0x0A)); | 1891 | MAKE_WM8775_DATA(0x0A)); |
1814 | } else { | 1892 | } else { |
@@ -1818,55 +1896,113 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1818 | goto error; | 1896 | goto error; |
1819 | } | 1897 | } |
1820 | 1898 | ||
1821 | /* Configure GPIO bit 14 change to line-in/mic-in */ | 1899 | if (hw->model != CTSB1270) { |
1822 | ctl = hw_read_20kx(hw, GPIO_CTRL); | 1900 | /* Configure GPIO bit 14 change to line-in/mic-in */ |
1823 | ctl |= 0x1 << 14; | 1901 | ctl = hw_read_20kx(hw, GPIO_CTRL); |
1824 | hw_write_20kx(hw, GPIO_CTRL, ctl); | 1902 | ctl |= 0x1 << 14; |
1825 | 1903 | hw_write_20kx(hw, GPIO_CTRL, ctl); | |
1826 | /* Check using Mic-in or Line-in */ | 1904 | hw_adc_input_select(hw, ADC_LINEIN); |
1827 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1828 | |||
1829 | if (mux == 1) { | ||
1830 | /* Configures GPIO data to select Mic-in */ | ||
1831 | data |= 0x1 << 14; | ||
1832 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1833 | |||
1834 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | ||
1835 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | ||
1836 | hw20k2_i2c_write(hw, | ||
1837 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), | ||
1838 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1839 | hw20k2_i2c_write(hw, | ||
1840 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1841 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1842 | } else if (mux == 2) { | ||
1843 | /* Configures GPIO data to select Line-in */ | ||
1844 | data &= ~(0x1 << 14); | ||
1845 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1846 | |||
1847 | /* Setup ADC */ | ||
1848 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), | ||
1849 | MAKE_WM8775_DATA(0x102)); /* Line-in */ | ||
1850 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), | ||
1851 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1852 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), | ||
1853 | MAKE_WM8775_DATA(0xCF)); /* No boost */ | ||
1854 | } else { | 1905 | } else { |
1855 | printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n"); | 1906 | hw_wm8775_input_select(hw, 0, 0); |
1856 | err = -EINVAL; | ||
1857 | goto error; | ||
1858 | } | 1907 | } |
1859 | 1908 | ||
1860 | return 0; | 1909 | return 0; |
1861 | |||
1862 | error: | 1910 | error: |
1863 | hw20k2_i2c_uninit(hw); | 1911 | hw20k2_i2c_uninit(hw); |
1864 | return err; | 1912 | return err; |
1865 | } | 1913 | } |
1866 | 1914 | ||
1867 | static int hw_have_digit_io_switch(struct hw *hw) | 1915 | static struct capabilities hw_capabilities(struct hw *hw) |
1868 | { | 1916 | { |
1869 | return 0; | 1917 | struct capabilities cap; |
1918 | |||
1919 | cap.digit_io_switch = 0; | ||
1920 | cap.dedicated_mic = hw->model == CTSB1270; | ||
1921 | cap.output_switch = hw->model == CTSB1270; | ||
1922 | cap.mic_source_switch = hw->model == CTSB1270; | ||
1923 | |||
1924 | return cap; | ||
1925 | } | ||
1926 | |||
1927 | static int hw_output_switch_get(struct hw *hw) | ||
1928 | { | ||
1929 | u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); | ||
1930 | |||
1931 | switch (data & 0x30) { | ||
1932 | case 0x00: | ||
1933 | return 0; | ||
1934 | case 0x10: | ||
1935 | return 1; | ||
1936 | case 0x20: | ||
1937 | return 2; | ||
1938 | default: | ||
1939 | return 3; | ||
1940 | } | ||
1941 | } | ||
1942 | |||
1943 | static int hw_output_switch_put(struct hw *hw, int position) | ||
1944 | { | ||
1945 | u32 data; | ||
1946 | |||
1947 | if (position == hw_output_switch_get(hw)) | ||
1948 | return 0; | ||
1949 | |||
1950 | /* Mute line and headphones (intended for anti-pop). */ | ||
1951 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1952 | data |= (0x03 << 11); | ||
1953 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1954 | |||
1955 | data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; | ||
1956 | switch (position) { | ||
1957 | case 0: | ||
1958 | break; | ||
1959 | case 1: | ||
1960 | data |= 0x10; | ||
1961 | break; | ||
1962 | default: | ||
1963 | data |= 0x20; | ||
1964 | } | ||
1965 | hw_write_20kx(hw, GPIO_EXT_DATA, data); | ||
1966 | |||
1967 | /* Unmute line and headphones. */ | ||
1968 | data = hw_read_20kx(hw, GPIO_DATA); | ||
1969 | data &= ~(0x03 << 11); | ||
1970 | hw_write_20kx(hw, GPIO_DATA, data); | ||
1971 | |||
1972 | return 1; | ||
1973 | } | ||
1974 | |||
1975 | static int hw_mic_source_switch_get(struct hw *hw) | ||
1976 | { | ||
1977 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1978 | |||
1979 | return hw20k2->mic_source; | ||
1980 | } | ||
1981 | |||
1982 | static int hw_mic_source_switch_put(struct hw *hw, int position) | ||
1983 | { | ||
1984 | struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; | ||
1985 | |||
1986 | if (position == hw20k2->mic_source) | ||
1987 | return 0; | ||
1988 | |||
1989 | switch (position) { | ||
1990 | case 0: | ||
1991 | hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ | ||
1992 | break; | ||
1993 | case 1: | ||
1994 | hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ | ||
1995 | break; | ||
1996 | case 2: | ||
1997 | hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ | ||
1998 | break; | ||
1999 | default: | ||
2000 | return 0; | ||
2001 | } | ||
2002 | |||
2003 | hw20k2->mic_source = position; | ||
2004 | |||
2005 | return 1; | ||
1870 | } | 2006 | } |
1871 | 2007 | ||
1872 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) | 2008 | static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) |
@@ -1925,7 +2061,7 @@ static int hw_card_start(struct hw *hw) | |||
1925 | 2061 | ||
1926 | if (hw->irq < 0) { | 2062 | if (hw->irq < 0) { |
1927 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, | 2063 | err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, |
1928 | "ctxfi", hw); | 2064 | KBUILD_MODNAME, hw); |
1929 | if (err < 0) { | 2065 | if (err < 0) { |
1930 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); | 2066 | printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); |
1931 | goto error2; | 2067 | goto error2; |
@@ -2023,13 +2159,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
2023 | /* Reset all SRC pending interrupts */ | 2159 | /* Reset all SRC pending interrupts */ |
2024 | hw_write_20kx(hw, SRC_IP, 0); | 2160 | hw_write_20kx(hw, SRC_IP, 0); |
2025 | 2161 | ||
2026 | /* TODO: detect the card ID and configure GPIO accordingly. */ | 2162 | if (hw->model != CTSB1270) { |
2027 | /* Configures GPIO (0xD802 0x98028) */ | 2163 | /* TODO: detect the card ID and configure GPIO accordingly. */ |
2028 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ | 2164 | /* Configures GPIO (0xD802 0x98028) */ |
2029 | /* Configures GPIO (SB0880) */ | 2165 | /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ |
2030 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ | 2166 | /* Configures GPIO (SB0880) */ |
2031 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | 2167 | /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ |
2032 | 2168 | hw_write_20kx(hw, GPIO_CTRL, 0xD802); | |
2169 | } else { | ||
2170 | hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); | ||
2171 | } | ||
2033 | /* Enable audio ring */ | 2172 | /* Enable audio ring */ |
2034 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); | 2173 | hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); |
2035 | 2174 | ||
@@ -2106,7 +2245,11 @@ static struct hw ct20k2_preset __devinitdata = { | |||
2106 | .pll_init = hw_pll_init, | 2245 | .pll_init = hw_pll_init, |
2107 | .is_adc_source_selected = hw_is_adc_input_selected, | 2246 | .is_adc_source_selected = hw_is_adc_input_selected, |
2108 | .select_adc_source = hw_adc_input_select, | 2247 | .select_adc_source = hw_adc_input_select, |
2109 | .have_digit_io_switch = hw_have_digit_io_switch, | 2248 | .capabilities = hw_capabilities, |
2249 | .output_switch_get = hw_output_switch_get, | ||
2250 | .output_switch_put = hw_output_switch_put, | ||
2251 | .mic_source_switch_get = hw_mic_source_switch_get, | ||
2252 | .mic_source_switch_put = hw_mic_source_switch_put, | ||
2110 | #ifdef CONFIG_PM | 2253 | #ifdef CONFIG_PM |
2111 | .suspend = hw_suspend, | 2254 | .suspend = hw_suspend, |
2112 | .resume = hw_resume, | 2255 | .resume = hw_resume, |