ALSA: hda: Unify get_response handling
Now most of the get_response handling became quite similar between HDA-core and legacy drivers, and the only differences are: - the handling of extra-long polling delay for some codecs - the debug message for the stalled communication and both are worth to share in the common code. This patch unifies the code into snd_hdac_bus_get_response(), and use this from the legacy get_response callback. It results in a good amount of code reduction in the end. Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Link: https://lore.kernel.org/r/20191212191101.19517-3-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
89698ed5cc
commit
5f2cb361d7
|
@ -51,7 +51,6 @@ struct hda_bus {
|
||||||
DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
|
DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
|
||||||
|
|
||||||
/* misc op flags */
|
/* misc op flags */
|
||||||
unsigned int needs_damn_long_delay :1;
|
|
||||||
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
|
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
|
||||||
/* status for codec/controller */
|
/* status for codec/controller */
|
||||||
unsigned int shutdown :1; /* being unloaded */
|
unsigned int shutdown :1; /* being unloaded */
|
||||||
|
|
|
@ -338,6 +338,7 @@ struct hdac_bus {
|
||||||
bool reverse_assign:1; /* assign devices in reverse order */
|
bool reverse_assign:1; /* assign devices in reverse order */
|
||||||
bool corbrp_self_clear:1; /* CORBRP clears itself after reset */
|
bool corbrp_self_clear:1; /* CORBRP clears itself after reset */
|
||||||
bool polling_mode:1;
|
bool polling_mode:1;
|
||||||
|
bool needs_damn_long_delay:1;
|
||||||
|
|
||||||
int poll_count;
|
int poll_count;
|
||||||
|
|
||||||
|
|
|
@ -242,6 +242,7 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long loopcounter;
|
unsigned long loopcounter;
|
||||||
wait_queue_entry_t wait;
|
wait_queue_entry_t wait;
|
||||||
|
bool warned = false;
|
||||||
|
|
||||||
init_wait_entry(&wait, 0);
|
init_wait_entry(&wait, 0);
|
||||||
timeout = jiffies + msecs_to_jiffies(1000);
|
timeout = jiffies + msecs_to_jiffies(1000);
|
||||||
|
@ -264,9 +265,17 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
|
||||||
spin_unlock_irq(&bus->reg_lock);
|
spin_unlock_irq(&bus->reg_lock);
|
||||||
if (time_after(jiffies, timeout))
|
if (time_after(jiffies, timeout))
|
||||||
break;
|
break;
|
||||||
|
#define LOOP_COUNT_MAX 3000
|
||||||
if (!bus->polling_mode) {
|
if (!bus->polling_mode) {
|
||||||
schedule_timeout(msecs_to_jiffies(2));
|
schedule_timeout(msecs_to_jiffies(2));
|
||||||
} else if (loopcounter > 3000) {
|
} else if (bus->needs_damn_long_delay ||
|
||||||
|
loopcounter > LOOP_COUNT_MAX) {
|
||||||
|
if (loopcounter > LOOP_COUNT_MAX && !warned) {
|
||||||
|
dev_dbg_ratelimited(bus->dev,
|
||||||
|
"too slow response, last cmd=%#08x\n",
|
||||||
|
bus->last_cmd[addr]);
|
||||||
|
warned = true;
|
||||||
|
}
|
||||||
msleep(2); /* temporary workaround */
|
msleep(2); /* temporary workaround */
|
||||||
} else {
|
} else {
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
|
|
@ -784,53 +784,12 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
|
||||||
{
|
{
|
||||||
struct azx *chip = bus_to_azx(bus);
|
struct azx *chip = bus_to_azx(bus);
|
||||||
struct hda_bus *hbus = &chip->bus;
|
struct hda_bus *hbus = &chip->bus;
|
||||||
unsigned long timeout;
|
int err;
|
||||||
unsigned long loopcounter;
|
|
||||||
wait_queue_entry_t wait;
|
|
||||||
bool warned = false;
|
|
||||||
|
|
||||||
init_wait_entry(&wait, 0);
|
|
||||||
again:
|
again:
|
||||||
timeout = jiffies + msecs_to_jiffies(1000);
|
err = snd_hdac_bus_get_response(bus, addr, res);
|
||||||
|
if (!err)
|
||||||
for (loopcounter = 0;; loopcounter++) {
|
return 0;
|
||||||
spin_lock_irq(&bus->reg_lock);
|
|
||||||
if (!bus->polling_mode)
|
|
||||||
prepare_to_wait(&bus->rirb_wq, &wait,
|
|
||||||
TASK_UNINTERRUPTIBLE);
|
|
||||||
if (bus->polling_mode)
|
|
||||||
snd_hdac_bus_update_rirb(bus);
|
|
||||||
if (!bus->rirb.cmds[addr]) {
|
|
||||||
if (res)
|
|
||||||
*res = bus->rirb.res[addr]; /* the last value */
|
|
||||||
if (!bus->polling_mode)
|
|
||||||
finish_wait(&bus->rirb_wq, &wait);
|
|
||||||
spin_unlock_irq(&bus->reg_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
spin_unlock_irq(&bus->reg_lock);
|
|
||||||
if (time_after(jiffies, timeout))
|
|
||||||
break;
|
|
||||||
#define LOOP_COUNT_MAX 3000
|
|
||||||
if (!bus->polling_mode) {
|
|
||||||
schedule_timeout(msecs_to_jiffies(2));
|
|
||||||
} else if (hbus->needs_damn_long_delay ||
|
|
||||||
loopcounter > LOOP_COUNT_MAX) {
|
|
||||||
if (loopcounter > LOOP_COUNT_MAX && !warned) {
|
|
||||||
dev_dbg_ratelimited(chip->card->dev,
|
|
||||||
"too slow response, last cmd=%#08x\n",
|
|
||||||
bus->last_cmd[addr]);
|
|
||||||
warned = true;
|
|
||||||
}
|
|
||||||
msleep(2); /* temporary workaround */
|
|
||||||
} else {
|
|
||||||
udelay(10);
|
|
||||||
cond_resched();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bus->polling_mode)
|
|
||||||
finish_wait(&bus->rirb_wq, &wait);
|
|
||||||
|
|
||||||
if (hbus->no_response_fallback)
|
if (hbus->no_response_fallback)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
|
@ -1809,7 +1809,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
|
||||||
|
|
||||||
if (chip->driver_type == AZX_DRIVER_NVIDIA) {
|
if (chip->driver_type == AZX_DRIVER_NVIDIA) {
|
||||||
dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
|
dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
|
||||||
chip->bus.needs_damn_long_delay = 1;
|
chip->bus.core.needs_damn_long_delay = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
||||||
|
|
|
@ -394,7 +394,7 @@ static int hda_tegra_create(struct snd_card *card,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
chip->bus.needs_damn_long_delay = 1;
|
chip->bus.core.needs_damn_long_delay = 1;
|
||||||
|
|
||||||
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ static int patch_ca0110(struct hda_codec *codec)
|
||||||
codec->patch_ops = ca0110_patch_ops;
|
codec->patch_ops = ca0110_patch_ops;
|
||||||
|
|
||||||
spec->multi_cap_vol = 1;
|
spec->multi_cap_vol = 1;
|
||||||
codec->bus->needs_damn_long_delay = 1;
|
codec->bus->core.needs_damn_long_delay = 1;
|
||||||
|
|
||||||
err = ca0110_parse_auto_config(codec);
|
err = ca0110_parse_auto_config(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
@ -4908,7 +4908,7 @@ static int patch_stac927x(struct hda_codec *codec)
|
||||||
* The below flag enables the longer delay (see get_response
|
* The below flag enables the longer delay (see get_response
|
||||||
* in hda_intel.c).
|
* in hda_intel.c).
|
||||||
*/
|
*/
|
||||||
codec->bus->needs_damn_long_delay = 1;
|
codec->bus->core.needs_damn_long_delay = 1;
|
||||||
|
|
||||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue