mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 17:23:55 +08:00
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. -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAluhankOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE8hRxAAtMnqlbnld2ihoENWWwDPD1RedUhICP3ItOUB 8t5QXhzLlZ1fHKiDy8XAE7bljdEk8VJJDkva1umGztaAe9vxFzqjIvYn2yYvdX0d M9qxrJtY8V65Tsq9s1hUYdbONGGveXOabWEa+PwQOQdsIq4O+kwvyOvjWShvcdHQ vwKyaeC3E3pM0BIwna6O35E7GEEAauNhC/7ejdVNOD53Gn+gD3aREQqmiQvpFpqU 6/uhptM6Pp5Q18WOoKgVyDojPe2kNUDZ3SqMIyX90CDiIzVOvT8arB+19Ne5cnb+ lKItWDaVqzGX+hdG2WwsGNKrxVrAgZpETmeVjlvfyUIH+fcfierpiNuQi++v1hAH VMHAYUF8ks9wS0FzmEX98PtlkPb2y1AyrcxrhWcZjfItmAFihXu+mE4EIG+4mTk6 JvqewxFegVgQxK3ohwkl5+dv01HV3BJJ/1W5hYq+qmXzRqU0XIrOt9wBOwXJPREo BDQBbsWNejZYbJYuR3N2b7GCDK3u7wt1KoSfehN3t1ueSqJkq07BHw81RpC1uZ4h q6DWOfS5XZf+fDSwCabddYzlZwR9R/dFbYC+LogW0eRhMIMga0HSc2sSNNQjBE3I I7wgiU3NhRt6bGSg3B8/za52TaWD61QigXNmKSxRqgw1l1y+VeMkVoIjgxz9it8j GWDFG3g= =Qk/8 -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
d82920849f
@ -13449,9 +13449,8 @@ F: drivers/i2c/busses/i2c-synquacer.c
|
||||
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
|
||||
|
||||
SOCIONEXT UNIPHIER SOUND DRIVER
|
||||
M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
|
||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: sound/soc/uniphier/
|
||||
|
||||
SOEKRIS NET48XX LED SUPPORT
|
||||
|
@ -215,6 +215,8 @@ static void vga_switcheroo_enable(void)
|
||||
return;
|
||||
|
||||
client->id = ret | ID_BIT_AUDIO;
|
||||
if (client->ops->gpu_bound)
|
||||
client->ops->gpu_bound(client->pdev, ret);
|
||||
}
|
||||
|
||||
vga_switcheroo_debugfs_init(&vgasr_priv);
|
||||
|
@ -133,15 +133,18 @@ struct vga_switcheroo_handler {
|
||||
* @can_switch: check if the device is in a position to switch now.
|
||||
* Mandatory. The client should return false if a user space process
|
||||
* 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.
|
||||
* The @set_gpu_state and @can_switch methods are mandatory, @reprobe may be
|
||||
* 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 {
|
||||
void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
|
||||
void (*reprobe)(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)
|
||||
|
@ -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_enter_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);
|
||||
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,
|
||||
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);
|
||||
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd,
|
||||
const struct snd_soc_pcm_stream *params,
|
||||
unsigned int num_params,
|
||||
struct snd_soc_dapm_widget *source,
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef __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
|
||||
* SST types start at higher to avoid any overlapping in future
|
||||
@ -143,10 +145,10 @@ enum skl_module_param_type {
|
||||
};
|
||||
|
||||
struct skl_dfw_algo_data {
|
||||
u32 set_params:2;
|
||||
u32 rsvd:30;
|
||||
u32 param_id;
|
||||
u32 max;
|
||||
__u32 set_params:2;
|
||||
__u32 rsvd:30;
|
||||
__u32 param_id;
|
||||
__u32 max;
|
||||
char params[0];
|
||||
} __packed;
|
||||
|
||||
@ -163,68 +165,68 @@ enum skl_tuple_type {
|
||||
/* v4 configuration data */
|
||||
|
||||
struct skl_dfw_v4_module_pin {
|
||||
u16 module_id;
|
||||
u16 instance_id;
|
||||
__u16 module_id;
|
||||
__u16 instance_id;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_v4_module_fmt {
|
||||
u32 channels;
|
||||
u32 freq;
|
||||
u32 bit_depth;
|
||||
u32 valid_bit_depth;
|
||||
u32 ch_cfg;
|
||||
u32 interleaving_style;
|
||||
u32 sample_type;
|
||||
u32 ch_map;
|
||||
__u32 channels;
|
||||
__u32 freq;
|
||||
__u32 bit_depth;
|
||||
__u32 valid_bit_depth;
|
||||
__u32 ch_cfg;
|
||||
__u32 interleaving_style;
|
||||
__u32 sample_type;
|
||||
__u32 ch_map;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_v4_module_caps {
|
||||
u32 set_params:2;
|
||||
u32 rsvd:30;
|
||||
u32 param_id;
|
||||
u32 caps_size;
|
||||
u32 caps[HDA_SST_CFG_MAX];
|
||||
__u32 set_params:2;
|
||||
__u32 rsvd:30;
|
||||
__u32 param_id;
|
||||
__u32 caps_size;
|
||||
__u32 caps[HDA_SST_CFG_MAX];
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_v4_pipe {
|
||||
u8 pipe_id;
|
||||
u8 pipe_priority;
|
||||
u16 conn_type:4;
|
||||
u16 rsvd:4;
|
||||
u16 memory_pages:8;
|
||||
__u8 pipe_id;
|
||||
__u8 pipe_priority;
|
||||
__u16 conn_type:4;
|
||||
__u16 rsvd:4;
|
||||
__u16 memory_pages:8;
|
||||
} __packed;
|
||||
|
||||
struct skl_dfw_v4_module {
|
||||
char uuid[SKL_UUID_STR_SZ];
|
||||
|
||||
u16 module_id;
|
||||
u16 instance_id;
|
||||
u32 max_mcps;
|
||||
u32 mem_pages;
|
||||
u32 obs;
|
||||
u32 ibs;
|
||||
u32 vbus_id;
|
||||
__u16 module_id;
|
||||
__u16 instance_id;
|
||||
__u32 max_mcps;
|
||||
__u32 mem_pages;
|
||||
__u32 obs;
|
||||
__u32 ibs;
|
||||
__u32 vbus_id;
|
||||
|
||||
u32 max_in_queue:8;
|
||||
u32 max_out_queue:8;
|
||||
u32 time_slot:8;
|
||||
u32 core_id:4;
|
||||
u32 rsvd1:4;
|
||||
__u32 max_in_queue:8;
|
||||
__u32 max_out_queue:8;
|
||||
__u32 time_slot:8;
|
||||
__u32 core_id:4;
|
||||
__u32 rsvd1:4;
|
||||
|
||||
u32 module_type:8;
|
||||
u32 conn_type:4;
|
||||
u32 dev_type:4;
|
||||
u32 hw_conn_type:4;
|
||||
u32 rsvd2:12;
|
||||
__u32 module_type:8;
|
||||
__u32 conn_type:4;
|
||||
__u32 dev_type:4;
|
||||
__u32 hw_conn_type:4;
|
||||
__u32 rsvd2:12;
|
||||
|
||||
u32 params_fixup:8;
|
||||
u32 converter:8;
|
||||
u32 input_pin_type:1;
|
||||
u32 output_pin_type:1;
|
||||
u32 is_dynamic_in_pin:1;
|
||||
u32 is_dynamic_out_pin:1;
|
||||
u32 is_loadable:1;
|
||||
u32 rsvd3:11;
|
||||
__u32 params_fixup:8;
|
||||
__u32 converter:8;
|
||||
__u32 input_pin_type:1;
|
||||
__u32 output_pin_type:1;
|
||||
__u32 is_dynamic_in_pin:1;
|
||||
__u32 is_dynamic_out_pin:1;
|
||||
__u32 is_loadable:1;
|
||||
__u32 rsvd3:11;
|
||||
|
||||
struct skl_dfw_v4_pipe pipe;
|
||||
struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE];
|
||||
|
@ -263,6 +263,8 @@ do_registration(struct work_struct *work)
|
||||
error:
|
||||
mutex_unlock(&devices_mutex);
|
||||
snd_bebob_stream_destroy_duplex(bebob);
|
||||
kfree(bebob->maudio_special_quirk);
|
||||
bebob->maudio_special_quirk = NULL;
|
||||
snd_card_free(bebob->card);
|
||||
dev_info(&bebob->unit->device,
|
||||
"Sound card registration failed: %d\n", err);
|
||||
|
@ -96,17 +96,13 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
|
||||
struct fw_device *device = fw_parent_device(unit);
|
||||
int err, rcode;
|
||||
u64 date;
|
||||
__le32 cues[3] = {
|
||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE1),
|
||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE2),
|
||||
cpu_to_le32(MAUDIO_BOOTLOADER_CUE3)
|
||||
};
|
||||
__le32 *cues;
|
||||
|
||||
/* check date of software used to build */
|
||||
err = snd_bebob_read_block(unit, INFO_OFFSET_SW_DATE,
|
||||
&date, sizeof(u64));
|
||||
if (err < 0)
|
||||
goto end;
|
||||
return err;
|
||||
/*
|
||||
* firmware version 5058 or later has date later than "20070401", but
|
||||
* 'date' is not null-terminated.
|
||||
@ -114,20 +110,28 @@ int snd_bebob_maudio_load_firmware(struct fw_unit *unit)
|
||||
if (date < 0x3230303730343031LL) {
|
||||
dev_err(&unit->device,
|
||||
"Use firmware version 5058 or later\n");
|
||||
err = -ENOSYS;
|
||||
goto end;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
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,
|
||||
device->node_id, device->generation,
|
||||
device->max_speed, BEBOB_ADDR_REG_REQ,
|
||||
cues, sizeof(cues));
|
||||
cues, 3 * sizeof(*cues));
|
||||
kfree(cues);
|
||||
if (rcode != RCODE_COMPLETE) {
|
||||
dev_err(&unit->device,
|
||||
"Failed to send a cue to load firmware\n");
|
||||
err = -EIO;
|
||||
}
|
||||
end:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -290,10 +294,6 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814)
|
||||
bebob->midi_output_ports = 2;
|
||||
}
|
||||
end:
|
||||
if (err < 0) {
|
||||
kfree(params);
|
||||
bebob->maudio_special_quirk = NULL;
|
||||
}
|
||||
mutex_unlock(&bebob->mutex);
|
||||
return err;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ static void dg00x_free(struct snd_dg00x *dg00x)
|
||||
fw_unit_put(dg00x->unit);
|
||||
|
||||
mutex_destroy(&dg00x->mutex);
|
||||
kfree(dg00x);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
__le32 *reg;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
reg = kcalloc(18, sizeof(__le32), GFP_KERNEL);
|
||||
if (reg == NULL)
|
||||
@ -163,9 +164,11 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable)
|
||||
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,
|
||||
sizeof(__le32) * 18, 0);
|
||||
kfree(reg);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ff400_dump_sync_status(struct snd_ff *ff,
|
||||
|
@ -301,6 +301,8 @@ error:
|
||||
snd_efw_transaction_remove_instance(efw);
|
||||
snd_efw_stream_destroy_duplex(efw);
|
||||
snd_card_free(efw->card);
|
||||
kfree(efw->resp_buf);
|
||||
efw->resp_buf = NULL;
|
||||
dev_info(&efw->unit->device,
|
||||
"Sound card registration failed: %d\n", err);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ static void oxfw_free(struct snd_oxfw *oxfw)
|
||||
|
||||
kfree(oxfw->spec);
|
||||
mutex_destroy(&oxfw->mutex);
|
||||
kfree(oxfw);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -207,6 +208,7 @@ static int detect_quirks(struct snd_oxfw *oxfw)
|
||||
static void do_registration(struct work_struct *work)
|
||||
{
|
||||
struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work);
|
||||
int i;
|
||||
int err;
|
||||
|
||||
if (oxfw->registered)
|
||||
@ -269,7 +271,15 @@ error:
|
||||
snd_oxfw_stream_destroy_simplex(oxfw, &oxfw->rx_stream);
|
||||
if (oxfw->has_output)
|
||||
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);
|
||||
kfree(oxfw->spec);
|
||||
oxfw->spec = NULL;
|
||||
dev_info(&oxfw->unit->device,
|
||||
"Sound card registration failed: %d\n", err);
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ static void tscm_free(struct snd_tscm *tscm)
|
||||
fw_unit_put(tscm->unit);
|
||||
|
||||
mutex_destroy(&tscm->mutex);
|
||||
kfree(tscm);
|
||||
}
|
||||
|
||||
static void tscm_card_free(struct snd_card *card)
|
||||
|
@ -40,6 +40,8 @@ static void azx_clear_corbrp(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);
|
||||
/* CORB set up */
|
||||
bus->corb.addr = bus->rb.addr;
|
||||
@ -383,7 +385,7 @@ void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset);
|
||||
|
||||
/* 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)
|
||||
goto skip_reset;
|
||||
@ -408,7 +410,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset)
|
||||
skip_reset:
|
||||
/* check to see if controller is ready */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -423,6 +425,7 @@ static int azx_reset(struct hdac_bus *bus, bool full_reset)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_bus_reset_link);
|
||||
|
||||
/* enable interrupts */
|
||||
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)
|
||||
return false;
|
||||
|
||||
/* 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_enable(bus);
|
||||
|
||||
/* initialize the codec command I/O */
|
||||
snd_hdac_bus_init_cmd_io(bus);
|
||||
|
||||
/* enable interrupts after CORB/RIRB buffers are initialized above */
|
||||
azx_int_enable(bus);
|
||||
|
||||
/* program the position buffer */
|
||||
if (bus->use_posbuf && 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
|
||||
emu->support_tlv = 1;
|
||||
return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
|
||||
case SNDRV_EMU10K1_IOCTL_INFO:
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
snd_emu10k1_fx8010_info(emu, info);
|
||||
|
@ -365,8 +365,10 @@ enum {
|
||||
*/
|
||||
#ifdef SUPPORT_VGA_SWITCHEROO
|
||||
#define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo)
|
||||
#define needs_eld_notify_link(chip) ((chip)->need_eld_notify_link)
|
||||
#else
|
||||
#define use_vga_switcheroo(chip) 0
|
||||
#define needs_eld_notify_link(chip) false
|
||||
#endif
|
||||
|
||||
#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,
|
||||
#endif
|
||||
|
||||
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
|
||||
static void set_default_power_save(struct azx *chip);
|
||||
|
||||
/*
|
||||
* initialize the PCI registers
|
||||
@ -1201,6 +1204,10 @@ static int azx_runtime_idle(struct device *dev)
|
||||
azx_bus(chip)->codec_powered || !chip->running)
|
||||
return -EBUSY;
|
||||
|
||||
/* ELD notification gets broken when HD-audio bus is off */
|
||||
if (needs_eld_notify_link(hda))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1298,6 +1305,36 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
|
||||
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)
|
||||
{
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
@ -1306,6 +1343,7 @@ static void init_vga_switcheroo(struct azx *chip)
|
||||
dev_info(chip->card->dev,
|
||||
"Handle vga_switcheroo audio client\n");
|
||||
hda->use_vga_switcheroo = 1;
|
||||
hda->need_eld_notify_link = 1; /* cleared in gpu_bound op */
|
||||
chip->driver_caps |= AZX_DCAPS_PM_RUNTIME;
|
||||
pci_dev_put(p);
|
||||
}
|
||||
@ -1314,6 +1352,7 @@ static void init_vga_switcheroo(struct azx *chip)
|
||||
static const struct vga_switcheroo_client_ops azx_vs_ops = {
|
||||
.set_gpu_state = azx_vs_set_state,
|
||||
.can_switch = azx_vs_can_switch,
|
||||
.gpu_bound = azx_vs_gpu_bound,
|
||||
};
|
||||
|
||||
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 register_vga_switcheroo(chip) 0
|
||||
#define check_hdmi_disabled(pci) false
|
||||
#define setup_vga_switcheroo_runtime_pm(chip) /* NOP */
|
||||
#endif /* SUPPORT_VGA_SWITCHER */
|
||||
|
||||
/*
|
||||
@ -1352,6 +1392,7 @@ static int azx_free(struct azx *chip)
|
||||
|
||||
if (azx_has_pm_runtime(chip) && chip->running)
|
||||
pm_runtime_get_noresume(&pci->dev);
|
||||
chip->running = 0;
|
||||
|
||||
azx_del_card_list(chip);
|
||||
|
||||
@ -2230,6 +2271,25 @@ static struct snd_pci_quirk power_save_blacklist[] = {
|
||||
};
|
||||
#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) */
|
||||
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
|
||||
[AZX_DRIVER_NVIDIA] = 8,
|
||||
@ -2241,9 +2301,7 @@ static int azx_probe_continue(struct azx *chip)
|
||||
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
|
||||
struct hdac_bus *bus = azx_bus(chip);
|
||||
struct pci_dev *pci = chip->pci;
|
||||
struct hda_codec *codec;
|
||||
int dev = chip->dev_index;
|
||||
int val;
|
||||
int err;
|
||||
|
||||
hda->probe_continued = 1;
|
||||
@ -2322,31 +2380,13 @@ static int azx_probe_continue(struct azx *chip)
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
|
||||
setup_vga_switcheroo_runtime_pm(chip);
|
||||
|
||||
chip->running = 1;
|
||||
azx_add_card_list(chip);
|
||||
|
||||
val = power_save;
|
||||
#ifdef CONFIG_PM
|
||||
if (pm_blacklist) {
|
||||
const struct snd_pci_quirk *q;
|
||||
set_default_power_save(chip);
|
||||
|
||||
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))
|
||||
pm_runtime_put_autosuspend(&pci->dev);
|
||||
|
||||
|
@ -37,6 +37,7 @@ struct hda_intel {
|
||||
|
||||
/* vga_switcheroo setup */
|
||||
unsigned int use_vga_switcheroo:1;
|
||||
unsigned int need_eld_notify_link:1;
|
||||
unsigned int vga_switcheroo_registered:1;
|
||||
unsigned int init_failed:1; /* delayed init failed */
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
* system memory <-> ACP SRAM
|
||||
@ -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,
|
||||
&dmadscr[i]);
|
||||
}
|
||||
pre_config_reset(acp_mmio, ch);
|
||||
config_acp_dma_channel(acp_mmio, ch,
|
||||
dma_dscr_idx - 1,
|
||||
NUM_DSCRS_PER_CHANNEL,
|
||||
@ -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,
|
||||
&dmadscr[i]);
|
||||
}
|
||||
pre_config_reset(acp_mmio, ch);
|
||||
/* Configure the DMA channel with the above descriptore */
|
||||
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
|
||||
NUM_DSCRS_PER_CHANNEL,
|
||||
|
@ -157,8 +157,8 @@ static const struct snd_kcontrol_new cs4265_snd_controls[] = {
|
||||
SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
|
||||
3, 1, 0),
|
||||
SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
|
||||
SOC_SINGLE("MMTLR Data Switch", 0,
|
||||
1, 1, 0),
|
||||
SOC_SINGLE("MMTLR Data Switch", CS4265_SPDIF_CTL2,
|
||||
0, 1, 0),
|
||||
SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
|
||||
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)
|
||||
{
|
||||
switch (reg) {
|
||||
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_R2055_MEAS_ADC_THERM_CH_READBACK:
|
||||
case MAX98373_R20B6_BDE_CUR_STATE_READBACK:
|
||||
@ -729,6 +730,7 @@ static int max98373_probe(struct snd_soc_component *component)
|
||||
/* Software Reset */
|
||||
regmap_write(max98373->regmap,
|
||||
MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
/* IV default slot configuration */
|
||||
regmap_write(max98373->regmap,
|
||||
@ -817,6 +819,7 @@ static int max98373_resume(struct device *dev)
|
||||
|
||||
regmap_write(max98373->regmap,
|
||||
MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET);
|
||||
usleep_range(10000, 11000);
|
||||
regcache_cache_only(max98373->regmap, false);
|
||||
regcache_sync(max98373->regmap);
|
||||
return 0;
|
||||
|
@ -64,8 +64,8 @@ static const struct reg_sequence rt5514_patch[] = {
|
||||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_ADCFED, 0x00000800},
|
||||
{RT5514_ASRC_IN_CTRL1, 0x00000003},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000342},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000342},
|
||||
};
|
||||
|
||||
static const struct reg_default rt5514_reg[] = {
|
||||
@ -92,10 +92,10 @@ static const struct reg_default rt5514_reg[] = {
|
||||
{RT5514_ASRC_IN_CTRL1, 0x00000003},
|
||||
{RT5514_DOWNFILTER0_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER0_CTRL3, 0x10000342},
|
||||
{RT5514_DOWNFILTER1_CTRL1, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL2, 0x00020c2f},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000352},
|
||||
{RT5514_DOWNFILTER1_CTRL3, 0x10000342},
|
||||
{RT5514_ANA_CTRL_LDO10, 0x00028604},
|
||||
{RT5514_ANA_CTRL_LDO18_16, 0x02000345},
|
||||
{RT5514_ANA_CTRL_ADC12, 0x0000a2a8},
|
||||
|
@ -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(dac_vol_tlv, -65625, 375, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 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);
|
||||
|
||||
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
|
||||
@ -1114,7 +1114,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = {
|
||||
|
||||
/* DAC Digital Volume */
|
||||
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 */
|
||||
SOC_SINGLE_TLV("CBJ Boost Volume", RT5682_CBJ_BST_CTRL,
|
||||
@ -1124,7 +1124,7 @@ static const struct snd_kcontrol_new rt5682_snd_controls[] = {
|
||||
SOC_DOUBLE("STO1 ADC Capture Switch", RT5682_STO1_ADC_DIG_VOL,
|
||||
RT5682_L_MUTE_SFT, RT5682_R_MUTE_SFT, 1, 1),
|
||||
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 */
|
||||
SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5682_STO1_ADC_BOOST,
|
||||
|
@ -117,8 +117,7 @@ static int sigmadsp_ctrl_write(struct sigmadsp *sigmadsp,
|
||||
struct sigmadsp_control *ctrl, void *data)
|
||||
{
|
||||
/* safeload loads up to 20 bytes in a atomic operation */
|
||||
if (ctrl->num_bytes > 4 && ctrl->num_bytes <= 20 && sigmadsp->ops &&
|
||||
sigmadsp->ops->safeload)
|
||||
if (ctrl->num_bytes <= 20 && sigmadsp->ops && sigmadsp->ops->safeload)
|
||||
return sigmadsp->ops->safeload(sigmadsp, ctrl->addr, data,
|
||||
ctrl->num_bytes);
|
||||
else
|
||||
|
@ -424,8 +424,10 @@ static void tas6424_fault_check_work(struct work_struct *work)
|
||||
TAS6424_FAULT_PVDD_UV |
|
||||
TAS6424_FAULT_VBAT_UV;
|
||||
|
||||
if (reg)
|
||||
if (!reg) {
|
||||
tas6424->last_fault1 = reg;
|
||||
goto check_global_fault2_reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only flag errors once for a given occurrence. This is needed as
|
||||
@ -461,8 +463,10 @@ check_global_fault2_reg:
|
||||
TAS6424_FAULT_OTSD_CH3 |
|
||||
TAS6424_FAULT_OTSD_CH4;
|
||||
|
||||
if (!reg)
|
||||
if (!reg) {
|
||||
tas6424->last_fault2 = reg;
|
||||
goto check_warn_reg;
|
||||
}
|
||||
|
||||
if ((reg & TAS6424_FAULT_OTSD) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD))
|
||||
dev_crit(dev, "experienced a global overtemp shutdown\n");
|
||||
@ -497,8 +501,10 @@ check_warn_reg:
|
||||
TAS6424_WARN_VDD_OTW_CH3 |
|
||||
TAS6424_WARN_VDD_OTW_CH4;
|
||||
|
||||
if (!reg)
|
||||
if (!reg) {
|
||||
tas6424->last_warn = reg;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((reg & TAS6424_WARN_VDD_UV) && !(tas6424->last_warn & TAS6424_WARN_VDD_UV))
|
||||
dev_warn(dev, "experienced a VDD under voltage condition\n");
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "wm8804.h"
|
||||
|
||||
@ -40,17 +41,29 @@ static const struct i2c_device_id wm8804_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id wm8804_of_match[] = {
|
||||
{ .compatible = "wlf,wm8804", },
|
||||
{ }
|
||||
};
|
||||
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 = {
|
||||
.driver = {
|
||||
.name = "wm8804",
|
||||
.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,
|
||||
.remove = wm8804_i2c_remove,
|
||||
|
@ -719,7 +719,7 @@ static int wm9712_probe(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm9712_component_driver = {
|
||||
.driver = {
|
||||
.name = "wm9712-component",
|
||||
.name = "wm9712-codec",
|
||||
},
|
||||
|
||||
.probe = wm9712_probe,
|
||||
|
@ -575,6 +575,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
||||
BYT_RT5640_MONO_SPEAKER |
|
||||
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 */
|
||||
.matches = {
|
||||
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[] = {
|
||||
BYT_RT5640_SSP0_AIF1 |
|
||||
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 */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
|
@ -834,7 +834,7 @@ static int skl_first_init(struct hdac_bus *bus)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
skl_init_chip(bus, true);
|
||||
snd_hdac_bus_reset_link(bus, true);
|
||||
|
||||
snd_hdac_bus_parse_capabilities(bus);
|
||||
|
||||
|
@ -960,8 +960,10 @@ static int msm_routing_probe(struct snd_soc_component *c)
|
||||
{
|
||||
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].fedai_id = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -462,6 +462,11 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
|
||||
goto rsnd_adg_get_clkout_end;
|
||||
|
||||
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);
|
||||
req_48kHz_rate = 0;
|
||||
|
@ -478,7 +478,7 @@ static int rsnd_status_update(u32 *status,
|
||||
(func_call && (mod)->ops->fn) ? #fn : ""); \
|
||||
if (func_call && (mod)->ops->fn) \
|
||||
tmp = (mod)->ops->fn(mod, io, param); \
|
||||
if (tmp) \
|
||||
if (tmp && (tmp != -EPROBE_DEFER)) \
|
||||
dev_err(dev, "%s[%d] : %s error %d\n", \
|
||||
rsnd_mod_name(mod), rsnd_mod_id(mod), \
|
||||
#fn, tmp); \
|
||||
@ -958,12 +958,23 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
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 = {
|
||||
.startup = rsnd_soc_dai_startup,
|
||||
.shutdown = rsnd_soc_dai_shutdown,
|
||||
.trigger = rsnd_soc_dai_trigger,
|
||||
.set_fmt = rsnd_soc_dai_set_fmt,
|
||||
.set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
|
||||
.prepare = rsnd_soc_dai_prepare,
|
||||
};
|
||||
|
||||
void rsnd_parse_connect_common(struct rsnd_dai *rdai,
|
||||
@ -1550,6 +1561,14 @@ exit_snd_probe:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -241,6 +241,10 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
|
||||
/* try to get DMAEngine channel */
|
||||
chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
|
||||
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
|
||||
* see
|
||||
|
@ -280,6 +280,9 @@ struct rsnd_mod_ops {
|
||||
int (*nolock_stop)(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv);
|
||||
int (*prepare)(struct rsnd_mod *mod,
|
||||
struct rsnd_dai_stream *io,
|
||||
struct rsnd_priv *priv);
|
||||
};
|
||||
|
||||
struct rsnd_dai_stream;
|
||||
@ -309,6 +312,7 @@ struct rsnd_mod {
|
||||
* H 0: fallback
|
||||
* H 0: hw_params
|
||||
* H 0: pointer
|
||||
* H 0: prepare
|
||||
*/
|
||||
#define __rsnd_mod_shift_nolock_start 0
|
||||
#define __rsnd_mod_shift_nolock_stop 0
|
||||
@ -323,6 +327,7 @@ struct rsnd_mod {
|
||||
#define __rsnd_mod_shift_fallback 28 /* always called */
|
||||
#define __rsnd_mod_shift_hw_params 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_remove 0
|
||||
@ -337,6 +342,7 @@ struct rsnd_mod {
|
||||
#define __rsnd_mod_add_fallback 0
|
||||
#define __rsnd_mod_add_hw_params 0
|
||||
#define __rsnd_mod_add_pointer 0
|
||||
#define __rsnd_mod_add_prepare 0
|
||||
|
||||
#define __rsnd_mod_call_probe 0
|
||||
#define __rsnd_mod_call_remove 0
|
||||
@ -351,6 +357,7 @@ struct rsnd_mod {
|
||||
#define __rsnd_mod_call_pointer 0
|
||||
#define __rsnd_mod_call_nolock_start 0
|
||||
#define __rsnd_mod_call_nolock_stop 1
|
||||
#define __rsnd_mod_call_prepare 0
|
||||
|
||||
#define rsnd_mod_to_priv(mod) ((mod)->priv)
|
||||
#define rsnd_mod_name(mod) ((mod)->ops->name)
|
||||
|
@ -283,7 +283,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
|
||||
if (rsnd_ssi_is_multi_slave(mod, io))
|
||||
return 0;
|
||||
|
||||
if (ssi->usrcnt > 1) {
|
||||
if (ssi->rate) {
|
||||
if (ssi->rate != rate) {
|
||||
dev_err(dev, "SSI parent/child should use same rate\n");
|
||||
return -EINVAL;
|
||||
@ -434,7 +434,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
|
||||
struct rsnd_priv *priv)
|
||||
{
|
||||
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
|
||||
int ret;
|
||||
|
||||
if (!rsnd_ssi_is_run_mods(mod, io))
|
||||
return 0;
|
||||
@ -443,10 +442,6 @@ static int rsnd_ssi_init(struct rsnd_mod *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_register_setup(mod);
|
||||
@ -852,6 +847,13 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
|
||||
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 = {
|
||||
.name = SSI_NAME,
|
||||
.probe = rsnd_ssi_common_probe,
|
||||
@ -864,6 +866,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
|
||||
.pointer = rsnd_ssi_pio_pointer,
|
||||
.pcm_new = rsnd_ssi_pcm_new,
|
||||
.hw_params = rsnd_ssi_hw_params,
|
||||
.prepare = rsnd_ssi_prepare,
|
||||
};
|
||||
|
||||
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
|
||||
@ -940,6 +943,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
|
||||
.pcm_new = rsnd_ssi_pcm_new,
|
||||
.fallback = rsnd_ssi_fallback,
|
||||
.hw_params = rsnd_ssi_hw_params,
|
||||
.prepare = rsnd_ssi_prepare,
|
||||
};
|
||||
|
||||
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,
|
||||
sink = codec_dai->playback_widget;
|
||||
source = cpu_dai->capture_widget;
|
||||
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,
|
||||
source, sink);
|
||||
if (ret != 0) {
|
||||
@ -1460,7 +1460,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
|
||||
sink = cpu_dai->playback_widget;
|
||||
source = codec_dai->capture_widget;
|
||||
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,
|
||||
source, sink);
|
||||
if (ret != 0) {
|
||||
|
@ -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_dai *source, *sink;
|
||||
struct snd_soc_pcm_runtime *rtd = w->priv;
|
||||
const struct snd_soc_pcm_stream *config = w->params + w->params_select;
|
||||
struct snd_pcm_substream substream;
|
||||
struct snd_pcm_hw_params *params = NULL;
|
||||
@ -3711,6 +3712,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
|
||||
goto out;
|
||||
}
|
||||
substream.runtime = runtime;
|
||||
substream.private_data = rtd;
|
||||
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
@ -3895,6 +3897,7 @@ outfree_w_param:
|
||||
}
|
||||
|
||||
int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
|
||||
struct snd_soc_pcm_runtime *rtd,
|
||||
const struct snd_soc_pcm_stream *params,
|
||||
unsigned int num_params,
|
||||
struct snd_soc_dapm_widget *source,
|
||||
@ -3963,6 +3966,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
|
||||
|
||||
w->params = params;
|
||||
w->num_params = num_params;
|
||||
w->priv = rtd;
|
||||
|
||||
ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
|
||||
if (ret)
|
||||
|
Loading…
Reference in New Issue
Block a user