Merge branch 'topic/hda-cache' into topic/hda
authorTakashi Iwai <tiwai@suse.de>
Tue, 21 Apr 2009 09:11:54 +0000 (11:11 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 21 Apr 2009 09:11:54 +0000 (11:11 +0200)
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c

index 66a7d3de9fa05ee83227977a569b0cae2d207358..b649033a4c8181549be2a6a460cdf3263ea28b32 100644 (file)
@@ -175,14 +175,23 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
                                unsigned int verb, unsigned int parm)
 {
        struct hda_bus *bus = codec->bus;
-       unsigned int res;
+       unsigned int cmd, res;
+       int repeated = 0;
 
-       res = make_codec_cmd(codec, nid, direct, verb, parm);
+       cmd = make_codec_cmd(codec, nid, direct, verb, parm);
        snd_hda_power_up(codec);
        mutex_lock(&bus->cmd_mutex);
-       if (!bus->ops.command(bus, res))
+ again:
+       if (!bus->ops.command(bus, cmd)) {
                res = bus->ops.get_response(bus);
-       else
+               if (res == -1 && bus->rirb_error) {
+                       if (repeated++ < 1) {
+                               snd_printd(KERN_WARNING "hda_codec: "
+                                          "Trying verb 0x%08x again\n", cmd);
+                               goto again;
+                       }
+               }
+       } else
                res = (unsigned int)-1;
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
@@ -1056,6 +1065,8 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
 /* FIXME: more better hash key? */
 #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
 #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
+#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
+#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
 #define INFO_AMP_CAPS  (1<<0)
 #define INFO_AMP_VOL(ch)       (1 << (1 + (ch)))
 
@@ -1146,19 +1157,32 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 }
 EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
 
-u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+static unsigned int
+query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
+               unsigned int (*func)(struct hda_codec *, hda_nid_t))
 {
        struct hda_amp_info *info;
 
-       info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
+       info = get_alloc_amp_hash(codec, key);
        if (!info)
                return 0;
        if (!info->head.val) {
-               info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
                info->head.val |= INFO_AMP_CAPS;
+               info->amp_caps = func(codec, nid);
        }
        return info->amp_caps;
 }
+
+static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
+{
+       return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+}
+
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+{
+       return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
+                              read_pin_cap);
+}
 EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
 
 /*
@@ -2547,6 +2571,41 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 }
 EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
 
+static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
+{
+       unsigned int val = 0;
+       if (nid != codec->afg &&
+           (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
+               val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+       if (!val || val == -1)
+               val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+       if (!val || val == -1)
+               return 0;
+       return val;
+}
+
+static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
+{
+       return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
+                              get_pcm_param);
+}
+
+static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
+{
+       unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+       if (!streams || streams == -1)
+               streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+       if (!streams || streams == -1)
+               return 0;
+       return streams;
+}
+
+static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
+{
+       return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
+                              get_stream_param);
+}
+
 /**
  * snd_hda_query_supported_pcm - query the supported PCM rates and formats
  * @codec: the HDA codec
@@ -2565,15 +2624,8 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 {
        unsigned int i, val, wcaps;
 
-       val = 0;
        wcaps = get_wcaps(codec, nid);
-       if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) {
-               val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
-               if (val == -1)
-                       return -EIO;
-       }
-       if (!val)
-               val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+       val = query_pcm_param(codec, nid);
 
        if (ratesp) {
                u32 rates = 0;
@@ -2595,15 +2647,9 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
                u64 formats = 0;
                unsigned int streams, bps;
 
-               streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
-               if (streams == -1)
+               streams = query_stream_param(codec, nid);
+               if (!streams)
                        return -EIO;
-               if (!streams) {
-                       streams = snd_hda_param_read(codec, codec->afg,
-                                                    AC_PAR_STREAM);
-                       if (streams == -1)
-                               return -EIO;
-               }
 
                bps = 0;
                if (streams & AC_SUPFMT_PCM) {
@@ -2677,17 +2723,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
        int i;
        unsigned int val = 0, rate, stream;
 
-       if (nid != codec->afg &&
-           (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
-               val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
-               if (val == -1)
-                       return 0;
-       }
-       if (!val) {
-               val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
-               if (val == -1)
-                       return 0;
-       }
+       val = query_pcm_param(codec, nid);
+       if (!val)
+               return 0;
 
        rate = format & 0xff00;
        for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
@@ -2699,12 +2737,8 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
        if (i >= AC_PAR_PCM_RATE_BITS)
                return 0;
 
-       stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
-       if (stream == -1)
-               return 0;
-       if (!stream && nid != codec->afg)
-               stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
-       if (!stream || stream == -1)
+       stream = query_stream_param(codec, nid);
+       if (!stream)
                return 0;
 
        if (stream & AC_SUPFMT_PCM) {
index 2fdecf4b0eb631b89ef15f47ef1f37c3ac2e13ed..cd8979c7670b9d36a717827c66ff056dcf4ac7d5 100644 (file)
@@ -623,6 +623,7 @@ struct hda_bus {
        /* misc op flags */
        unsigned int needs_damn_long_delay :1;
        unsigned int shutdown :1;       /* being unloaded */
+       unsigned int rirb_error:1;      /* error in codec communication */
 };
 
 /*
index 41db5d4da47821c20cbc63e580ff130578a44689..04f19f8cad84c4d606635145b6436345c04f1009 100644 (file)
@@ -606,6 +606,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                }
                if (!chip->rirb.cmds) {
                        smp_rmb();
+                       bus->rirb_error = 0;
                        return chip->rirb.res; /* the last value */
                }
                if (time_after(jiffies, timeout))
@@ -625,8 +626,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                chip->irq = -1;
                pci_disable_msi(chip->pci);
                chip->msi = 0;
-               if (azx_acquire_irq(chip, 1) < 0)
+               if (azx_acquire_irq(chip, 1) < 0) {
+                       bus->rirb_error = 1;
                        return -1;
+               }
                goto again;
        }
 
@@ -646,14 +649,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                return -1;
        }
 
-       snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
-                  "switching to single_cmd mode: last cmd=0x%08x\n",
-                  chip->last_cmd);
-       chip->rirb.rp = azx_readb(chip, RIRBWP);
-       chip->rirb.cmds = 0;
-       /* switch to single_cmd mode */
-       chip->single_cmd = 1;
-       azx_free_cmd_io(chip);
+       snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
+                  "last cmd=0x%08x\n", chip->last_cmd);
+       spin_lock_irq(&chip->reg_lock);
+       chip->rirb.cmds = 0; /* reset the index */
+       bus->rirb_error = 1;
+       spin_unlock_irq(&chip->reg_lock);
        return -1;
 }
 
index c9300a3427ea79604bfe7e81e3ec8b80f51ca16d..a6ec87a5c066b3ca58c145d9c1d94f8216228cec 100644 (file)
@@ -1024,6 +1024,9 @@ static void alc_subsystem_id(struct hda_codec *codec,
        if (codec->vendor_id == 0x10ec0260)
                nid = 0x17;
        ass = snd_hda_codec_get_pincfg(codec, nid);
+       snd_printd("realtek: No valid SSID, "
+                  "checking pincfg 0x%08x for NID 0x%x\n",
+                  nid, ass);
        if (!(ass & 1) && !(ass & 0x100000))
                return;
        if ((ass >> 30) != 1)   /* no physical connection */
@@ -1038,6 +1041,8 @@ static void alc_subsystem_id(struct hda_codec *codec,
        if (((ass >> 16) & 0xf) != tmp)
                return;
 do_sku:
+       snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
+                  ass & 0xffff, codec->vendor_id);
        /*
         * 0 : override
         * 1 :  Swap Jack