diff options
author | madmonkey <madfkingmonkey@gmail.com> | 2018-07-26 01:47:45 +0300 |
---|---|---|
committer | madmonkey <madfkingmonkey@gmail.com> | 2018-07-26 02:05:38 +0300 |
commit | 9f53fdde860f03c64b78091dea3b1055652965a0 (patch) | |
tree | 09b584c85761d1a95cbc6fe27c96d425f599282b /sound | |
parent | 625bbe29047b654b511443263d7cd28ee4810638 (diff) |
update to 3.4.113
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1 | ||||
-rw-r--r-- | sound/pci/rme96.c | 41 | ||||
-rw-r--r-- | sound/soc/codecs/wm8962.c | 4 | ||||
-rw-r--r-- | sound/soc/sunxi/i2s0/sunxi-i2s0.c | 80 | ||||
-rw-r--r-- | sound/usb/midi.c | 46 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 11 | ||||
-rw-r--r-- | sound/usb/quirks.c | 1 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 1 |
9 files changed, 136 insertions, 51 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f461737e..833d8355 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3144,11 +3144,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | + AZX_DCAPS_NO_64BIT | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #else /* this entry seems still valid -- i.e. without emu20kx chip */ { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | + AZX_DCAPS_NO_64BIT | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif /* Vortex86MX */ diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 606f87aa..247b1a15 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4932,6 +4932,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity) static int hp_blike_system(u32 subsystem_id) { switch (subsystem_id) { + case 0x103c1473: /* HP ProBook 6550b */ case 0x103c1520: case 0x103c1521: case 0x103c1523: diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index ba894158..03eb085d 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -704,10 +704,11 @@ snd_rme96_playback_setrate(struct rme96 *rme96, { /* change to/from double-speed: reset the DAC (if available) */ snd_rme96_reset_dac(rme96); + return 1; /* need to restore volume */ } else { writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); + return 0; } - return 0; } static int @@ -945,6 +946,7 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, struct rme96 *rme96 = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err, rate, dummy; + bool apply_dac_volume = false; runtime->dma_area = (void __force *)(rme96->iobase + RME96_IO_PLAY_BUFFER); @@ -958,24 +960,26 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, { /* slave clock */ if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme96->lock); - return -EIO; - } - } else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) { - spin_unlock_irq(&rme96->lock); - return err; - } - if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) { - spin_unlock_irq(&rme96->lock); - return err; + err = -EIO; + goto error; + } + } else { + err = snd_rme96_playback_setrate(rme96, params_rate(params)); + if (err < 0) + goto error; + apply_dac_volume = err > 0; /* need to restore volume later? */ } + + err = snd_rme96_playback_setformat(rme96, params_format(params)); + if (err < 0) + goto error; snd_rme96_setframelog(rme96, params_channels(params), 1); if (rme96->capture_periodsize != 0) { if (params_period_size(params) << rme96->playback_frlog != rme96->capture_periodsize) { - spin_unlock_irq(&rme96->lock); - return -EBUSY; + err = -EBUSY; + goto error; } } rme96->playback_periodsize = @@ -986,9 +990,16 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); } + + err = 0; + error: spin_unlock_irq(&rme96->lock); - - return 0; + if (apply_dac_volume) { + usleep_range(3000, 10000); + snd_rme96_apply_dac_volume(rme96); + } + + return err; } static int diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 451ec480..fd06baae 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -363,8 +363,8 @@ static struct reg_default wm8962_reg[] = { { 16924, 0x0059 }, /* R16924 - HDBASS_PG_1 */ { 16925, 0x999A }, /* R16925 - HDBASS_PG_0 */ - { 17048, 0x0083 }, /* R17408 - HPF_C_1 */ - { 17049, 0x98AD }, /* R17409 - HPF_C_0 */ + { 17408, 0x0083 }, /* R17408 - HPF_C_1 */ + { 17409, 0x98AD }, /* R17409 - HPF_C_0 */ { 17920, 0x007F }, /* R17920 - ADCL_RETUNE_C1_1 */ { 17921, 0xFFFF }, /* R17921 - ADCL_RETUNE_C1_0 */ diff --git a/sound/soc/sunxi/i2s0/sunxi-i2s0.c b/sound/soc/sunxi/i2s0/sunxi-i2s0.c index 91525a90..b9f028e7 100644 --- a/sound/soc/sunxi/i2s0/sunxi-i2s0.c +++ b/sound/soc/sunxi/i2s0/sunxi-i2s0.c @@ -35,6 +35,20 @@ #include "sunxi-i2s0dma.h" #include "sunxi-i2s0.h" +/* <workaround> + * Based on Testing teams feedback, HDMI standard conformance tests, and + * TV field testing. + * + * i2s tx shutdown is not performed as a workaround: + * - to avoid wrong transient CTS values computed by the EP952 chip. + * The i2s codec must continue sending data to the TX FIFO to avoid + * timing breakage at the HDMI link level. Some TVs seem unable + * to recover from this timing inconsistencies. + * - to suppress slight sound glitches during application switches + * </workaround> + * Set it to either 0 or 1 */ +#define CLOVER_WORKAROUND_HDMI_CTS_DISCONTINUITY_AND_SOUND_GLITCHES 1 + struct sunxi_i2s0_info sunxi_i2s0; static unsigned int pin_count = 0; static script_item_u *pin_i2s0_list; @@ -98,7 +112,7 @@ static void sunxi_snd_txctrl_i2s0(struct snd_pcm_substream *substream, int on) reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); reg_val &= ~SUNXI_I2S0CTL_SDO3EN; reg_val &= ~SUNXI_I2S0CTL_SDO2EN; - reg_val &= ~SUNXI_I2S0CTL_SDO1EN; + reg_val &= ~SUNXI_I2S0CTL_SDO1EN; reg_val &= ~SUNXI_I2S0CTL_SDO0EN; switch(substream->runtime->channels) { case 1: @@ -125,7 +139,7 @@ static void sunxi_snd_txctrl_i2s0(struct snd_pcm_substream *substream, int on) /*flush TX FIFO*/ reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0FCTL); - reg_val |= SUNXI_I2S0FCTL_FTX; + reg_val |= SUNXI_I2S0FCTL_FTX; writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0FCTL); /*clear TX counter*/ @@ -142,12 +156,14 @@ static void sunxi_snd_txctrl_i2s0(struct snd_pcm_substream *substream, int on) reg_val |= SUNXI_I2S0INT_TXDRQEN; writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0INT); } else { - /* I2S0 TX DISABLE */ - reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); - reg_val &= ~SUNXI_I2S0CTL_TXEN; - writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0CTL); + if (!CLOVER_WORKAROUND_HDMI_CTS_DISCONTINUITY_AND_SOUND_GLITCHES) { + /* I2S0 TX DISABLE */ + reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); + reg_val &= ~SUNXI_I2S0CTL_TXEN; + writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0CTL); + } - /* DISBALE dma DRQ mode */ + /* DISABLE dma DRQ mode */ reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0INT); reg_val &= ~SUNXI_I2S0INT_TXDRQEN; writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0INT); @@ -361,45 +377,41 @@ static int sunxi_i2s0_hw_params(struct snd_pcm_substream *substream, return 0; } +static void sunxi_i2s0_trigger_common(struct snd_pcm_substream *substream, + int on) +{ + u32 reg_val; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + sunxi_snd_rxctrl_i2s0(substream, on); + } else { + sunxi_snd_txctrl_i2s0(substream, on); + } + + /*Deal with the Global Enable Digital Audio Interface*/ + reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); + if (on) { + reg_val |= SUNXI_I2S0CTL_GEN; + } else if (!CLOVER_WORKAROUND_HDMI_CTS_DISCONTINUITY_AND_SOUND_GLITCHES) { + reg_val &= ~SUNXI_I2S0CTL_GEN; + } + writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0CTL); +} + static int sunxi_i2s0_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { int ret = 0; - u32 reg_val; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - sunxi_snd_rxctrl_i2s0(substream, 1); - } else { - sunxi_snd_txctrl_i2s0(substream, 1); - } - /*Global Enable Digital Audio Interface*/ - reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); - reg_val |= SUNXI_I2S0CTL_GEN; -// reg_val |= SUNXI_I2S0CTL_LOOP; - writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0CTL); + sunxi_i2s0_trigger_common(substream, 1); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - // <hack> - // We disable i2s disabling to avoid wrong transient CTS - // values computed by EP952, and to suppress slight pops - // on i2s status change. -#if 0 - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - sunxi_snd_rxctrl_i2s0(substream, 0); - } else { - sunxi_snd_txctrl_i2s0(substream, 0); - } - Global disable Digital Audio Interface - reg_val = readl(sunxi_i2s0.regs + SUNXI_I2S0CTL); - reg_val &= ~SUNXI_I2S0CTL_GEN; - writel(reg_val, sunxi_i2s0.regs + SUNXI_I2S0CTL); -#endif - // </hack> + sunxi_i2s0_trigger_common(substream, 0); break; default: ret = -EINVAL; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index de86e748..075f3248 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -174,6 +174,8 @@ struct snd_usb_midi_in_endpoint { u8 running_status_length; } ports[0x10]; u8 seen_f5; + bool in_sysex; + u8 last_cin; u8 error_resubmit; int current_port; }; @@ -465,6 +467,39 @@ static void snd_usbmidi_maudio_broken_running_status_input( } /* + * QinHeng CH345 is buggy: every second packet inside a SysEx has not CIN 4 + * but the previously seen CIN, but still with three data bytes. + */ +static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep, + uint8_t *buffer, int buffer_length) +{ + unsigned int i, cin, length; + + for (i = 0; i + 3 < buffer_length; i += 4) { + if (buffer[i] == 0 && i > 0) + break; + cin = buffer[i] & 0x0f; + if (ep->in_sysex && + cin == ep->last_cin && + (buffer[i + 1 + (cin == 0x6)] & 0x80) == 0) + cin = 0x4; +#if 0 + if (buffer[i + 1] == 0x90) { + /* + * Either a corrupted running status or a real note-on + * message; impossible to detect reliably. + */ + } +#endif + length = snd_usbmidi_cin_length[cin]; + snd_usbmidi_input_data(ep, 0, &buffer[i + 1], length); + ep->in_sysex = cin == 0x4; + if (!ep->in_sysex) + ep->last_cin = cin; + } +} + +/* * CME protocol: like the standard protocol, but SysEx commands are sent as a * single USB packet preceded by a 0x0F byte. */ @@ -650,6 +685,12 @@ static struct usb_protocol_ops snd_usbmidi_cme_ops = { .output_packet = snd_usbmidi_output_standard_packet, }; +static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = { + .input = ch345_broken_sysex_input, + .output = snd_usbmidi_standard_output, + .output_packet = snd_usbmidi_output_standard_packet, +}; + /* * AKAI MPD16 protocol: * @@ -1326,6 +1367,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, * Various chips declare a packet size larger than 4 bytes, but * do not actually work with larger packets: */ + case USB_ID(0x0a67, 0x5011): /* Medeli DD305 */ case USB_ID(0x0a92, 0x1020): /* ESI M4U */ case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */ case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */ @@ -2214,6 +2256,10 @@ int snd_usbmidi_create(struct snd_card *card, err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); break; + case QUIRK_MIDI_CH345: + umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops; + err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); + break; default: snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); err = -ENXIO; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 4cebbf7f..862ed16a 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2689,6 +2689,17 @@ YAMAHA_DEVICE(0x7010, "UB99"), .idProduct = 0x1020, }, +/* QinHeng devices */ +{ + USB_DEVICE(0x1a86, 0x752d), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "QinHeng", + .product_name = "CH345", + .ifnum = 1, + .type = QUIRK_MIDI_CH345 + } +}, + /* KeithMcMillen Stringport */ { USB_DEVICE(0x1f38, 0x0001), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 9c82f8b6..b01d3cf3 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -311,6 +311,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_CME] = create_any_midi_quirk, [QUIRK_MIDI_AKAI] = create_any_midi_quirk, [QUIRK_MIDI_FTDI] = create_any_midi_quirk, + [QUIRK_MIDI_CH345] = create_any_midi_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 6c805a51..5e0e58ad 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -81,6 +81,7 @@ enum quirk_type { QUIRK_MIDI_AKAI, QUIRK_MIDI_US122L, QUIRK_MIDI_FTDI, + QUIRK_MIDI_CH345, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, |