Sound fixes for 3.7-rc7
The highlight of this update is the fixes for ASoC kirkwood by Russell. In addition to that, a couple of regression fixes for HD-audio due to the runtime PM support on 3.7, and other driver-specific regression fixes like USB MIDI on non-standard USB audio drivers. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJQrzbsAAoJEGwxgFQ9KSmk8ZUP+QEw/yuIThjnkpQyLOVOBOnR r/skbaKiZ9CcPRLmRyCWL+16BnXIVi4mATlUzCUtR6ftiQ9wG0FhbeZbyZi856PO FDA2TAbrdSUTxixgC0G0N0MpxD33qyYUFUZ9Yz9StpRoIplkDtvCPfRAkir8AGNI p5/mDOTtN8c5lZt4HZFUDs3GgnFMtLGcV13dECM4Spq1HXimdfQcOlQR5NuM9ZaS BbAG7nf+7SWLmFdmfMxgy+SZXcnEZXkOK5oi3tzJ/LctZSXKWoaFsu9nkd20a4BK fG4pNbD8Tct/Z4I8vnc8EScqNyhtFp52F4qmZL+xK8cj2xU1XbhTJafDbnR2ZRlv rIdVaE4PkfMBz21Nhzq54ue3M4GOqOljvRTtNIxi/9rEyyK1+1GJnWk2Bc3tDiZ6 zOK+24us4NKT4YL6m/Y199Ax1t2TlvHzd7bvakbHrtS9j+E4enO8maLVrnt6a7U+ c9coVL9/zK98lxPny5CsjUkZarTARw3gCuddJ+NdFqkS0obLosnAgc3fu/0XVAM2 ybN7OPEPsW4LVeaa+T93ZtNvUOc7/h+CY5FXi33U24CzPoK9jG8sGTbRqInXShgn uDUP2wO3bKBTKwtMX6JpDrSgTX4RkKHN6USLpgUuDTZKzcr/jyxJ/vsN20CT3zIZ K3nDzmvbLuhGS4i0Adwu =wOVN -----END PGP SIGNATURE----- Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "The highlight of this update is the fixes for ASoC kirkwood by Russell. In addition to that, a couple of regression fixes for HD-audio due to the runtime PM support on 3.7, and other driver- specific regression fixes like USB MIDI on non-standard USB audio drivers." * tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: snd-usb: properly initialize the sync endpoint ALSA: hda - Cirrus: Correctly clear line_out_pins when moving to speaker ALSA: hda - Add support for Realtek ALC292 ASoC: kirkwood-i2s: more pause-mode fixes ASoC: kirkwood-i2s: fix DMA underruns ASoC: kirkwood-i2s: fix DCO lock detection ASoC: kirkwood-dma: don't ignore other irq causes on error ASoC: kirkwood-dma: fix use of virt_to_phys() ALSA: hda - Limit runtime PM support only to known Intel chips ALSA: hda - Fix recursive suspend/resume call ALSA: ua101, usx2y: fix broken MIDI output ASoC: arizona: Fix typo - Swap value in 48k_rates[] and 44k1_rates[] ASoC: bells: Fix up git patch application failure ASoC: cs4271: free allocated GPIO
This commit is contained in:
commit
f470b8c258
@ -228,7 +228,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
|
|||||||
}
|
}
|
||||||
mutex_unlock(&bus->cmd_mutex);
|
mutex_unlock(&bus->cmd_mutex);
|
||||||
snd_hda_power_down(codec);
|
snd_hda_power_down(codec);
|
||||||
if (res && *res == -1 && bus->rirb_error) {
|
if (!codec->in_pm && res && *res == -1 && bus->rirb_error) {
|
||||||
if (bus->response_reset) {
|
if (bus->response_reset) {
|
||||||
snd_printd("hda_codec: resetting BUS due to "
|
snd_printd("hda_codec: resetting BUS due to "
|
||||||
"fatal communication error\n");
|
"fatal communication error\n");
|
||||||
@ -238,7 +238,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
|
|||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
/* clear reset-flag when the communication gets recovered */
|
/* clear reset-flag when the communication gets recovered */
|
||||||
if (!err)
|
if (!err || codec->in_pm)
|
||||||
bus->response_reset = 0;
|
bus->response_reset = 0;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -3616,6 +3616,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
|
|||||||
{
|
{
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
|
||||||
|
codec->in_pm = 1;
|
||||||
|
|
||||||
if (codec->patch_ops.suspend)
|
if (codec->patch_ops.suspend)
|
||||||
codec->patch_ops.suspend(codec);
|
codec->patch_ops.suspend(codec);
|
||||||
hda_cleanup_all_streams(codec);
|
hda_cleanup_all_streams(codec);
|
||||||
@ -3630,6 +3632,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
|
|||||||
codec->power_transition = 0;
|
codec->power_transition = 0;
|
||||||
codec->power_jiffies = jiffies;
|
codec->power_jiffies = jiffies;
|
||||||
spin_unlock(&codec->power_lock);
|
spin_unlock(&codec->power_lock);
|
||||||
|
codec->in_pm = 0;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3638,6 +3641,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
|
|||||||
*/
|
*/
|
||||||
static void hda_call_codec_resume(struct hda_codec *codec)
|
static void hda_call_codec_resume(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
|
codec->in_pm = 1;
|
||||||
|
|
||||||
/* set as if powered on for avoiding re-entering the resume
|
/* set as if powered on for avoiding re-entering the resume
|
||||||
* in the resume / power-save sequence
|
* in the resume / power-save sequence
|
||||||
*/
|
*/
|
||||||
@ -3656,6 +3661,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
|
|||||||
snd_hda_codec_resume_cache(codec);
|
snd_hda_codec_resume_cache(codec);
|
||||||
}
|
}
|
||||||
snd_hda_jack_report_sync(codec);
|
snd_hda_jack_report_sync(codec);
|
||||||
|
|
||||||
|
codec->in_pm = 0;
|
||||||
snd_hda_power_down(codec); /* flag down before returning */
|
snd_hda_power_down(codec); /* flag down before returning */
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
@ -869,6 +869,7 @@ struct hda_codec {
|
|||||||
unsigned int power_on :1; /* current (global) power-state */
|
unsigned int power_on :1; /* current (global) power-state */
|
||||||
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
||||||
unsigned int pm_down_notified:1; /* PM notified to controller */
|
unsigned int pm_down_notified:1; /* PM notified to controller */
|
||||||
|
unsigned int in_pm:1; /* suspend/resume being performed */
|
||||||
int power_transition; /* power-state in transition */
|
int power_transition; /* power-state in transition */
|
||||||
int power_count; /* current (global) power refcount */
|
int power_count; /* current (global) power refcount */
|
||||||
struct delayed_work power_work; /* delayed task for powerdown */
|
struct delayed_work power_work; /* delayed task for powerdown */
|
||||||
|
@ -556,6 +556,12 @@ enum {
|
|||||||
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
|
#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
|
||||||
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
|
#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
|
||||||
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
|
#define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
|
||||||
|
#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
|
||||||
|
|
||||||
|
/* quirks for Intel PCH */
|
||||||
|
#define AZX_DCAPS_INTEL_PCH \
|
||||||
|
(AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
|
||||||
|
AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
|
||||||
|
|
||||||
/* quirks for ATI SB / AMD Hudson */
|
/* quirks for ATI SB / AMD Hudson */
|
||||||
#define AZX_DCAPS_PRESET_ATI_SB \
|
#define AZX_DCAPS_PRESET_ATI_SB \
|
||||||
@ -2433,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
|
|||||||
{
|
{
|
||||||
struct azx *chip = bus->private_data;
|
struct azx *chip = bus->private_data;
|
||||||
|
|
||||||
|
if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
||||||
|
return;
|
||||||
|
|
||||||
if (power_up)
|
if (power_up)
|
||||||
pm_runtime_get_sync(&chip->pci->dev);
|
pm_runtime_get_sync(&chip->pci->dev);
|
||||||
else
|
else
|
||||||
@ -2548,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
|
|||||||
struct snd_card *card = dev_get_drvdata(dev);
|
struct snd_card *card = dev_get_drvdata(dev);
|
||||||
struct azx *chip = card->private_data;
|
struct azx *chip = card->private_data;
|
||||||
|
|
||||||
if (!power_save_controller)
|
if (!power_save_controller ||
|
||||||
|
!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
azx_stop_chip(chip);
|
azx_stop_chip(chip);
|
||||||
@ -3429,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
|
|||||||
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
|
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
|
||||||
/* CPT */
|
/* CPT */
|
||||||
{ PCI_DEVICE(0x8086, 0x1c20),
|
{ PCI_DEVICE(0x8086, 0x1c20),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* PBG */
|
/* PBG */
|
||||||
{ PCI_DEVICE(0x8086, 0x1d20),
|
{ PCI_DEVICE(0x8086, 0x1d20),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE},
|
|
||||||
/* Panther Point */
|
/* Panther Point */
|
||||||
{ PCI_DEVICE(0x8086, 0x1e20),
|
{ PCI_DEVICE(0x8086, 0x1e20),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* Lynx Point */
|
/* Lynx Point */
|
||||||
{ PCI_DEVICE(0x8086, 0x8c20),
|
{ PCI_DEVICE(0x8086, 0x8c20),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* Lynx Point-LP */
|
/* Lynx Point-LP */
|
||||||
{ PCI_DEVICE(0x8086, 0x9c20),
|
{ PCI_DEVICE(0x8086, 0x9c20),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* Lynx Point-LP */
|
/* Lynx Point-LP */
|
||||||
{ PCI_DEVICE(0x8086, 0x9c21),
|
{ PCI_DEVICE(0x8086, 0x9c21),
|
||||||
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* Haswell */
|
/* Haswell */
|
||||||
{ PCI_DEVICE(0x8086, 0x0c0c),
|
{ PCI_DEVICE(0x8086, 0x0c0c),
|
||||||
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
{ PCI_DEVICE(0x8086, 0x0d0c),
|
{ PCI_DEVICE(0x8086, 0x0d0c),
|
||||||
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* 5 Series/3400 */
|
/* 5 Series/3400 */
|
||||||
{ PCI_DEVICE(0x8086, 0x3b56),
|
{ PCI_DEVICE(0x8086, 0x3b56),
|
||||||
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
|
||||||
AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
|
|
||||||
/* SCH */
|
/* SCH */
|
||||||
{ PCI_DEVICE(0x8086, 0x811b),
|
{ PCI_DEVICE(0x8086, 0x811b),
|
||||||
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
|
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
|
||||||
|
@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
|
|||||||
memcpy(cfg->speaker_pins, cfg->line_out_pins,
|
memcpy(cfg->speaker_pins, cfg->line_out_pins,
|
||||||
sizeof(cfg->speaker_pins));
|
sizeof(cfg->speaker_pins));
|
||||||
cfg->line_outs = 0;
|
cfg->line_outs = 0;
|
||||||
|
memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -7065,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
|
|||||||
{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
|
{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
|
||||||
{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
|
{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
|
||||||
{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
|
{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
|
||||||
|
{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
|
||||||
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
|
{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
|
||||||
.patch = patch_alc861 },
|
.patch = patch_alc861 },
|
||||||
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
|
{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
|
||||||
|
@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
|
|||||||
static unsigned int arizona_sysclk_48k_rates[] = {
|
static unsigned int arizona_sysclk_48k_rates[] = {
|
||||||
6144000,
|
6144000,
|
||||||
12288000,
|
12288000,
|
||||||
22579200,
|
24576000,
|
||||||
49152000,
|
49152000,
|
||||||
73728000,
|
73728000,
|
||||||
98304000,
|
98304000,
|
||||||
@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
|
|||||||
static unsigned int arizona_sysclk_44k1_rates[] = {
|
static unsigned int arizona_sysclk_44k1_rates[] = {
|
||||||
5644800,
|
5644800,
|
||||||
11289600,
|
11289600,
|
||||||
24576000,
|
22579200,
|
||||||
45158400,
|
45158400,
|
||||||
67737600,
|
67737600,
|
||||||
90316800,
|
90316800,
|
||||||
|
@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
|||||||
gpio_nreset = cs4271plat->gpio_nreset;
|
gpio_nreset = cs4271plat->gpio_nreset;
|
||||||
|
|
||||||
if (gpio_nreset >= 0)
|
if (gpio_nreset >= 0)
|
||||||
if (gpio_request(gpio_nreset, "CS4271 Reset"))
|
if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
|
||||||
gpio_nreset = -EINVAL;
|
gpio_nreset = -EINVAL;
|
||||||
if (gpio_nreset >= 0) {
|
if (gpio_nreset >= 0) {
|
||||||
/* Reset codec */
|
/* Reset codec */
|
||||||
@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
|
|||||||
static int cs4271_remove(struct snd_soc_codec *codec)
|
static int cs4271_remove(struct snd_soc_codec *codec)
|
||||||
{
|
{
|
||||||
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
|
struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
|
||||||
int gpio_nreset;
|
|
||||||
|
|
||||||
gpio_nreset = cs4271->gpio_nreset;
|
if (gpio_is_valid(cs4271->gpio_nreset))
|
||||||
|
|
||||||
if (gpio_is_valid(gpio_nreset)) {
|
|
||||||
/* Set codec to the reset state */
|
/* Set codec to the reset state */
|
||||||
gpio_set_value(gpio_nreset, 0);
|
gpio_set_value(cs4271->gpio_nreset, 0);
|
||||||
gpio_free(gpio_nreset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
|
|||||||
printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
|
printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
|
||||||
__func__, cause);
|
__func__, cause);
|
||||||
writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
|
writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we've enabled only bytes interrupts ... */
|
/* we've enabled only bytes interrupts ... */
|
||||||
@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dram = mv_mbus_dram_info();
|
dram = mv_mbus_dram_info();
|
||||||
addr = virt_to_phys(substream->dma_buffer.area);
|
addr = substream->dma_buffer.addr;
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
prdata->play_stream = substream;
|
prdata->play_stream = substream;
|
||||||
kirkwood_dma_conf_mbus_windows(priv->io,
|
kirkwood_dma_conf_mbus_windows(priv->io,
|
||||||
|
@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
|
|||||||
do {
|
do {
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
|
value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
|
||||||
value &= KIRKWOOD_DCO_SPCR_STATUS;
|
value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
|
||||||
} while (value == 0);
|
} while (value == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
|||||||
int cmd, struct snd_soc_dai *dai)
|
int cmd, struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned long value;
|
uint32_t ctl, value;
|
||||||
|
|
||||||
/*
|
ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
|
||||||
* specs says KIRKWOOD_PLAYCTL must be read 2 times before
|
if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
|
||||||
* changing it. So read 1 time here and 1 later.
|
unsigned timeout = 5000;
|
||||||
*/
|
/*
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
* The Armada510 spec says that if we enter pause mode, the
|
||||||
|
* busy bit must be read back as clear _twice_. Make sure
|
||||||
|
* we respect that otherwise we get DMA underruns.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
value = ctl;
|
||||||
|
ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
|
||||||
|
if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
|
||||||
|
break;
|
||||||
|
udelay(1);
|
||||||
|
} while (timeout--);
|
||||||
|
|
||||||
|
if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
|
||||||
|
dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
|
||||||
|
ctl);
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
/* stop audio, enable interrupts */
|
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
value |= KIRKWOOD_PLAYCTL_PAUSE;
|
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
|
|
||||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||||
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
||||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||||
|
|
||||||
/* configure audio & enable i2s playback */
|
/* configure audio & enable i2s playback */
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
|
||||||
value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
|
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
|
||||||
value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
|
|
||||||
| KIRKWOOD_PLAYCTL_SPDIF_EN);
|
| KIRKWOOD_PLAYCTL_SPDIF_EN);
|
||||||
|
|
||||||
if (priv->burst == 32)
|
if (priv->burst == 32)
|
||||||
value |= KIRKWOOD_PLAYCTL_BURST_32;
|
ctl |= KIRKWOOD_PLAYCTL_BURST_32;
|
||||||
else
|
else
|
||||||
value |= KIRKWOOD_PLAYCTL_BURST_128;
|
ctl |= KIRKWOOD_PLAYCTL_BURST_128;
|
||||||
value |= KIRKWOOD_PLAYCTL_I2S_EN;
|
ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
/* stop audio, disable interrupts */
|
/* stop audio, disable interrupts */
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
||||||
value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
|
|
||||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||||
value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
||||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||||
|
|
||||||
/* disable all playbacks */
|
/* disable all playbacks */
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
|
||||||
value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
||||||
value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
value = readl(priv->io + KIRKWOOD_PLAYCTL);
|
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
|
||||||
value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
/* stop audio, enable interrupts */
|
|
||||||
value = readl(priv->io + KIRKWOOD_RECCTL);
|
|
||||||
value |= KIRKWOOD_RECCTL_PAUSE;
|
|
||||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
|
||||||
|
|
||||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||||
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
|
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
|
||||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||||
|
@ -212,7 +212,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
|
|||||||
{
|
{
|
||||||
.name = "Sub",
|
.name = "Sub",
|
||||||
.stream_name = "Sub",
|
.stream_name = "Sub",
|
||||||
.cpu_dai_name = "wm5110-aif3",
|
.cpu_dai_name = "wm5102-aif3",
|
||||||
.codec_dai_name = "wm9081-hifi",
|
.codec_dai_name = "wm9081-hifi",
|
||||||
.codec_name = "wm9081.1-006c",
|
.codec_name = "wm9081.1-006c",
|
||||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||||
@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = {
|
|||||||
{
|
{
|
||||||
.name = "Sub",
|
.name = "Sub",
|
||||||
.stream_name = "Sub",
|
.stream_name = "Sub",
|
||||||
.cpu_dai_name = "wm5102-aif3",
|
.cpu_dai_name = "wm5110-aif3",
|
||||||
.codec_dai_name = "wm9081-hifi",
|
.codec_dai_name = "wm9081-hifi",
|
||||||
.codec_name = "wm9081.1-006c",
|
.codec_name = "wm9081.1-006c",
|
||||||
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
|
||||||
|
@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
|
|||||||
struct snd_usb_midi_out_endpoint* ep;
|
struct snd_usb_midi_out_endpoint* ep;
|
||||||
struct snd_rawmidi_substream *substream;
|
struct snd_rawmidi_substream *substream;
|
||||||
int active;
|
int active;
|
||||||
|
bool autopm_reference;
|
||||||
uint8_t cable; /* cable number << 4 */
|
uint8_t cable; /* cable number << 4 */
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
#define STATE_UNKNOWN 0
|
#define STATE_UNKNOWN 0
|
||||||
@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
|
|||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
err = usb_autopm_get_interface(umidi->iface);
|
err = usb_autopm_get_interface(umidi->iface);
|
||||||
if (err < 0)
|
port->autopm_reference = err >= 0;
|
||||||
|
if (err < 0 && err != -EACCES)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
substream->runtime->private_data = port;
|
substream->runtime->private_data = port;
|
||||||
port->state = STATE_UNKNOWN;
|
port->state = STATE_UNKNOWN;
|
||||||
@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
|
|||||||
static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
|
static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
|
||||||
{
|
{
|
||||||
struct snd_usb_midi* umidi = substream->rmidi->private_data;
|
struct snd_usb_midi* umidi = substream->rmidi->private_data;
|
||||||
|
struct usbmidi_out_port *port = substream->runtime->private_data;
|
||||||
|
|
||||||
substream_open(substream, 0);
|
substream_open(substream, 0);
|
||||||
usb_autopm_put_interface(umidi->iface);
|
if (port->autopm_reference)
|
||||||
|
usb_autopm_put_interface(umidi->iface);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +459,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (subs->sync_endpoint)
|
if (subs->sync_endpoint)
|
||||||
ret = snd_usb_endpoint_set_params(subs->data_endpoint,
|
ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
|
||||||
subs->pcm_format,
|
subs->pcm_format,
|
||||||
subs->channels,
|
subs->channels,
|
||||||
subs->period_bytes,
|
subs->period_bytes,
|
||||||
|
Loading…
Reference in New Issue
Block a user