Commit ed42e71a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-4.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "Most of changes in this pull request are about the fixes of crash of
  FireWire drivers at hot-unplugging.  In addition, there are a few
  HD-audio fixes (removal of wrong static, a pin quirk for an ASUS mobo,
  a regression fix for runtime PM on Panther Point) and a long-standing
  (but fairly minor) bug of PCM core"

* tag 'sound-4.0-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Disable runtime PM for Panther Point again
  ALSA: hda: controller code - do not export static functions
  ALSA: pcm: Don't leave PREPARED state after draining
  ALSA: fireworks/bebob/dice/oxfw: make it possible to shutdown safely
  ALSA: fireworks/bebob/dice/oxfw: allow stream destructor after releasing runtime
  ALSA: firewire-lib: remove reference counting
  ALSA: fireworks/bebob/dice/oxfw: add reference-counting for FireWire unit
  ALSA: hda - Add pin configs for ASUS mobo with IDT 92HD73XX codec
  ALSA: firewire-lib: fix an unexpected byte sequence for micro sign
parents 7dac5cb1 de5d0ad5
......@@ -1552,6 +1552,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
if (! snd_pcm_playback_empty(substream)) {
snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
} else {
runtime->status->state = SNDRV_PCM_STATE_SETUP;
}
break;
case SNDRV_PCM_STATE_RUNNING:
......
......@@ -33,7 +33,7 @@
*/
#define MAX_MIDI_RX_BLOCKS 8
#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */
#define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 microseconds */
/* isochronous header parameters */
#define ISO_DATA_LENGTH_SHIFT 16
......@@ -78,7 +78,7 @@ static void pcm_period_tasklet(unsigned long data);
int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir, enum cip_flags flags)
{
s->unit = fw_unit_get(unit);
s->unit = unit;
s->direction = dir;
s->flags = flags;
s->context = ERR_PTR(-1);
......@@ -102,7 +102,6 @@ void amdtp_stream_destroy(struct amdtp_stream *s)
{
WARN_ON(amdtp_stream_running(s));
mutex_destroy(&s->mutex);
fw_unit_put(s->unit);
}
EXPORT_SYMBOL(amdtp_stream_destroy);
......
......@@ -116,11 +116,22 @@ name_device(struct snd_bebob *bebob, unsigned int vendor_id)
return err;
}
/*
* This module releases the FireWire unit data after all ALSA character devices
* are released by applications. This is for releasing stream data or finishing
* transactions safely. Thus at returning from .remove(), this module still keep
* references for the unit.
*/
static void
bebob_card_free(struct snd_card *card)
{
struct snd_bebob *bebob = card->private_data;
snd_bebob_stream_destroy_duplex(bebob);
fw_unit_put(bebob->unit);
kfree(bebob->maudio_special_quirk);
if (bebob->card_index >= 0) {
mutex_lock(&devices_mutex);
clear_bit(bebob->card_index, devices_used);
......@@ -205,7 +216,7 @@ bebob_probe(struct fw_unit *unit,
card->private_free = bebob_card_free;
bebob->card = card;
bebob->unit = unit;
bebob->unit = fw_unit_get(unit);
bebob->spec = spec;
mutex_init(&bebob->mutex);
spin_lock_init(&bebob->lock);
......@@ -306,10 +317,11 @@ static void bebob_remove(struct fw_unit *unit)
if (bebob == NULL)
return;
kfree(bebob->maudio_special_quirk);
/* Awake bus-reset waiters. */
if (!completion_done(&bebob->bus_reset))
complete_all(&bebob->bus_reset);
snd_bebob_stream_destroy_duplex(bebob);
snd_card_disconnect(bebob->card);
/* No need to wait for releasing card object in this context. */
snd_card_free_when_closed(bebob->card);
}
......
......@@ -410,8 +410,6 @@ break_both_connections(struct snd_bebob *bebob)
static void
destroy_both_connections(struct snd_bebob *bebob)
{
break_both_connections(bebob);
cmp_connection_destroy(&bebob->in_conn);
cmp_connection_destroy(&bebob->out_conn);
}
......@@ -712,22 +710,16 @@ void snd_bebob_stream_update_duplex(struct snd_bebob *bebob)
mutex_unlock(&bebob->mutex);
}
/*
* This function should be called before starting streams or after stopping
* streams.
*/
void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob)
{
mutex_lock(&bebob->mutex);
amdtp_stream_pcm_abort(&bebob->rx_stream);
amdtp_stream_pcm_abort(&bebob->tx_stream);
amdtp_stream_stop(&bebob->rx_stream);
amdtp_stream_stop(&bebob->tx_stream);
amdtp_stream_destroy(&bebob->rx_stream);
amdtp_stream_destroy(&bebob->tx_stream);
destroy_both_connections(bebob);
mutex_unlock(&bebob->mutex);
}
/*
......
......@@ -311,14 +311,21 @@ static int init_stream(struct snd_dice *dice, struct amdtp_stream *stream)
return err;
}
/*
* This function should be called before starting streams or after stopping
* streams.
*/
static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream)
{
amdtp_stream_destroy(stream);
struct fw_iso_resources *resources;
if (stream == &dice->tx_stream)
fw_iso_resources_destroy(&dice->tx_resources);
resources = &dice->tx_resources;
else
fw_iso_resources_destroy(&dice->rx_resources);
resources = &dice->rx_resources;
amdtp_stream_destroy(stream);
fw_iso_resources_destroy(resources);
}
int snd_dice_stream_init_duplex(struct snd_dice *dice)
......@@ -332,6 +339,8 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice)
goto end;
err = init_stream(dice, &dice->rx_stream);
if (err < 0)
destroy_stream(dice, &dice->tx_stream);
end:
return err;
}
......@@ -340,10 +349,7 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
{
snd_dice_transaction_clear_enable(dice);
stop_stream(dice, &dice->tx_stream);
destroy_stream(dice, &dice->tx_stream);
stop_stream(dice, &dice->rx_stream);
destroy_stream(dice, &dice->rx_stream);
dice->substreams_counter = 0;
......
......@@ -226,11 +226,20 @@ static void dice_card_strings(struct snd_dice *dice)
strcpy(card->mixername, "DICE");
}
/*
* This module releases the FireWire unit data after all ALSA character devices
* are released by applications. This is for releasing stream data or finishing
* transactions safely. Thus at returning from .remove(), this module still keep
* references for the unit.
*/
static void dice_card_free(struct snd_card *card)
{
struct snd_dice *dice = card->private_data;
snd_dice_stream_destroy_duplex(dice);
snd_dice_transaction_destroy(dice);
fw_unit_put(dice->unit);
mutex_destroy(&dice->mutex);
}
......@@ -251,7 +260,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
dice = card->private_data;
dice->card = card;
dice->unit = unit;
dice->unit = fw_unit_get(unit);
card->private_free = dice_card_free;
spin_lock_init(&dice->lock);
......@@ -305,10 +314,7 @@ static void dice_remove(struct fw_unit *unit)
{
struct snd_dice *dice = dev_get_drvdata(&unit->device);
snd_card_disconnect(dice->card);
snd_dice_stream_destroy_duplex(dice);
/* No need to wait for releasing card object in this context. */
snd_card_free_when_closed(dice->card);
}
......
......@@ -173,11 +173,23 @@ get_hardware_info(struct snd_efw *efw)
return err;
}
/*
* This module releases the FireWire unit data after all ALSA character devices
* are released by applications. This is for releasing stream data or finishing
* transactions safely. Thus at returning from .remove(), this module still keep
* references for the unit.
*/
static void
efw_card_free(struct snd_card *card)
{
struct snd_efw *efw = card->private_data;
snd_efw_stream_destroy_duplex(efw);
snd_efw_transaction_remove_instance(efw);
fw_unit_put(efw->unit);
kfree(efw->resp_buf);
if (efw->card_index >= 0) {
mutex_lock(&devices_mutex);
clear_bit(efw->card_index, devices_used);
......@@ -185,7 +197,6 @@ efw_card_free(struct snd_card *card)
}
mutex_destroy(&efw->mutex);
kfree(efw->resp_buf);
}
static int
......@@ -218,7 +229,7 @@ efw_probe(struct fw_unit *unit,
card->private_free = efw_card_free;
efw->card = card;
efw->unit = unit;
efw->unit = fw_unit_get(unit);
mutex_init(&efw->mutex);
spin_lock_init(&efw->lock);
init_waitqueue_head(&efw->hwdep_wait);
......@@ -289,10 +300,7 @@ static void efw_remove(struct fw_unit *unit)
{
struct snd_efw *efw = dev_get_drvdata(&unit->device);
snd_efw_stream_destroy_duplex(efw);
snd_efw_transaction_remove_instance(efw);
snd_card_disconnect(efw->card);
/* No need to wait for releasing card object in this context. */
snd_card_free_when_closed(efw->card);
}
......
......@@ -100,17 +100,22 @@ start_stream(struct snd_efw *efw, struct amdtp_stream *stream,
return err;
}
/*
* This function should be called before starting the stream or after stopping
* the streams.
*/
static void
destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
{
stop_stream(efw, stream);
amdtp_stream_destroy(stream);
struct cmp_connection *conn;
if (stream == &efw->tx_stream)
cmp_connection_destroy(&efw->out_conn);
conn = &efw->out_conn;
else
cmp_connection_destroy(&efw->in_conn);
conn = &efw->in_conn;
amdtp_stream_destroy(stream);
cmp_connection_destroy(&efw->out_conn);
}
static int
......@@ -319,12 +324,8 @@ void snd_efw_stream_update_duplex(struct snd_efw *efw)
void snd_efw_stream_destroy_duplex(struct snd_efw *efw)
{
mutex_lock(&efw->mutex);
destroy_stream(efw, &efw->rx_stream);
destroy_stream(efw, &efw->tx_stream);
mutex_unlock(&efw->mutex);
}
void snd_efw_stream_lock_changed(struct snd_efw *efw)
......
......@@ -337,6 +337,10 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw,
stop_stream(oxfw, stream);
}
/*
* This function should be called before starting the stream or after stopping
* the streams.
*/
void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
struct amdtp_stream *stream)
{
......@@ -347,8 +351,6 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
else
conn = &oxfw->in_conn;
stop_stream(oxfw, stream);
amdtp_stream_destroy(stream);
cmp_connection_destroy(conn);
}
......
......@@ -104,11 +104,23 @@ static int name_card(struct snd_oxfw *oxfw)
return err;
}
/*
* This module releases the FireWire unit data after all ALSA character devices
* are released by applications. This is for releasing stream data or finishing
* transactions safely. Thus at returning from .remove(), this module still keep
* references for the unit.
*/
static void oxfw_card_free(struct snd_card *card)
{
struct snd_oxfw *oxfw = card->private_data;
unsigned int i;
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
if (oxfw->has_output)
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
fw_unit_put(oxfw->unit);
for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
kfree(oxfw->tx_stream_formats[i]);
kfree(oxfw->rx_stream_formats[i]);
......@@ -136,7 +148,7 @@ static int oxfw_probe(struct fw_unit *unit,
oxfw = card->private_data;
oxfw->card = card;
mutex_init(&oxfw->mutex);
oxfw->unit = unit;
oxfw->unit = fw_unit_get(unit);
oxfw->device_info = (const struct device_info *)id->driver_data;
spin_lock_init(&oxfw->lock);
init_waitqueue_head(&oxfw->hwdep_wait);
......@@ -212,12 +224,7 @@ static void oxfw_remove(struct fw_unit *unit)
{
struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
snd_card_disconnect(oxfw->card);
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
if (oxfw->has_output)
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
/* No need to wait for releasing card object in this context. */
snd_card_free_when_closed(oxfw->card);
}
......
......@@ -961,7 +961,6 @@ static int azx_alloc_cmd_io(struct azx *chip)
dev_err(chip->card->dev, "cannot allocate CORB/RIRB\n");
return err;
}
EXPORT_SYMBOL_GPL(azx_alloc_cmd_io);
static void azx_init_cmd_io(struct azx *chip)
{
......@@ -1026,7 +1025,6 @@ static void azx_init_cmd_io(struct azx *chip)
azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
spin_unlock_irq(&chip->reg_lock);
}
EXPORT_SYMBOL_GPL(azx_init_cmd_io);
static void azx_free_cmd_io(struct azx *chip)
{
......@@ -1036,7 +1034,6 @@ static void azx_free_cmd_io(struct azx *chip)
azx_writeb(chip, CORBCTL, 0);
spin_unlock_irq(&chip->reg_lock);
}
EXPORT_SYMBOL_GPL(azx_free_cmd_io);
static unsigned int azx_command_addr(u32 cmd)
{
......@@ -1316,7 +1313,6 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
else
return azx_corb_send_cmd(bus, val);
}
EXPORT_SYMBOL_GPL(azx_send_cmd);
/* get a response */
static unsigned int azx_get_response(struct hda_bus *bus,
......@@ -1330,7 +1326,6 @@ static unsigned int azx_get_response(struct hda_bus *bus,
else
return azx_rirb_get_response(bus, addr);
}
EXPORT_SYMBOL_GPL(azx_get_response);
#ifdef CONFIG_SND_HDA_DSP_LOADER
/*
......
......@@ -1966,7 +1966,7 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Lynx Point */
{ PCI_DEVICE(0x8086, 0x8c20),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
......
......@@ -79,6 +79,7 @@ enum {
STAC_ALIENWARE_M17X,
STAC_92HD89XX_HP_FRONT_JACK,
STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
STAC_92HD73XX_ASUS_MOBO,
STAC_92HD73XX_MODELS
};
......@@ -1911,7 +1912,18 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
[STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
.type = HDA_FIXUP_PINS,
.v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
}
},
[STAC_92HD73XX_ASUS_MOBO] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
/* enable 5.1 and SPDIF out */
{ 0x0c, 0x01014411 },
{ 0x0d, 0x01014410 },
{ 0x0e, 0x01014412 },
{ 0x22, 0x014b1180 },
{ }
}
},
};
static const struct hda_model_fixup stac92hd73xx_models[] = {
......@@ -1923,6 +1935,7 @@ static const struct hda_model_fixup stac92hd73xx_models[] = {
{ .id = STAC_DELL_M6_BOTH, .name = "dell-m6" },
{ .id = STAC_DELL_EQ, .name = "dell-eq" },
{ .id = STAC_ALIENWARE_M17X, .name = "alienware" },
{ .id = STAC_92HD73XX_ASUS_MOBO, .name = "asus-mobo" },
{}
};
......@@ -1975,6 +1988,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
"HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
SND_PCI_QUIRK(PCI_VENDOR_ID_ASUSTEK, 0x83f8, "ASUS AT4NM10",
STAC_92HD73XX_ASUS_MOBO),
{} /* terminator */
};
......
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