Commit 2fc07efa authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound updates #2 from Takashi Iwai:
 "This update contains a few cleanup works, regression/stable fixes
  gathered since the last pull request.

   - Clean up with generic hd-audio jack handling code by David
     Henningsson
   - A few regression fixes for standardized HD-audio auto-parser
   - Misc clean-up and small fixes"

* tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - do not detect jack on internal speakers for Realtek
  ALSA: hda - Fix missing beep on ASUS X43U notebook
  ALSA: hda - Remove AZX_DCAPS_POSFIX_COMBO
  ALSA: hda - Warn an allocation for an uninitialized array
  ALSA: hda/cirrus - Add missing init/free of hda_gen_spec
  ALSA: hda - Fix memory leaks at error path in patch_cirrus.c
  ALSA: hda - Add missing hda_gen_spec to struct via_spec
  ALSA: hda - remove "Mic Jack Mode" for headset jacks (Latitude Exx30)
  ALSA: hda - make Cirrus codec use generic unsol event handler
  ALSA: hda - make VIA codec use generic unsol event handler
  ALSA: hda - Remove dead GPIO code for VIA codec
  ALSA: usb-audio: Add TASCAM US122 MKII playback
parents 79360ddd f7f4b232
...@@ -5168,6 +5168,8 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); ...@@ -5168,6 +5168,8 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
*/ */
void *snd_array_new(struct snd_array *array) void *snd_array_new(struct snd_array *array)
{ {
if (snd_BUG_ON(!array->elem_size))
return NULL;
if (array->used >= array->alloced) { if (array->used >= array->alloced) {
int num = array->alloced + array->alloc_align; int num = array->alloced + array->alloc_align;
int size = (num + 1) * array->elem_size; int size = (num + 1) * array->elem_size;
......
...@@ -554,7 +554,6 @@ enum { ...@@ -554,7 +554,6 @@ enum {
#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
#define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
/* quirks for ATI SB / AMD Hudson */ /* quirks for ATI SB / AMD Hudson */
...@@ -2858,10 +2857,6 @@ static int __devinit check_position_fix(struct azx *chip, int fix) ...@@ -2858,10 +2857,6 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
snd_printd(SFX "Using LPIB position fix\n"); snd_printd(SFX "Using LPIB position fix\n");
return POS_FIX_LPIB; return POS_FIX_LPIB;
} }
if (chip->driver_caps & AZX_DCAPS_POSFIX_COMBO) {
snd_printd(SFX "Using COMBO position fix\n");
return POS_FIX_COMBO;
}
return POS_FIX_AUTO; return POS_FIX_AUTO;
} }
......
...@@ -897,7 +897,7 @@ static int build_digital_input(struct hda_codec *codec) ...@@ -897,7 +897,7 @@ static int build_digital_input(struct hda_codec *codec)
* HP/SPK/SPDIF * HP/SPK/SPDIF
*/ */
static void cs_automute(struct hda_codec *codec) static void cs_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
{ {
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
...@@ -973,7 +973,7 @@ static void cs_automute(struct hda_codec *codec) ...@@ -973,7 +973,7 @@ static void cs_automute(struct hda_codec *codec)
* Switch max 3 inputs of a single ADC (nid 3) * Switch max 3 inputs of a single ADC (nid 3)
*/ */
static void cs_automic(struct hda_codec *codec) static void cs_automic(struct hda_codec *codec, struct hda_jack_tbl *tbl)
{ {
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
...@@ -1035,7 +1035,7 @@ static void init_output(struct hda_codec *codec) ...@@ -1035,7 +1035,7 @@ static void init_output(struct hda_codec *codec)
if (!cfg->speaker_outs) if (!cfg->speaker_outs)
continue; continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
snd_hda_jack_detect_enable(codec, nid, HP_EVENT); snd_hda_jack_detect_enable_callback(codec, nid, HP_EVENT, cs_automute);
spec->hp_detect = 1; spec->hp_detect = 1;
} }
} }
...@@ -1046,7 +1046,7 @@ static void init_output(struct hda_codec *codec) ...@@ -1046,7 +1046,7 @@ static void init_output(struct hda_codec *codec)
/* SPDIF is enabled on presence detect for CS421x */ /* SPDIF is enabled on presence detect for CS421x */
if (spec->hp_detect || spec->spdif_detect) if (spec->hp_detect || spec->spdif_detect)
cs_automute(codec); cs_automute(codec, NULL);
} }
static void init_input(struct hda_codec *codec) static void init_input(struct hda_codec *codec)
...@@ -1070,13 +1070,13 @@ static void init_input(struct hda_codec *codec) ...@@ -1070,13 +1070,13 @@ static void init_input(struct hda_codec *codec)
AC_VERB_SET_AMP_GAIN_MUTE, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i])); AMP_IN_MUTE(spec->adc_idx[i]));
if (spec->mic_detect && spec->automic_idx == i) if (spec->mic_detect && spec->automic_idx == i)
snd_hda_jack_detect_enable(codec, pin, MIC_EVENT); snd_hda_jack_detect_enable_callback(codec, pin, MIC_EVENT, cs_automic);
} }
/* CS420x has multiple ADC, CS421x has single ADC */ /* CS420x has multiple ADC, CS421x has single ADC */
if (spec->vendor_nid == CS420X_VENDOR_NID) { if (spec->vendor_nid == CS420X_VENDOR_NID) {
change_cur_input(codec, spec->cur_input, 1); change_cur_input(codec, spec->cur_input, 1);
if (spec->mic_detect) if (spec->mic_detect)
cs_automic(codec); cs_automic(codec, NULL);
coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
if (is_active_pin(codec, CS_DMIC2_PIN_NID)) if (is_active_pin(codec, CS_DMIC2_PIN_NID))
...@@ -1089,7 +1089,7 @@ static void init_input(struct hda_codec *codec) ...@@ -1089,7 +1089,7 @@ static void init_input(struct hda_codec *codec)
cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
} else { } else {
if (spec->mic_detect) if (spec->mic_detect)
cs_automic(codec); cs_automic(codec, NULL);
else { else {
spec->cur_adc = spec->adc_nid[spec->cur_input]; spec->cur_adc = spec->adc_nid[spec->cur_input];
cs_update_input_select(codec); cs_update_input_select(codec);
...@@ -1243,28 +1243,16 @@ static void cs_free(struct hda_codec *codec) ...@@ -1243,28 +1243,16 @@ static void cs_free(struct hda_codec *codec)
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
kfree(spec->capture_bind[0]); kfree(spec->capture_bind[0]);
kfree(spec->capture_bind[1]); kfree(spec->capture_bind[1]);
snd_hda_gen_free(&spec->gen);
kfree(codec->spec); kfree(codec->spec);
} }
static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
{
switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
cs_automute(codec);
break;
case MIC_EVENT:
cs_automic(codec);
break;
}
snd_hda_jack_report_sync(codec);
}
static const struct hda_codec_ops cs_patch_ops = { static const struct hda_codec_ops cs_patch_ops = {
.build_controls = cs_build_controls, .build_controls = cs_build_controls,
.build_pcms = cs_build_pcms, .build_pcms = cs_build_pcms,
.init = cs_init, .init = cs_init,
.free = cs_free, .free = cs_free,
.unsol_event = cs_unsol_event, .unsol_event = snd_hda_jack_unsol_event,
}; };
static int cs_parse_auto_config(struct hda_codec *codec) static int cs_parse_auto_config(struct hda_codec *codec)
...@@ -1439,6 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec) ...@@ -1439,6 +1427,7 @@ static int patch_cs420x(struct hda_codec *codec)
if (!spec) if (!spec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
snd_hda_gen_init(&spec->gen);
spec->vendor_nid = CS420X_VENDOR_NID; spec->vendor_nid = CS420X_VENDOR_NID;
...@@ -1457,7 +1446,7 @@ static int patch_cs420x(struct hda_codec *codec) ...@@ -1457,7 +1446,7 @@ static int patch_cs420x(struct hda_codec *codec)
return 0; return 0;
error: error:
kfree(codec->spec); cs_free(codec);
codec->spec = NULL; codec->spec = NULL;
return err; return err;
} }
...@@ -1674,7 +1663,7 @@ static void init_cs421x_digital(struct hda_codec *codec) ...@@ -1674,7 +1663,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
if (!cfg->speaker_outs) if (!cfg->speaker_outs)
continue; continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT); snd_hda_jack_detect_enable_callback(codec, nid, SPDIF_EVENT, cs_automute);
spec->spdif_detect = 1; spec->spdif_detect = 1;
} }
} }
...@@ -1889,21 +1878,6 @@ static int cs421x_build_controls(struct hda_codec *codec) ...@@ -1889,21 +1878,6 @@ static int cs421x_build_controls(struct hda_codec *codec)
return 0; return 0;
} }
static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
{
switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
case SPDIF_EVENT:
cs_automute(codec);
break;
case MIC_EVENT:
cs_automic(codec);
break;
}
snd_hda_jack_report_sync(codec);
}
static int parse_cs421x_input(struct hda_codec *codec) static int parse_cs421x_input(struct hda_codec *codec)
{ {
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
...@@ -1977,7 +1951,7 @@ static struct hda_codec_ops cs421x_patch_ops = { ...@@ -1977,7 +1951,7 @@ static struct hda_codec_ops cs421x_patch_ops = {
.build_pcms = cs_build_pcms, .build_pcms = cs_build_pcms,
.init = cs421x_init, .init = cs421x_init,
.free = cs_free, .free = cs_free,
.unsol_event = cs421x_unsol_event, .unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = cs421x_suspend, .suspend = cs421x_suspend,
#endif #endif
...@@ -1992,6 +1966,7 @@ static int patch_cs4210(struct hda_codec *codec) ...@@ -1992,6 +1966,7 @@ static int patch_cs4210(struct hda_codec *codec)
if (!spec) if (!spec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
snd_hda_gen_init(&spec->gen);
spec->vendor_nid = CS4210_VENDOR_NID; spec->vendor_nid = CS4210_VENDOR_NID;
...@@ -2017,7 +1992,7 @@ static int patch_cs4210(struct hda_codec *codec) ...@@ -2017,7 +1992,7 @@ static int patch_cs4210(struct hda_codec *codec)
return 0; return 0;
error: error:
kfree(codec->spec); cs_free(codec);
codec->spec = NULL; codec->spec = NULL;
return err; return err;
} }
...@@ -2031,6 +2006,7 @@ static int patch_cs4213(struct hda_codec *codec) ...@@ -2031,6 +2006,7 @@ static int patch_cs4213(struct hda_codec *codec)
if (!spec) if (!spec)
return -ENOMEM; return -ENOMEM;
codec->spec = spec; codec->spec = spec;
snd_hda_gen_init(&spec->gen);
spec->vendor_nid = CS4213_VENDOR_NID; spec->vendor_nid = CS4213_VENDOR_NID;
...@@ -2042,7 +2018,7 @@ static int patch_cs4213(struct hda_codec *codec) ...@@ -2042,7 +2018,7 @@ static int patch_cs4213(struct hda_codec *codec)
return 0; return 0;
error: error:
kfree(codec->spec); cs_free(codec);
codec->spec = NULL; codec->spec = NULL;
return err; return err;
} }
......
...@@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack ...@@ -611,6 +611,8 @@ static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
return;
/* check LO jack only when it's different from HP */ /* check LO jack only when it's different from HP */
if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
return; return;
...@@ -4245,6 +4247,7 @@ static void alc_auto_init_std(struct hda_codec *codec) ...@@ -4245,6 +4247,7 @@ static void alc_auto_init_std(struct hda_codec *codec)
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
static const struct snd_pci_quirk beep_white_list[] = { static const struct snd_pci_quirk beep_white_list[] = {
SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
......
...@@ -104,6 +104,7 @@ enum { ...@@ -104,6 +104,7 @@ enum {
STAC_92HD83XXX_HP_LED, STAC_92HD83XXX_HP_LED,
STAC_92HD83XXX_HP_INV_LED, STAC_92HD83XXX_HP_INV_LED,
STAC_92HD83XXX_HP_MIC_LED, STAC_92HD83XXX_HP_MIC_LED,
STAC_92HD83XXX_HEADSET_JACK,
STAC_92HD83XXX_MODELS STAC_92HD83XXX_MODELS
}; };
...@@ -204,6 +205,7 @@ struct sigmatel_spec { ...@@ -204,6 +205,7 @@ struct sigmatel_spec {
unsigned int check_volume_offset:1; unsigned int check_volume_offset:1;
unsigned int auto_mic:1; unsigned int auto_mic:1;
unsigned int linear_tone_beep:1; unsigned int linear_tone_beep:1;
unsigned int headset_jack:1; /* 4-pin headset jack (hp + mono mic) */
/* gpio lines */ /* gpio lines */
unsigned int eapd_mask; unsigned int eapd_mask;
...@@ -1684,6 +1686,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { ...@@ -1684,6 +1686,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_HP_LED] = "hp-led", [STAC_92HD83XXX_HP_LED] = "hp-led",
[STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led",
[STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led", [STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led",
[STAC_92HD83XXX_HEADSET_JACK] = "headset-jack",
}; };
static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
...@@ -1694,6 +1697,24 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { ...@@ -1694,6 +1697,24 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
"DFI LanParty", STAC_92HD83XXX_REF), "DFI LanParty", STAC_92HD83XXX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
"unknown Dell", STAC_DELL_S14), "unknown Dell", STAC_DELL_S14),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0532,
"Dell Latitude E6230", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0533,
"Dell Latitude E6330", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0534,
"Dell Latitude E6430", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0535,
"Dell Latitude E6530", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053c,
"Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x053d,
"Dell Latitude E5530", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0549,
"Dell Latitude E5430", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x057d,
"Dell Latitude E6430s", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0584,
"Dell Latitude E6430U", STAC_92HD83XXX_HEADSET_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
"Dell Vostro 3500", STAC_DELL_VOSTRO_3500), "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
...@@ -2855,6 +2876,9 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, ...@@ -2855,6 +2876,9 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
char name[22]; char name[22];
if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
if (spec->headset_jack && snd_hda_get_input_pin_attr(def_conf)
!= INPUT_PIN_ATTR_DOCK)
return 0;
if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
&& nid == spec->line_switch) && nid == spec->line_switch)
control = STAC_CTL_WIDGET_IO_SWITCH; control = STAC_CTL_WIDGET_IO_SWITCH;
...@@ -5626,6 +5650,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5626,6 +5650,9 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
case STAC_92HD83XXX_HP_MIC_LED: case STAC_92HD83XXX_HP_MIC_LED:
spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
break; break;
case STAC_92HD83XXX_HEADSET_JACK:
spec->headset_jack = 1;
break;
} }
if (find_mute_led_cfg(codec, default_polarity)) if (find_mute_led_cfg(codec, default_polarity))
......
...@@ -118,6 +118,8 @@ enum { ...@@ -118,6 +118,8 @@ enum {
}; };
struct via_spec { struct via_spec {
struct hda_gen_spec gen;
/* codec parameterization */ /* codec parameterization */
const struct snd_kcontrol_new *mixers[6]; const struct snd_kcontrol_new *mixers[6];
unsigned int num_mixers; unsigned int num_mixers;
...@@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec) ...@@ -246,6 +248,7 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
/* VT1708BCE & VT1708S are almost same */ /* VT1708BCE & VT1708S are almost same */
if (spec->codec_type == VT1708BCE) if (spec->codec_type == VT1708BCE)
spec->codec_type = VT1708S; spec->codec_type = VT1708S;
snd_hda_gen_init(&spec->gen);
return spec; return spec;
} }
...@@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec) ...@@ -299,7 +302,6 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
#define VIA_JACK_EVENT 0x20 #define VIA_JACK_EVENT 0x20
#define VIA_HP_EVENT 0x01 #define VIA_HP_EVENT 0x01
#define VIA_GPIO_EVENT 0x02
#define VIA_LINE_EVENT 0x03 #define VIA_LINE_EVENT 0x03
enum { enum {
...@@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec) ...@@ -1628,6 +1630,7 @@ static void via_free(struct hda_codec *codec)
vt1708_stop_hp_work(spec); vt1708_stop_hp_work(spec);
kfree(spec->bind_cap_vol); kfree(spec->bind_cap_vol);
kfree(spec->bind_cap_sw); kfree(spec->bind_cap_sw);
snd_hda_gen_free(&spec->gen);
kfree(spec); kfree(spec);
} }
...@@ -1685,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec) ...@@ -1685,69 +1688,6 @@ static void via_hp_automute(struct hda_codec *codec)
via_line_automute(codec, present); via_line_automute(codec, present);
} }
static void via_gpio_control(struct hda_codec *codec)
{
unsigned int gpio_data;
unsigned int vol_counter;
unsigned int vol;
unsigned int master_vol;
struct via_spec *spec = codec->spec;
gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
AC_VERB_GET_GPIO_DATA, 0) & 0x03;
vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
0xF84, 0) & 0x3F0000) >> 16;
vol = vol_counter & 0x1F;
master_vol = snd_hda_codec_read(codec, 0x1A, 0,
AC_VERB_GET_AMP_GAIN_MUTE,
AC_AMP_GET_INPUT);
if (gpio_data == 0x02) {
/* unmute line out */
snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0],
PIN_OUT);
if (vol_counter & 0x20) {
/* decrease volume */
if (vol > master_vol)
vol = master_vol;
snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
0, HDA_AMP_VOLMASK,
master_vol-vol);
} else {
/* increase volume */
snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
HDA_AMP_VOLMASK,
((master_vol+vol) > 0x2A) ? 0x2A :
(master_vol+vol));
}
} else if (!(gpio_data & 0x02)) {
/* mute line out */
snd_hda_set_pin_ctl(codec, spec->autocfg.line_out_pins[0], 0);
}
}
/* unsolicited event for jack sensing */
static void via_unsol_event(struct hda_codec *codec,
unsigned int res)
{
res >>= 26;
res = snd_hda_jack_get_action(codec, res);
if (res & VIA_JACK_EVENT)
set_widgets_power_state(codec);
res &= ~VIA_JACK_EVENT;
if (res == VIA_HP_EVENT || res == VIA_LINE_EVENT)
via_hp_automute(codec);
else if (res == VIA_GPIO_EVENT)
via_gpio_control(codec);
snd_hda_jack_report_sync(codec);
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int via_suspend(struct hda_codec *codec) static int via_suspend(struct hda_codec *codec)
{ {
...@@ -1783,7 +1723,7 @@ static const struct hda_codec_ops via_patch_ops = { ...@@ -1783,7 +1723,7 @@ static const struct hda_codec_ops via_patch_ops = {
.build_pcms = via_build_pcms, .build_pcms = via_build_pcms,
.init = via_init, .init = via_init,
.free = via_free, .free = via_free,
.unsol_event = via_unsol_event, .unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = via_suspend, .suspend = via_suspend,
.check_power_status = via_check_power_status, .check_power_status = via_check_power_status,
...@@ -2761,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec) ...@@ -2761,6 +2701,17 @@ static void via_auto_init_dig_in(struct hda_codec *codec)
snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN); snd_hda_set_pin_ctl(codec, spec->autocfg.dig_in_pin, PIN_IN);
} }
static void via_jack_output_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
{
set_widgets_power_state(codec);
via_hp_automute(codec);
}
static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
{
set_widgets_power_state(codec);
}
/* initialize the unsolicited events */ /* initialize the unsolicited events */
static void via_auto_init_unsol_event(struct hda_codec *codec) static void via_auto_init_unsol_event(struct hda_codec *codec)
{ {
...@@ -2768,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec) ...@@ -2768,26 +2719,31 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int ev; unsigned int ev;
int i; int i;
hda_jack_callback cb;
if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0])) if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
snd_hda_jack_detect_enable(codec, cfg->hp_pins[0], snd_hda_jack_detect_enable_callback(codec, cfg->hp_pins[0],
VIA_HP_EVENT | VIA_JACK_EVENT); VIA_HP_EVENT | VIA_JACK_EVENT,
via_jack_output_event);
if (cfg->speaker_pins[0]) if (cfg->speaker_pins[0])
ev = VIA_LINE_EVENT; ev = VIA_LINE_EVENT;
else else
ev = 0; ev = 0;
cb = ev ? via_jack_output_event : via_jack_powerstate_event;
for (i = 0; i < cfg->line_outs; i++) { for (i = 0; i < cfg->line_outs; i++) {
if (cfg->line_out_pins[i] && if (cfg->line_out_pins[i] &&
is_jack_detectable(codec, cfg->line_out_pins[i])) is_jack_detectable(codec, cfg->line_out_pins[i]))
snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i], snd_hda_jack_detect_enable_callback(codec, cfg->line_out_pins[i],
ev | VIA_JACK_EVENT); ev | VIA_JACK_EVENT, cb);
} }
for (i = 0; i < cfg->num_inputs; i++) { for (i = 0; i < cfg->num_inputs; i++) {
if (is_jack_detectable(codec, cfg->inputs[i].pin)) if (is_jack_detectable(codec, cfg->inputs[i].pin))
snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin, snd_hda_jack_detect_enable_callback(codec, cfg->inputs[i].pin,
VIA_JACK_EVENT); VIA_JACK_EVENT,
via_jack_powerstate_event);
} }
} }
......
...@@ -2780,6 +2780,52 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -2780,6 +2780,52 @@ YAMAHA_DEVICE(0x7010, "UB99"),
} }
}, },
{
/* Tascam US122 MKII - playback-only support */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
.idProduct = 0x8021,
.bInterfaceClass = USB_CLASS_AUDIO,
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "TASCAM",
.product_name = "US122 MKII",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
.endpoint = 0x02,
.ep_attr = USB_ENDPOINT_XFER_ISOC,
.rates = SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 44100,
.rate_max = 96000,
.nr_rates = 4,
.rate_table = (unsigned int[]) {
44100, 48000, 88200, 96000
}
}
},
{
.ifnum = -1
}
}
}
},
/* Microsoft XboxLive Headset/Xbox Communicator */ /* Microsoft XboxLive Headset/Xbox Communicator */
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment