mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
Merge branch 'topic/ca0106-spdif-stream' into topic/ca0106
This commit is contained in:
commit
ebef7cfc81
3 changed files with 90 additions and 26 deletions
|
@ -694,7 +694,8 @@ struct snd_ca0106 {
|
||||||
|
|
||||||
struct snd_ca0106_channel playback_channels[4];
|
struct snd_ca0106_channel playback_channels[4];
|
||||||
struct snd_ca0106_channel capture_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 spdif_enable;
|
||||||
int capture_source;
|
int capture_source;
|
||||||
int i2c_capture_source;
|
int i2c_capture_source;
|
||||||
|
|
|
@ -485,6 +485,15 @@ static const int spi_dacd_bit[] = {
|
||||||
[PCM_UNKNOWN_CHANNEL] = SPI_DACD1_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 */
|
/* open_playback callback */
|
||||||
static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
|
static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
|
||||||
int channel_id)
|
int channel_id)
|
||||||
|
@ -530,6 +539,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restore_spdif_bits(chip, channel_id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +553,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
|
||||||
struct snd_ca0106_pcm *epcm = runtime->private_data;
|
struct snd_ca0106_pcm *epcm = runtime->private_data;
|
||||||
chip->playback_channels[epcm->channel_id].use = 0;
|
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) {
|
if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
|
||||||
const int reg = spi_dacd_reg[epcm->channel_id];
|
const int reg = spi_dacd_reg[epcm->channel_id];
|
||||||
|
|
||||||
|
@ -1336,16 +1350,16 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
|
||||||
SPCS_GENERATIONSTATUS | 0x00001200 |
|
SPCS_GENERATIONSTATUS | 0x00001200 |
|
||||||
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
|
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
|
||||||
if (!resume) {
|
if (!resume) {
|
||||||
chip->spdif_bits[0] = def_bits;
|
chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits;
|
||||||
chip->spdif_bits[1] = def_bits;
|
chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits;
|
||||||
chip->spdif_bits[2] = def_bits;
|
chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits;
|
||||||
chip->spdif_bits[3] = def_bits;
|
chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits;
|
||||||
}
|
}
|
||||||
/* Only SPCS1 has been tested */
|
/* Only SPCS1 has been tested */
|
||||||
snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]);
|
snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]);
|
||||||
snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]);
|
snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]);
|
||||||
snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]);
|
snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]);
|
||||||
snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]);
|
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, PLAYBACK_MUTE, 0, 0x00fc0000);
|
||||||
snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
|
snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
|
||||||
|
|
|
@ -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)
|
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -353,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
|
||||||
return 0;
|
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_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
|
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
|
||||||
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||||
|
|
||||||
ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
|
decode_spdif_bits(ucontrol->value.iec958.status,
|
||||||
ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
|
emu->spdif_bits[idx]);
|
||||||
ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
|
return 0;
|
||||||
ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
decode_spdif_bits(ucontrol->value.iec958.status,
|
||||||
|
emu->spdif_str_bits[idx]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
|
||||||
return 0;
|
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_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
|
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
|
||||||
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||||
int change;
|
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
val = (ucontrol->value.iec958.status[0] << 0) |
|
val = encode_spdif_bits(ucontrol->value.iec958.status);
|
||||||
(ucontrol->value.iec958.status[1] << 8) |
|
if (val != emu->spdif_bits[idx]) {
|
||||||
(ucontrol->value.iec958.status[2] << 16) |
|
|
||||||
(ucontrol->value.iec958.status[3] << 24);
|
|
||||||
change = val != emu->spdif_bits[idx];
|
|
||||||
if (change) {
|
|
||||||
emu->spdif_bits[idx] = val;
|
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);
|
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,
|
static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
|
||||||
|
@ -604,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
|
||||||
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
|
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
|
||||||
.count = 4,
|
.count = 4,
|
||||||
.info = snd_ca0106_spdif_info,
|
.info = snd_ca0106_spdif_info,
|
||||||
.get = snd_ca0106_spdif_get,
|
.get = snd_ca0106_spdif_get_default,
|
||||||
.put = snd_ca0106_spdif_put
|
.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…
Reference in a new issue