#include <sound/core.h>
#include "hda_codec.h"
#include <sound/asoundef.h>
+#include <sound/tlv.h>
#include <sound/initval.h>
#include "hda_local.h"
/* codec vendor labels */
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x10ec, "Realtek" },
+ { 0x1057, "Motorola" },
{ 0x11d4, "Analog Devices" },
{ 0x13f6, "C-Media" },
+ { 0x14f1, "Conexant" },
{ 0x434d, "C-Media" },
{ 0x8384, "SigmaTel" },
{} /* terminator */
/*
* process queueud unsolicited events
*/
-static void process_unsol_events(void *data)
+static void process_unsol_events(struct work_struct *work)
{
- struct hda_bus *bus = data;
- struct hda_bus_unsolicited *unsol = bus->unsol;
+ struct hda_bus_unsolicited *unsol =
+ container_of(work, struct hda_bus_unsolicited, work);
+ struct hda_bus *bus = unsol->bus;
struct hda_codec *codec;
unsigned int rp, caddr, res;
kfree(unsol);
return -ENOMEM;
}
- INIT_WORK(&unsol->work, process_unsol_events, bus);
+ INIT_WORK(&unsol->work, process_unsol_events);
+ unsol->bus = bus;
bus->unsol = unsol;
return 0;
}
return change;
}
+int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *_tlv)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ u32 caps, val1, val2;
+
+ if (size < 4 * sizeof(unsigned int))
+ return -ENOMEM;
+ caps = query_amp_caps(codec, nid, dir);
+ val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25;
+ val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
+ val1 = ((int)val1) * ((int)val2);
+ if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
+ return -EFAULT;
+ if (put_user(2 * sizeof(unsigned int), _tlv + 1))
+ return -EFAULT;
+ if (put_user(val1, _tlv + 2))
+ return -EFAULT;
+ if (put_user(val2, _tlv + 3))
+ return -EFAULT;
+ return 0;
+}
+
/* switch */
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
- /* not autodetected value */
- { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
-
{ 0 } /* terminator */
};
formats |= SNDRV_PCM_FMTBIT_S32_LE;
if (val & AC_SUPPCM_BITS_32)
bps = 32;
- else if (val & AC_SUPPCM_BITS_20)
- bps = 20;
else if (val & AC_SUPPCM_BITS_24)
bps = 24;
+ else if (val & AC_SUPPCM_BITS_20)
+ bps = 20;
}
}
else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */
/* front */
snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
- if (mout->hp_nid)
+ if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
/* headphone out will just decode front left/right (stereo) */
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* extra outputs copied from front */
* in the order of front, rear, CLFE, side, ...
*
* If more extra outputs (speaker and headphone) are found, the pins are
- * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack
+ * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
* is detected, one of speaker of HP pins is assigned as the primary
* output, i.e. to line_out_pins[0]. So, line_outs is always positive
* if any analog output exists.
cfg->speaker_outs++;
break;
case AC_JACK_HP_OUT:
- cfg->hp_pin = nid;
+ if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
+ continue;
+ cfg->hp_pins[cfg->hp_outs] = nid;
+ cfg->hp_outs++;
break;
- case AC_JACK_MIC_IN:
- if (loc == AC_JACK_LOC_FRONT)
- cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
- else
- cfg->input_pins[AUTO_PIN_MIC] = nid;
+ case AC_JACK_MIC_IN: {
+ int preferred, alt;
+ if (loc == AC_JACK_LOC_FRONT) {
+ preferred = AUTO_PIN_FRONT_MIC;
+ alt = AUTO_PIN_MIC;
+ } else {
+ preferred = AUTO_PIN_MIC;
+ alt = AUTO_PIN_FRONT_MIC;
+ }
+ if (!cfg->input_pins[preferred])
+ cfg->input_pins[preferred] = nid;
+ else if (!cfg->input_pins[alt])
+ cfg->input_pins[alt] = nid;
break;
+ }
case AC_JACK_LINE_IN:
if (loc == AC_JACK_LOC_FRONT)
cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
cfg->speaker_outs, cfg->speaker_pins[0],
cfg->speaker_pins[1], cfg->speaker_pins[2],
cfg->speaker_pins[3], cfg->speaker_pins[4]);
- snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n",
- cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin);
+ snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ cfg->hp_outs, cfg->hp_pins[0],
+ cfg->hp_pins[1], cfg->hp_pins[2],
+ cfg->hp_pins[3], cfg->hp_pins[4]);
snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
" cd=0x%x, aux=0x%x\n",
cfg->input_pins[AUTO_PIN_MIC],
sizeof(cfg->speaker_pins));
cfg->speaker_outs = 0;
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
- } else if (cfg->hp_pin) {
- cfg->line_outs = 1;
- cfg->line_out_pins[0] = cfg->hp_pin;
- cfg->hp_pin = 0;
+ } else if (cfg->hp_outs) {
+ cfg->line_outs = cfg->hp_outs;
+ memcpy(cfg->line_out_pins, cfg->hp_pins,
+ sizeof(cfg->hp_pins));
+ cfg->hp_outs = 0;
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
}
}