]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/pci/hda/hda_codec.c
Merge branch 'topic/misc' into for-linus
[karo-tx-linux.git] / sound / pci / hda / hda_codec.c
index 3252945f3743a6e7a8f7d633440ff6c7a75c0252..a7802b99436cfcf60be3c7124a4c10ef55ef40e6 100644 (file)
@@ -396,15 +396,18 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
                        }
                        for (n = prev_nid + 1; n <= val; n++) {
                                if (conns >= max_conns) {
-                                       snd_printk(KERN_ERR
-                                                  "Too many connections\n");
+                                       snd_printk(KERN_ERR "hda_codec: "
+                                                  "Too many connections %d for NID 0x%x\n",
+                                                  conns, nid);
                                        return -EINVAL;
                                }
                                conn_list[conns++] = n;
                        }
                } else {
                        if (conns >= max_conns) {
-                               snd_printk(KERN_ERR "Too many connections\n");
+                               snd_printk(KERN_ERR "hda_codec: "
+                                          "Too many connections %d for NID 0x%x\n",
+                                          conns, nid);
                                return -EINVAL;
                        }
                        conn_list[conns++] = val;
@@ -786,6 +789,9 @@ static int read_pin_defaults(struct hda_codec *codec)
                pin->nid = nid;
                pin->cfg = snd_hda_codec_read(codec, nid, 0,
                                              AC_VERB_GET_CONFIG_DEFAULT, 0);
+               pin->ctrl = snd_hda_codec_read(codec, nid, 0,
+                                              AC_VERB_GET_PIN_WIDGET_CONTROL,
+                                              0);
        }
        return 0;
 }
@@ -914,15 +920,38 @@ static void restore_pincfgs(struct hda_codec *codec)
 void snd_hda_shutup_pins(struct hda_codec *codec)
 {
        int i;
+       /* don't shut up pins when unloading the driver; otherwise it breaks
+        * the default pin setup at the next load of the driver
+        */
+       if (codec->bus->shutdown)
+               return;
        for (i = 0; i < codec->init_pins.used; i++) {
                struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
                /* use read here for syncing after issuing each verb */
                snd_hda_codec_read(codec, pin->nid, 0,
                                   AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
        }
+       codec->pins_shutup = 1;
 }
 EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
 
+/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
+static void restore_shutup_pins(struct hda_codec *codec)
+{
+       int i;
+       if (!codec->pins_shutup)
+               return;
+       if (codec->bus->shutdown)
+               return;
+       for (i = 0; i < codec->init_pins.used; i++) {
+               struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+               snd_hda_codec_write(codec, pin->nid, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   pin->ctrl);
+       }
+       codec->pins_shutup = 0;
+}
+
 static void init_hda_cache(struct hda_cache_rec *cache,
                           unsigned int record_size);
 static void free_hda_cache(struct hda_cache_rec *cache);
@@ -1541,6 +1570,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
 EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
 #endif /* SND_HDA_NEEDS_RESUME */
 
+static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
+                            unsigned int ofs)
+{
+       u32 caps = query_amp_caps(codec, nid, dir);
+       /* get num steps */
+       caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+       if (ofs < caps)
+               caps -= ofs;
+       return caps;
+}
+
 /**
  * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
  *
@@ -1555,23 +1595,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
        u8 chs = get_amp_channels(kcontrol);
        int dir = get_amp_direction(kcontrol);
        unsigned int ofs = get_amp_offset(kcontrol);
-       u32 caps;
 
-       caps = query_amp_caps(codec, nid, dir);
-       /* num steps */
-       caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
-       if (!caps) {
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = chs == 3 ? 2 : 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
+       if (!uinfo->value.integer.max) {
                printk(KERN_WARNING "hda_codec: "
                       "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
                       kcontrol->id.name);
                return -EINVAL;
        }
-       if (ofs < caps)
-               caps -= ofs;
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = chs == 3 ? 2 : 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = caps;
        return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
@@ -1596,8 +1630,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
                 int ch, int dir, int idx, unsigned int ofs,
                 unsigned int val)
 {
+       unsigned int maxval;
+
        if (val > 0)
                val += ofs;
+       /* ofs = 0: raw max value */
+       maxval = get_amp_max_value(codec, nid, dir, 0);
+       if (val > maxval)
+               val = maxval;
        return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
                                        HDA_AMP_VOLMASK, val);
 }
@@ -2909,6 +2949,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                            codec->afg ? codec->afg : codec->mfg,
                            AC_PWRST_D0);
        restore_pincfgs(codec); /* restore all current pin configs */
+       restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
        if (codec->patch_ops.resume)
                codec->patch_ops.resume(codec);
@@ -2974,26 +3015,31 @@ struct hda_rate_tbl {
        unsigned int hda_fmt;
 };
 
+/* rate = base * mult / div */
+#define HDA_RATE(base, mult, div) \
+       (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
+        (((div) - 1) << AC_FMT_DIV_SHIFT))
+
 static struct hda_rate_tbl rate_bits[] = {
        /* rate in Hz, ALSA rate bitmask, HDA format value */
 
        /* autodetected value used in snd_hda_query_supported_pcm */
-       { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
-       { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
-       { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
-       { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
-       { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
-       { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
-       { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
-       { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
-       { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
-       { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
-       { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
+       { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
+       { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
+       { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
+       { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
+       { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
+       { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
+       { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
+       { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
+       { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
+       { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
+       { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
 #define AC_PAR_PCM_RATE_BITS   11
        /* up to bits 10, 384kHZ isn't supported properly */
 
        /* not autodetected value */
-       { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
+       { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
 
        { 0 } /* terminator */
 };
@@ -3012,7 +3058,8 @@ static struct hda_rate_tbl rate_bits[] = {
 unsigned int snd_hda_calc_stream_format(unsigned int rate,
                                        unsigned int channels,
                                        unsigned int format,
-                                       unsigned int maxbps)
+                                       unsigned int maxbps,
+                                       unsigned short spdif_ctls)
 {
        int i;
        unsigned int val = 0;
@@ -3035,20 +3082,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 
        switch (snd_pcm_format_width(format)) {
        case 8:
-               val |= 0x00;
+               val |= AC_FMT_BITS_8;
                break;
        case 16:
-               val |= 0x10;
+               val |= AC_FMT_BITS_16;
                break;
        case 20:
        case 24:
        case 32:
                if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
-                       val |= 0x40;
+                       val |= AC_FMT_BITS_32;
                else if (maxbps >= 24)
-                       val |= 0x30;
+                       val |= AC_FMT_BITS_24;
                else
-                       val |= 0x20;
+                       val |= AC_FMT_BITS_20;
                break;
        default:
                snd_printdd("invalid format width %d\n",
@@ -3056,6 +3103,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
                return 0;
        }
 
+       if (spdif_ctls & AC_DIG1_NONAUDIO)
+               val |= AC_FMT_TYPE_NON_PCM;
+
        return val;
 }
 EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);