📄 pcxhr_mixer.c
字号:
struct snd_ctl_elem_value *ucontrol){ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol); int i, err, rate; down(&mgr->mixer_mutex); for(i = 0; i < 3 + mgr->capture_chips; i++) { if (i == PCXHR_CLOCK_TYPE_INTERNAL) rate = mgr->sample_rate_real; else { err = pcxhr_get_external_clock(mgr, i, &rate); if (err) break; } ucontrol->value.integer.value[i] = rate; } up(&mgr->mixer_mutex); return 0;}static struct snd_kcontrol_new pcxhr_control_clock_rate = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "Clock Rates", .info = pcxhr_clock_rate_info, .get = pcxhr_clock_rate_get,};/* * IEC958 status bits */static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits){ int i, err; unsigned char temp; struct pcxhr_rmh rmh; pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); rmh.cmd[0] |= IO_NUM_UER_CHIP_REG; switch (chip->chip_idx) { case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */ case 1: rmh.cmd[1] = CS8420_23_CS; break; case 2: rmh.cmd[1] = CS8420_45_CS; break; case 3: rmh.cmd[1] = CS8420_67_CS; break; default: return -EINVAL; } switch (aes_idx) { case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */ case 1: rmh.cmd[2] = CS8420_CSB1; break; case 2: rmh.cmd[2] = CS8420_CSB2; break; case 3: rmh.cmd[2] = CS8420_CSB3; break; case 4: rmh.cmd[2] = CS8420_CSB4; break; default: return -EINVAL; } rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */ rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */ rmh.cmd_len = 3; err = pcxhr_send_msg(chip->mgr, &rmh); if (err) return err; temp = 0; for (i = 0; i < 8; i++) { /* attention : reversed bit order (not with CS8416_01_CS) */ temp <<= 1; if (rmh.stat[1] & (1 << i)) temp |= 1; } snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp); *aes_bits = temp; return 0;}static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); unsigned char aes_bits; int i, err; down(&chip->mgr->mixer_mutex); for(i = 0; i < 5; i++) { if (kcontrol->private_value == 0) /* playback */ aes_bits = chip->aes_bits[i]; else { /* capture */ err = pcxhr_iec958_capture_byte(chip, i, &aes_bits); if (err) break; } ucontrol->value.iec958.status[i] = aes_bits; } up(&chip->mgr->mixer_mutex); return 0;}static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ int i; for (i = 0; i < 5; i++) ucontrol->value.iec958.status[i] = 0xff; return 0;}static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits){ int i, err, cmd; unsigned char new_bits = aes_bits; unsigned char old_bits = chip->aes_bits[aes_idx]; struct pcxhr_rmh rmh; for (i = 0; i < 8; i++) { if ((old_bits & 0x01) != (new_bits & 0x01)) { cmd = chip->chip_idx & 0x03; /* chip index 0..3 */ if(chip->chip_idx > 3) /* new bit used if chip_idx>3 (PCX1222HR) */ cmd |= 1 << 22; cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */ cmd |= (new_bits & 0x01) << 23; /* add bit value */ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); rmh.cmd[0] |= IO_NUM_REG_CUER; rmh.cmd[1] = cmd; rmh.cmd_len = 2; snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n", chip->chip_idx, aes_idx, i, cmd); err = pcxhr_send_msg(chip->mgr, &rmh); if (err) return err; } old_bits >>= 1; new_bits >>= 1; } chip->aes_bits[aes_idx] = aes_bits; return 0;}static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol); int i, changed = 0; /* playback */ down(&chip->mgr->mixer_mutex); for (i = 0; i < 5; i++) { if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) { pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]); changed = 1; } } up(&chip->mgr->mixer_mutex); return changed;}static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), .info = pcxhr_iec958_info, .get = pcxhr_iec958_mask_get};static struct snd_kcontrol_new pcxhr_control_playback_iec958 = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = pcxhr_iec958_info, .get = pcxhr_iec958_get, .put = pcxhr_iec958_put, .private_value = 0 /* playback */};static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK), .info = pcxhr_iec958_info, .get = pcxhr_iec958_mask_get};static struct snd_kcontrol_new pcxhr_control_capture_iec958 = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), .info = pcxhr_iec958_info, .get = pcxhr_iec958_get, .private_value = 1 /* capture */};static void pcxhr_init_audio_levels(struct snd_pcxhr *chip){ int i; for (i = 0; i < 2; i++) { if (chip->nb_streams_play) { int j; /* at boot time the digital volumes are unmuted 0dB */ for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) { chip->digital_playback_active[j][i] = 1; chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL; } /* after boot, only two bits are set on the uer interface */ chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;/* only for test purpose, remove later */#ifdef CONFIG_SND_DEBUG /* analog volumes for playback (is LEVEL_MIN after boot) */ chip->analog_playback_active[i] = 1; chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL; pcxhr_update_analog_audio_level(chip, 0, i);#endif/* test end */ } if (chip->nb_streams_capt) { /* at boot time the digital volumes are unmuted 0dB */ chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;/* only for test purpose, remove later */#ifdef CONFIG_SND_DEBUG /* analog volumes for playback (is LEVEL_MIN after boot) */ chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL; pcxhr_update_analog_audio_level(chip, 1, i);#endif/* test end */ } } return;}int pcxhr_create_mixer(struct pcxhr_mgr *mgr){ struct snd_pcxhr *chip; int err, i; init_MUTEX(&mgr->mixer_mutex); /* can be in another place */ for (i = 0; i < mgr->num_cards; i++) { struct snd_kcontrol_new temp; chip = mgr->chip[i]; if (chip->nb_streams_play) { /* analog output level control */ temp = pcxhr_control_analog_level; temp.name = "Master Playback Volume"; temp.private_value = 0; /* playback */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; /* output mute controls */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_output_switch, chip))) < 0) return err; temp = snd_pcxhr_pcm_vol; temp.name = "PCM Playback Volume"; temp.count = PCXHR_PLAYBACK_STREAMS; temp.private_value = 0; /* playback */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_pcm_switch, chip))) < 0) return err; /* IEC958 controls */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_playback_iec958_mask, chip))) < 0) return err; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_playback_iec958, chip))) < 0) return err; } if (chip->nb_streams_capt) { /* analog input level control only on first two chips !*/ temp = pcxhr_control_analog_level; temp.name = "Master Capture Volume"; temp.private_value = 1; /* capture */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; temp = snd_pcxhr_pcm_vol; temp.name = "PCM Capture Volume"; temp.count = 1; temp.private_value = 1; /* capture */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; /* Audio source */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_audio_src, chip))) < 0) return err; /* IEC958 controls */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_capture_iec958_mask, chip))) < 0) return err; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_capture_iec958, chip))) < 0) return err; } /* monitoring only if playback and capture device available */ if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) { /* monitoring */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_monitor_vol, chip))) < 0) return err; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_monitor_sw, chip))) < 0) return err; } if (i == 0) { /* clock mode only one control per pcxhr */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_clock_type, mgr))) < 0) return err; /* non standard control used to scan the external clock presence/frequencies */ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&pcxhr_control_clock_rate, mgr))) < 0) return err; } /* init values for the mixer data */ pcxhr_init_audio_levels(chip); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -