Loading sound/pci/ca0106/ca0106.h +2 −1 Original line number Diff line number Diff line Loading @@ -694,7 +694,8 @@ struct snd_ca0106 { struct snd_ca0106_channel playback_channels[4]; struct snd_ca0106_channel capture_channels[4]; u32 spdif_bits[4]; /* s/pdif out setup */ u32 spdif_bits[4]; /* s/pdif out default setup */ u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */ int spdif_enable; int capture_source; int i2c_capture_source; Loading sound/pci/ca0106/ca0106_main.c +22 −8 Original line number Diff line number Diff line Loading @@ -485,6 +485,15 @@ static const int spi_dacd_bit[] = { [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, }; static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) { if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) { chip->spdif_str_bits[idx] = chip->spdif_bits[idx]; snd_ca0106_ptr_write(chip, SPCS0 + idx, 0, chip->spdif_str_bits[idx]); } } /* open_playback callback */ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) Loading Loading @@ -530,6 +539,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr if (err < 0) return err; } restore_spdif_bits(chip, channel_id); return 0; } Loading @@ -541,6 +553,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) struct snd_ca0106_pcm *epcm = runtime->private_data; chip->playback_channels[epcm->channel_id].use = 0; restore_spdif_bits(chip, epcm->channel_id); if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { const int reg = spi_dacd_reg[epcm->channel_id]; Loading Loading @@ -1336,16 +1350,16 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; if (!resume) { chip->spdif_bits[0] = def_bits; chip->spdif_bits[1] = def_bits; chip->spdif_bits[2] = def_bits; chip->spdif_bits[3] = def_bits; chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits; chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits; chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits; chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits; } /* Only SPCS1 has been tested */ snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]); snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]); snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]); snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]); snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]); snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]); snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]); snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); Loading sound/pci/ca0106/ca0106_mixer.c +66 −17 Original line number Diff line number Diff line Loading @@ -148,7 +148,7 @@ static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) { snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]); snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); } /* Loading Loading @@ -353,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, return 0; } static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol, static void decode_spdif_bits(unsigned char *status, unsigned int bits) { status[0] = (bits >> 0) & 0xff; status[1] = (bits >> 8) & 0xff; status[2] = (bits >> 16) & 0xff; status[3] = (bits >> 24) & 0xff; } static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); decode_spdif_bits(ucontrol->value.iec958.status, emu->spdif_bits[idx]); return 0; } static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; decode_spdif_bits(ucontrol->value.iec958.status, emu->spdif_str_bits[idx]); return 0; } Loading @@ -376,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, return 0; } static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, static unsigned int encode_spdif_bits(unsigned char *status) { return ((unsigned int)status[0] << 0) | ((unsigned int)status[1] << 8) | ((unsigned int)status[2] << 16) | ((unsigned int)status[3] << 24); } static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); int change; unsigned int val; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); change = val != emu->spdif_bits[idx]; if (change) { val = encode_spdif_bits(ucontrol->value.iec958.status); if (val != emu->spdif_bits[idx]) { emu->spdif_bits[idx] = val; /* FIXME: this isn't safe, but needed to keep the compatibility * with older alsa-lib config */ emu->spdif_str_bits[idx] = val; ca0106_set_spdif_bits(emu, idx); return 1; } return change; return 0; } static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int val; val = encode_spdif_bits(ucontrol->value.iec958.status); if (val != emu->spdif_str_bits[idx]) { emu->spdif_str_bits[idx] = val; ca0106_set_spdif_bits(emu, idx); return 1; } return 0; } static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, Loading Loading @@ -604,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .count = 4, .info = snd_ca0106_spdif_info, .get = snd_ca0106_spdif_get, .put = snd_ca0106_spdif_put .get = snd_ca0106_spdif_get_default, .put = snd_ca0106_spdif_put_default }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), .count = 4, .info = snd_ca0106_spdif_info, .get = snd_ca0106_spdif_get_stream, .put = snd_ca0106_spdif_put_stream }, }; Loading Loading
sound/pci/ca0106/ca0106.h +2 −1 Original line number Diff line number Diff line Loading @@ -694,7 +694,8 @@ struct snd_ca0106 { struct snd_ca0106_channel playback_channels[4]; struct snd_ca0106_channel capture_channels[4]; u32 spdif_bits[4]; /* s/pdif out setup */ u32 spdif_bits[4]; /* s/pdif out default setup */ u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */ int spdif_enable; int capture_source; int i2c_capture_source; Loading
sound/pci/ca0106/ca0106_main.c +22 −8 Original line number Diff line number Diff line Loading @@ -485,6 +485,15 @@ static const int spi_dacd_bit[] = { [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, }; static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) { if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) { chip->spdif_str_bits[idx] = chip->spdif_bits[idx]; snd_ca0106_ptr_write(chip, SPCS0 + idx, 0, chip->spdif_str_bits[idx]); } } /* open_playback callback */ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) Loading Loading @@ -530,6 +539,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr if (err < 0) return err; } restore_spdif_bits(chip, channel_id); return 0; } Loading @@ -541,6 +553,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) struct snd_ca0106_pcm *epcm = runtime->private_data; chip->playback_channels[epcm->channel_id].use = 0; restore_spdif_bits(chip, epcm->channel_id); if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { const int reg = spi_dacd_reg[epcm->channel_id]; Loading Loading @@ -1336,16 +1350,16 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) SPCS_GENERATIONSTATUS | 0x00001200 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; if (!resume) { chip->spdif_bits[0] = def_bits; chip->spdif_bits[1] = def_bits; chip->spdif_bits[2] = def_bits; chip->spdif_bits[3] = def_bits; chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits; chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits; chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits; chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits; } /* Only SPCS1 has been tested */ snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]); snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]); snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]); snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]); snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]); snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]); snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]); snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]); snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); Loading
sound/pci/ca0106/ca0106_mixer.c +66 −17 Original line number Diff line number Diff line Loading @@ -148,7 +148,7 @@ static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) { snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]); snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); } /* Loading Loading @@ -353,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, return 0; } static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol, static void decode_spdif_bits(unsigned char *status, unsigned int bits) { status[0] = (bits >> 0) & 0xff; status[1] = (bits >> 8) & 0xff; status[2] = (bits >> 16) & 0xff; status[3] = (bits >> 24) & 0xff; } static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); decode_spdif_bits(ucontrol->value.iec958.status, emu->spdif_bits[idx]); return 0; } static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; decode_spdif_bits(ucontrol->value.iec958.status, emu->spdif_str_bits[idx]); return 0; } Loading @@ -376,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, return 0; } static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, static unsigned int encode_spdif_bits(unsigned char *status) { return ((unsigned int)status[0] << 0) | ((unsigned int)status[1] << 8) | ((unsigned int)status[2] << 16) | ((unsigned int)status[3] << 24); } static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); int change; unsigned int val; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); change = val != emu->spdif_bits[idx]; if (change) { val = encode_spdif_bits(ucontrol->value.iec958.status); if (val != emu->spdif_bits[idx]) { emu->spdif_bits[idx] = val; /* FIXME: this isn't safe, but needed to keep the compatibility * with older alsa-lib config */ emu->spdif_str_bits[idx] = val; ca0106_set_spdif_bits(emu, idx); return 1; } return change; return 0; } static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int val; val = encode_spdif_bits(ucontrol->value.iec958.status); if (val != emu->spdif_str_bits[idx]) { emu->spdif_str_bits[idx] = val; ca0106_set_spdif_bits(emu, idx); return 1; } return 0; } static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, Loading Loading @@ -604,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .count = 4, .info = snd_ca0106_spdif_info, .get = snd_ca0106_spdif_get, .put = snd_ca0106_spdif_put .get = snd_ca0106_spdif_get_default, .put = snd_ca0106_spdif_put_default }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), .count = 4, .info = snd_ca0106_spdif_info, .get = snd_ca0106_spdif_get_stream, .put = snd_ca0106_spdif_put_stream }, }; Loading