aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ca0106
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-17 04:40:18 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:17:01 -0500
commit95a98265eb7b112b3268761053d643635171e219 (patch)
treedaf88b4858b1ba856609c2a3138522ea4a2b6269 /sound/pci/ca0106
parent954bea35571461b083390a82b03f077f901fe678 (diff)
[ALSA] ca0106 - Code clean up
Modules: CA0106 driver Clean up snd-ca0106 driver code: - Fix spaces and indents - Remove unnecessary spinlocks - Clean up the mixer callbacks using private_value - Clean up mixer constructors using an array Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ca0106')
-rw-r--r--sound/pci/ca0106/ca0106_main.c74
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c417
2 files changed, 131 insertions, 360 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index a89eed255098..0120c4683c79 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -207,7 +207,8 @@ static snd_pcm_hardware_t snd_ca0106_playback_hw = {
207 SNDRV_PCM_INFO_BLOCK_TRANSFER | 207 SNDRV_PCM_INFO_BLOCK_TRANSFER |
208 SNDRV_PCM_INFO_MMAP_VALID), 208 SNDRV_PCM_INFO_MMAP_VALID),
209 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 209 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
210 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, 210 .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
211 SNDRV_PCM_RATE_192000),
211 .rate_min = 48000, 212 .rate_min = 48000,
212 .rate_max = 192000, 213 .rate_max = 192000,
213 .channels_min = 2, //1, 214 .channels_min = 2, //1,
@@ -226,7 +227,8 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
226 SNDRV_PCM_INFO_BLOCK_TRANSFER | 227 SNDRV_PCM_INFO_BLOCK_TRANSFER |
227 SNDRV_PCM_INFO_MMAP_VALID), 228 SNDRV_PCM_INFO_MMAP_VALID),
228 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 229 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
229 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, 230 .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
231 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
230 .rate_min = 44100, 232 .rate_min = 44100,
231 .rate_max = 192000, 233 .rate_max = 192000,
232 .channels_min = 2, 234 .channels_min = 2,
@@ -276,11 +278,10 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
276 u32 value) 278 u32 value)
277{ 279{
278 u32 tmp; 280 u32 tmp;
279 int timeout=0; 281 int timeout = 0;
280 int status; 282 int status;
281 int retry; 283 int retry;
282 if ((reg > 0x7f) || (value > 0x1ff)) 284 if ((reg > 0x7f) || (value > 0x1ff)) {
283 {
284 snd_printk(KERN_ERR "i2c_write: invalid values.\n"); 285 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
285 return -EINVAL; 286 return -EINVAL;
286 } 287 }
@@ -292,8 +293,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
292 /* This controls the I2C connected to the WM8775 ADC Codec */ 293 /* This controls the I2C connected to the WM8775 ADC Codec */
293 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); 294 snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
294 295
295 for(retry=0;retry<10;retry++) 296 for (retry = 0; retry < 10; retry++) {
296 {
297 /* Send the data to i2c */ 297 /* Send the data to i2c */
298 tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); 298 tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
299 tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); 299 tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
@@ -301,24 +301,22 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
301 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); 301 snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
302 302
303 /* Wait till the transaction ends */ 303 /* Wait till the transaction ends */
304 while(1) 304 while (1) {
305 {
306 status = snd_ca0106_ptr_read(emu, I2C_A, 0); 305 status = snd_ca0106_ptr_read(emu, I2C_A, 0);
307 //snd_printk("I2C:status=0x%x\n", status); 306 //snd_printk("I2C:status=0x%x\n", status);
308 timeout++; 307 timeout++;
309 if((status & I2C_A_ADC_START)==0) 308 if ((status & I2C_A_ADC_START) == 0)
310 break; 309 break;
311 310
312 if(timeout>1000) 311 if (timeout > 1000)
313 break; 312 break;
314 } 313 }
315 //Read back and see if the transaction is successful 314 //Read back and see if the transaction is successful
316 if((status & I2C_A_ADC_ABORT)==0) 315 if ((status & I2C_A_ADC_ABORT) == 0)
317 break; 316 break;
318 } 317 }
319 318
320 if(retry==10) 319 if (retry == 10) {
321 {
322 snd_printk(KERN_ERR "Writing to ADC failed!\n"); 320 snd_printk(KERN_ERR "Writing to ADC failed!\n");
323 return -EINVAL; 321 return -EINVAL;
324 } 322 }
@@ -380,10 +378,10 @@ static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream,
380 channel->emu = chip; 378 channel->emu = chip;
381 channel->number = channel_id; 379 channel->number = channel_id;
382 380
383 channel->use=1; 381 channel->use = 1;
384 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); 382 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
385 //channel->interrupt = snd_ca0106_pcm_channel_interrupt; 383 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
386 channel->epcm=epcm; 384 channel->epcm = epcm;
387 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) 385 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
388 return err; 386 return err;
389 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) 387 if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
@@ -448,10 +446,10 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i
448 channel->emu = chip; 446 channel->emu = chip;
449 channel->number = channel_id; 447 channel->number = channel_id;
450 448
451 channel->use=1; 449 channel->use = 1;
452 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); 450 //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
453 //channel->interrupt = snd_ca0106_pcm_channel_interrupt; 451 //channel->interrupt = snd_ca0106_pcm_channel_interrupt;
454 channel->epcm=epcm; 452 channel->epcm = epcm;
455 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) 453 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
456 return err; 454 return err;
457 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); 455 //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
@@ -593,8 +591,8 @@ static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
593 591
594 /* FIXME: Check emu->buffer.size before actually writing to it. */ 592 /* FIXME: Check emu->buffer.size before actually writing to it. */
595 for(i=0; i < runtime->periods; i++) { 593 for(i=0; i < runtime->periods; i++) {
596 table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); 594 table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
597 table_base[(i*2)+1]=period_size_bytes<<16; 595 table_base[i*2+1] = period_size_bytes << 16;
598 } 596 }
599 597
600 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel)); 598 snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
@@ -1008,13 +1006,8 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1008 unsigned int stat76; 1006 unsigned int stat76;
1009 ca0106_channel_t *pchannel; 1007 ca0106_channel_t *pchannel;
1010 1008
1011 spin_lock(&chip->emu_lock);
1012
1013 status = inl(chip->port + IPR); 1009 status = inl(chip->port + IPR);
1014 1010
1015 // call updater, unlock before it
1016 spin_unlock(&chip->emu_lock);
1017
1018 if (! status) 1011 if (! status)
1019 return IRQ_NONE; 1012 return IRQ_NONE;
1020 1013
@@ -1024,11 +1017,11 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1024 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */ 1017 mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
1025 for(i = 0; i < 4; i++) { 1018 for(i = 0; i < 4; i++) {
1026 pchannel = &(chip->playback_channels[i]); 1019 pchannel = &(chip->playback_channels[i]);
1027 if(stat76 & mask) { 1020 if (stat76 & mask) {
1028/* FIXME: Select the correct substream for period elapsed */ 1021/* FIXME: Select the correct substream for period elapsed */
1029 if(pchannel->use) { 1022 if(pchannel->use) {
1030 snd_pcm_period_elapsed(pchannel->epcm->substream); 1023 snd_pcm_period_elapsed(pchannel->epcm->substream);
1031 //printk(KERN_INFO "interrupt [%d] used\n", i); 1024 //printk(KERN_INFO "interrupt [%d] used\n", i);
1032 } 1025 }
1033 } 1026 }
1034 //printk(KERN_INFO "channel=%p\n",pchannel); 1027 //printk(KERN_INFO "channel=%p\n",pchannel);
@@ -1038,11 +1031,11 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1038 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */ 1031 mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
1039 for(i = 0; i < 4; i++) { 1032 for(i = 0; i < 4; i++) {
1040 pchannel = &(chip->capture_channels[i]); 1033 pchannel = &(chip->capture_channels[i]);
1041 if(stat76 & mask) { 1034 if (stat76 & mask) {
1042/* FIXME: Select the correct substream for period elapsed */ 1035/* FIXME: Select the correct substream for period elapsed */
1043 if(pchannel->use) { 1036 if(pchannel->use) {
1044 snd_pcm_period_elapsed(pchannel->epcm->substream); 1037 snd_pcm_period_elapsed(pchannel->epcm->substream);
1045 //printk(KERN_INFO "interrupt [%d] used\n", i); 1038 //printk(KERN_INFO "interrupt [%d] used\n", i);
1046 } 1039 }
1047 } 1040 }
1048 //printk(KERN_INFO "channel=%p\n",pchannel); 1041 //printk(KERN_INFO "channel=%p\n",pchannel);
@@ -1051,10 +1044,9 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1051 } 1044 }
1052 1045
1053 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76); 1046 snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
1054 spin_lock(&chip->emu_lock);
1055 1047
1056 if (chip->midi.dev_id && 1048 if (chip->midi.dev_id &&
1057 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) { 1049 (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
1058 if (chip->midi.interrupt) 1050 if (chip->midi.interrupt)
1059 chip->midi.interrupt(&chip->midi, status); 1051 chip->midi.interrupt(&chip->midi, status);
1060 else 1052 else
@@ -1064,8 +1056,6 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
1064 // acknowledge the interrupt if necessary 1056 // acknowledge the interrupt if necessary
1065 outl(status, chip->port+IPR); 1057 outl(status, chip->port+IPR);
1066 1058
1067 spin_unlock(&chip->emu_lock);
1068
1069 return IRQ_HANDLED; 1059 return IRQ_HANDLED;
1070} 1060}
1071 1061
@@ -1202,8 +1192,9 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
1202 strcpy(card->driver, "CA0106"); 1192 strcpy(card->driver, "CA0106");
1203 strcpy(card->shortname, "CA0106"); 1193 strcpy(card->shortname, "CA0106");
1204 1194
1205 for (c=ca0106_chip_details; c->serial; c++) { 1195 for (c = ca0106_chip_details; c->serial; c++) {
1206 if (c->serial == chip->serial) break; 1196 if (c->serial == chip->serial)
1197 break;
1207 } 1198 }
1208 chip->details = c; 1199 chip->details = c;
1209 sprintf(card->longname, "%s at 0x%lx irq %i", 1200 sprintf(card->longname, "%s at 0x%lx irq %i",
@@ -1359,7 +1350,7 @@ static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel)
1359 char *name; 1350 char *name;
1360 int err; 1351 int err;
1361 1352
1362 if(channel==CA0106_MIDI_CHAN_B) { 1353 if (channel == CA0106_MIDI_CHAN_B) {
1363 name = "CA0106 MPU-401 (UART) B"; 1354 name = "CA0106 MPU-401 (UART) B";
1364 midi = &chip->midi2; 1355 midi = &chip->midi2;
1365 midi->tx_enable = INTE_MIDI_TX_B; 1356 midi->tx_enable = INTE_MIDI_TX_B;
@@ -1499,12 +1490,7 @@ static struct pci_driver driver = {
1499// initialization of the module 1490// initialization of the module
1500static int __init alsa_card_ca0106_init(void) 1491static int __init alsa_card_ca0106_init(void)
1501{ 1492{
1502 int err; 1493 return pci_register_driver(&driver);
1503
1504 if ((err = pci_register_driver(&driver)) > 0)
1505 return err;
1506
1507 return 0;
1508} 1494}
1509 1495
1510// clean up the module 1496// clean up the module
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index c10e4a54301b..0730dc7c66e5 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -125,18 +125,11 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
125 return change; 125 return change;
126} 126}
127 127
128static snd_kcontrol_new_t snd_ca0106_shared_spdif __devinitdata =
129{
130 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
131 .name = "SPDIF Out",
132 .info = snd_ca0106_shared_spdif_info,
133 .get = snd_ca0106_shared_spdif_get,
134 .put = snd_ca0106_shared_spdif_put
135};
136
137static int snd_ca0106_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 128static int snd_ca0106_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
138{ 129{
139 static char *texts[6] = { "SPDIF out", "i2s mixer out", "SPDIF in", "i2s in", "AC97 in", "SRC out" }; 130 static char *texts[6] = {
131 "SPDIF out", "i2s mixer out", "SPDIF in", "i2s in", "AC97 in", "SRC out"
132 };
140 133
141 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 134 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
142 uinfo->count = 1; 135 uinfo->count = 1;
@@ -176,15 +169,6 @@ static int snd_ca0106_capture_source_put(snd_kcontrol_t * kcontrol,
176 return change; 169 return change;
177} 170}
178 171
179static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata =
180{
181 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
182 .name = "Capture Source",
183 .info = snd_ca0106_capture_source_info,
184 .get = snd_ca0106_capture_source_get,
185 .put = snd_ca0106_capture_source_put
186};
187
188static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 172static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
189{ 173{
190 static char *texts[2] = { "Line in", "Mic in" }; 174 static char *texts[2] = { "Line in", "Mic in" };
@@ -294,26 +278,6 @@ static int snd_ca0106_spdif_put(snd_kcontrol_t * kcontrol,
294 return change; 278 return change;
295} 279}
296 280
297static snd_kcontrol_new_t snd_ca0106_spdif_mask_control =
298{
299 .access = SNDRV_CTL_ELEM_ACCESS_READ,
300 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
301 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
302 .count = 4,
303 .info = snd_ca0106_spdif_info,
304 .get = snd_ca0106_spdif_get_mask
305};
306
307static snd_kcontrol_new_t snd_ca0106_spdif_control =
308{
309 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
310 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
311 .count = 4,
312 .info = snd_ca0106_spdif_info,
313 .get = snd_ca0106_spdif_get,
314 .put = snd_ca0106_spdif_put
315};
316
317static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 281static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
318{ 282{
319 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 283 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -324,10 +288,14 @@ static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
324} 288}
325 289
326static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol, 290static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol,
327 snd_ctl_elem_value_t * ucontrol, int reg, int channel_id) 291 snd_ctl_elem_value_t * ucontrol)
328{ 292{
329 ca0106_t *emu = snd_kcontrol_chip(kcontrol); 293 ca0106_t *emu = snd_kcontrol_chip(kcontrol);
330 unsigned int value; 294 unsigned int value;
295 int channel_id, reg;
296
297 channel_id = (kcontrol->private_value >> 8) & 0xff;
298 reg = kcontrol->private_value & 0xff;
331 299
332 value = snd_ca0106_ptr_read(emu, reg, channel_id); 300 value = snd_ca0106_ptr_read(emu, reg, channel_id);
333 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */ 301 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
@@ -335,226 +303,92 @@ static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol,
335 return 0; 303 return 0;
336} 304}
337 305
338static int snd_ca0106_volume_get_spdif_front(snd_kcontrol_t * kcontrol,
339 snd_ctl_elem_value_t * ucontrol)
340{
341 int channel_id = CONTROL_FRONT_CHANNEL;
342 int reg = PLAYBACK_VOLUME1;
343 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
344}
345
346static int snd_ca0106_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol,
347 snd_ctl_elem_value_t * ucontrol)
348{
349 int channel_id = CONTROL_CENTER_LFE_CHANNEL;
350 int reg = PLAYBACK_VOLUME1;
351 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
352}
353static int snd_ca0106_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol,
354 snd_ctl_elem_value_t * ucontrol)
355{
356 int channel_id = CONTROL_UNKNOWN_CHANNEL;
357 int reg = PLAYBACK_VOLUME1;
358 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
359}
360static int snd_ca0106_volume_get_spdif_rear(snd_kcontrol_t * kcontrol,
361 snd_ctl_elem_value_t * ucontrol)
362{
363 int channel_id = CONTROL_REAR_CHANNEL;
364 int reg = PLAYBACK_VOLUME1;
365 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
366}
367static int snd_ca0106_volume_get_analog_front(snd_kcontrol_t * kcontrol,
368 snd_ctl_elem_value_t * ucontrol)
369{
370 int channel_id = CONTROL_FRONT_CHANNEL;
371 int reg = PLAYBACK_VOLUME2;
372 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
373}
374
375static int snd_ca0106_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol,
376 snd_ctl_elem_value_t * ucontrol)
377{
378 int channel_id = CONTROL_CENTER_LFE_CHANNEL;
379 int reg = PLAYBACK_VOLUME2;
380 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
381}
382static int snd_ca0106_volume_get_analog_unknown(snd_kcontrol_t * kcontrol,
383 snd_ctl_elem_value_t * ucontrol)
384{
385 int channel_id = CONTROL_UNKNOWN_CHANNEL;
386 int reg = PLAYBACK_VOLUME2;
387 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
388}
389static int snd_ca0106_volume_get_analog_rear(snd_kcontrol_t * kcontrol,
390 snd_ctl_elem_value_t * ucontrol)
391{
392 int channel_id = CONTROL_REAR_CHANNEL;
393 int reg = PLAYBACK_VOLUME2;
394 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
395}
396
397static int snd_ca0106_volume_get_feedback(snd_kcontrol_t * kcontrol,
398 snd_ctl_elem_value_t * ucontrol)
399{
400 int channel_id = 1;
401 int reg = CAPTURE_CONTROL;
402 return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
403}
404
405static int snd_ca0106_volume_put(snd_kcontrol_t * kcontrol, 306static int snd_ca0106_volume_put(snd_kcontrol_t * kcontrol,
406 snd_ctl_elem_value_t * ucontrol, int reg, int channel_id) 307 snd_ctl_elem_value_t * ucontrol)
407{ 308{
408 ca0106_t *emu = snd_kcontrol_chip(kcontrol); 309 ca0106_t *emu = snd_kcontrol_chip(kcontrol);
409 unsigned int value; 310 unsigned int oval, nval;
410 //value = snd_ca0106_ptr_read(emu, reg, channel_id); 311 int channel_id, reg;
411 //value = value & 0xffff; 312
412 value = ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16); 313 channel_id = (kcontrol->private_value >> 8) & 0xff;
413 value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) ); 314 reg = kcontrol->private_value & 0xff;
414 snd_ca0106_ptr_write(emu, reg, channel_id, value); 315
415 return 1; 316 oval = snd_ca0106_ptr_read(emu, reg, channel_id);
416} 317 nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
417static int snd_ca0106_volume_put_spdif_front(snd_kcontrol_t * kcontrol, 318 ((0xff - ucontrol->value.integer.value[1]) << 16);
418 snd_ctl_elem_value_t * ucontrol) 319 nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
419{ 320 ((0xff - ucontrol->value.integer.value[1]) );
420 int channel_id = CONTROL_FRONT_CHANNEL; 321 if (oval == nval)
421 int reg = PLAYBACK_VOLUME1; 322 return 0;
422 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 323 snd_ca0106_ptr_write(emu, reg, channel_id, nval);
423} 324 return 1;
424static int snd_ca0106_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol, 325}
425 snd_ctl_elem_value_t * ucontrol) 326
426{ 327#define CA_VOLUME(xname,chid,reg) \
427 int channel_id = CONTROL_CENTER_LFE_CHANNEL; 328{ \
428 int reg = PLAYBACK_VOLUME1; 329 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
429 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 330 .info = snd_ca0106_volume_info, \
430} 331 .get = snd_ca0106_volume_get, \
431static int snd_ca0106_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol, 332 .put = snd_ca0106_volume_put, \
432 snd_ctl_elem_value_t * ucontrol) 333 .private_value = ((chid) << 8) | (reg) \
433{ 334}
434 int channel_id = CONTROL_UNKNOWN_CHANNEL; 335
435 int reg = PLAYBACK_VOLUME1; 336
436 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 337static snd_kcontrol_new_t snd_ca0106_volume_ctls[] __devinitdata = {
437} 338 CA_VOLUME("Analog Front Playback Volume",
438static int snd_ca0106_volume_put_spdif_rear(snd_kcontrol_t * kcontrol, 339 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
439 snd_ctl_elem_value_t * ucontrol) 340 CA_VOLUME("Analog Rear Playback Volume",
440{ 341 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
441 int channel_id = CONTROL_REAR_CHANNEL; 342 CA_VOLUME("Analog Center/LFE Playback Volume",
442 int reg = PLAYBACK_VOLUME1; 343 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
443 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 344 CA_VOLUME("Analog Side Playback Volume",
444} 345 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
445static int snd_ca0106_volume_put_analog_front(snd_kcontrol_t * kcontrol, 346
446 snd_ctl_elem_value_t * ucontrol) 347 CA_VOLUME("SPDIF Front Playback Volume",
447{ 348 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
448 int channel_id = CONTROL_FRONT_CHANNEL; 349 CA_VOLUME("SPDIF Rear Playback Volume",
449 int reg = PLAYBACK_VOLUME2; 350 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
450 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 351 CA_VOLUME("SPDIF Center/LFE Playback Volume",
451} 352 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
452static int snd_ca0106_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol, 353 CA_VOLUME("SPDIF Unknown Playback Volume",
453 snd_ctl_elem_value_t * ucontrol) 354 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
454{ 355
455 int channel_id = CONTROL_CENTER_LFE_CHANNEL; 356 CA_VOLUME("CAPTURE feedback Playback Volume",
456 int reg = PLAYBACK_VOLUME2; 357 1, CAPTURE_CONTROL),
457 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 358
458} 359 {
459static int snd_ca0106_volume_put_analog_unknown(snd_kcontrol_t * kcontrol, 360 .access = SNDRV_CTL_ELEM_ACCESS_READ,
460 snd_ctl_elem_value_t * ucontrol) 361 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
461{ 362 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
462 int channel_id = CONTROL_UNKNOWN_CHANNEL; 363 .count = 4,
463 int reg = PLAYBACK_VOLUME2; 364 .info = snd_ca0106_spdif_info,
464 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 365 .get = snd_ca0106_spdif_get_mask
465} 366 },
466static int snd_ca0106_volume_put_analog_rear(snd_kcontrol_t * kcontrol, 367 {
467 snd_ctl_elem_value_t * ucontrol) 368 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
468{ 369 .name = "SPDIF Out",
469 int channel_id = CONTROL_REAR_CHANNEL; 370 .info = snd_ca0106_shared_spdif_info,
470 int reg = PLAYBACK_VOLUME2; 371 .get = snd_ca0106_shared_spdif_get,
471 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 372 .put = snd_ca0106_shared_spdif_put
472} 373 },
473 374 {
474static int snd_ca0106_volume_put_feedback(snd_kcontrol_t * kcontrol, 375 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
475 snd_ctl_elem_value_t * ucontrol) 376 .name = "Capture Source",
476{ 377 .info = snd_ca0106_capture_source_info,
477 int channel_id = 1; 378 .get = snd_ca0106_capture_source_get,
478 int reg = CAPTURE_CONTROL; 379 .put = snd_ca0106_capture_source_put
479 return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id); 380 },
480} 381 {
481 382 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
482static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front = 383 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
483{ 384 .count = 4,
484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 385 .info = snd_ca0106_spdif_info,
485 .name = "Analog Front Playback Volume", 386 .get = snd_ca0106_spdif_get,
486 .info = snd_ca0106_volume_info, 387 .put = snd_ca0106_spdif_put
487 .get = snd_ca0106_volume_get_analog_front, 388 },
488 .put = snd_ca0106_volume_put_analog_front
489};
490static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
491{
492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
493 .name = "Analog Center/LFE Playback Volume",
494 .info = snd_ca0106_volume_info,
495 .get = snd_ca0106_volume_get_analog_center_lfe,
496 .put = snd_ca0106_volume_put_analog_center_lfe
497};
498static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
499{
500 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
501 .name = "Analog Side Playback Volume",
502 .info = snd_ca0106_volume_info,
503 .get = snd_ca0106_volume_get_analog_unknown,
504 .put = snd_ca0106_volume_put_analog_unknown
505};
506static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
507{
508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
509 .name = "Analog Rear Playback Volume",
510 .info = snd_ca0106_volume_info,
511 .get = snd_ca0106_volume_get_analog_rear,
512 .put = snd_ca0106_volume_put_analog_rear
513};
514static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
515{
516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
517 .name = "SPDIF Front Playback Volume",
518 .info = snd_ca0106_volume_info,
519 .get = snd_ca0106_volume_get_spdif_front,
520 .put = snd_ca0106_volume_put_spdif_front
521};
522static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
523{
524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
525 .name = "SPDIF Center/LFE Playback Volume",
526 .info = snd_ca0106_volume_info,
527 .get = snd_ca0106_volume_get_spdif_center_lfe,
528 .put = snd_ca0106_volume_put_spdif_center_lfe
529};
530static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
531{
532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
533 .name = "SPDIF Unknown Playback Volume",
534 .info = snd_ca0106_volume_info,
535 .get = snd_ca0106_volume_get_spdif_unknown,
536 .put = snd_ca0106_volume_put_spdif_unknown
537};
538static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
539{
540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
541 .name = "SPDIF Rear Playback Volume",
542 .info = snd_ca0106_volume_info,
543 .get = snd_ca0106_volume_get_spdif_rear,
544 .put = snd_ca0106_volume_put_spdif_rear
545};
546
547static snd_kcontrol_new_t snd_ca0106_volume_control_feedback =
548{
549 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
550 .name = "CAPTURE feedback Playback Volume",
551 .info = snd_ca0106_volume_info,
552 .get = snd_ca0106_volume_get_feedback,
553 .put = snd_ca0106_volume_put_feedback
554}; 389};
555 390
556 391static int __devinit remove_ctl(snd_card_t *card, const char *name)
557static int remove_ctl(snd_card_t *card, const char *name)
558{ 392{
559 snd_ctl_elem_id_t id; 393 snd_ctl_elem_id_t id;
560 memset(&id, 0, sizeof(id)); 394 memset(&id, 0, sizeof(id));
@@ -563,7 +397,7 @@ static int remove_ctl(snd_card_t *card, const char *name)
563 return snd_ctl_remove_id(card, &id); 397 return snd_ctl_remove_id(card, &id);
564} 398}
565 399
566static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name) 400static snd_kcontrol_t __devinit *ctl_find(snd_card_t *card, const char *name)
567{ 401{
568 snd_ctl_elem_id_t sid; 402 snd_ctl_elem_id_t sid;
569 memset(&sid, 0, sizeof(sid)); 403 memset(&sid, 0, sizeof(sid));
@@ -573,7 +407,7 @@ static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
573 return snd_ctl_find_id(card, &sid); 407 return snd_ctl_find_id(card, &sid);
574} 408}
575 409
576static int rename_ctl(snd_card_t *card, const char *src, const char *dst) 410static int __devinit rename_ctl(snd_card_t *card, const char *src, const char *dst)
577{ 411{
578 snd_kcontrol_t *kctl = ctl_find(card, src); 412 snd_kcontrol_t *kctl = ctl_find(card, src);
579 if (kctl) { 413 if (kctl) {
@@ -585,8 +419,7 @@ static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
585 419
586int __devinit snd_ca0106_mixer(ca0106_t *emu) 420int __devinit snd_ca0106_mixer(ca0106_t *emu)
587{ 421{
588 int err; 422 int i, err;
589 snd_kcontrol_t *kctl;
590 snd_card_t *card = emu->card; 423 snd_card_t *card = emu->card;
591 char **c; 424 char **c;
592 static char *ca0106_remove_ctls[] = { 425 static char *ca0106_remove_ctls[] = {
@@ -627,70 +460,22 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu)
627 NULL 460 NULL
628 }; 461 };
629#if 1 462#if 1
630 for (c=ca0106_remove_ctls; *c; c++) 463 for (c = ca0106_remove_ctls; *c; c++)
631 remove_ctl(card, *c); 464 remove_ctl(card, *c);
632 for (c=ca0106_rename_ctls; *c; c += 2) 465 for (c = ca0106_rename_ctls; *c; c += 2)
633 rename_ctl(card, c[0], c[1]); 466 rename_ctl(card, c[0], c[1]);
634#endif 467#endif
635 468
636 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_front, emu)) == NULL) 469 for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) {
637 return -ENOMEM; 470 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu));
638 if ((err = snd_ctl_add(card, kctl))) 471 if (err < 0)
639 return err; 472 return err;
640 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_rear, emu)) == NULL) 473 }
641 return -ENOMEM;
642 if ((err = snd_ctl_add(card, kctl)))
643 return err;
644 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_center_lfe, emu)) == NULL)
645 return -ENOMEM;
646 if ((err = snd_ctl_add(card, kctl)))
647 return err;
648 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_unknown, emu)) == NULL)
649 return -ENOMEM;
650 if ((err = snd_ctl_add(card, kctl)))
651 return err;
652 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_front, emu)) == NULL)
653 return -ENOMEM;
654 if ((err = snd_ctl_add(card, kctl)))
655 return err;
656 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_rear, emu)) == NULL)
657 return -ENOMEM;
658 if ((err = snd_ctl_add(card, kctl)))
659 return err;
660 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_center_lfe, emu)) == NULL)
661 return -ENOMEM;
662 if ((err = snd_ctl_add(card, kctl)))
663 return err;
664 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_unknown, emu)) == NULL)
665 return -ENOMEM;
666 if ((err = snd_ctl_add(card, kctl)))
667 return err;
668 if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_feedback, emu)) == NULL)
669 return -ENOMEM;
670 if ((err = snd_ctl_add(card, kctl)))
671 return err;
672 if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_mask_control, emu)) == NULL)
673 return -ENOMEM;
674 if ((err = snd_ctl_add(card, kctl)))
675 return err;
676 if ((kctl = snd_ctl_new1(&snd_ca0106_shared_spdif, emu)) == NULL)
677 return -ENOMEM;
678 if ((err = snd_ctl_add(card, kctl)))
679 return err;
680 if ((kctl = snd_ctl_new1(&snd_ca0106_capture_source, emu)) == NULL)
681 return -ENOMEM;
682 if ((err = snd_ctl_add(card, kctl)))
683 return err;
684 if (emu->details->i2c_adc == 1) { 474 if (emu->details->i2c_adc == 1) {
685 if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL) 475 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
686 return -ENOMEM; 476 if (err < 0)
687 if ((err = snd_ctl_add(card, kctl)))
688 return err; 477 return err;
689 } 478 }
690 if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
691 return -ENOMEM;
692 if ((err = snd_ctl_add(card, kctl)))
693 return err;
694 return 0; 479 return 0;
695} 480}
696 481