|
|
@@ -806,6 +806,108 @@ static struct snd_kcontrol_new snd_emu1010_internal_clock =
|
|
|
.put = snd_emu1010_internal_clock_put
|
|
|
};
|
|
|
|
|
|
+static int snd_emu1010_optical_out_info(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_info *uinfo)
|
|
|
+{
|
|
|
+ static const char * const texts[2] = {
|
|
|
+ "SPDIF", "ADAT"
|
|
|
+ };
|
|
|
+
|
|
|
+ return snd_ctl_enum_info(uinfo, 1, 2, texts);
|
|
|
+}
|
|
|
+
|
|
|
+static int snd_emu1010_optical_out_get(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|
|
+
|
|
|
+ ucontrol->value.enumerated.item[0] = emu->emu1010.optical_out;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|
|
+ unsigned int val;
|
|
|
+ u32 tmp;
|
|
|
+ int change = 0;
|
|
|
+
|
|
|
+ val = ucontrol->value.enumerated.item[0];
|
|
|
+ /* Limit: uinfo->value.enumerated.items = 2; */
|
|
|
+ if (val >= 2)
|
|
|
+ return -EINVAL;
|
|
|
+ change = (emu->emu1010.optical_out != val);
|
|
|
+ if (change) {
|
|
|
+ emu->emu1010.optical_out = val;
|
|
|
+ tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
|
|
|
+ (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
|
|
|
+ snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
|
|
|
+ }
|
|
|
+ return change;
|
|
|
+}
|
|
|
+
|
|
|
+static struct snd_kcontrol_new snd_emu1010_optical_out = {
|
|
|
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
|
|
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
|
|
+ .name = "Optical Output Mode",
|
|
|
+ .count = 1,
|
|
|
+ .info = snd_emu1010_optical_out_info,
|
|
|
+ .get = snd_emu1010_optical_out_get,
|
|
|
+ .put = snd_emu1010_optical_out_put
|
|
|
+};
|
|
|
+
|
|
|
+static int snd_emu1010_optical_in_info(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_info *uinfo)
|
|
|
+{
|
|
|
+ static const char * const texts[2] = {
|
|
|
+ "SPDIF", "ADAT"
|
|
|
+ };
|
|
|
+
|
|
|
+ return snd_ctl_enum_info(uinfo, 1, 2, texts);
|
|
|
+}
|
|
|
+
|
|
|
+static int snd_emu1010_optical_in_get(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|
|
+
|
|
|
+ ucontrol->value.enumerated.item[0] = emu->emu1010.optical_in;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
|
|
+ unsigned int val;
|
|
|
+ u32 tmp;
|
|
|
+ int change = 0;
|
|
|
+
|
|
|
+ val = ucontrol->value.enumerated.item[0];
|
|
|
+ /* Limit: uinfo->value.enumerated.items = 2; */
|
|
|
+ if (val >= 2)
|
|
|
+ return -EINVAL;
|
|
|
+ change = (emu->emu1010.optical_in != val);
|
|
|
+ if (change) {
|
|
|
+ emu->emu1010.optical_in = val;
|
|
|
+ tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
|
|
|
+ (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
|
|
|
+ snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
|
|
|
+ }
|
|
|
+ return change;
|
|
|
+}
|
|
|
+
|
|
|
+static struct snd_kcontrol_new snd_emu1010_optical_in = {
|
|
|
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
|
|
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
|
|
+ .name = "Optical Input Mode",
|
|
|
+ .count = 1,
|
|
|
+ .info = snd_emu1010_optical_in_info,
|
|
|
+ .get = snd_emu1010_optical_in_get,
|
|
|
+ .put = snd_emu1010_optical_in_put
|
|
|
+};
|
|
|
+
|
|
|
static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
{
|
|
|
@@ -2051,6 +2153,14 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
|
|
|
snd_ctl_new1(&snd_emu1010_internal_clock, emu));
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
+ err = snd_ctl_add(card,
|
|
|
+ snd_ctl_new1(&snd_emu1010_optical_out, emu));
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+ err = snd_ctl_add(card,
|
|
|
+ snd_ctl_new1(&snd_emu1010_optical_in, emu));
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
|
|
|
} else if (emu->card_capabilities->emu_model) {
|
|
|
/* all other e-mu cards for now */
|
|
|
@@ -2086,6 +2196,14 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
|
|
|
snd_ctl_new1(&snd_emu1010_internal_clock, emu));
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
+ err = snd_ctl_add(card,
|
|
|
+ snd_ctl_new1(&snd_emu1010_optical_out, emu));
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+ err = snd_ctl_add(card,
|
|
|
+ snd_ctl_new1(&snd_emu1010_optical_in, emu));
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
if ( emu->card_capabilities->i2c_adc) {
|