diff options
Diffstat (limited to 'sound/pci/ca0106/ca0106_mixer.c')
-rw-r--r-- | sound/pci/ca0106/ca0106_mixer.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index cccc32cdb943..8727881a10b8 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -148,7 +148,7 @@ static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) | |||
148 | 148 | ||
149 | static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) | 149 | static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) |
150 | { | 150 | { |
151 | snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]); | 151 | snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); |
152 | } | 152 | } |
153 | 153 | ||
154 | /* | 154 | /* |
@@ -353,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, | |||
353 | return 0; | 353 | return 0; |
354 | } | 354 | } |
355 | 355 | ||
356 | static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol, | 356 | static void decode_spdif_bits(unsigned char *status, unsigned int bits) |
357 | { | ||
358 | status[0] = (bits >> 0) & 0xff; | ||
359 | status[1] = (bits >> 8) & 0xff; | ||
360 | status[2] = (bits >> 16) & 0xff; | ||
361 | status[3] = (bits >> 24) & 0xff; | ||
362 | } | ||
363 | |||
364 | static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, | ||
357 | struct snd_ctl_elem_value *ucontrol) | 365 | struct snd_ctl_elem_value *ucontrol) |
358 | { | 366 | { |
359 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 367 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
360 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 368 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
361 | 369 | ||
362 | ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; | 370 | decode_spdif_bits(ucontrol->value.iec958.status, |
363 | ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; | 371 | emu->spdif_bits[idx]); |
364 | ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; | 372 | return 0; |
365 | ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; | 373 | } |
374 | |||
375 | static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, | ||
376 | struct snd_ctl_elem_value *ucontrol) | ||
377 | { | ||
378 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
379 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
380 | |||
381 | decode_spdif_bits(ucontrol->value.iec958.status, | ||
382 | emu->spdif_str_bits[idx]); | ||
366 | return 0; | 383 | return 0; |
367 | } | 384 | } |
368 | 385 | ||
@@ -376,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, | |||
376 | return 0; | 393 | return 0; |
377 | } | 394 | } |
378 | 395 | ||
379 | static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, | 396 | static unsigned int encode_spdif_bits(unsigned char *status) |
397 | { | ||
398 | return ((unsigned int)status[0] << 0) | | ||
399 | ((unsigned int)status[1] << 8) | | ||
400 | ((unsigned int)status[2] << 16) | | ||
401 | ((unsigned int)status[3] << 24); | ||
402 | } | ||
403 | |||
404 | static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, | ||
380 | struct snd_ctl_elem_value *ucontrol) | 405 | struct snd_ctl_elem_value *ucontrol) |
381 | { | 406 | { |
382 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 407 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
383 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 408 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
384 | int change; | ||
385 | unsigned int val; | 409 | unsigned int val; |
386 | 410 | ||
387 | val = (ucontrol->value.iec958.status[0] << 0) | | 411 | val = encode_spdif_bits(ucontrol->value.iec958.status); |
388 | (ucontrol->value.iec958.status[1] << 8) | | 412 | if (val != emu->spdif_bits[idx]) { |
389 | (ucontrol->value.iec958.status[2] << 16) | | ||
390 | (ucontrol->value.iec958.status[3] << 24); | ||
391 | change = val != emu->spdif_bits[idx]; | ||
392 | if (change) { | ||
393 | emu->spdif_bits[idx] = val; | 413 | emu->spdif_bits[idx] = val; |
414 | /* FIXME: this isn't safe, but needed to keep the compatibility | ||
415 | * with older alsa-lib config | ||
416 | */ | ||
417 | emu->spdif_str_bits[idx] = val; | ||
394 | ca0106_set_spdif_bits(emu, idx); | 418 | ca0106_set_spdif_bits(emu, idx); |
419 | return 1; | ||
395 | } | 420 | } |
396 | return change; | 421 | return 0; |
422 | } | ||
423 | |||
424 | static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, | ||
425 | struct snd_ctl_elem_value *ucontrol) | ||
426 | { | ||
427 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
428 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
429 | unsigned int val; | ||
430 | |||
431 | val = encode_spdif_bits(ucontrol->value.iec958.status); | ||
432 | if (val != emu->spdif_str_bits[idx]) { | ||
433 | emu->spdif_str_bits[idx] = val; | ||
434 | ca0106_set_spdif_bits(emu, idx); | ||
435 | return 1; | ||
436 | } | ||
437 | return 0; | ||
397 | } | 438 | } |
398 | 439 | ||
399 | static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, | 440 | static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, |
@@ -604,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | |||
604 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 645 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
605 | .count = 4, | 646 | .count = 4, |
606 | .info = snd_ca0106_spdif_info, | 647 | .info = snd_ca0106_spdif_info, |
607 | .get = snd_ca0106_spdif_get, | 648 | .get = snd_ca0106_spdif_get_default, |
608 | .put = snd_ca0106_spdif_put | 649 | .put = snd_ca0106_spdif_put_default |
650 | }, | ||
651 | { | ||
652 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
653 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), | ||
654 | .count = 4, | ||
655 | .info = snd_ca0106_spdif_info, | ||
656 | .get = snd_ca0106_spdif_get_stream, | ||
657 | .put = snd_ca0106_spdif_put_stream | ||
609 | }, | 658 | }, |
610 | }; | 659 | }; |
611 | 660 | ||