mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'for-next' into for-linus
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -2376,6 +2376,13 @@ quirk_flags
|
||||
Skip the probe-time interface setup (usb_set_interface,
|
||||
init_pitch, init_sample_rate); redundant with
|
||||
snd_usb_endpoint_prepare() at stream-open time
|
||||
* bit 27: ``mixer_playback_linear_vol``
|
||||
Set linear volume mapping for devices where the playback volume
|
||||
control value is mapped to voltage (instead of dB) level linearly.
|
||||
In short: ``x(raw) = (raw - raw_min) / (raw_max - raw_min)``;
|
||||
``V(x) = k * x``; ``dB(x) = 20 * log10(x)``. Overrides bit 24
|
||||
* bit 28: ``mixer_capture_linear_vol``
|
||||
Similar to bit 27 but for capture streams. Overrides bit 25
|
||||
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
|
||||
@@ -133,6 +133,9 @@ struct snd_card {
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
struct dentry *debugfs_root; /* debugfs root for card */
|
||||
#endif
|
||||
#ifdef CONFIG_SND_CTL_DEBUG
|
||||
struct snd_ctl_elem_value *value_buf; /* buffer for kctl->put() verification */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned int power_state; /* power state */
|
||||
|
||||
@@ -536,6 +536,7 @@ int snd_gf1_dma_transfer_block(struct snd_gus_card * gus,
|
||||
struct snd_gf1_dma_block * block,
|
||||
int atomic,
|
||||
int synth);
|
||||
void snd_gf1_dma_suspend(struct snd_gus_card *gus);
|
||||
|
||||
/* gus_volume.c */
|
||||
|
||||
@@ -552,6 +553,8 @@ struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, i
|
||||
void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice);
|
||||
int snd_gf1_start(struct snd_gus_card * gus);
|
||||
int snd_gf1_stop(struct snd_gus_card * gus);
|
||||
int snd_gf1_suspend(struct snd_gus_card *gus);
|
||||
int snd_gf1_resume(struct snd_gus_card *gus);
|
||||
|
||||
/* gus_mixer.c */
|
||||
|
||||
@@ -572,6 +575,8 @@ int snd_gus_create(struct snd_card *card,
|
||||
int effect,
|
||||
struct snd_gus_card ** rgus);
|
||||
int snd_gus_initialize(struct snd_gus_card * gus);
|
||||
int snd_gus_suspend(struct snd_gus_card *gus);
|
||||
int snd_gus_resume(struct snd_gus_card *gus);
|
||||
|
||||
/* gus_irq.c */
|
||||
|
||||
@@ -583,6 +588,8 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus);
|
||||
/* gus_uart.c */
|
||||
|
||||
int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device);
|
||||
void snd_gf1_uart_suspend(struct snd_gus_card *gus);
|
||||
void snd_gf1_uart_resume(struct snd_gus_card *gus);
|
||||
|
||||
/* gus_dram.c */
|
||||
int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr,
|
||||
@@ -593,5 +600,6 @@ int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr,
|
||||
/* gus_timer.c */
|
||||
void snd_gf1_timers_init(struct snd_gus_card *gus);
|
||||
void snd_gf1_timers_done(struct snd_gus_card *gus);
|
||||
void snd_gf1_timers_resume(struct snd_gus_card *gus);
|
||||
|
||||
#endif /* __SOUND_GUS_H */
|
||||
|
||||
@@ -336,6 +336,17 @@ snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
|
||||
return snd_hdac_codec_write(&codec->core, nid, flags, verb, parm);
|
||||
}
|
||||
|
||||
/* sync after write */
|
||||
static inline int
|
||||
snd_hda_codec_write_sync(struct hda_codec *codec, hda_nid_t nid, int flags,
|
||||
unsigned int verb, unsigned int parm)
|
||||
{
|
||||
/* use snd_hda_codec_read() for writing;
|
||||
* the returned value is usually discarded
|
||||
*/
|
||||
return snd_hdac_codec_read(&codec->core, nid, flags, verb, parm);
|
||||
}
|
||||
|
||||
#define snd_hda_param_read(codec, nid, param) \
|
||||
snd_hdac_read_parm(&(codec)->core, nid, param)
|
||||
#define snd_hda_get_sub_nodes(codec, nid, start_nid) \
|
||||
@@ -470,6 +481,10 @@ void snd_hda_unlock_devices(struct hda_bus *bus);
|
||||
void snd_hda_bus_reset(struct hda_bus *bus);
|
||||
void snd_hda_bus_reset_codecs(struct hda_bus *bus);
|
||||
|
||||
void snd_hda_codec_set_gpio(struct hda_codec *codec, unsigned int mask,
|
||||
unsigned int dir, unsigned int data,
|
||||
unsigned int delay);
|
||||
|
||||
int snd_hda_codec_set_name(struct hda_codec *codec, const char *name);
|
||||
|
||||
/*
|
||||
|
||||
@@ -56,7 +56,12 @@ enum {
|
||||
#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d
|
||||
#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */
|
||||
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
|
||||
/* f10-f1a: GPIO */
|
||||
/* f10-f1a: GPI/GPO/GPIO */
|
||||
#define AC_VERB_GET_GPI_DATA 0x0f10
|
||||
#define AC_VERB_GET_GPI_WAKE_MASK 0x0f11
|
||||
#define AC_VERB_GET_GPI_UNSOLICITED_RSP_MASK 0x0f12
|
||||
#define AC_VERB_GET_GPI_STICKY_MASK 0x0f13
|
||||
#define AC_VERB_GET_GPO_DATA 0x0f14
|
||||
#define AC_VERB_GET_GPIO_DATA 0x0f15
|
||||
#define AC_VERB_GET_GPIO_MASK 0x0f16
|
||||
#define AC_VERB_GET_GPIO_DIRECTION 0x0f17
|
||||
@@ -99,6 +104,11 @@ enum {
|
||||
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
|
||||
#define AC_VERB_SET_DIGI_CONVERT_3 0x73e
|
||||
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
|
||||
#define AC_VERB_SET_GPI_DATA 0x710
|
||||
#define AC_VERB_SET_GPI_WAKE_MASK 0x711
|
||||
#define AC_VERB_SET_SPI_UNSOLICITED_RSP_MASK 0x712
|
||||
#define AC_VERB_SET_GPI_STICKY_MASK 0x713
|
||||
#define AC_VERB_SET_GPO_DATA 0x714
|
||||
#define AC_VERB_SET_GPIO_DATA 0x715
|
||||
#define AC_VERB_SET_GPIO_MASK 0x716
|
||||
#define AC_VERB_SET_GPIO_DIRECTION 0x717
|
||||
|
||||
@@ -729,6 +729,10 @@ static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime,
|
||||
runtime->status->state = state; /* copy for mmap */
|
||||
}
|
||||
|
||||
void snd_pcm_set_state(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state);
|
||||
snd_pcm_state_t snd_pcm_get_state(struct snd_pcm_substream *substream);
|
||||
|
||||
/**
|
||||
* bytes_to_samples - Unit conversion of the size from bytes to samples
|
||||
* @runtime: PCM runtime instance
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer);
|
||||
int snd_tea6330t_update_mixer(struct snd_card *card, struct snd_i2c_bus *bus,
|
||||
int equalizer, int fader);
|
||||
int snd_tea6330t_restore_mixer(struct snd_i2c_bus *bus);
|
||||
|
||||
#endif /* __SOUND_TEA6330T_H */
|
||||
|
||||
@@ -102,6 +102,7 @@ struct snd_timer_instance {
|
||||
unsigned int slave_id;
|
||||
struct list_head open_list;
|
||||
struct list_head active_list;
|
||||
struct list_head master_list;
|
||||
struct list_head ack_list;
|
||||
struct list_head slave_list_head;
|
||||
struct list_head slave_active_head;
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ struct aoa_codec {
|
||||
u32 connected;
|
||||
|
||||
/* data the fabric can associate with this structure */
|
||||
void *fabric_data;
|
||||
const void *fabric_data;
|
||||
|
||||
/* private! */
|
||||
struct list_head list;
|
||||
|
||||
+36
-5
@@ -32,6 +32,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <sound/asoundef.h>
|
||||
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
|
||||
@@ -514,8 +515,36 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int onyx_set_spdif_pcm_rate(struct onyx *onyx, unsigned int rate)
|
||||
{
|
||||
u8 dig_info3, fs;
|
||||
|
||||
switch (rate) {
|
||||
case 32000:
|
||||
fs = IEC958_AES3_CON_FS_32000;
|
||||
break;
|
||||
case 44100:
|
||||
fs = IEC958_AES3_CON_FS_44100;
|
||||
break;
|
||||
case 48000:
|
||||
fs = IEC958_AES3_CON_FS_48000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &dig_info3))
|
||||
return -EBUSY;
|
||||
dig_info3 = (dig_info3 & ~IEC958_AES3_CON_FS) | fs;
|
||||
if (onyx_write_register(onyx, ONYX_REG_DIG_INFO3, dig_info3))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new onyx_spdif_ctrl = {
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
|
||||
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
||||
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
|
||||
.info = onyx_spdif_info,
|
||||
@@ -695,9 +724,9 @@ static int onyx_prepare(struct codec_info_item *cii,
|
||||
case 32000:
|
||||
case 44100:
|
||||
case 48000:
|
||||
/* these rates are ok for all outputs */
|
||||
/* FIXME: program spdif channel control bits here so that
|
||||
* userspace doesn't have to if it only plays pcm! */
|
||||
if (onyx->codec.connected & 2)
|
||||
return onyx_set_spdif_pcm_rate(onyx,
|
||||
substream->runtime->rate);
|
||||
return 0;
|
||||
default:
|
||||
/* got some rate that the digital output can't do,
|
||||
@@ -980,10 +1009,12 @@ static int onyx_i2c_probe(struct i2c_client *client)
|
||||
onyx->codec.node = of_node_get(node);
|
||||
|
||||
if (aoa_codec_register(&onyx->codec)) {
|
||||
goto fail;
|
||||
goto fail_put;
|
||||
}
|
||||
printk(KERN_DEBUG PFX "created and attached onyx instance\n");
|
||||
return 0;
|
||||
fail_put:
|
||||
of_node_put(onyx->codec.node);
|
||||
fail:
|
||||
kfree(onyx);
|
||||
return -ENODEV;
|
||||
|
||||
@@ -872,6 +872,7 @@ static int tas_i2c_probe(struct i2c_client *client)
|
||||
return 0;
|
||||
fail:
|
||||
mutex_destroy(&tas->mtx);
|
||||
of_node_put(tas->codec.node);
|
||||
kfree(tas);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+14
-14
@@ -55,7 +55,7 @@ struct codec_connection {
|
||||
|
||||
struct codec_connect_info {
|
||||
char *name;
|
||||
struct codec_connection *connections;
|
||||
const struct codec_connection *connections;
|
||||
};
|
||||
|
||||
#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)
|
||||
@@ -116,7 +116,7 @@ MODULE_ALIAS("aoa-device-id-35");
|
||||
MODULE_ALIAS("aoa-device-id-44");
|
||||
|
||||
/* onyx with all but microphone connected */
|
||||
static struct codec_connection onyx_connections_nomic[] = {
|
||||
static const struct codec_connection onyx_connections_nomic[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
|
||||
.codec_bit = 0,
|
||||
@@ -133,7 +133,7 @@ static struct codec_connection onyx_connections_nomic[] = {
|
||||
};
|
||||
|
||||
/* onyx on machines without headphone */
|
||||
static struct codec_connection onyx_connections_noheadphones[] = {
|
||||
static const struct codec_connection onyx_connections_noheadphones[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_LINEOUT |
|
||||
CC_LINEOUT_LABELLED_HEADPHONE,
|
||||
@@ -157,7 +157,7 @@ static struct codec_connection onyx_connections_noheadphones[] = {
|
||||
};
|
||||
|
||||
/* onyx on machines with real line-out */
|
||||
static struct codec_connection onyx_connections_reallineout[] = {
|
||||
static const struct codec_connection onyx_connections_reallineout[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
|
||||
.codec_bit = 0,
|
||||
@@ -174,7 +174,7 @@ static struct codec_connection onyx_connections_reallineout[] = {
|
||||
};
|
||||
|
||||
/* tas on machines without line out */
|
||||
static struct codec_connection tas_connections_nolineout[] = {
|
||||
static const struct codec_connection tas_connections_nolineout[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE,
|
||||
.codec_bit = 0,
|
||||
@@ -191,7 +191,7 @@ static struct codec_connection tas_connections_nolineout[] = {
|
||||
};
|
||||
|
||||
/* tas on machines with neither line out nor line in */
|
||||
static struct codec_connection tas_connections_noline[] = {
|
||||
static const struct codec_connection tas_connections_noline[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE,
|
||||
.codec_bit = 0,
|
||||
@@ -204,7 +204,7 @@ static struct codec_connection tas_connections_noline[] = {
|
||||
};
|
||||
|
||||
/* tas on machines without microphone */
|
||||
static struct codec_connection tas_connections_nomic[] = {
|
||||
static const struct codec_connection tas_connections_nomic[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
|
||||
.codec_bit = 0,
|
||||
@@ -217,7 +217,7 @@ static struct codec_connection tas_connections_nomic[] = {
|
||||
};
|
||||
|
||||
/* tas on machines with everything connected */
|
||||
static struct codec_connection tas_connections_all[] = {
|
||||
static const struct codec_connection tas_connections_all[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
|
||||
.codec_bit = 0,
|
||||
@@ -233,7 +233,7 @@ static struct codec_connection tas_connections_all[] = {
|
||||
{} /* terminate array by .connected == 0 */
|
||||
};
|
||||
|
||||
static struct codec_connection toonie_connections[] = {
|
||||
static const struct codec_connection toonie_connections[] = {
|
||||
{
|
||||
.connected = CC_SPEAKERS | CC_HEADPHONE,
|
||||
.codec_bit = 0,
|
||||
@@ -241,7 +241,7 @@ static struct codec_connection toonie_connections[] = {
|
||||
{} /* terminate array by .connected == 0 */
|
||||
};
|
||||
|
||||
static struct codec_connection topaz_input[] = {
|
||||
static const struct codec_connection topaz_input[] = {
|
||||
{
|
||||
.connected = CC_DIGITALIN,
|
||||
.codec_bit = 0,
|
||||
@@ -249,7 +249,7 @@ static struct codec_connection topaz_input[] = {
|
||||
{} /* terminate array by .connected == 0 */
|
||||
};
|
||||
|
||||
static struct codec_connection topaz_output[] = {
|
||||
static const struct codec_connection topaz_output[] = {
|
||||
{
|
||||
.connected = CC_DIGITALOUT,
|
||||
.codec_bit = 1,
|
||||
@@ -257,7 +257,7 @@ static struct codec_connection topaz_output[] = {
|
||||
{} /* terminate array by .connected == 0 */
|
||||
};
|
||||
|
||||
static struct codec_connection topaz_inout[] = {
|
||||
static const struct codec_connection topaz_inout[] = {
|
||||
{
|
||||
.connected = CC_DIGITALIN,
|
||||
.codec_bit = 0,
|
||||
@@ -772,7 +772,7 @@ static int check_codec(struct aoa_codec *codec,
|
||||
{
|
||||
const u32 *ref;
|
||||
char propname[32];
|
||||
struct codec_connection *cc;
|
||||
const struct codec_connection *cc;
|
||||
|
||||
/* if the codec has a 'codec' node, we require a reference */
|
||||
if (of_node_name_eq(codec->node, "codec")) {
|
||||
@@ -895,7 +895,7 @@ static void layout_notify(void *data)
|
||||
|
||||
static void layout_attached_codec(struct aoa_codec *codec)
|
||||
{
|
||||
struct codec_connection *cc;
|
||||
const struct codec_connection *cc;
|
||||
struct snd_kcontrol *ctl;
|
||||
int headphones, lineout;
|
||||
struct layout_dev *ldev = layout_device;
|
||||
|
||||
@@ -84,6 +84,7 @@ static void i2sbus_release_dev(struct device *dev)
|
||||
for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
|
||||
free_irq(i2sdev->interrupts[i], i2sdev);
|
||||
i2sbus_control_remove_dev(i2sdev->control, i2sdev);
|
||||
of_node_put(i2sdev->sound.ofdev.dev.of_node);
|
||||
mutex_destroy(&i2sdev->lock);
|
||||
kfree(i2sdev);
|
||||
}
|
||||
@@ -147,7 +148,6 @@ static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index,
|
||||
}
|
||||
|
||||
/* Returns 1 if added, 0 for otherwise; don't return a negative value! */
|
||||
/* FIXME: look at device node refcounting */
|
||||
static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
struct i2sbus_control *control,
|
||||
struct device_node *np)
|
||||
@@ -178,8 +178,9 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
i = 0;
|
||||
for_each_child_of_node(np, child) {
|
||||
if (of_node_name_eq(child, "sound")) {
|
||||
of_node_put(sound);
|
||||
i++;
|
||||
sound = child;
|
||||
sound = of_node_get(child);
|
||||
}
|
||||
}
|
||||
if (i == 1) {
|
||||
@@ -205,6 +206,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
}
|
||||
}
|
||||
}
|
||||
of_node_put(sound);
|
||||
/* for the time being, until we can handle non-layout-id
|
||||
* things in some fabric, refuse to attach if there is no
|
||||
* layout-id property or we haven't been forced to attach.
|
||||
@@ -219,7 +221,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
mutex_init(&dev->lock);
|
||||
spin_lock_init(&dev->low_lock);
|
||||
dev->sound.ofdev.archdata.dma_mask = macio->ofdev.archdata.dma_mask;
|
||||
dev->sound.ofdev.dev.of_node = np;
|
||||
dev->sound.ofdev.dev.of_node = of_node_get(np);
|
||||
dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.archdata.dma_mask;
|
||||
dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
|
||||
dev->sound.ofdev.dev.release = i2sbus_release_dev;
|
||||
@@ -327,6 +329,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
|
||||
for (i=0;i<3;i++)
|
||||
release_and_free_resource(dev->allocated_resource[i]);
|
||||
mutex_destroy(&dev->lock);
|
||||
of_node_put(dev->sound.ofdev.dev.of_node);
|
||||
kfree(dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -405,6 +408,9 @@ static int i2sbus_resume(struct macio_dev* dev)
|
||||
int err, ret = 0;
|
||||
|
||||
list_for_each_entry(i2sdev, &control->list, item) {
|
||||
if (list_empty(&i2sdev->sound.codec_list))
|
||||
continue;
|
||||
|
||||
/* reset i2s bus format etc. */
|
||||
i2sbus_pcm_prepare_both(i2sdev);
|
||||
|
||||
|
||||
@@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
|
||||
* currently in use (if any). */
|
||||
hw->rate_min = 5512;
|
||||
hw->rate_max = 192000;
|
||||
/* if the other stream is active, then we can only
|
||||
* support what it is currently using.
|
||||
* FIXME: I lied. This comment is wrong. We can support
|
||||
* anything that works with the same serial format, ie.
|
||||
* when recording 24 bit sound we can well play 16 bit
|
||||
* sound at the same time iff using the same transfer mode.
|
||||
/* If the other stream is already prepared, keep this stream
|
||||
* on the same duplex format and rate.
|
||||
*
|
||||
* i2sbus_pcm_prepare() still programs one shared transport
|
||||
* configuration for both directions, so mixed duplex formats
|
||||
* are not supported here.
|
||||
*/
|
||||
if (other->active) {
|
||||
/* FIXME: is this guaranteed by the alsa api? */
|
||||
hw->formats &= pcm_format_to_bits(i2sdev->format);
|
||||
/* see above, restrict rates to the one we already have */
|
||||
/* Restrict rates to the one already in use. */
|
||||
hw->rate_min = i2sdev->rate;
|
||||
hw->rate_max = i2sdev->rate;
|
||||
}
|
||||
@@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void i2sbus_pcm_clear_active(struct i2sbus_dev *i2sdev, int in)
|
||||
{
|
||||
struct pcm_info *pi;
|
||||
|
||||
guard(mutex)(&i2sdev->lock);
|
||||
|
||||
get_pcm_info(i2sdev, in, &pi, NULL);
|
||||
pi->active = 0;
|
||||
}
|
||||
|
||||
static inline int i2sbus_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params, int in)
|
||||
{
|
||||
i2sbus_pcm_clear_active(snd_pcm_substream_chip(substream), in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
|
||||
{
|
||||
struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
|
||||
@@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
|
||||
get_pcm_info(i2sdev, in, &pi, NULL);
|
||||
if (pi->dbdma_ring.stopping)
|
||||
i2sbus_wait_for_stop(i2sdev, pi);
|
||||
i2sbus_pcm_clear_active(i2sdev, in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2sbus_playback_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return i2sbus_hw_params(substream, params, 0);
|
||||
}
|
||||
|
||||
static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return i2sbus_hw_free(substream, 0);
|
||||
}
|
||||
|
||||
static int i2sbus_record_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
return i2sbus_hw_params(substream, params, 1);
|
||||
}
|
||||
|
||||
static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return i2sbus_hw_free(substream, 1);
|
||||
@@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
return -EINVAL;
|
||||
|
||||
runtime = pi->substream->runtime;
|
||||
pi->active = 1;
|
||||
if (other->active &&
|
||||
((i2sdev->format != runtime->format)
|
||||
|| (i2sdev->rate != runtime->rate)))
|
||||
@@ -383,6 +411,9 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
/* set stop command */
|
||||
command->command = cpu_to_le16(DBDMA_STOP);
|
||||
|
||||
cii = list_first_entry(&i2sdev->sound.codec_list,
|
||||
struct codec_info_item, list);
|
||||
|
||||
/* ok, let's set the serial format and stuff */
|
||||
switch (runtime->format) {
|
||||
/* 16 bit formats */
|
||||
@@ -390,13 +421,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
case SNDRV_PCM_FORMAT_U16_BE:
|
||||
/* FIXME: if we add different bus factors we need to
|
||||
* do more here!! */
|
||||
bi.bus_factor = 0;
|
||||
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
|
||||
bi.bus_factor = cii->codec->bus_factor;
|
||||
break;
|
||||
}
|
||||
if (!bi.bus_factor)
|
||||
return -ENODEV;
|
||||
bi.bus_factor = cii->codec->bus_factor;
|
||||
input_16bit = 1;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_BE:
|
||||
@@ -410,10 +435,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
return -EINVAL;
|
||||
}
|
||||
/* we assume all sysclocks are the same! */
|
||||
list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
|
||||
bi.sysclock_factor = cii->codec->sysclock_factor;
|
||||
break;
|
||||
}
|
||||
bi.sysclock_factor = cii->codec->sysclock_factor;
|
||||
|
||||
if (clock_and_divisors(bi.sysclock_factor,
|
||||
bi.bus_factor,
|
||||
@@ -450,9 +472,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
|
||||
/* early exit if already programmed correctly */
|
||||
/* not locking these is fine since we touch them only in this function */
|
||||
if (in_le32(&i2sdev->intfregs->serial_format) == sfr
|
||||
&& in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
|
||||
if (in_le32(&i2sdev->intfregs->serial_format) == sfr &&
|
||||
in_le32(&i2sdev->intfregs->data_word_sizes) == dws) {
|
||||
pi->active = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* let's notify the codecs about clocks going away.
|
||||
* For now we only do mastering on the i2s cell... */
|
||||
@@ -490,6 +514,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
|
||||
if (cii->codec->switch_clock)
|
||||
cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
|
||||
|
||||
pi->active = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -734,6 +759,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
|
||||
static const struct snd_pcm_ops i2sbus_playback_ops = {
|
||||
.open = i2sbus_playback_open,
|
||||
.close = i2sbus_playback_close,
|
||||
.hw_params = i2sbus_playback_hw_params,
|
||||
.hw_free = i2sbus_playback_hw_free,
|
||||
.prepare = i2sbus_playback_prepare,
|
||||
.trigger = i2sbus_playback_trigger,
|
||||
@@ -802,6 +828,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
|
||||
static const struct snd_pcm_ops i2sbus_record_ops = {
|
||||
.open = i2sbus_record_open,
|
||||
.close = i2sbus_record_close,
|
||||
.hw_params = i2sbus_record_hw_params,
|
||||
.hw_free = i2sbus_record_hw_free,
|
||||
.prepare = i2sbus_record_prepare,
|
||||
.trigger = i2sbus_record_trigger,
|
||||
|
||||
@@ -23,6 +23,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
|
||||
# for trace-points
|
||||
CFLAGS_pcm_lib.o := -I$(src)
|
||||
CFLAGS_pcm_native.o := -I$(src)
|
||||
CFLAGS_control.o := -I$(src)
|
||||
|
||||
snd-pcm-dmaengine-y := pcm_dmaengine.o
|
||||
|
||||
|
||||
@@ -41,13 +41,6 @@
|
||||
#define COMPR_CODEC_CAPS_OVERFLOW
|
||||
#endif
|
||||
|
||||
/* TODO:
|
||||
* - add substream support for multiple devices in case of
|
||||
* SND_DYNAMIC_MINORS is not used
|
||||
* - Multiple node representation
|
||||
* driver should be able to register multiple nodes
|
||||
*/
|
||||
|
||||
struct snd_compr_file {
|
||||
unsigned long caps;
|
||||
struct snd_compr_stream stream;
|
||||
@@ -190,9 +183,21 @@ snd_compr_tstamp32_from_64(struct snd_compr_tstamp *tstamp32,
|
||||
static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
|
||||
struct snd_compr_tstamp64 *tstamp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!stream->ops->pointer)
|
||||
return -ENOTSUPP;
|
||||
stream->ops->pointer(stream, tstamp);
|
||||
|
||||
switch (stream->runtime->state) {
|
||||
case SNDRV_PCM_STATE_OPEN:
|
||||
return -EBADFD;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = stream->ops->pointer(stream, tstamp);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
pr_debug("dsp consumed till %u total %llu bytes\n", tstamp->byte_offset,
|
||||
tstamp->copied_total);
|
||||
if (stream->direction == SND_COMPRESS_PLAYBACK)
|
||||
|
||||
+75
-1
@@ -19,6 +19,13 @@
|
||||
#include <sound/info.h>
|
||||
#include <sound/control.h>
|
||||
|
||||
#ifdef CONFIG_SND_CTL_DEBUG
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "control_trace.h"
|
||||
#else
|
||||
#define trace_snd_ctl_put(card, kctl, iname, expected, actual)
|
||||
#endif
|
||||
|
||||
// Max allocation size for user controls.
|
||||
static int max_user_ctl_alloc_size = 8 * 1024 * 1024;
|
||||
module_param_named(max_user_ctl_alloc_size, max_user_ctl_alloc_size, int, 0444);
|
||||
@@ -1264,6 +1271,72 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
|
||||
return result;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_CTL_DEBUG)
|
||||
|
||||
static const char *const snd_ctl_elem_iface_names[] = {
|
||||
[SNDRV_CTL_ELEM_IFACE_CARD] = "CARD",
|
||||
[SNDRV_CTL_ELEM_IFACE_HWDEP] = "HWDEP",
|
||||
[SNDRV_CTL_ELEM_IFACE_MIXER] = "MIXER",
|
||||
[SNDRV_CTL_ELEM_IFACE_PCM] = "PCM",
|
||||
[SNDRV_CTL_ELEM_IFACE_RAWMIDI] = "RAWMIDI",
|
||||
[SNDRV_CTL_ELEM_IFACE_TIMER] = "TIMER",
|
||||
[SNDRV_CTL_ELEM_IFACE_SEQUENCER] = "SEQUENCER",
|
||||
};
|
||||
|
||||
static int snd_ctl_put_verify(struct snd_card *card, struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *control)
|
||||
{
|
||||
struct snd_ctl_elem_value *original = card->value_buf;
|
||||
struct snd_ctl_elem_info info;
|
||||
const char *iname;
|
||||
int ret, retcmp;
|
||||
|
||||
memset(original, 0, sizeof(*original));
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
ret = kctl->info(kctl, &info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kctl->get(kctl, original);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = kctl->put(kctl, control);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Sanitize the new value (control->value) before comparing. */
|
||||
fill_remaining_elem_value(control, &info, 0);
|
||||
|
||||
/* With known state for both new and original, do the comparison. */
|
||||
retcmp = memcmp(&original->value, &control->value, sizeof(original->value));
|
||||
if (retcmp)
|
||||
retcmp = 1;
|
||||
|
||||
iname = snd_ctl_elem_iface_names[kctl->id.iface];
|
||||
trace_snd_ctl_put(&kctl->id, iname, card->number, ret, retcmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *control, unsigned int access)
|
||||
{
|
||||
if ((access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK) ||
|
||||
(access & SNDRV_CTL_ELEM_ACCESS_VOLATILE))
|
||||
return kctl->put(kctl, control);
|
||||
|
||||
return snd_ctl_put_verify(card, kctl, control);
|
||||
}
|
||||
#else
|
||||
static inline int snd_ctl_put(struct snd_card *card, struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *control, unsigned int access)
|
||||
{
|
||||
return kctl->put(kctl, control);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
struct snd_ctl_elem_value *control)
|
||||
{
|
||||
@@ -1300,7 +1373,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
false);
|
||||
}
|
||||
if (!result)
|
||||
result = kctl->put(kctl, control);
|
||||
result = snd_ctl_put(card, kctl, control, vd->access);
|
||||
|
||||
if (result < 0) {
|
||||
up_write(&card->controls_rwsem);
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM snd_ctl
|
||||
|
||||
#if !defined(_TRACE_SND_CTL_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_SND_CTL_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include <uapi/sound/asound.h>
|
||||
|
||||
TRACE_EVENT(snd_ctl_put,
|
||||
|
||||
TP_PROTO(struct snd_ctl_elem_id *id, const char *iname, unsigned int card,
|
||||
int expected, int actual),
|
||||
|
||||
TP_ARGS(id, iname, card, expected, actual),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, numid)
|
||||
__string(iname, iname)
|
||||
__string(kname, id->name)
|
||||
__field(unsigned int, index)
|
||||
__field(unsigned int, device)
|
||||
__field(unsigned int, subdevice)
|
||||
__field(unsigned int, card)
|
||||
__field(int, expected)
|
||||
__field(int, actual)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->numid = id->numid;
|
||||
__assign_str(iname);
|
||||
__assign_str(kname);
|
||||
__entry->index = id->index;
|
||||
__entry->device = id->device;
|
||||
__entry->subdevice = id->subdevice;
|
||||
__entry->card = card;
|
||||
__entry->expected = expected;
|
||||
__entry->actual = actual;
|
||||
),
|
||||
|
||||
TP_printk("%s: expected=%d, actual=%d for ctl numid=%d, iface=%s, name='%s', index=%d, device=%d, subdevice=%d, card=%d\n",
|
||||
__entry->expected == __entry->actual ? "success" : "fail",
|
||||
__entry->expected, __entry->actual, __entry->numid,
|
||||
__get_str(iname), __get_str(kname), __entry->index,
|
||||
__entry->device, __entry->subdevice, __entry->card)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_SND_CTL_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE control_trace
|
||||
#include <trace/define_trace.h>
|
||||
@@ -362,6 +362,11 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
|
||||
#ifdef CONFIG_SND_DEBUG
|
||||
card->debugfs_root = debugfs_create_dir(dev_name(&card->card_dev),
|
||||
sound_debugfs_root);
|
||||
#endif
|
||||
#ifdef CONFIG_SND_CTL_DEBUG
|
||||
card->value_buf = kmalloc(sizeof(*card->value_buf), GFP_KERNEL);
|
||||
if (!card->value_buf)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -587,6 +592,9 @@ static int snd_card_do_free(struct snd_card *card)
|
||||
snd_device_free_all(card);
|
||||
if (card->private_free)
|
||||
card->private_free(card);
|
||||
#ifdef CONFIG_SND_CTL_DEBUG
|
||||
kfree(card->value_buf);
|
||||
#endif
|
||||
if (snd_info_card_free(card) < 0) {
|
||||
dev_warn(card->dev, "unable to free card info\n");
|
||||
/* Not fatal error */
|
||||
|
||||
+25
-19
@@ -1227,14 +1227,16 @@ static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substrea
|
||||
snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_state_t state;
|
||||
int ret;
|
||||
while (1) {
|
||||
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
|
||||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
state = snd_pcm_get_state(substream);
|
||||
if (state == SNDRV_PCM_STATE_XRUN ||
|
||||
state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
#ifdef OSS_DEBUG
|
||||
pcm_dbg(substream->pcm,
|
||||
"pcm_oss: write: recovering from %s\n",
|
||||
runtime->state == SNDRV_PCM_STATE_XRUN ?
|
||||
state == SNDRV_PCM_STATE_XRUN ?
|
||||
"XRUN" : "SUSPEND");
|
||||
#endif
|
||||
ret = snd_pcm_oss_prepare(substream);
|
||||
@@ -1249,7 +1251,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
|
||||
break;
|
||||
/* test, if we can't store new data, because the stream */
|
||||
/* has not been started */
|
||||
if (runtime->state == SNDRV_PCM_STATE_PREPARED)
|
||||
if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_PREPARED)
|
||||
return -EAGAIN;
|
||||
}
|
||||
return ret;
|
||||
@@ -1259,20 +1261,22 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_sframes_t delay;
|
||||
snd_pcm_state_t state;
|
||||
int ret;
|
||||
while (1) {
|
||||
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
|
||||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
state = snd_pcm_get_state(substream);
|
||||
if (state == SNDRV_PCM_STATE_XRUN ||
|
||||
state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
#ifdef OSS_DEBUG
|
||||
pcm_dbg(substream->pcm,
|
||||
"pcm_oss: read: recovering from %s\n",
|
||||
runtime->state == SNDRV_PCM_STATE_XRUN ?
|
||||
state == SNDRV_PCM_STATE_XRUN ?
|
||||
"XRUN" : "SUSPEND");
|
||||
#endif
|
||||
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
} else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
|
||||
} else if (state == SNDRV_PCM_STATE_SETUP) {
|
||||
ret = snd_pcm_oss_prepare(substream);
|
||||
if (ret < 0)
|
||||
break;
|
||||
@@ -1285,7 +1289,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
|
||||
frames, in_kernel);
|
||||
mutex_lock(&runtime->oss.params_lock);
|
||||
if (ret == -EPIPE) {
|
||||
if (runtime->state == SNDRV_PCM_STATE_DRAINING) {
|
||||
if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DRAINING) {
|
||||
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
@@ -1301,15 +1305,16 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
|
||||
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
|
||||
snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_state_t state;
|
||||
int ret;
|
||||
while (1) {
|
||||
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
|
||||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
state = snd_pcm_get_state(substream);
|
||||
if (state == SNDRV_PCM_STATE_XRUN ||
|
||||
state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
#ifdef OSS_DEBUG
|
||||
pcm_dbg(substream->pcm,
|
||||
"pcm_oss: writev: recovering from %s\n",
|
||||
runtime->state == SNDRV_PCM_STATE_XRUN ?
|
||||
state == SNDRV_PCM_STATE_XRUN ?
|
||||
"XRUN" : "SUSPEND");
|
||||
#endif
|
||||
ret = snd_pcm_oss_prepare(substream);
|
||||
@@ -1322,7 +1327,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
|
||||
|
||||
/* test, if we can't store new data, because the stream */
|
||||
/* has not been started */
|
||||
if (runtime->state == SNDRV_PCM_STATE_PREPARED)
|
||||
if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_PREPARED)
|
||||
return -EAGAIN;
|
||||
}
|
||||
return ret;
|
||||
@@ -1330,21 +1335,22 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
|
||||
|
||||
snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_state_t state;
|
||||
int ret;
|
||||
while (1) {
|
||||
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
|
||||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
state = snd_pcm_get_state(substream);
|
||||
if (state == SNDRV_PCM_STATE_XRUN ||
|
||||
state == SNDRV_PCM_STATE_SUSPENDED) {
|
||||
#ifdef OSS_DEBUG
|
||||
pcm_dbg(substream->pcm,
|
||||
"pcm_oss: readv: recovering from %s\n",
|
||||
runtime->state == SNDRV_PCM_STATE_XRUN ?
|
||||
state == SNDRV_PCM_STATE_XRUN ?
|
||||
"XRUN" : "SUSPEND");
|
||||
#endif
|
||||
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
|
||||
if (ret < 0)
|
||||
break;
|
||||
} else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
|
||||
} else if (state == SNDRV_PCM_STATE_SETUP) {
|
||||
ret = snd_pcm_oss_prepare(substream);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user