Commit b97bedcd authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda-cache' into topic/hda

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