Commit d8292084 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Takashi writes:
  "sound fixes for 4.19-rc5

   here comes a collection of various fixes, mostly for stable-tree
   or regression fixes.

   Two relatively high LOCs are about the (rather simple) conversion of
   uapi integer types in topology API, and a regression fix about HDMI
   hotplug notification on AMD HD-audio.  The rest are all small
   individual fixes like ASoC Intel Skylake race condition, minor
   uninitialized page leak in emu10k1 ioctl, Firewire audio error paths,
   and so on."

* tag 'sound-4.19-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (33 commits)
  ALSA: fireworks: fix memory leak of response buffer at error path
  ALSA: oxfw: fix memory leak of discovered stream formats at error path
  ALSA: oxfw: fix memory leak for model-dependent data at error path
  ALSA: bebob: fix memory leak for M-Audio FW1814 and ProjectMix I/O at error path
  ALSA: hda - Enable runtime PM only for discrete GPU
  ALSA: oxfw: fix memory leak of private data
  ALSA: firewire-tascam: fix memory leak of private data
  ALSA: firewire-digi00x: fix memory leak of private data
  sound: don't call skl_init_chip() to reset intel skl soc
  sound: enable interrupt after dma buffer initialization
  Revert "ASoC: Intel: Skylake: Acquire irq after RIRB allocation"
  ALSA: emu10k1: fix possible info leak to userspace on SNDRV_EMU10K1_IOCTL_INFO
  ASoC: cs4265: fix MMTLR Data switch control
  ASoC: AMD: Ensure reset bit is cleared before configuring
  ALSA: fireface: fix memory leak in ff400_switch_fetching_mode()
  ALSA: bebob: use address returned by kmalloc() instead of kernel stack for streaming DMA mapping
  ASoC: rsnd: don't fallback to PIO mode when -EPROBE_DEFER
  ASoC: rsnd: adg: care clock-frequency size
  ASoC: uniphier: change status to orphan
  ASoC: rsnd: fixup not to call clk_get/set under non-atomic
  ...
parents eb9a29f9 196f4eee
...@@ -13449,9 +13449,8 @@ F: drivers/i2c/busses/i2c-synquacer.c ...@@ -13449,9 +13449,8 @@ F: drivers/i2c/busses/i2c-synquacer.c
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
SOCIONEXT UNIPHIER SOUND DRIVER SOCIONEXT UNIPHIER SOUND DRIVER
M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained S: Orphan
F: sound/soc/uniphier/ F: sound/soc/uniphier/
SOEKRIS NET48XX LED SUPPORT SOEKRIS NET48XX LED SUPPORT
......
...@@ -215,6 +215,8 @@ static void vga_switcheroo_enable(void) ...@@ -215,6 +215,8 @@ static void vga_switcheroo_enable(void)
return; return;
client->id = ret | ID_BIT_AUDIO; client->id = ret | ID_BIT_AUDIO;
if (client->ops->gpu_bound)
client->ops->gpu_bound(client->pdev, ret);
} }
vga_switcheroo_debugfs_init(&vgasr_priv); vga_switcheroo_debugfs_init(&vgasr_priv);
......
...@@ -133,15 +133,18 @@ struct vga_switcheroo_handler { ...@@ -133,15 +133,18 @@ struct vga_switcheroo_handler {
* @can_switch: check if the device is in a position to switch now. * @can_switch: check if the device is in a position to switch now.
* Mandatory. The client should return false if a user space process * Mandatory. The client should return false if a user space process
* has one of its device files open * has one of its device files open
* @gpu_bound: notify the client id to audio client when the GPU is bound.
* *
* Client callbacks. A client can be either a GPU or an audio device on a GPU. * Client callbacks. A client can be either a GPU or an audio device on a GPU.
* The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be * The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be
* set to NULL. For audio clients, the @reprobe member is bogus. * set to NULL. For audio clients, the @reprobe member is bogus.
* OTOH, @gpu_bound is only for audio clients, and not used for GPU clients.
*/ */
struct vga_switcheroo_client_ops { struct vga_switcheroo_client_ops {
void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state); void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
void (*reprobe)(struct pci_dev *dev); void (*reprobe)(struct pci_dev *dev);
bool (*can_switch)(struct pci_dev *dev); bool (*can_switch)(struct pci_dev *dev);
void (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id);
}; };
#if defined(CONFIG_VGA_SWITCHEROO) #if defined(CONFIG_VGA_SWITCHEROO)
......
...@@ -412,6 +412,7 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus); ...@@ -412,6 +412,7 @@ void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus);
void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus); void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
void snd_hdac_bus_update_rirb(struct hdac_bus *bus); void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
......
...@@ -407,6 +407,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, ...@@ -407,6 +407,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
int snd_soc_dapm_new_pcm(struct snd_soc_card *card, int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd,
const struct snd_soc_pcm_stream *params, const struct snd_soc_pcm_stream *params,
unsigned int num_params, unsigned int num_params,
struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *source,
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#ifndef __HDA_TPLG_INTERFACE_H__ #ifndef __HDA_TPLG_INTERFACE_H__
#define __HDA_TPLG_INTERFACE_H__ #define __HDA_TPLG_INTERFACE_H__
#include <linux/types.h>
/* /*
* Default types range from 0~12. type can range from 0 to 0xff * Default types range from 0~12. type can range from 0 to 0xff
* SST types start at higher to avoid any overlapping in future * SST types start at higher to avoid any overlapping in future
...@@ -143,10 +145,10 @@ enum skl_module_param_type { ...@@ -143,10 +145,10 @@ enum skl_module_param_type {
}; };
struct skl_dfw_algo_data { struct skl_dfw_algo_data {
u32 set_params:2; __u32 set_params:2;
u32 rsvd:30; __u32 rsvd:30;
u32 param_id; __u32 param_id;
u32 max; __u32 max;
char params[0]; char params[0];
} __packed; } __packed;
...@@ -163,68 +165,68 @@ enum skl_tuple_type { ...@@ -163,68 +165,68 @@ enum skl_tuple_type {
/* v4 configuration data */ /* v4 configuration data */
struct skl_dfw_v4_module_pin { struct skl_dfw_v4_module_pin {
u16 module_id; __u16 module_id;
u16 instance_id; __u16 instance_id;
} __packed; } __packed;
struct skl_dfw_v4_module_fmt { struct skl_dfw_v4_module_fmt {
u32 channels; __u32 channels;
u32 freq; __u32 freq;
u32 bit_depth; __u32 bit_depth;
u32 valid_bit_depth; __u32 valid_bit_depth;
u32 ch_cfg; __u32 ch_cfg;
u32 interleaving_style; __u32 interleaving_style;
u32 sample_type; __u32 sample_type;
u32 ch_map; __u32 ch_map;
} __packed; } __packed;
struct skl_dfw_v4_module_caps { struct skl_dfw_v4_module_caps {
u32 set_params:2; __u32 set_params:2;
u32 rsvd:30; __u32 rsvd:30;
u32 param_id; __u32 param_id;
u32 caps_size; __u32 caps_size;
u32 caps[HDA_SST_CFG_MAX]; __u32 caps[HDA_SST_CFG_MAX];
} __packed; } __packed;
struct skl_dfw_v4_pipe { struct skl_dfw_v4_pipe {
u8 pipe_id; __u8 pipe_id;
u8 pipe_priority; __u8 pipe_priority;
u16 conn_type:4; __u16 conn_type:4;
u16 rsvd:4; __u16 rsvd:4;
u16 memory_pages:8; __u16 memory_pages:8;
} __packed; } __packed;
struct skl_dfw_v4_module { struct skl_dfw_v4_module {
char uuid[SKL_UUID_STR_SZ]; char uuid[SKL_UUID_STR_SZ];
u16 module_id; __u16 module_id;
u16 instance_id; __u16 instance_id;
u32 max_mcps; __u32 max_mcps;
u32 mem_pages; __u32 mem_pages;
u32 obs; __u32 obs;
u32 ibs; __u32 ibs;
u32 vbus_id; __u32 vbus_id;
u32 max_in_queue:8; __u32 max_in_queue:8;
u32 max_out_queue:8; __u32 max_out_queue:8;
u32 time_slot:8; __u32 time_slot:8;
u32 core_id:4; __u32 core_id:4;
u32 rsvd1:4; __u32 rsvd1:4;
u32 module_type:8; __u32 module_type:8;
u32 conn_type:4; __u32 conn_type:4;
u32 dev_type:4; __u32 dev_type:4;
u32 hw_conn_type:4; __u32 hw_conn_type:4;
u32 rsvd2:12; __u32 rsvd2:12;
u32 params_fixup:8; __u32 params_fixup:8;
u32 converter:8; __u32 converter:8;
u32 input_pin_type:1; __u32 input_pin_type:1;
u32 output_pin_type:1; __u32 output_pin_type:1;
u32 is_dynamic_in_pin:1; __u32 is_dynamic_in_pin:1;
u32 is_dynamic_out_pin:1; __u32 is_dynamic_out_pin:1;
u32 is_loadable:1; __u32 is_loadable:1;
u32 rsvd3:11; __u32 rsvd3:11;
struct skl_dfw_v4_pipe pipe; struct skl_dfw_v4_pipe pipe;
struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE]; struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
......
...@@ -263,6 +263,8 @@ do_registration(struct work_struct *work) ...@@ -263,6 +263,8 @@ do_registration(struct work_struct *work)
error: error:
mutex_unlock(&devices_mutex); mutex_unlock(&devices_mutex);
snd_bebob_stream_destroy_duplex(bebob); snd_bebob_stream_destroy_duplex(bebob);
kfree(bebob->maudio_special_quirk);
bebob->maudio_special_quirk = NULL;
snd_card_free(bebob->card); snd_card_free(bebob->card);
dev_info(&bebob->unit->device, dev_info(&bebob->unit->device,
"Sound card registration failed: %d\n", err); "Sound card registration failed: %d\n", err);
......
...@@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit) ...@@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
struct fw_device *device = fw_parent_device(unit); struct fw_device *device = fw_parent_device(unit);
int err, rcode; int err, rcode;
u64 date; u64 date;
__le32 cues[3] = { __le32 *cues;
cpu_to_le32(MAUDIO_BOOTLOADER_CUE1),
cpu_to_le32(MAUDIO_BOOTLOADER_CUE2),
cpu_to_le32(MAUDIO_BOOTLOADER_CUE3)
};
/* check date of software used to build */ /* check date of software used to build */
err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE, err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
&date, sizeof(u64)); &date, sizeof(u64));
if (err < 0) if (err < 0)
goto end; return err;
/* /*
* firmware version 5058 or later has date later than "20070401", but * firmware version 5058 or later has date later than "20070401", but
* 'date' is not null-terminated. * 'date' is not null-terminated.
...@@ -114,20 +110,28 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit) ...@@ -114,20 +110,28 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
if (date < 0x3230303730343031LL) { if (date < 0x3230303730343031LL) {
dev_err(&unit->device, dev_err(&unit->device,
"Use firmware version 5058 or later\n"); "Use firmware version 5058 or later\n");
err = -ENOSYS; return -ENXIO;
goto end;
} }
cues = kmalloc_array(3, sizeof(*cues), GFP_KERNEL);
if (!cues)
return -ENOMEM;
cues[0] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE1);
cues[1] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE2);
cues[2] = cpu_to_le32(MAUDIO_BOOTLOADER_CUE3);
rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST, rcode = fw_run_transaction(device->card, TCODE_WRITE_BLOCK_REQUEST,
device->node_id, device->generation, device->node_id, device->generation,
device->max_speed, BEBOB_ADDR_REG_REQ, device->max_speed, BEBOB_ADDR_REG_REQ,
cues, sizeof(cues)); cues, 3 * sizeof(*cues));
kfree(cues);
if (rcode != RCODE_COMPLETE) { if (rcode != RCODE_COMPLETE) {
dev_err(&unit->device, dev_err(&unit->device,
"Failed to send a cue to load firmware\n"); "Failed to send a cue to load firmware\n");
err = -EIO; err = -EIO;
} }
end:
return err; return err;
} }
...@@ -290,10 +294,6 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814) ...@@ -290,10 +294,6 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814)
bebob->midi_output_ports = 2; bebob->midi_output_ports = 2;
} }
end: end:
if (err < 0) {
kfree(params);
bebob->maudio_special_quirk = NULL;
}
mutex_unlock(&bebob->mutex); mutex_unlock(&bebob->mutex);
return err; return err;
} }
......
...@@ -49,6 +49,7 @@ static void dg00x_free(struct snd_dg00x *dg00x) ...@@ -49,6 +49,7 @@ static void dg00x_free(struct snd_dg00x *dg00x)
fw_unit_put(dg00x->unit); fw_unit_put(dg00x->unit);
mutex_destroy(&dg00x->mutex); mutex_destroy(&dg00x->mutex);
kfree(dg00x);
} }
static void dg00x_card_free(struct snd_card *card) static void dg00x_card_free(struct snd_card *card)
......
...@@ -146,6 +146,7 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable) ...@@ -146,6 +146,7 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable)
{ {
__le32 *reg; __le32 *reg;
int i; int i;
int err;
reg = kcalloc(18, sizeof(__le32), GFP_KERNEL); reg = kcalloc(18, sizeof(__le32), GFP_KERNEL);
if (reg == NULL) if (reg == NULL)
...@@ -163,9 +164,11 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable) ...@@ -163,9 +164,11 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable)
reg[i] = cpu_to_le32(0x00000001); reg[i] = cpu_to_le32(0x00000001);
} }
return snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST, err = snd_fw_transaction(ff->unit, TCODE_WRITE_BLOCK_REQUEST,
FF400_FETCH_PCM_FRAMES, reg, FF400_FETCH_PCM_FRAMES, reg,
sizeof(__le32) * 18, 0); sizeof(__le32) * 18, 0);
kfree(reg);
return err;
} }
static void ff400_dump_sync_status(struct snd_ff *ff, static void ff400_dump_sync_status(struct snd_ff *ff,
......
...@@ -301,6 +301,8 @@ do_registration(struct work_struct *work) ...@@ -301,6 +301,8 @@ do_registration(struct work_struct *work)
snd_efw_transaction_remove_instance(efw); snd_efw_transaction_remove_instance(efw);
snd_efw_stream_destroy_duplex(efw); snd_efw_stream_destroy_duplex(efw);
snd_card_free(efw->card); snd_card_free(efw->card);
kfree(efw->resp_buf);
efw->resp_buf = NULL;
dev_info(&efw->unit->device, dev_info(&efw->unit->device,
"Sound card registration failed: %d\n", err); "Sound card registration failed: %d\n", err);
} }
......
...@@ -130,6 +130,7 @@ static void oxfw_free(struct snd_oxfw *oxfw) ...@@ -130,6 +130,7 @@ static void oxfw_free(struct snd_oxfw *oxfw)
kfree(oxfw->spec); kfree(oxfw->spec);
mutex_destroy(&oxfw->mutex); mutex_destroy(&oxfw->mutex);
kfree(oxfw);
} }
/* /*
...@@ -207,6 +208,7 @@ static int detect_quirks(struct snd_oxfw *oxfw) ...@@ -207,6 +208,7 @@ static int detect_quirks(struct snd_oxfw *oxfw)
static void do_registration(struct work_struct *work) static void do_registration(struct work_struct *work)
{ {
struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work);
int i;
int err; int err;
if (oxfw->registered) if (oxfw->registered)
...@@ -269,7 +271,15 @@ static void do_registration(struct work_struct *work) ...@@ -269,7 +271,15 @@ static void do_registration(struct work_struct *work)
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream); snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
if (oxfw->has_output) if (oxfw->has_output)
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream); snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->tx_stream);
for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; ++i) {
kfree(oxfw->tx_stream_formats[i]);
oxfw->tx_stream_formats[i] = NULL;
kfree(oxfw->rx_stream_formats[i]);
oxfw->rx_stream_formats[i] = NULL;
}
snd_card_free(oxfw->card); snd_card_free(oxfw->card);
kfree(oxfw->spec);
oxfw->spec = NULL;
dev_info(&oxfw->unit->device, dev_info(&oxfw->unit->device,
"Sound card registration failed: %d\n", err); "Sound card registration failed: %d\n", err);
} }
......
...@@ -93,6 +93,7 @@ static void tscm_free(struct snd_tscm *tscm) ...@@ -93,6 +93,7 @@ static void tscm_free(struct snd_tscm *tscm)
fw_unit_put(tscm->unit); fw_unit_put(tscm->unit);
mutex_destroy(&tscm->mutex); mutex_destroy(&tscm->mutex);
kfree(tscm);
} }
static void tscm_card_free(struct snd_card *card) static void tscm_card_free(struct snd_card *card)
......
...@@ -40,6 +40,8 @@ static void azx_clear_corbrp(struct hdac_bus *bus) ...@@ -40,6 +40,8 @@ static void azx_clear_corbrp(struct hdac_bus *bus)
*/ */
void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus) void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
{ {
WARN_ON_ONCE(!bus->rb.area);
spin_lock_irq(&bus->reg_lock); spin_lock_irq(&bus->reg_lock);
/* CORB set up */ /* CORB set up */
bus->corb.addr = bus->rb.addr; bus->corb.addr = bus->rb.addr;
...@@ -383,7 +385,7 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus) ...@@ -383,7 +385,7 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset); EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset);
/* reset codec link */ /* reset codec link */
static int azx_reset(struct hdac_bus *bus, bool full_reset) int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
{ {
if (!full_reset) if (!full_reset)
goto skip_reset; goto skip_reset;
...@@ -408,7 +410,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset) ...@@ -408,7 +410,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset)
skip_reset: skip_reset:
/* check to see if controller is ready */ /* check to see if controller is ready */
if (!snd_hdac_chip_readb(bus, GCTL)) { if (!snd_hdac_chip_readb(bus, GCTL)) {
dev_dbg(bus->dev, "azx_reset: controller not ready!\n"); dev_dbg(bus->dev, "controller not ready!\n");
return -EBUSY; return -EBUSY;
} }
...@@ -423,6 +425,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset) ...@@ -423,6 +425,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_hdac_bus_reset_link);
/* enable interrupts */ /* enable interrupts */
static void azx_int_enable(struct hdac_bus *bus) static void azx_int_enable(struct hdac_bus *bus)
...@@ -477,15 +480,17 @@ bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset) ...@@ -477,15 +480,17 @@ bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
return false; return false;
/* reset controller */ /* reset controller */
azx_reset(bus, full_reset); snd_hdac_bus_reset_link(bus, full_reset);
/* initialize interrupts */ /* clear interrupts */
azx_int_clear(bus); azx_int_clear(bus);
azx_int_enable(bus);
/* initialize the codec command I/O */ /* initialize the codec command I/O */
snd_hdac_bus_init_cmd_io(bus); snd_hdac_bus_init_cmd_io(bus);
/* enable interrupts after CORB/RIRB buffers are initialized above */
azx_int_enable(bus);
/* program the position buffer */ /* program the position buffer */
if (bus->use_posbuf && bus->posbuf.addr) { if (bus->use_posbuf && bus->posbuf.addr) {
snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr); snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr);
......
...@@ -2540,7 +2540,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un ...@@ -2540,7 +2540,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
emu->support_tlv = 1; emu->support_tlv = 1;
return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp); return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
case SNDRV_EMU10K1_IOCTL_INFO: case SNDRV_EMU10K1_IOCTL_INFO:
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
snd_emu10k1_fx8010_info(emu, info); snd_emu10k1_fx8010_info(emu, info);
......
...@@ -365,8 +365,10 @@ enum { ...@@ -365,8 +365,10 @@ enum {
*/ */
#ifdef SUPPORT_VGA_SWITCHEROO #ifdef SUPPORT_VGA_SWITCHEROO
#define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo) #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo)
#define needs_eld_notify_link(chip) ((chip)->need_eld_notify_link)
#else #else
#define use_vga_switcheroo(chip) 0 #define use_vga_switcheroo(chip) 0
#define needs_eld_notify_link(chip) false
#endif #endif
#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \ #define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
...@@ -453,6 +455,7 @@ static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, ...@@ -453,6 +455,7 @@ static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
#endif #endif
static int azx_acquire_irq(struct azx *chip, int do_disconnect); static int azx_acquire_irq(struct azx *chip, int do_disconnect);
static void set_default_power_save(struct azx *chip);
/* /*
* initialize the PCI registers * initialize the PCI registers
...@@ -1201,6 +1204,10 @@ static int azx_runtime_idle(struct device *dev) ...@@ -1201,6 +1204,10 @@ static int azx_runtime_idle(struct device *dev)
azx_bus(chip)->codec_powered || !chip->running) azx_bus(chip)->codec_powered || !chip->running)
return -EBUSY; return -EBUSY;
/* ELD notification gets broken when HD-audio bus is off */
if (needs_eld_notify_link(hda))
return -EBUSY;
return 0; return 0;
} }
...@@ -1298,6 +1305,36 @@ static bool azx_vs_can_switch(struct pci_dev *pci) ...@@ -1298,6 +1305,36 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
return true; return true;
} }
/*
* The discrete GPU cannot power down unless the HDA controller runtime
* suspends, so activate runtime PM on codecs even if power_save == 0.
*/
static void setup_vga_switcheroo_runtime_pm(struct azx *chip)
{
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct hda_codec *codec;
if (hda->use_vga_switcheroo && !hda->need_eld_notify_link) {
list_for_each_codec(codec, &chip->bus)
codec->auto_runtime_pm = 1;
/* reset the power save setup */
if (chip->running)
set_default_power_save(chip);
}
}
static void azx_vs_gpu_bound(struct pci_dev *pci,
enum vga_switcheroo_client_id client_id)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
if (client_id == VGA_SWITCHEROO_DIS)
hda->need_eld_notify_link = 0;
setup_vga_switcheroo_runtime_pm(chip);
}
static void init_vga_switcheroo(struct azx *chip) static void init_vga_switcheroo(struct azx *chip)
{ {
struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
...@@ -1306,6 +1343,7 @@ static void init_vga_switcheroo(struct azx *chip) ...@@ -1306,6 +1343,7 @@ static void init_vga_switcheroo(struct azx *chip)
dev_info(chip->card->dev, dev_info(chip->card->dev,
"Handle vga_switcheroo audio client\n"); "Handle vga_switcheroo audio client\n");
hda->use_vga_switcheroo = 1; hda->use_vga_switcheroo = 1;
hda->need_eld_notify_link = 1; /* cleared in gpu_bound op */
chip->driver_caps |= AZX_DCAPS_PM_RUNTIME; chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
pci_dev_put(p); pci_dev_put(p);
} }
...@@ -1314,6 +1352,7 @@ static void init_vga_switcheroo(struct azx *chip) ...@@ -1314,6 +1352,7 @@ static void init_vga_switcheroo(struct azx *chip)
static const struct vga_switcheroo_client_ops azx_vs_ops = { static const struct vga_switcheroo_client_ops azx_vs_ops = {
.set_gpu_state = azx_vs_set_state, .set_gpu_state = azx_vs_set_state,
.can_switch = azx_vs_can_switch, .can_switch = azx_vs_can_switch,
.gpu_bound = azx_vs_gpu_bound,
}; };
static int register_vga_switcheroo(struct azx *chip) static int register_vga_switcheroo(struct azx *chip)
...@@ -1339,6 +1378,7 @@ static int register_vga_switcheroo(struct azx *chip) ...@@ -1339,6 +1378,7 @@ static int register_vga_switcheroo(struct azx *chip)
#define init_vga_switcheroo(chip) /* NOP */ #define init_vga_switcheroo(chip) /* NOP */
#define register_vga_switcheroo(chip) 0 #define register_vga_switcheroo(chip) 0
#define check_hdmi_disabled(pci) false #define check_hdmi_disabled(pci) false
#define setup_vga_switcheroo_runtime_pm(chip) /* NOP */
#endif /* SUPPORT_VGA_SWITCHER */ #endif /* SUPPORT_VGA_SWITCHER */
/* /*
...@@ -1352,6 +1392,7 @@ static int azx_free(struct azx *chip) ...@@ -1352,6 +1392,7 @@ static int azx_free(struct azx *chip)
if (azx_has_pm_runtime(chip) && chip->running) if (azx_has_pm_runtime(chip) && chip->running)
pm_runtime_get_noresume(&pci->dev); pm_runtime_get_noresume(&pci->dev);
chip->running = 0;
azx_del_card_list(chip); azx_del_card_list(chip);
...@@ -2230,6 +2271,25 @@ static struct snd_pci_quirk power_save_blacklist[] = { ...@@ -2230,6 +2271,25 @@ static struct snd_pci_quirk power_save_blacklist[] = {
}; };
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
static void set_default_power_save(struct azx *chip)
{
int val = power_save;
#ifdef CONFIG_PM
if (pm_blacklist) {
const struct snd_pci_quirk *q;
q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist);
if (q && val) {
dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n",
q->subvendor, q->subdevice);
val = 0;
}
}
#endif /* CONFIG_PM */
snd_hda_set_power_save(&chip->bus, val * 1000);
}
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = { static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
[AZX_DRIVER_NVIDIA] = 8, [AZX_DRIVER_NVIDIA] = 8,
...@@ -2241,9 +2301,7 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2241,9 +2301,7 @@ static int azx_probe_continue(struct azx *chip)
struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
struct hdac_bus *bus = azx_bus(chip); struct hdac_bus *bus = azx_bus(chip);
struct pci_dev *pci = chip->pci; struct pci_dev *pci = chip->pci;
struct hda_codec *codec;
int dev = chip->dev_index; int dev = chip->dev_index;
int val;
int err; int err;
hda->probe_continued = 1; hda->probe_continued = 1;
...@@ -2322,31 +2380,13 @@ static int azx_probe_continue(struct azx *chip) ...@@ -2322,31 +2380,13 @@ static int azx_probe_continue(struct azx *chip)
if (err < 0) if (err < 0)
goto out_free; goto out_free;
setup_vga_switcheroo_runtime_pm(chip);
chip->running = 1; chip->running = 1;
azx_add_card_list(chip); azx_add_card_list(chip);
val = power_save; set_default_power_save(chip);
#ifdef CONFIG_PM
if (pm_blacklist) {
const struct snd_pci_quirk *q;
q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist);
if (q && val) {
dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n",
q->subvendor, q->subdevice);
val = 0;
}
}
#endif /* CONFIG_PM */
/*
* The discrete GPU cannot power down unless the HDA controller runtime
* suspends, so activate runtime PM on codecs even if power_save == 0.
*/
if (use_vga_switcheroo(hda))
list_for_each_codec(codec, &chip->bus)
codec->auto_runtime_pm = 1;
snd_hda_set_power_save(&chip->bus, val * 1000);
if (azx_has_pm_runtime(chip)) if (azx_has_pm_runtime(chip))
pm_runtime_put_autosuspend(&pci->dev); pm_runtime_put_autosuspend(&pci->dev);
......
...@@ -37,6 +37,7 @@ struct hda_intel { ...@@ -37,6 +37,7 @@ struct hda_intel {
/* vga_switcheroo setup */ /* vga_switcheroo setup */
unsigned int use_vga_switcheroo:1; unsigned int use_vga_switcheroo:1;
unsigned int need_eld_notify_link:1;
unsigned int vga_switcheroo_registered:1; unsigned int vga_switcheroo_registered:1;
unsigned int init_failed:1; /* delayed init failed */ unsigned int init_failed:1; /* delayed init failed */
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio, ...@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio,
acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data); acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
} }
static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
{
u32 dma_ctrl;
int ret;
/* clear the reset bit */
dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
/* check the reset bit before programming configuration registers */
ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
dma_ctrl,
!(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
100, ACP_DMA_RESET_TIME);
if (ret < 0)
pr_err("Failed to clear reset of channel : %d\n", ch_num);
}
/* /*
* Initialize the DMA descriptor information for transfer between * Initialize the DMA descriptor information for transfer between
* system memory <-> ACP SRAM * system memory <-> ACP SRAM
...@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio, ...@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem *acp_mmio,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
&dmadscr[i]); &dmadscr[i]);
} }
pre_config_reset(acp_mmio, ch);
config_acp_dma_channel(acp_mmio, ch, config_acp_dma_channel(acp_mmio, ch,
dma_dscr_idx - 1, dma_dscr_idx - 1,
NUM_DSCRS_PER_CHANNEL, NUM_DSCRS_PER_CHANNEL,
...@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size, ...@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx, config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
&dmadscr[i]); &dmadscr[i]);
} }
pre_config_reset(acp_mmio, ch);
/* Configure the DMA channel with the above descriptore */ /* Configure the DMA channel with the above descriptore */
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1, config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
NUM_DSCRS_PER_CHANNEL, NUM_DSCRS_PER_CHANNEL,
......
...@@ -157,8 +157,8 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = { ...@@ -157,8 +157,8 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = {
SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2, SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
3, 1, 0), 3, 1, 0),
SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum), SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
SOC_SINGLE("MMTLR Data Switch", 0, SOC_SINGLE("MMTLR Data Switch", CS4265_SPDIF_CTL2,
1, 1, 0), 0, 1, 0),
SOC_ENUM("Mono Channel Select", spdif_mono_select_enum), SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24), SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
}; };
......
...@@ -520,6 +520,7 @@ static bool max98373_volatile_reg(struct device *dev, unsigned int reg) ...@@ -520,6 +520,7 @@ static bool max98373_volatile_reg(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3:
case MAX98373_R203E_AMP_PATH_GAIN:
case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK:
case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK:
case MAX98373_R20B6_BDE_CUR_STATE_READBACK: case MAX98373_R20B6_BDE_CUR_STATE_READBACK:
...@@ -729,6 +730,7 @@ static int max98373_probe(struct snd_soc_component *component) ...@@ -729,6 +730,7 @@ static int max98373_probe(struct snd_soc_component *component)
/* Software Reset */ /* Software Reset */
regmap_write(max98373->regmap, regmap_write(max98373->regmap,
MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET); MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
usleep_range(10000, 11000);
/* IV default slot configuration */ /* IV default slot configuration */
regmap_write(max98373->regmap, regmap_write(max98373->regmap,
...@@ -817,6 +819,7 @@ static int max98373_resume(struct device *dev) ...@@ -817,6 +819,7 @@ static int max98373_resume(struct device *dev)
regmap_write(max98373->regmap, regmap_write(max98373->regmap,
MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET); MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
usleep_range(10000, 11000);
regcache_cache_only(max98373->regmap, false); regcache_cache_only(max98373->regmap, false);
regcache_sync(max98373->regmap); regcache_sync(max98373->regmap);
return 0; return 0;
......
...@@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = { ...@@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = {
{RT5514_ANA_CTRL_LDO10, 0x00028604}, {RT5514_ANA_CTRL_LDO10, 0x00028604},
{RT5514_ANA_CTRL_ADCFED, 0x00000800}, {RT5514_ANA_CTRL_ADCFED, 0x00000800},
{RT5514_ASRC_IN_CTRL1, 0x00000003}, {RT5514_ASRC_IN_CTRL1, 0x00000003},
{RT5514_DOWNFILTER0_CTRL3, 0x10000352}, {RT5514_DOWNFILTER0_CTRL3, 0x10000342},
{RT5514_DOWNFILTER1_CTRL3, 0x10000352}, {RT5514_DOWNFILTER1_CTRL3, 0x10000342},
}; };
static const struct reg_default rt5514_reg[] = { static const struct reg_default rt5514_reg[] = {
...@@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = { ...@@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = {
{RT5514_ASRC_IN_CTRL1, 0x00000003}, {RT5514_ASRC_IN_CTRL1, 0x00000003},
{RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f},
{RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f},
{RT5514_DOWNFILTER0_CTRL3, 0x10000352}, {RT5514_DOWNFILTER0_CTRL3, 0x10000342},
{RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f},
{RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f},
{RT5514_DOWNFILTER1_CTRL3, 0x10000352}, {RT5514_DOWNFILTER1_CTRL3, 0x10000342},
{RT5514_ANA_CTRL_LDO10, 0x00028604}, {RT5514_ANA_CTRL_LDO10, 0x00028604},
{RT5514_ANA_CTRL_LDO18_16, 0x02000345}, {RT5514_ANA_CTRL_LDO18_16, 0x02000345},
{RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, {RT5514_ANA_CTRL_ADC12, 0x0000a2a8},
......
...@@ -750,8 +750,8 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg) ...@@ -750,8 +750,8 @@ static bool rt5682_readable_register(struct device *dev, unsigned int reg)
} }
static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2250, 150, 0); static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -2250, 150, 0);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
...@@ -1114,7 +1114,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = { ...@@ -1114,7 +1114,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = {
/* DAC Digital Volume */ /* DAC Digital Volume */
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL, SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5682_DAC1_DIG_VOL,
RT5682_L_VOL_SFT, RT5682_R_VOL_SFT, 175, 0, dac_vol_tlv), RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 86, 0, dac_vol_tlv),
/* IN Boost Volume */ /* IN Boost Volume */
SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL, SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL,
...@@ -1124,7 +1124,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = { ...@@ -1124,7 +1124,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = {
SOC_DOUBLE("STO1 ADC Capture Switch", RT5682_STO1_ADC_DIG_VOL, SOC_DOUBLE("STO1 ADC Capture Switch", RT5682_STO1_ADC_DIG_VOL,
RT5682_L_MUTE_SFT, RT5682_R_MUTE_SFT, 1, 1), RT5682_L_MUTE_SFT, RT5682_R_MUTE_SFT, 1, 1),
SOC_DOUBLE_TLV("STO1 ADC Capture Volume", RT5682_STO1_ADC_DIG_VOL, SOC_DOUBLE_TLV("STO1 ADC Capture Volume", RT5682_STO1_ADC_DIG_VOL,
RT5682_L_VOL_SFT, RT5682_R_VOL_SFT, 127, 0, adc_vol_tlv), RT5682_L_VOL_SFT + 1, RT5682_R_VOL_SFT + 1, 63, 0, adc_vol_tlv),
/* ADC Boost Volume Control */ /* ADC Boost Volume Control */
SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5682_STO1_ADC_BOOST, SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5682_STO1_ADC_BOOST,
......
...@@ -117,8 +117,7 @@ static int sigmadsp_ctrl_write(struct sigmadsp *sigmadsp, ...@@ -117,8 +117,7 @@ static int sigmadsp_ctrl_write(struct sigmadsp *sigmadsp,
struct sigmadsp_control *ctrl, void *data) struct sigmadsp_control *ctrl, void *data)
{ {
/* safeload loads up to 20 bytes in a atomic operation */ /* safeload loads up to 20 bytes in a atomic operation */
if (ctrl->num_bytes > 4 && ctrl->num_bytes <= 20 && sigmadsp->ops && if (ctrl->num_bytes <= 20 && sigmadsp->ops && sigmadsp->ops->safeload)
sigmadsp->ops->safeload)
return sigmadsp->ops->safeload(sigmadsp, ctrl->addr, data, return sigmadsp->ops->safeload(sigmadsp, ctrl->addr, data,
ctrl->num_bytes); ctrl->num_bytes);
else else
......
...@@ -424,8 +424,10 @@ static void tas6424_fault_check_work(struct work_struct *work) ...@@ -424,8 +424,10 @@ static void tas6424_fault_check_work(struct work_struct *work)
TAS6424_FAULT_PVDD_UV | TAS6424_FAULT_PVDD_UV |
TAS6424_FAULT_VBAT_UV; TAS6424_FAULT_VBAT_UV;
if (reg) if (!reg) {
tas6424->last_fault1 = reg;
goto check_global_fault2_reg; goto check_global_fault2_reg;
}
/* /*
* Only flag errors once for a given occurrence. This is needed as * Only flag errors once for a given occurrence. This is needed as
...@@ -461,8 +463,10 @@ static void tas6424_fault_check_work(struct work_struct *work) ...@@ -461,8 +463,10 @@ static void tas6424_fault_check_work(struct work_struct *work)
TAS6424_FAULT_OTSD_CH3 | TAS6424_FAULT_OTSD_CH3 |
TAS6424_FAULT_OTSD_CH4; TAS6424_FAULT_OTSD_CH4;
if (!reg) if (!reg) {
tas6424->last_fault2 = reg;
goto check_warn_reg; goto check_warn_reg;
}
if ((reg & TAS6424_FAULT_OTSD) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD)) if ((reg & TAS6424_FAULT_OTSD) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD))
dev_crit(dev, "experienced a global overtemp shutdown\n"); dev_crit(dev, "experienced a global overtemp shutdown\n");
...@@ -497,8 +501,10 @@ static void tas6424_fault_check_work(struct work_struct *work) ...@@ -497,8 +501,10 @@ static void tas6424_fault_check_work(struct work_struct *work)
TAS6424_WARN_VDD_OTW_CH3 | TAS6424_WARN_VDD_OTW_CH3 |
TAS6424_WARN_VDD_OTW_CH4; TAS6424_WARN_VDD_OTW_CH4;
if (!reg) if (!reg) {
tas6424->last_warn = reg;
goto out; goto out;
}
if ((reg & TAS6424_WARN_VDD_UV) && !(tas6424->last_warn & TAS6424_WARN_VDD_UV)) if ((reg & TAS6424_WARN_VDD_UV) && !(tas6424->last_warn & TAS6424_WARN_VDD_UV))
dev_warn(dev, "experienced a VDD under voltage condition\n"); dev_warn(dev, "experienced a VDD under voltage condition\n");
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/acpi.h>
#include "wm8804.h" #include "wm8804.h"
...@@ -40,17 +41,29 @@ static const struct i2c_device_id wm8804_i2c_id[] = { ...@@ -40,17 +41,29 @@ static const struct i2c_device_id wm8804_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id); MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
#if defined(CONFIG_OF)
static const struct of_device_id wm8804_of_match[] = { static const struct of_device_id wm8804_of_match[] = {
{ .compatible = "wlf,wm8804", }, { .compatible = "wlf,wm8804", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, wm8804_of_match); MODULE_DEVICE_TABLE(of, wm8804_of_match);
#endif
#ifdef CONFIG_ACPI
static const struct acpi_device_id wm8804_acpi_match[] = {
{ "1AEC8804", 0 }, /* Wolfson PCI ID + part ID */
{ "10138804", 0 }, /* Cirrus Logic PCI ID + part ID */
{ },
};
MODULE_DEVICE_TABLE(acpi, wm8804_acpi_match);
#endif
static struct i2c_driver wm8804_i2c_driver = { static struct i2c_driver wm8804_i2c_driver = {
.driver = { .driver = {
.name = "wm8804", .name = "wm8804",
.pm = &wm8804_pm, .pm = &wm8804_pm,
.of_match_table = wm8804_of_match, .of_match_table = of_match_ptr(wm8804_of_match),
.acpi_match_table = ACPI_PTR(wm8804_acpi_match),
}, },
.probe = wm8804_i2c_probe, .probe = wm8804_i2c_probe,
.remove = wm8804_i2c_remove, .remove = wm8804_i2c_remove,
......
...@@ -719,7 +719,7 @@ static int wm9712_probe(struct platform_device *pdev) ...@@ -719,7 +719,7 @@ static int wm9712_probe(struct platform_device *pdev)
static struct platform_driver wm9712_component_driver = { static struct platform_driver wm9712_component_driver = {
.driver = { .driver = {
.name = "wm9712-component", .name = "wm9712-codec",
}, },
.probe = wm9712_probe, .probe = wm9712_probe,
......
...@@ -575,6 +575,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -575,6 +575,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MONO_SPEAKER | BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ /* Linx Linx7 tablet */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_MONO_SPEAKER |
BYT_RT5640_JD_NOT_INV |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ /* MSI S100 tablet */ { /* MSI S100 tablet */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
...@@ -602,6 +613,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -602,6 +613,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ /* Onda v975w */
.matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
/* The above are too generic, also match BIOS info */
DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"),
DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"),
},
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
BYT_RT5640_JD_SRC_JD2_IN4N |
BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_0P75 |
BYT_RT5640_DIFF_MIC |
BYT_RT5640_MCLK_EN),
},
{ /* Pipo W4 */ { /* Pipo W4 */
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
......
...@@ -834,7 +834,7 @@ static int skl_first_init(struct hdac_bus *bus) ...@@ -834,7 +834,7 @@ static int skl_first_init(struct hdac_bus *bus)
return -ENXIO; return -ENXIO;
} }
skl_init_chip(bus, true); snd_hdac_bus_reset_link(bus, true);
snd_hdac_bus_parse_capabilities(bus); snd_hdac_bus_parse_capabilities(bus);
......
...@@ -960,8 +960,10 @@ static int msm_routing_probe(struct snd_soc_component *c) ...@@ -960,8 +960,10 @@ static int msm_routing_probe(struct snd_soc_component *c)
{ {
int i; int i;
for (i = 0; i < MAX_SESSIONS; i++) for (i = 0; i < MAX_SESSIONS; i++) {
routing_data->sessions[i].port_id = -1; routing_data->sessions[i].port_id = -1;
routing_data->sessions[i].fedai_id = -1;
}
return 0; return 0;
} }
......
...@@ -462,6 +462,11 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, ...@@ -462,6 +462,11 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
goto rsnd_adg_get_clkout_end; goto rsnd_adg_get_clkout_end;
req_size = prop->length / sizeof(u32); req_size = prop->length / sizeof(u32);
if (req_size > REQ_SIZE) {
dev_err(dev,
"too many clock-frequency, use top %d\n", REQ_SIZE);
req_size = REQ_SIZE;
}
of_property_read_u32_array(np, "clock-frequency", req_rate, req_size); of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);
req_48kHz_rate = 0; req_48kHz_rate = 0;
......
...@@ -478,7 +478,7 @@ static int rsnd_status_update(u32 *status, ...@@ -478,7 +478,7 @@ static int rsnd_status_update(u32 *status,
(func_call && (mod)->ops->fn) ? #fn : ""); \ (func_call && (mod)->ops->fn) ? #fn : ""); \
if (func_call && (mod)->ops->fn) \ if (func_call && (mod)->ops->fn) \
tmp = (mod)->ops->fn(mod, io, param); \ tmp = (mod)->ops->fn(mod, io, param); \
if (tmp) \ if (tmp && (tmp != -EPROBE_DEFER)) \
dev_err(dev, "%s[%d] : %s error %d\n", \ dev_err(dev, "%s[%d] : %s error %d\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), \ rsnd_mod_name(mod), rsnd_mod_id(mod), \
#fn, tmp); \ #fn, tmp); \
...@@ -958,12 +958,23 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, ...@@ -958,12 +958,23 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
rsnd_dai_stream_quit(io); rsnd_dai_stream_quit(io);
} }
static int rsnd_soc_dai_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
return rsnd_dai_call(prepare, io, priv);
}
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
.startup = rsnd_soc_dai_startup, .startup = rsnd_soc_dai_startup,
.shutdown = rsnd_soc_dai_shutdown, .shutdown = rsnd_soc_dai_shutdown,
.trigger = rsnd_soc_dai_trigger, .trigger = rsnd_soc_dai_trigger,
.set_fmt = rsnd_soc_dai_set_fmt, .set_fmt = rsnd_soc_dai_set_fmt,
.set_tdm_slot = rsnd_soc_set_dai_tdm_slot, .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
.prepare = rsnd_soc_dai_prepare,
}; };
void rsnd_parse_connect_common(struct rsnd_dai *rdai, void rsnd_parse_connect_common(struct rsnd_dai *rdai,
...@@ -1550,6 +1561,14 @@ static int rsnd_probe(struct platform_device *pdev) ...@@ -1550,6 +1561,14 @@ static int rsnd_probe(struct platform_device *pdev)
rsnd_dai_call(remove, &rdai->capture, priv); rsnd_dai_call(remove, &rdai->capture, priv);
} }
/*
* adg is very special mod which can't use rsnd_dai_call(remove),
* and it registers ADG clock on probe.
* It should be unregister if probe failed.
* Mainly it is assuming -EPROBE_DEFER case
*/
rsnd_adg_remove(priv);
return ret; return ret;
} }
......
...@@ -241,6 +241,10 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io, ...@@ -241,6 +241,10 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
/* try to get DMAEngine channel */ /* try to get DMAEngine channel */
chan = rsnd_dmaen_request_channel(io, mod_from, mod_to); chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
if (IS_ERR_OR_NULL(chan)) { if (IS_ERR_OR_NULL(chan)) {
/* Let's follow when -EPROBE_DEFER case */
if (PTR_ERR(chan) == -EPROBE_DEFER)
return PTR_ERR(chan);
/* /*
* DMA failed. try to PIO mode * DMA failed. try to PIO mode
* see * see
......
...@@ -280,6 +280,9 @@ struct rsnd_mod_ops { ...@@ -280,6 +280,9 @@ struct rsnd_mod_ops {
int (*nolock_stop)(struct rsnd_mod *mod, int (*nolock_stop)(struct rsnd_mod *mod,
struct rsnd_dai_stream *io, struct rsnd_dai_stream *io,
struct rsnd_priv *priv); struct rsnd_priv *priv);
int (*prepare)(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv);
}; };
struct rsnd_dai_stream; struct rsnd_dai_stream;
...@@ -309,6 +312,7 @@ struct rsnd_mod { ...@@ -309,6 +312,7 @@ struct rsnd_mod {
* H 0: fallback * H 0: fallback
* H 0: hw_params * H 0: hw_params
* H 0: pointer * H 0: pointer
* H 0: prepare
*/ */
#define __rsnd_mod_shift_nolock_start 0 #define __rsnd_mod_shift_nolock_start 0
#define __rsnd_mod_shift_nolock_stop 0 #define __rsnd_mod_shift_nolock_stop 0
...@@ -323,6 +327,7 @@ struct rsnd_mod { ...@@ -323,6 +327,7 @@ struct rsnd_mod {
#define __rsnd_mod_shift_fallback 28 /* always called */ #define __rsnd_mod_shift_fallback 28 /* always called */
#define __rsnd_mod_shift_hw_params 28 /* always called */ #define __rsnd_mod_shift_hw_params 28 /* always called */
#define __rsnd_mod_shift_pointer 28 /* always called */ #define __rsnd_mod_shift_pointer 28 /* always called */
#define __rsnd_mod_shift_prepare 28 /* always called */
#define __rsnd_mod_add_probe 0 #define __rsnd_mod_add_probe 0
#define __rsnd_mod_add_remove 0 #define __rsnd_mod_add_remove 0
...@@ -337,6 +342,7 @@ struct rsnd_mod { ...@@ -337,6 +342,7 @@ struct rsnd_mod {
#define __rsnd_mod_add_fallback 0 #define __rsnd_mod_add_fallback 0
#define __rsnd_mod_add_hw_params 0 #define __rsnd_mod_add_hw_params 0
#define __rsnd_mod_add_pointer 0 #define __rsnd_mod_add_pointer 0
#define __rsnd_mod_add_prepare 0
#define __rsnd_mod_call_probe 0 #define __rsnd_mod_call_probe 0
#define __rsnd_mod_call_remove 0 #define __rsnd_mod_call_remove 0
...@@ -351,6 +357,7 @@ struct rsnd_mod { ...@@ -351,6 +357,7 @@ struct rsnd_mod {
#define __rsnd_mod_call_pointer 0 #define __rsnd_mod_call_pointer 0
#define __rsnd_mod_call_nolock_start 0 #define __rsnd_mod_call_nolock_start 0
#define __rsnd_mod_call_nolock_stop 1 #define __rsnd_mod_call_nolock_stop 1
#define __rsnd_mod_call_prepare 0
#define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_to_priv(mod) ((mod)->priv)
#define rsnd_mod_name(mod) ((mod)->ops->name) #define rsnd_mod_name(mod) ((mod)->ops->name)
......
...@@ -283,7 +283,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, ...@@ -283,7 +283,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
if (rsnd_ssi_is_multi_slave(mod, io)) if (rsnd_ssi_is_multi_slave(mod, io))
return 0; return 0;
if (ssi->usrcnt > 1) { if (ssi->rate) {
if (ssi->rate != rate) { if (ssi->rate != rate) {
dev_err(dev, "SSI parent/child should use same rate\n"); dev_err(dev, "SSI parent/child should use same rate\n");
return -EINVAL; return -EINVAL;
...@@ -434,7 +434,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ...@@ -434,7 +434,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
struct rsnd_priv *priv) struct rsnd_priv *priv)
{ {
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
int ret;
if (!rsnd_ssi_is_run_mods(mod, io)) if (!rsnd_ssi_is_run_mods(mod, io))
return 0; return 0;
...@@ -443,10 +442,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ...@@ -443,10 +442,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
rsnd_mod_power_on(mod); rsnd_mod_power_on(mod);
ret = rsnd_ssi_master_clk_start(mod, io);
if (ret < 0)
return ret;
rsnd_ssi_config_init(mod, io); rsnd_ssi_config_init(mod, io);
rsnd_ssi_register_setup(mod); rsnd_ssi_register_setup(mod);
...@@ -852,6 +847,13 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod, ...@@ -852,6 +847,13 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
return 0; return 0;
} }
static int rsnd_ssi_prepare(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
return rsnd_ssi_master_clk_start(mod, io);
}
static struct rsnd_mod_ops rsnd_ssi_pio_ops = { static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.name = SSI_NAME, .name = SSI_NAME,
.probe = rsnd_ssi_common_probe, .probe = rsnd_ssi_common_probe,
...@@ -864,6 +866,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { ...@@ -864,6 +866,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.pointer = rsnd_ssi_pio_pointer, .pointer = rsnd_ssi_pio_pointer,
.pcm_new = rsnd_ssi_pcm_new, .pcm_new = rsnd_ssi_pcm_new,
.hw_params = rsnd_ssi_hw_params, .hw_params = rsnd_ssi_hw_params,
.prepare = rsnd_ssi_prepare,
}; };
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
...@@ -940,6 +943,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { ...@@ -940,6 +943,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.pcm_new = rsnd_ssi_pcm_new, .pcm_new = rsnd_ssi_pcm_new,
.fallback = rsnd_ssi_fallback, .fallback = rsnd_ssi_fallback,
.hw_params = rsnd_ssi_hw_params, .hw_params = rsnd_ssi_hw_params,
.prepare = rsnd_ssi_prepare,
}; };
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
......
...@@ -1447,7 +1447,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card, ...@@ -1447,7 +1447,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
sink = codec_dai->playback_widget; sink = codec_dai->playback_widget;
source = cpu_dai->capture_widget; source = cpu_dai->capture_widget;
if (sink && source) { if (sink && source) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params, ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params,
dai_link->num_params, dai_link->num_params,
source, sink); source, sink);
if (ret != 0) { if (ret != 0) {
...@@ -1460,7 +1460,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card, ...@@ -1460,7 +1460,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
sink = cpu_dai->playback_widget; sink = cpu_dai->playback_widget;
source = codec_dai->capture_widget; source = codec_dai->capture_widget;
if (sink && source) { if (sink && source) {
ret = snd_soc_dapm_new_pcm(card, dai_link->params, ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params,
dai_link->num_params, dai_link->num_params,
source, sink); source, sink);
if (ret != 0) { if (ret != 0) {
......
...@@ -3652,6 +3652,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ...@@ -3652,6 +3652,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
{ {
struct snd_soc_dapm_path *source_p, *sink_p; struct snd_soc_dapm_path *source_p, *sink_p;
struct snd_soc_dai *source, *sink; struct snd_soc_dai *source, *sink;
struct snd_soc_pcm_runtime *rtd = w->priv;
const struct snd_soc_pcm_stream *config = w->params + w->params_select; const struct snd_soc_pcm_stream *config = w->params + w->params_select;
struct snd_pcm_substream substream; struct snd_pcm_substream substream;
struct snd_pcm_hw_params *params = NULL; struct snd_pcm_hw_params *params = NULL;
...@@ -3711,6 +3712,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, ...@@ -3711,6 +3712,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
goto out; goto out;
} }
substream.runtime = runtime; substream.runtime = runtime;
substream.private_data = rtd;
switch (event) { switch (event) {
case SND_SOC_DAPM_PRE_PMU: case SND_SOC_DAPM_PRE_PMU:
...@@ -3895,6 +3897,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card, ...@@ -3895,6 +3897,7 @@ snd_soc_dapm_alloc_kcontrol(struct snd_soc_card *card,
} }
int snd_soc_dapm_new_pcm(struct snd_soc_card *card, int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd,
const struct snd_soc_pcm_stream *params, const struct snd_soc_pcm_stream *params,
unsigned int num_params, unsigned int num_params,
struct snd_soc_dapm_widget *source, struct snd_soc_dapm_widget *source,
...@@ -3963,6 +3966,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card, ...@@ -3963,6 +3966,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
w->params = params; w->params = params;
w->num_params = num_params; w->num_params = num_params;
w->priv = rtd;
ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL); ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
if (ret) if (ret)
......
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