aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712/aureon.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ice1712/aureon.c')
-rw-r--r--sound/pci/ice1712/aureon.c163
1 files changed, 160 insertions, 3 deletions
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 7e6608b14abc..336dc489aee1 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -87,7 +87,151 @@
87#define CS8415_C_BUFFER 0x20 87#define CS8415_C_BUFFER 0x20
88#define CS8415_ID 0x7F 88#define CS8415_ID 0x7F
89 89
90static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) { 90/* PCA9554 registers */
91#define PCA9554_DEV 0x40 /* I2C device address */
92#define PCA9554_IN 0x00 /* input port */
93#define PCA9554_OUT 0x01 /* output port */
94#define PCA9554_INVERT 0x02 /* input invert */
95#define PCA9554_DIR 0x03 /* port directions */
96
97/*
98 * Aureon Universe additional controls using PCA9554
99 */
100
101/*
102 * Send data to pca9554
103 */
104static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
105 unsigned char data)
106{
107 unsigned int tmp;
108 int i, j;
109 unsigned char dev = PCA9554_DEV; /* ID 0100000, write */
110 unsigned char val = 0;
111
112 tmp = snd_ice1712_gpio_read(ice);
113
114 snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
115 AUREON_WM_RW|AUREON_WM_CS|
116 AUREON_CS8415_CS));
117 tmp |= AUREON_WM_RW;
118 tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
119
120 tmp &= ~AUREON_SPI_MOSI;
121 tmp &= ~AUREON_SPI_CLK;
122 snd_ice1712_gpio_write(ice, tmp);
123 udelay(50);
124
125 /*
126 * send i2c stop condition and start condition
127 * to obtain sane state
128 */
129 tmp |= AUREON_SPI_CLK;
130 snd_ice1712_gpio_write(ice, tmp);
131 udelay(50);
132 tmp |= AUREON_SPI_MOSI;
133 snd_ice1712_gpio_write(ice, tmp);
134 udelay(100);
135 tmp &= ~AUREON_SPI_MOSI;
136 snd_ice1712_gpio_write(ice, tmp);
137 udelay(50);
138 tmp &= ~AUREON_SPI_CLK;
139 snd_ice1712_gpio_write(ice, tmp);
140 udelay(100);
141 /*
142 * send device address, command and value,
143 * skipping ack cycles inbetween
144 */
145 for (j = 0; j < 3; j++) {
146 switch(j) {
147 case 0: val = dev; break;
148 case 1: val = reg; break;
149 case 2: val = data; break;
150 }
151 for (i = 7; i >= 0; i--) {
152 tmp &= ~AUREON_SPI_CLK;
153 snd_ice1712_gpio_write(ice, tmp);
154 udelay(40);
155 if (val & (1 << i))
156 tmp |= AUREON_SPI_MOSI;
157 else
158 tmp &= ~AUREON_SPI_MOSI;
159 snd_ice1712_gpio_write(ice, tmp);
160 udelay(40);
161 tmp |= AUREON_SPI_CLK;
162 snd_ice1712_gpio_write(ice, tmp);
163 udelay(40);
164 }
165 tmp &= ~AUREON_SPI_CLK;
166 snd_ice1712_gpio_write(ice, tmp);
167 udelay(40);
168 tmp |= AUREON_SPI_CLK;
169 snd_ice1712_gpio_write(ice, tmp);
170 udelay(40);
171 tmp &= ~AUREON_SPI_CLK;
172 snd_ice1712_gpio_write(ice, tmp);
173 udelay(40);
174 }
175 tmp &= ~AUREON_SPI_CLK;
176 snd_ice1712_gpio_write(ice, tmp);
177 udelay(40);
178 tmp &= ~AUREON_SPI_MOSI;
179 snd_ice1712_gpio_write(ice, tmp);
180 udelay(40);
181 tmp |= AUREON_SPI_CLK;
182 snd_ice1712_gpio_write(ice, tmp);
183 udelay(50);
184 tmp |= AUREON_SPI_MOSI;
185 snd_ice1712_gpio_write(ice, tmp);
186 udelay(100);
187}
188
189static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
190 struct snd_ctl_elem_info *uinfo)
191{
192 char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
193
194 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
195 uinfo->count = 1;
196 uinfo->value.enumerated.items = 3;
197 if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
198 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
199 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
200 return 0;
201}
202
203static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_value *ucontrol)
205{
206 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
207 ucontrol->value.integer.value[0] = ice->spec.aureon.pca9554_out;
208 return 0;
209}
210
211static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
212 struct snd_ctl_elem_value *ucontrol)
213{
214 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
215 unsigned char oval, nval;
216 int change;
217
218 snd_ice1712_save_gpio_status(ice);
219
220 oval = ice->spec.aureon.pca9554_out;
221 nval = ucontrol->value.integer.value[0];
222 if ((change = (oval != nval))) {
223 aureon_pca9554_write(ice, PCA9554_OUT, nval);
224 ice->spec.aureon.pca9554_out = nval;
225 }
226 snd_ice1712_restore_gpio_status(ice);
227
228 return change;
229}
230
231
232static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
233 unsigned short val)
234{
91 unsigned int tmp; 235 unsigned int tmp;
92 236
93 /* Send address to XILINX chip */ 237 /* Send address to XILINX chip */
@@ -146,7 +290,8 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r
146/* 290/*
147 * Initialize STAC9744 chip 291 * Initialize STAC9744 chip
148 */ 292 */
149static int aureon_ac97_init (struct snd_ice1712 *ice) { 293static int aureon_ac97_init (struct snd_ice1712 *ice)
294{
150 int i; 295 int i;
151 static unsigned short ac97_defaults[] = { 296 static unsigned short ac97_defaults[] = {
152 0x00, 0x9640, 297 0x00, 0x9640,
@@ -1598,7 +1743,15 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1598 .get = aureon_ac97_vol_get, 1743 .get = aureon_ac97_vol_get,
1599 .put = aureon_ac97_vol_put, 1744 .put = aureon_ac97_vol_put,
1600 .private_value = AC97_VIDEO|AUREON_AC97_STEREO 1745 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1601 } 1746 },
1747 {
1748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1749 .name = "Aux Source",
1750 .info = aureon_universe_inmux_info,
1751 .get = aureon_universe_inmux_get,
1752 .put = aureon_universe_inmux_put
1753 }
1754
1602}; 1755};
1603 1756
1604 1757
@@ -1856,6 +2009,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
1856 } 2009 }
1857 2010
1858 snd_ice1712_restore_gpio_status(ice); 2011 snd_ice1712_restore_gpio_status(ice);
2012
2013 /* initialize PCA9554 pin directions & set default input*/
2014 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2015 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
1859 2016
1860 ice->spec.aureon.master[0] = WM_VOL_MUTE; 2017 ice->spec.aureon.master[0] = WM_VOL_MUTE;
1861 ice->spec.aureon.master[1] = WM_VOL_MUTE; 2018 ice->spec.aureon.master[1] = WM_VOL_MUTE;