Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/sun-nontendocm-kernel.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authormadmonkey <madfkingmonkey@gmail.com>2018-07-26 01:47:45 +0300
committermadmonkey <madfkingmonkey@gmail.com>2018-07-26 02:05:38 +0300
commit9f53fdde860f03c64b78091dea3b1055652965a0 (patch)
tree09b584c85761d1a95cbc6fe27c96d425f599282b /sound
parent625bbe29047b654b511443263d7cd28ee4810638 (diff)
update to 3.4.113
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c1
-rw-r--r--sound/pci/rme96.c41
-rw-r--r--sound/soc/codecs/wm8962.c4
-rw-r--r--sound/soc/sunxi/i2s0/sunxi-i2s0.c80
-rw-r--r--sound/usb/midi.c46
-rw-r--r--sound/usb/quirks-table.h11
-rw-r--r--sound/usb/quirks.c1
-rw-r--r--sound/usb/usbaudio.h1
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,