diff options
Diffstat (limited to 'sound/pci/ice1712/aureon.c')
-rw-r--r-- | sound/pci/ice1712/aureon.c | 163 |
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 | ||
90 | static 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 | */ | ||
104 | static 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 | |||
189 | static 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 | |||
203 | static 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 | |||
211 | static 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 | |||
232 | static 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 | */ |
149 | static int aureon_ac97_init (struct snd_ice1712 *ice) { | 293 | static 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; |