mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
sound fixes for 5.6-rc1
A collection of pending small fixes since the previous PR. ALSA core: - PCM memory leak fix ASoC: - Lots of SOF and Intel driver fixes - Addition of COMMON_CLK for wcd934x - Regression fixes for AMD and Tegra platforms HD-audio: - DP-MST HDMI regression fix, Tegra workarounds, HP quirk fix Others: - A few fixes relevant with the recent uapi-updates - Sparse warnings and endianness fixes -----BEGIN PGP SIGNATURE----- iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAl47+oEOHHRpd2FpQHN1 c2UuZGUACgkQLtJE4w1nLE+GYg//dNu8r2M6y60btHjaWxblmdhHF3XQ5EwSxvSX QT1gm3pg8PMefJNOSD5IhD7Spll6SYz89YpKpPr3NneV5bcDSozdAt50vbtZvqry notOqSpL4DubIcYIrhLWI6mq9cIOXIgGnY1cs2KIkoDdNUSDD44nCG1FoUu163tI mBPDgjZqAAMseCu4jwRInfE2iUJHGNrkQBDc3+1yZFPog/APoLocRKF7paF1N73f A8kGDCoWUmk8mGb93lUxiDg09gK0aCHNmcjIR4Q4MPD16Yg+o1RgGwY81xdyKjs1 neNCfSCyhYgkON8rvJIsE46qGbqax6/JT7QxCqbyy/Vj4s5MfUivqnWRFwnUisB+ OoQa37Vd893gjxz1+JvmjrqKTWPmSbHMiuqFj5e1X+HqEVxdKDJMMPwzqlVjRq4K Ma18ACK1EQmb4Hsh2U488EjZp/n/FoOmqFSjE6qaHpfdq7YT0bv2lV+f8QFNmliF aeJ+ktp6GU2FFV2U4/iZmRUeTZgJpz6m2mLix++Jn11RbSewxj4uyZPKbBYPj7JZ NK2l/OgMUxj4qM3ZkgQUOnihIWSqdx0lySgXPWe7fLokMTPNsVr5X2ztD9m1uyX8 lbJuZsXNGMUS6v3aAy8zoCp2sc1G8heM5Z/WUiZQtUtjpUJ3DATK7sEdv3hLJpFB sYw41vs= =Mcey -----END PGP SIGNATURE----- Merge tag 'sound-fix-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "A collection of pending small fixes: ALSA core: - PCM memory leak fix ASoC: - Lots of SOF and Intel driver fixes - Addition of COMMON_CLK for wcd934x - Regression fixes for AMD and Tegra platforms HD-audio: - DP-MST HDMI regression fix, Tegra workarounds, HP quirk fix Others: - A few fixes relevant with the recent uapi-updates - Sparse warnings and endianness fixes" * tag 'sound-fix-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (35 commits) ALSA: hda: Clear RIRB status before reading WP ALSA: hda/realtek - Fixed one of HP ALC671 platform Headset Mic supported ASoC: wcd934x: Add missing COMMON_CLK dependency to SND_SOC_ALL_CODECS ALSA: hda - Fix DP-MST support for NVIDIA codecs ASoC: wcd934x: Add missing COMMON_CLK dependency MAINTAINERS: Remove the Bard Liao from the MAINTAINERS of Realtek CODECs ASoC: tegra: Revert 24 and 32 bit support ASoC: SOF: Intel: add PCI ID for JasperLake ALSA: hdsp: Make the firmware loading ioctl a bit more readable ALSA: emu10k1: Fix annotation and cast for the recent uapi header change ALSA: dummy: Fix PCM format loop in proc output ALSA: usb-audio: Annotate endianess in Scarlett gen2 quirk ALSA: usb-audio: Fix endianess in descriptor validation ALSA: hda: Add JasperLake PCI ID and codec vid ALSA: pcm: Fix sparse warnings wrt snd_pcm_state_t ALSA: pcm: Fix memory leak at closing a stream without hw_free ALSA: uapi: Fix sparse warning ASoC: rt715: Add __maybe_unused to PM callbacks ASoC: rt711: Add __maybe_unused to PM callbacks ASoC: rt700: Add __maybe_unused to PM callbacks ...
This commit is contained in:
commit
750ce8ccd8
@ -14106,7 +14106,6 @@ F: include/linux/platform_data/rtc-*
|
||||
F: tools/testing/selftests/rtc/
|
||||
|
||||
REALTEK AUDIO CODECS
|
||||
M: Bard Liao <bardliao@realtek.com>
|
||||
M: Oder Chiou <oder_chiou@realtek.com>
|
||||
S: Maintained
|
||||
F: sound/soc/codecs/rt*
|
||||
|
@ -1450,7 +1450,7 @@ struct snd_pcm_status64 {
|
||||
#define SNDRV_PCM_IOCTL_STATUS_EXT64 _IOWR('A', 0x24, struct snd_pcm_status64)
|
||||
|
||||
struct snd_pcm_status32 {
|
||||
s32 state; /* stream state */
|
||||
snd_pcm_state_t state; /* stream state */
|
||||
s32 trigger_tstamp_sec; /* time when stream was started/stopped/paused */
|
||||
s32 trigger_tstamp_nsec;
|
||||
s32 tstamp_sec; /* reference timestamp */
|
||||
@ -1461,7 +1461,7 @@ struct snd_pcm_status32 {
|
||||
u32 avail; /* number of frames available */
|
||||
u32 avail_max; /* max frames available on hw since last status */
|
||||
u32 overrange; /* count of ADC (capture) overrange detections from last status */
|
||||
s32 suspended_state; /* suspended stream state */
|
||||
snd_pcm_state_t suspended_state; /* suspended stream state */
|
||||
u32 audio_tstamp_data; /* needed for 64-bit alignment, used for configs/report to/from userspace */
|
||||
s32 audio_tstamp_sec; /* sample counter, wall clock, PHC or on-demand sync'ed */
|
||||
s32 audio_tstamp_nsec;
|
||||
|
@ -564,13 +564,13 @@ typedef char __pad_after_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
|
||||
#endif
|
||||
|
||||
struct __snd_pcm_mmap_status64 {
|
||||
__s32 state; /* RO: state - SNDRV_PCM_STATE_XXXX */
|
||||
snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
|
||||
__u32 pad1; /* Needed for 64 bit alignment */
|
||||
__pad_before_uframe __pad1;
|
||||
snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
|
||||
__pad_after_uframe __pad2;
|
||||
struct __snd_timespec64 tstamp; /* Timestamp */
|
||||
__s32 suspended_state; /* RO: suspended stream state */
|
||||
snd_pcm_state_t suspended_state;/* RO: suspended stream state */
|
||||
__u32 pad3; /* Needed for 64 bit alignment */
|
||||
struct __snd_timespec64 audio_tstamp; /* sample counter or wall clock */
|
||||
};
|
||||
|
@ -156,7 +156,7 @@ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
|
||||
#endif /* CONFIG_X86_X32 */
|
||||
|
||||
struct compat_snd_pcm_status64 {
|
||||
s32 state;
|
||||
snd_pcm_state_t state;
|
||||
u8 rsvd[4]; /* alignment */
|
||||
s64 trigger_tstamp_sec;
|
||||
s64 trigger_tstamp_nsec;
|
||||
@ -168,7 +168,7 @@ struct compat_snd_pcm_status64 {
|
||||
u32 avail;
|
||||
u32 avail_max;
|
||||
u32 overrange;
|
||||
s32 suspended_state;
|
||||
snd_pcm_state_t suspended_state;
|
||||
u32 audio_tstamp_data;
|
||||
s64 audio_tstamp_sec;
|
||||
s64 audio_tstamp_nsec;
|
||||
@ -376,13 +376,13 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
|
||||
#ifdef CONFIG_X86_X32
|
||||
/* X32 ABI has 64bit timespec and 64bit alignment */
|
||||
struct snd_pcm_mmap_status_x32 {
|
||||
s32 state;
|
||||
snd_pcm_state_t state;
|
||||
s32 pad1;
|
||||
u32 hw_ptr;
|
||||
u32 pad2; /* alignment */
|
||||
s64 tstamp_sec;
|
||||
s64 tstamp_nsec;
|
||||
s32 suspended_state;
|
||||
snd_pcm_state_t suspended_state;
|
||||
s32 pad3;
|
||||
s64 audio_tstamp_sec;
|
||||
s64 audio_tstamp_nsec;
|
||||
|
@ -551,7 +551,8 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
|
||||
return usecs;
|
||||
}
|
||||
|
||||
static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_set_state(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
|
||||
@ -786,10 +787,22 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
snd_pcm_sync_stop(substream);
|
||||
if (substream->ops->hw_free)
|
||||
result = substream->ops->hw_free(substream);
|
||||
if (substream->managed_buffer_alloc)
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime;
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
if (PCM_RUNTIME_CHECK(substream))
|
||||
return -ENXIO;
|
||||
@ -806,11 +819,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
if (atomic_read(&substream->mmap_count))
|
||||
return -EBADFD;
|
||||
snd_pcm_sync_stop(substream);
|
||||
if (substream->ops->hw_free)
|
||||
result = substream->ops->hw_free(substream);
|
||||
if (substream->managed_buffer_alloc)
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
result = do_hw_free(substream);
|
||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
||||
pm_qos_remove_request(&substream->latency_pm_qos_req);
|
||||
return result;
|
||||
@ -1097,11 +1106,17 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
|
||||
runtime->trigger_master = NULL;
|
||||
}
|
||||
|
||||
#define ACTION_ARG_IGNORE (__force snd_pcm_state_t)0
|
||||
|
||||
struct action_ops {
|
||||
int (*pre_action)(struct snd_pcm_substream *substream, int state);
|
||||
int (*do_action)(struct snd_pcm_substream *substream, int state);
|
||||
void (*undo_action)(struct snd_pcm_substream *substream, int state);
|
||||
void (*post_action)(struct snd_pcm_substream *substream, int state);
|
||||
int (*pre_action)(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state);
|
||||
int (*do_action)(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state);
|
||||
void (*undo_action)(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state);
|
||||
void (*post_action)(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1111,7 +1126,8 @@ struct action_ops {
|
||||
*/
|
||||
static int snd_pcm_action_group(const struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state, int do_lock)
|
||||
snd_pcm_state_t state,
|
||||
bool do_lock)
|
||||
{
|
||||
struct snd_pcm_substream *s = NULL;
|
||||
struct snd_pcm_substream *s1;
|
||||
@ -1168,7 +1184,7 @@ static int snd_pcm_action_group(const struct action_ops *ops,
|
||||
*/
|
||||
static int snd_pcm_action_single(const struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
int res;
|
||||
|
||||
@ -1249,14 +1265,14 @@ snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
|
||||
*/
|
||||
static int snd_pcm_action(const struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_group *group;
|
||||
int res;
|
||||
|
||||
group = snd_pcm_stream_group_ref(substream);
|
||||
if (group)
|
||||
res = snd_pcm_action_group(ops, substream, state, 1);
|
||||
res = snd_pcm_action_group(ops, substream, state, true);
|
||||
else
|
||||
res = snd_pcm_action_single(ops, substream, state);
|
||||
snd_pcm_group_unref(group, substream);
|
||||
@ -1268,7 +1284,7 @@ static int snd_pcm_action(const struct action_ops *ops,
|
||||
*/
|
||||
static int snd_pcm_action_lock_irq(const struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
int res;
|
||||
|
||||
@ -1282,14 +1298,14 @@ static int snd_pcm_action_lock_irq(const struct action_ops *ops,
|
||||
*/
|
||||
static int snd_pcm_action_nonatomic(const struct action_ops *ops,
|
||||
struct snd_pcm_substream *substream,
|
||||
int state)
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Guarantee the group members won't change during non-atomic action */
|
||||
down_read(&snd_pcm_link_rwsem);
|
||||
if (snd_pcm_stream_linked(substream))
|
||||
res = snd_pcm_action_group(ops, substream, state, 0);
|
||||
res = snd_pcm_action_group(ops, substream, state, false);
|
||||
else
|
||||
res = snd_pcm_action_single(ops, substream, state);
|
||||
up_read(&snd_pcm_link_rwsem);
|
||||
@ -1299,7 +1315,8 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
|
||||
/*
|
||||
* start callbacks
|
||||
*/
|
||||
static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
|
||||
@ -1312,20 +1329,23 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_start(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master != substream)
|
||||
return 0;
|
||||
return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
|
||||
}
|
||||
|
||||
static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_undo_start(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master == substream)
|
||||
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
|
||||
}
|
||||
|
||||
static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_start(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_trigger_tstamp(substream);
|
||||
@ -1369,7 +1389,8 @@ static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
|
||||
/*
|
||||
* stop callbacks
|
||||
*/
|
||||
static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_pre_stop(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
|
||||
@ -1378,7 +1399,8 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master == substream &&
|
||||
snd_pcm_running(substream))
|
||||
@ -1386,7 +1408,8 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
|
||||
return 0; /* unconditonally stop all substreams */
|
||||
}
|
||||
|
||||
static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (runtime->status->state != state) {
|
||||
@ -1457,14 +1480,17 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
|
||||
EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
|
||||
|
||||
/*
|
||||
* pause callbacks
|
||||
* pause callbacks: pass boolean (to start pause or resume) as state argument
|
||||
*/
|
||||
static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
|
||||
#define pause_pushed(state) (__force bool)(state)
|
||||
|
||||
static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
|
||||
return -ENOSYS;
|
||||
if (push) {
|
||||
if (pause_pushed(state)) {
|
||||
if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
|
||||
return -EBADFD;
|
||||
} else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
|
||||
@ -1473,13 +1499,14 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
|
||||
static int snd_pcm_do_pause(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master != substream)
|
||||
return 0;
|
||||
/* some drivers might use hw_ptr to recover from the pause -
|
||||
update the hw_ptr now */
|
||||
if (push)
|
||||
if (pause_pushed(state))
|
||||
snd_pcm_update_hw_ptr(substream);
|
||||
/* The jiffies check in snd_pcm_update_hw_ptr*() is done by
|
||||
* a delta between the current jiffies, this gives a large enough
|
||||
@ -1487,23 +1514,27 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
|
||||
*/
|
||||
substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
|
||||
return substream->ops->trigger(substream,
|
||||
push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
|
||||
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
|
||||
pause_pushed(state) ?
|
||||
SNDRV_PCM_TRIGGER_PAUSE_PUSH :
|
||||
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
|
||||
}
|
||||
|
||||
static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
|
||||
static void snd_pcm_undo_pause(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master == substream)
|
||||
substream->ops->trigger(substream,
|
||||
push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
|
||||
pause_pushed(state) ?
|
||||
SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
|
||||
SNDRV_PCM_TRIGGER_PAUSE_PUSH);
|
||||
}
|
||||
|
||||
static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
|
||||
static void snd_pcm_post_pause(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_trigger_tstamp(substream);
|
||||
if (push) {
|
||||
if (pause_pushed(state)) {
|
||||
runtime->status->state = SNDRV_PCM_STATE_PAUSED;
|
||||
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
|
||||
wake_up(&runtime->sleep);
|
||||
@ -1524,15 +1555,24 @@ static const struct action_ops snd_pcm_action_pause = {
|
||||
/*
|
||||
* Push/release the pause for all linked streams.
|
||||
*/
|
||||
static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
|
||||
static int snd_pcm_pause(struct snd_pcm_substream *substream, bool push)
|
||||
{
|
||||
return snd_pcm_action(&snd_pcm_action_pause, substream, push);
|
||||
return snd_pcm_action(&snd_pcm_action_pause, substream,
|
||||
(__force snd_pcm_state_t)push);
|
||||
}
|
||||
|
||||
static int snd_pcm_pause_lock_irq(struct snd_pcm_substream *substream,
|
||||
bool push)
|
||||
{
|
||||
return snd_pcm_action_lock_irq(&snd_pcm_action_pause, substream,
|
||||
(__force snd_pcm_state_t)push);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* suspend */
|
||||
/* suspend callback: state argument ignored */
|
||||
|
||||
static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
switch (runtime->status->state) {
|
||||
@ -1548,7 +1588,8 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (runtime->trigger_master != substream)
|
||||
@ -1559,7 +1600,8 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
|
||||
return 0; /* suspend unconditionally */
|
||||
}
|
||||
|
||||
static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_suspend(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_trigger_tstamp(substream);
|
||||
@ -1590,7 +1632,8 @@ static int snd_pcm_suspend(struct snd_pcm_substream *substream)
|
||||
unsigned long flags;
|
||||
|
||||
snd_pcm_stream_lock_irqsave(substream, flags);
|
||||
err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
|
||||
err = snd_pcm_action(&snd_pcm_action_suspend, substream,
|
||||
ACTION_ARG_IGNORE);
|
||||
snd_pcm_stream_unlock_irqrestore(substream, flags);
|
||||
return err;
|
||||
}
|
||||
@ -1634,9 +1677,10 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
|
||||
}
|
||||
EXPORT_SYMBOL(snd_pcm_suspend_all);
|
||||
|
||||
/* resume */
|
||||
/* resume callbacks: state argument ignored */
|
||||
|
||||
static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_pre_resume(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
|
||||
@ -1645,7 +1689,8 @@ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_resume(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (runtime->trigger_master != substream)
|
||||
@ -1658,14 +1703,16 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
|
||||
return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
|
||||
}
|
||||
|
||||
static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_undo_resume(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
if (substream->runtime->trigger_master == substream &&
|
||||
snd_pcm_running(substream))
|
||||
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
|
||||
}
|
||||
|
||||
static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
snd_pcm_trigger_tstamp(substream);
|
||||
@ -1683,7 +1730,8 @@ static const struct action_ops snd_pcm_action_resume = {
|
||||
|
||||
static int snd_pcm_resume(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
|
||||
return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream,
|
||||
ACTION_ARG_IGNORE);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -1724,7 +1772,9 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
|
||||
/*
|
||||
* reset ioctl
|
||||
*/
|
||||
static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
|
||||
/* reset callbacks: state argument ignored */
|
||||
static int snd_pcm_pre_reset(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
switch (runtime->status->state) {
|
||||
@ -1738,7 +1788,8 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
|
||||
}
|
||||
}
|
||||
|
||||
static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
|
||||
@ -1752,7 +1803,8 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
runtime->control->appl_ptr = runtime->status->hw_ptr;
|
||||
@ -1769,17 +1821,20 @@ static const struct action_ops snd_pcm_action_reset = {
|
||||
|
||||
static int snd_pcm_reset(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
|
||||
return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream,
|
||||
ACTION_ARG_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* prepare ioctl
|
||||
*/
|
||||
/* we use the second argument for updating f_flags */
|
||||
/* pass f_flags as state argument */
|
||||
static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
|
||||
int f_flags)
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int f_flags = (__force int)state;
|
||||
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
|
||||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
|
||||
return -EBADFD;
|
||||
@ -1789,17 +1844,19 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
int err;
|
||||
snd_pcm_sync_stop(substream);
|
||||
err = substream->ops->prepare(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return snd_pcm_do_reset(substream, 0);
|
||||
return snd_pcm_do_reset(substream, state);
|
||||
}
|
||||
|
||||
static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_prepare(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
runtime->control->appl_ptr = runtime->status->hw_ptr;
|
||||
@ -1832,7 +1889,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
switch (substream->runtime->status->state) {
|
||||
case SNDRV_PCM_STATE_PAUSED:
|
||||
snd_pcm_pause(substream, 0);
|
||||
snd_pcm_pause(substream, false);
|
||||
/* fallthru */
|
||||
case SNDRV_PCM_STATE_SUSPENDED:
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
|
||||
@ -1841,14 +1898,17 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
|
||||
return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
|
||||
substream, f_flags);
|
||||
substream,
|
||||
(__force snd_pcm_state_t)f_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* drain ioctl
|
||||
*/
|
||||
|
||||
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
|
||||
/* drain init callbacks: state argument ignored */
|
||||
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
switch (runtime->status->state) {
|
||||
@ -1861,7 +1921,8 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
|
||||
static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
@ -1887,7 +1948,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
|
||||
} else {
|
||||
/* stop running stream */
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
|
||||
int new_state = snd_pcm_capture_avail(runtime) > 0 ?
|
||||
snd_pcm_state_t new_state;
|
||||
|
||||
new_state = snd_pcm_capture_avail(runtime) > 0 ?
|
||||
SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
|
||||
snd_pcm_do_stop(substream, new_state);
|
||||
snd_pcm_post_stop(substream, new_state);
|
||||
@ -1903,7 +1966,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
|
||||
static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream,
|
||||
snd_pcm_state_t state)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1946,10 +2010,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
/* resume pause */
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
|
||||
snd_pcm_pause(substream, 0);
|
||||
snd_pcm_pause(substream, false);
|
||||
|
||||
/* pre-start/stop - all running streams are changed to DRAINING state */
|
||||
result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
|
||||
result = snd_pcm_action(&snd_pcm_action_drain_init, substream,
|
||||
ACTION_ARG_IGNORE);
|
||||
if (result < 0)
|
||||
goto unlock;
|
||||
/* in non-blocking, we don't wait in ioctl but let caller poll */
|
||||
@ -2050,7 +2115,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
/* resume pause */
|
||||
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
|
||||
snd_pcm_pause(substream, 0);
|
||||
snd_pcm_pause(substream, false);
|
||||
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
|
||||
/* runtime->control->appl_ptr = runtime->status->hw_ptr; */
|
||||
@ -2529,9 +2594,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
|
||||
|
||||
snd_pcm_drop(substream);
|
||||
if (substream->hw_opened) {
|
||||
if (substream->ops->hw_free &&
|
||||
substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
|
||||
substream->ops->hw_free(substream);
|
||||
do_hw_free(substream);
|
||||
substream->ops->close(substream);
|
||||
substream->hw_opened = 0;
|
||||
}
|
||||
@ -2894,12 +2957,12 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
|
||||
}
|
||||
|
||||
struct snd_pcm_mmap_status32 {
|
||||
s32 state;
|
||||
snd_pcm_state_t state;
|
||||
s32 pad1;
|
||||
u32 hw_ptr;
|
||||
s32 tstamp_sec;
|
||||
s32 tstamp_nsec;
|
||||
s32 suspended_state;
|
||||
snd_pcm_state_t suspended_state;
|
||||
s32 audio_tstamp_sec;
|
||||
s32 audio_tstamp_nsec;
|
||||
} __attribute__((packed));
|
||||
@ -3177,9 +3240,7 @@ static int snd_pcm_common_ioctl(struct file *file,
|
||||
case SNDRV_PCM_IOCTL_DROP:
|
||||
return snd_pcm_drop(substream);
|
||||
case SNDRV_PCM_IOCTL_PAUSE:
|
||||
return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
|
||||
substream,
|
||||
(int)(unsigned long)arg);
|
||||
return snd_pcm_pause_lock_irq(substream, (unsigned long)arg);
|
||||
case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
|
||||
case SNDRV_PCM_IOCTL_READI_FRAMES:
|
||||
return snd_pcm_xferi_frames_ioctl(substream, arg);
|
||||
|
@ -903,7 +903,7 @@ static void print_formats(struct snd_dummy *dummy,
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
|
||||
for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
|
||||
if (dummy->pcm_hw.formats & (1ULL << i))
|
||||
snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
|
||||
}
|
||||
|
@ -631,20 +631,27 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
|
||||
nwait = 0;
|
||||
i = 0;
|
||||
list_for_each_entry(s, &bus->stream_list, list) {
|
||||
if (streams & (1 << i)) {
|
||||
if (start) {
|
||||
/* check FIFO gets ready */
|
||||
if (!(snd_hdac_stream_readb(s, SD_STS) &
|
||||
SD_STS_FIFO_READY))
|
||||
nwait++;
|
||||
} else {
|
||||
/* check RUN bit is cleared */
|
||||
if (snd_hdac_stream_readb(s, SD_CTL) &
|
||||
SD_CTL_DMA_START)
|
||||
nwait++;
|
||||
if (!(streams & (1 << i++)))
|
||||
continue;
|
||||
|
||||
if (start) {
|
||||
/* check FIFO gets ready */
|
||||
if (!(snd_hdac_stream_readb(s, SD_STS) &
|
||||
SD_STS_FIFO_READY))
|
||||
nwait++;
|
||||
} else {
|
||||
/* check RUN bit is cleared */
|
||||
if (snd_hdac_stream_readb(s, SD_CTL) &
|
||||
SD_CTL_DMA_START) {
|
||||
nwait++;
|
||||
/*
|
||||
* Perform stream reset if DMA RUN
|
||||
* bit not cleared within given timeout
|
||||
*/
|
||||
if (timeout == 1)
|
||||
snd_hdac_stream_reset(s);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!nwait)
|
||||
break;
|
||||
|
@ -463,7 +463,7 @@ static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode,
|
||||
u_int32_t *code;
|
||||
if (snd_BUG_ON(*ptr >= 512))
|
||||
return;
|
||||
code = (u_int32_t __force *)icode->code + (*ptr) * 2;
|
||||
code = icode->code + (*ptr) * 2;
|
||||
set_bit(*ptr, icode->code_valid);
|
||||
code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
|
||||
code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
|
||||
@ -480,7 +480,7 @@ static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode,
|
||||
u_int32_t *code;
|
||||
if (snd_BUG_ON(*ptr >= 1024))
|
||||
return;
|
||||
code = (u_int32_t __force *)icode->code + (*ptr) * 2;
|
||||
code = icode->code + (*ptr) * 2;
|
||||
set_bit(*ptr, icode->code_valid);
|
||||
code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
|
||||
code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
|
||||
@ -513,8 +513,8 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
|
||||
if (!test_bit(gpr, icode->gpr_valid))
|
||||
continue;
|
||||
if (in_kernel)
|
||||
val = *(__force u32 *)&icode->gpr_map[gpr];
|
||||
else if (get_user(val, &icode->gpr_map[gpr]))
|
||||
val = icode->gpr_map[gpr];
|
||||
else if (get_user(val, (__user u32 *)&icode->gpr_map[gpr]))
|
||||
return -EFAULT;
|
||||
snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
|
||||
}
|
||||
@ -530,7 +530,7 @@ static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
|
||||
for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
|
||||
set_bit(gpr, icode->gpr_valid);
|
||||
val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
|
||||
if (put_user(val, &icode->gpr_map[gpr]))
|
||||
if (put_user(val, (__user u32 *)&icode->gpr_map[gpr]))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
@ -547,11 +547,11 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
|
||||
if (!test_bit(tram, icode->tram_valid))
|
||||
continue;
|
||||
if (in_kernel) {
|
||||
val = *(__force u32 *)&icode->tram_data_map[tram];
|
||||
addr = *(__force u32 *)&icode->tram_addr_map[tram];
|
||||
val = icode->tram_data_map[tram];
|
||||
addr = icode->tram_addr_map[tram];
|
||||
} else {
|
||||
if (get_user(val, &icode->tram_data_map[tram]) ||
|
||||
get_user(addr, &icode->tram_addr_map[tram]))
|
||||
if (get_user(val, (__user __u32 *)&icode->tram_data_map[tram]) ||
|
||||
get_user(addr, (__user __u32 *)&icode->tram_addr_map[tram]))
|
||||
return -EFAULT;
|
||||
}
|
||||
snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
|
||||
@ -581,8 +581,8 @@ static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
|
||||
addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
|
||||
addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
|
||||
}
|
||||
if (put_user(val, &icode->tram_data_map[tram]) ||
|
||||
put_user(addr, &icode->tram_addr_map[tram]))
|
||||
if (put_user(val, (__user u32 *)&icode->tram_data_map[tram]) ||
|
||||
put_user(addr, (__user u32 *)&icode->tram_addr_map[tram]))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
@ -598,11 +598,11 @@ static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
|
||||
if (!test_bit(pc / 2, icode->code_valid))
|
||||
continue;
|
||||
if (in_kernel) {
|
||||
lo = *(__force u32 *)&icode->code[pc + 0];
|
||||
hi = *(__force u32 *)&icode->code[pc + 1];
|
||||
lo = icode->code[pc + 0];
|
||||
hi = icode->code[pc + 1];
|
||||
} else {
|
||||
if (get_user(lo, &icode->code[pc + 0]) ||
|
||||
get_user(hi, &icode->code[pc + 1]))
|
||||
if (get_user(lo, (__user u32 *)&icode->code[pc + 0]) ||
|
||||
get_user(hi, (__user u32 *)&icode->code[pc + 1]))
|
||||
return -EFAULT;
|
||||
}
|
||||
snd_emu10k1_efx_write(emu, pc + 0, lo);
|
||||
@ -619,17 +619,21 @@ static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu,
|
||||
memset(icode->code_valid, 0, sizeof(icode->code_valid));
|
||||
for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
|
||||
set_bit(pc / 2, icode->code_valid);
|
||||
if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
|
||||
if (put_user(snd_emu10k1_efx_read(emu, pc + 0),
|
||||
(__user u32 *)&icode->code[pc + 0]))
|
||||
return -EFAULT;
|
||||
if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
|
||||
if (put_user(snd_emu10k1_efx_read(emu, pc + 1),
|
||||
(__user u32 *)&icode->code[pc + 1]))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_emu10k1_fx8010_ctl *
|
||||
snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct emu10k1_ctl_elem_id *id)
|
||||
snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu,
|
||||
struct emu10k1_ctl_elem_id *_id)
|
||||
{
|
||||
struct snd_ctl_elem_id *id = (struct snd_ctl_elem_id *)_id;
|
||||
struct snd_emu10k1_fx8010_ctl *ctl;
|
||||
struct snd_kcontrol *kcontrol;
|
||||
|
||||
@ -672,41 +676,60 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel)
|
||||
}
|
||||
|
||||
static int copy_gctl(struct snd_emu10k1 *emu,
|
||||
struct snd_emu10k1_fx8010_control_gpr *gctl,
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
|
||||
struct snd_emu10k1_fx8010_control_gpr *dst,
|
||||
struct snd_emu10k1_fx8010_control_gpr *src,
|
||||
int idx, bool in_kernel)
|
||||
{
|
||||
struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *_src;
|
||||
struct snd_emu10k1_fx8010_control_old_gpr *octl;
|
||||
struct snd_emu10k1_fx8010_control_old_gpr __user *_octl;
|
||||
|
||||
_src = (struct snd_emu10k1_fx8010_control_gpr __user *)src;
|
||||
if (emu->support_tlv) {
|
||||
if (in_kernel)
|
||||
memcpy(gctl, (__force void *)&_gctl[idx], sizeof(*gctl));
|
||||
else if (copy_from_user(gctl, &_gctl[idx], sizeof(*gctl)))
|
||||
*dst = src[idx];
|
||||
else if (copy_from_user(dst, &_src[idx], sizeof(*src)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
|
||||
octl = (struct snd_emu10k1_fx8010_control_old_gpr *)src;
|
||||
_octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)octl;
|
||||
if (in_kernel)
|
||||
memcpy(gctl, (__force void *)&octl[idx], sizeof(*octl));
|
||||
else if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
|
||||
memcpy(dst, &octl[idx], sizeof(*octl));
|
||||
else if (copy_from_user(dst, &_octl[idx], sizeof(*octl)))
|
||||
return -EFAULT;
|
||||
gctl->tlv = NULL;
|
||||
dst->tlv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_gctl_to_user(struct snd_emu10k1 *emu,
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
|
||||
struct snd_emu10k1_fx8010_control_gpr *gctl,
|
||||
struct snd_emu10k1_fx8010_control_gpr *dst,
|
||||
struct snd_emu10k1_fx8010_control_gpr *src,
|
||||
int idx)
|
||||
{
|
||||
struct snd_emu10k1_fx8010_control_gpr __user *_dst;
|
||||
struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
|
||||
|
||||
_dst = (struct snd_emu10k1_fx8010_control_gpr __user *)dst;
|
||||
if (emu->support_tlv)
|
||||
return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
|
||||
return copy_to_user(&_dst[idx], src, sizeof(*src));
|
||||
|
||||
octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
|
||||
return copy_to_user(&octl[idx], gctl, sizeof(*octl));
|
||||
octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)dst;
|
||||
return copy_to_user(&octl[idx], src, sizeof(*octl));
|
||||
}
|
||||
|
||||
static int copy_ctl_elem_id(const struct emu10k1_ctl_elem_id *list, int i,
|
||||
struct emu10k1_ctl_elem_id *ret, bool in_kernel)
|
||||
{
|
||||
struct emu10k1_ctl_elem_id __user *_id =
|
||||
(struct emu10k1_ctl_elem_id __user *)&list[i];
|
||||
|
||||
if (in_kernel)
|
||||
*ret = list[i];
|
||||
else if (copy_from_user(ret, _id, sizeof(*ret)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
|
||||
@ -714,17 +737,16 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
|
||||
bool in_kernel)
|
||||
{
|
||||
unsigned int i;
|
||||
struct emu10k1_ctl_elem_id __user *_id;
|
||||
struct emu10k1_ctl_elem_id id;
|
||||
struct snd_emu10k1_fx8010_control_gpr *gctl;
|
||||
struct snd_ctl_elem_id *gctl_id;
|
||||
int err;
|
||||
|
||||
_id = (__force struct emu10k1_ctl_elem_id __user *)icode->gpr_del_controls;
|
||||
for (i = 0; i < icode->gpr_del_control_count; i++, _id++) {
|
||||
if (in_kernel)
|
||||
id = *(__force struct emu10k1_ctl_elem_id *)_id;
|
||||
else if (copy_from_user(&id, _id, sizeof(id)))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < icode->gpr_del_control_count; i++) {
|
||||
err = copy_ctl_elem_id(icode->gpr_del_controls, i, &id,
|
||||
in_kernel);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -740,16 +762,16 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
|
||||
}
|
||||
if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
|
||||
continue;
|
||||
gctl_id = (struct snd_ctl_elem_id *)&gctl->id;
|
||||
down_read(&emu->card->controls_rwsem);
|
||||
if (snd_ctl_find_id(emu->card,
|
||||
(struct snd_ctl_elem_id *)&gctl->id)) {
|
||||
if (snd_ctl_find_id(emu->card, gctl_id)) {
|
||||
up_read(&emu->card->controls_rwsem);
|
||||
err = -EEXIST;
|
||||
goto __error;
|
||||
}
|
||||
up_read(&emu->card->controls_rwsem);
|
||||
if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
|
||||
gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
|
||||
if (gctl_id->iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
|
||||
gctl_id->iface != SNDRV_CTL_ELEM_IFACE_PCM) {
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
@ -784,6 +806,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct snd_emu10k1_fx8010_control_gpr *gctl;
|
||||
struct snd_ctl_elem_id *gctl_id;
|
||||
struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
|
||||
struct snd_kcontrol_new knew;
|
||||
struct snd_kcontrol *kctl;
|
||||
@ -804,24 +827,25 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
|
||||
err = -EFAULT;
|
||||
goto __error;
|
||||
}
|
||||
if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
|
||||
gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
|
||||
gctl_id = (struct snd_ctl_elem_id *)&gctl->id;
|
||||
if (gctl_id->iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
|
||||
gctl_id->iface != SNDRV_CTL_ELEM_IFACE_PCM) {
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
if (! gctl->id.name[0]) {
|
||||
if (!*gctl_id->name) {
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
|
||||
memset(&knew, 0, sizeof(knew));
|
||||
knew.iface = gctl->id.iface;
|
||||
knew.name = gctl->id.name;
|
||||
knew.index = gctl->id.index;
|
||||
knew.device = gctl->id.device;
|
||||
knew.subdevice = gctl->id.subdevice;
|
||||
knew.iface = gctl_id->iface;
|
||||
knew.name = gctl_id->name;
|
||||
knew.index = gctl_id->index;
|
||||
knew.device = gctl_id->device;
|
||||
knew.subdevice = gctl_id->subdevice;
|
||||
knew.info = snd_emu10k1_gpr_ctl_info;
|
||||
knew.tlv.p = copy_tlv((__force const unsigned int __user *)gctl->tlv, in_kernel);
|
||||
knew.tlv.p = copy_tlv((const unsigned int __user *)gctl->tlv, in_kernel);
|
||||
if (knew.tlv.p)
|
||||
knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_READ;
|
||||
@ -878,17 +902,15 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
|
||||
{
|
||||
unsigned int i;
|
||||
struct emu10k1_ctl_elem_id id;
|
||||
struct emu10k1_ctl_elem_id __user *_id;
|
||||
struct snd_emu10k1_fx8010_ctl *ctl;
|
||||
struct snd_card *card = emu->card;
|
||||
int err;
|
||||
|
||||
_id = (__force struct emu10k1_ctl_elem_id __user *)icode->gpr_del_controls;
|
||||
|
||||
for (i = 0; i < icode->gpr_del_control_count; i++, _id++) {
|
||||
if (in_kernel)
|
||||
id = *(__force struct emu10k1_ctl_elem_id *)_id;
|
||||
else if (copy_from_user(&id, _id, sizeof(id)))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < icode->gpr_del_control_count; i++) {
|
||||
err = copy_ctl_elem_id(icode->gpr_del_controls, i, &id,
|
||||
in_kernel);
|
||||
if (err < 0)
|
||||
return err;
|
||||
down_write(&card->controls_rwsem);
|
||||
ctl = snd_emu10k1_look_for_ctl(emu, &id);
|
||||
if (ctl)
|
||||
@ -917,7 +939,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
|
||||
i < icode->gpr_list_control_count) {
|
||||
memset(gctl, 0, sizeof(*gctl));
|
||||
id = &ctl->kcontrol->id;
|
||||
gctl->id.iface = id->iface;
|
||||
gctl->id.iface = (__force int)id->iface;
|
||||
strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
|
||||
gctl->id.index = id->index;
|
||||
gctl->id.device = id->device;
|
||||
@ -1095,7 +1117,7 @@ static void
|
||||
snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 1;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
@ -1116,7 +1138,7 @@ static void
|
||||
snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 2;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
@ -1138,7 +1160,7 @@ static void
|
||||
snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 1;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
@ -1151,7 +1173,7 @@ static void
|
||||
snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
|
||||
const char *name, int gpr, int defval)
|
||||
{
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, name);
|
||||
ctl->vcount = ctl->count = 2;
|
||||
ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
|
||||
@ -1204,8 +1226,8 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
|
||||
if (!icode)
|
||||
return err;
|
||||
|
||||
icode->gpr_map = (u_int32_t __user *) kcalloc(512 + 256 + 256 + 2 * 1024,
|
||||
sizeof(u_int32_t), GFP_KERNEL);
|
||||
icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024,
|
||||
sizeof(u_int32_t), GFP_KERNEL);
|
||||
if (!icode->gpr_map)
|
||||
goto __err_gpr;
|
||||
controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
|
||||
@ -1213,7 +1235,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
|
||||
if (!controls)
|
||||
goto __err_ctrls;
|
||||
|
||||
gpr_map = (u32 __force *)icode->gpr_map;
|
||||
gpr_map = icode->gpr_map;
|
||||
|
||||
icode->tram_data_map = icode->gpr_map + 512;
|
||||
icode->tram_addr_map = icode->tram_data_map + 256;
|
||||
@ -1468,7 +1490,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
|
||||
|
||||
|
||||
ctl = &controls[nctl + 0];
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, "Tone Control - Bass");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
@ -1477,7 +1499,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
|
||||
ctl->value[0] = ctl->value[1] = 20;
|
||||
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
|
||||
ctl = &controls[nctl + 1];
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, "Tone Control - Treble");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
@ -1758,7 +1780,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
|
||||
A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
|
||||
|
||||
icode->gpr_add_control_count = nctl;
|
||||
icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
|
||||
icode->gpr_add_controls = controls;
|
||||
emu->support_tlv = 1; /* support TLV */
|
||||
err = snd_emu10k1_icode_poke(emu, icode, true);
|
||||
emu->support_tlv = 0; /* clear again */
|
||||
@ -1766,7 +1788,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
|
||||
__err:
|
||||
kfree(controls);
|
||||
__err_ctrls:
|
||||
kfree((void __force *)icode->gpr_map);
|
||||
kfree(icode->gpr_map);
|
||||
__err_gpr:
|
||||
kfree(icode);
|
||||
return err;
|
||||
@ -1839,8 +1861,8 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
if (!icode)
|
||||
return err;
|
||||
|
||||
icode->gpr_map = (u_int32_t __user *) kcalloc(256 + 160 + 160 + 2 * 512,
|
||||
sizeof(u_int32_t), GFP_KERNEL);
|
||||
icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512,
|
||||
sizeof(u_int32_t), GFP_KERNEL);
|
||||
if (!icode->gpr_map)
|
||||
goto __err_gpr;
|
||||
|
||||
@ -1854,7 +1876,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
if (!ipcm)
|
||||
goto __err_ipcm;
|
||||
|
||||
gpr_map = (u32 __force *)icode->gpr_map;
|
||||
gpr_map = icode->gpr_map;
|
||||
|
||||
icode->tram_data_map = icode->gpr_map + 256;
|
||||
icode->tram_addr_map = icode->tram_data_map + 160;
|
||||
@ -2188,7 +2210,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
|
||||
|
||||
ctl = &controls[i + 0];
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, "Tone Control - Bass");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
@ -2198,7 +2220,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
ctl->tlv = snd_emu10k1_bass_treble_db_scale;
|
||||
ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
|
||||
ctl = &controls[i + 1];
|
||||
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(ctl->id.name, "Tone Control - Treble");
|
||||
ctl->vcount = 2;
|
||||
ctl->count = 10;
|
||||
@ -2384,7 +2406,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
|
||||
goto __err;
|
||||
icode->gpr_add_control_count = i;
|
||||
icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
|
||||
icode->gpr_add_controls = controls;
|
||||
emu->support_tlv = 1; /* support TLV */
|
||||
err = snd_emu10k1_icode_poke(emu, icode, true);
|
||||
emu->support_tlv = 0; /* clear again */
|
||||
@ -2395,7 +2417,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
|
||||
__err_ipcm:
|
||||
kfree(controls);
|
||||
__err_ctrls:
|
||||
kfree((void __force *)icode->gpr_map);
|
||||
kfree(icode->gpr_map);
|
||||
__err_gpr:
|
||||
kfree(icode);
|
||||
return err;
|
||||
|
@ -1110,16 +1110,23 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
|
||||
if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
|
||||
active = true;
|
||||
|
||||
/* clear rirb int */
|
||||
status = azx_readb(chip, RIRBSTS);
|
||||
if (status & RIRB_INT_MASK) {
|
||||
/*
|
||||
* Clearing the interrupt status here ensures that no
|
||||
* interrupt gets masked after the RIRB wp is read in
|
||||
* snd_hdac_bus_update_rirb. This avoids a possible
|
||||
* race condition where codec response in RIRB may
|
||||
* remain unserviced by IRQ, eventually falling back
|
||||
* to polling mode in azx_rirb_get_response.
|
||||
*/
|
||||
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
|
||||
active = true;
|
||||
if (status & RIRB_INT_RESPONSE) {
|
||||
if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
|
||||
udelay(80);
|
||||
snd_hdac_bus_update_rirb(bus);
|
||||
}
|
||||
azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
|
||||
}
|
||||
} while (active && ++repeat < 10);
|
||||
|
||||
|
@ -2451,6 +2451,8 @@ static const struct pci_device_id azx_ids[] = {
|
||||
/* Jasperlake */
|
||||
{ PCI_DEVICE(0x8086, 0x38c8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
{ PCI_DEVICE(0x8086, 0x4dc8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
/* Tigerlake */
|
||||
{ PCI_DEVICE(0x8086, 0xa0c8),
|
||||
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
|
||||
|
@ -1550,6 +1550,34 @@ static bool update_eld(struct hda_codec *codec,
|
||||
return eld_changed;
|
||||
}
|
||||
|
||||
static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct snd_jack *jack = NULL;
|
||||
struct hda_jack_tbl *jack_tbl;
|
||||
|
||||
/* if !dyn_pcm_assign, get jack from hda_jack_tbl
|
||||
* in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
|
||||
* NULL even after snd_hda_jack_tbl_clear() is called to
|
||||
* free snd_jack. This may cause access invalid memory
|
||||
* when calling snd_jack_report
|
||||
*/
|
||||
if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign) {
|
||||
jack = spec->pcm_rec[per_pin->pcm_idx].jack;
|
||||
} else if (!spec->dyn_pcm_assign) {
|
||||
/*
|
||||
* jack tbl doesn't support DP MST
|
||||
* DP MST will use dyn_pcm_assign,
|
||||
* so DP MST will never come here
|
||||
*/
|
||||
jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
|
||||
per_pin->dev_id);
|
||||
if (jack_tbl)
|
||||
jack = jack_tbl->jack;
|
||||
}
|
||||
return jack;
|
||||
}
|
||||
/* update ELD and jack state via HD-audio verbs */
|
||||
static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
int repoll)
|
||||
@ -1571,6 +1599,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
int present;
|
||||
bool ret;
|
||||
bool do_repoll = false;
|
||||
struct snd_jack *pcm_jack = NULL;
|
||||
|
||||
present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
|
||||
|
||||
@ -1598,10 +1627,19 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
do_repoll = true;
|
||||
}
|
||||
|
||||
if (do_repoll)
|
||||
if (do_repoll) {
|
||||
schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300));
|
||||
else
|
||||
} else {
|
||||
/*
|
||||
* pcm_idx >=0 before update_eld() means it is in monitor
|
||||
* disconnected event. Jack must be fetched before
|
||||
* update_eld().
|
||||
*/
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
update_eld(codec, per_pin, eld);
|
||||
if (!pcm_jack)
|
||||
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
}
|
||||
|
||||
ret = !repoll || !eld->monitor_present || eld->eld_valid;
|
||||
|
||||
@ -1610,40 +1648,34 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
|
||||
jack->block_report = !ret;
|
||||
jack->pin_sense = (eld->monitor_present && eld->eld_valid) ?
|
||||
AC_PINSENSE_PRESENCE : 0;
|
||||
|
||||
if (spec->dyn_pcm_assign && pcm_jack && !do_repoll) {
|
||||
int state = 0;
|
||||
|
||||
if (jack->pin_sense & AC_PINSENSE_PRESENCE)
|
||||
state = SND_JACK_AVOUT;
|
||||
snd_jack_report(pcm_jack, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* snd_hda_jack_pin_sense() call at the beginning of this
|
||||
* function, updates jack->pins_sense and clears
|
||||
* jack->jack_dirty, therefore snd_hda_jack_report_sync() will
|
||||
* not override the jack->pin_sense.
|
||||
*
|
||||
* snd_hda_jack_report_sync() is superfluous for dyn_pcm_assign
|
||||
* case. The jack->pin_sense update was already performed, and
|
||||
* hda_jack->jack is NULL for dyn_pcm_assign.
|
||||
*
|
||||
* Don't call snd_hda_jack_report_sync() for
|
||||
* dyn_pcm_assign.
|
||||
*/
|
||||
ret = ret && !spec->dyn_pcm_assign;
|
||||
}
|
||||
mutex_unlock(&per_pin->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct snd_jack *jack = NULL;
|
||||
struct hda_jack_tbl *jack_tbl;
|
||||
|
||||
/* if !dyn_pcm_assign, get jack from hda_jack_tbl
|
||||
* in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
|
||||
* NULL even after snd_hda_jack_tbl_clear() is called to
|
||||
* free snd_jack. This may cause access invalid memory
|
||||
* when calling snd_jack_report
|
||||
*/
|
||||
if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign)
|
||||
jack = spec->pcm_rec[per_pin->pcm_idx].jack;
|
||||
else if (!spec->dyn_pcm_assign) {
|
||||
/*
|
||||
* jack tbl doesn't support DP MST
|
||||
* DP MST will use dyn_pcm_assign,
|
||||
* so DP MST will never come here
|
||||
*/
|
||||
jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
|
||||
per_pin->dev_id);
|
||||
if (jack_tbl)
|
||||
jack = jack_tbl->jack;
|
||||
}
|
||||
return jack;
|
||||
}
|
||||
|
||||
/* update ELD and jack state via audio component */
|
||||
static void sync_eld_via_acomp(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin)
|
||||
@ -1677,10 +1709,10 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
|
||||
/* pcm_idx >=0 before update_eld() means it is in monitor
|
||||
* disconnected event. Jack must be fetched before update_eld()
|
||||
*/
|
||||
jack = pin_idx_to_jack(codec, per_pin);
|
||||
jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
changed = update_eld(codec, per_pin, eld);
|
||||
if (jack == NULL)
|
||||
jack = pin_idx_to_jack(codec, per_pin);
|
||||
jack = pin_idx_to_pcm_jack(codec, per_pin);
|
||||
if (changed && jack)
|
||||
snd_jack_report(jack,
|
||||
(eld->monitor_present && eld->eld_valid) ?
|
||||
@ -4256,6 +4288,7 @@ HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
|
||||
|
@ -9111,6 +9111,7 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
|
||||
SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
|
||||
{0x14, 0x01014010},
|
||||
{0x17, 0x90170150},
|
||||
{0x19, 0x02a11060},
|
||||
{0x1b, 0x01813030},
|
||||
{0x21, 0x02211020}),
|
||||
SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
|
||||
|
@ -4802,7 +4802,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
|
||||
break;
|
||||
}
|
||||
case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
|
||||
struct hdsp_firmware __user *firmware;
|
||||
struct hdsp_firmware firmware;
|
||||
u32 __user *firmware_data;
|
||||
int err;
|
||||
|
||||
@ -4815,10 +4815,9 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
|
||||
|
||||
dev_info(hdsp->card->dev,
|
||||
"initializing firmware upload\n");
|
||||
firmware = (struct hdsp_firmware __user *)argp;
|
||||
|
||||
if (get_user(firmware_data, (__force void __user **)&firmware->firmware_data))
|
||||
if (copy_from_user(&firmware, argp, sizeof(firmware)))
|
||||
return -EFAULT;
|
||||
firmware_data = (u32 __user *)firmware.firmware_data;
|
||||
|
||||
if (hdsp_check_for_iobox (hdsp))
|
||||
return -EIO;
|
||||
|
@ -234,30 +234,32 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_ITER;
|
||||
ier_val = mmACP_BTTDM_IER;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_ITER;
|
||||
ier_val = mmACP_I2STDM_IER;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (rtd->i2s_instance) {
|
||||
case I2S_BT_INSTANCE:
|
||||
reg_val = mmACP_BTTDM_IRER;
|
||||
ier_val = mmACP_BTTDM_IER;
|
||||
break;
|
||||
case I2S_SP_INSTANCE:
|
||||
default:
|
||||
reg_val = mmACP_I2STDM_IRER;
|
||||
ier_val = mmACP_I2STDM_IER;
|
||||
}
|
||||
}
|
||||
val = rv_readl(rtd->acp3x_base + reg_val);
|
||||
val = val & ~BIT(0);
|
||||
rv_writel(val, rtd->acp3x_base + reg_val);
|
||||
rv_writel(0, rtd->acp3x_base + ier_val);
|
||||
|
||||
if (!(rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER) & BIT(0)) &&
|
||||
!(rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER) & BIT(0)))
|
||||
rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
|
||||
if (!(rv_readl(rtd->acp3x_base + mmACP_I2STDM_ITER) & BIT(0)) &&
|
||||
!(rv_readl(rtd->acp3x_base + mmACP_I2STDM_IRER) & BIT(0)))
|
||||
rv_writel(0, rtd->acp3x_base + mmACP_I2STDM_IER);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
|
@ -349,13 +349,6 @@ static int acp3x_dma_close(struct snd_soc_component *component,
|
||||
component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
|
||||
adata = dev_get_drvdata(component->dev);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
adata->play_stream = NULL;
|
||||
adata->i2ssp_play_stream = NULL;
|
||||
} else {
|
||||
adata->capture_stream = NULL;
|
||||
adata->i2ssp_capture_stream = NULL;
|
||||
}
|
||||
|
||||
/* Disable ACP irq, when the current stream is being closed and
|
||||
* another stream is also not active.
|
||||
@ -363,6 +356,13 @@ static int acp3x_dma_close(struct snd_soc_component *component,
|
||||
if (!adata->play_stream && !adata->capture_stream &&
|
||||
!adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
|
||||
rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
adata->play_stream = NULL;
|
||||
adata->i2ssp_play_stream = NULL;
|
||||
} else {
|
||||
adata->capture_stream = NULL;
|
||||
adata->i2ssp_capture_stream = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ config SND_SOC_ALL_CODECS
|
||||
select SND_SOC_UDA134X
|
||||
select SND_SOC_UDA1380 if I2C
|
||||
select SND_SOC_WCD9335 if SLIMBUS
|
||||
select SND_SOC_WCD934X if MFD_WCD934X
|
||||
select SND_SOC_WCD934X if MFD_WCD934X && COMMON_CLK
|
||||
select SND_SOC_WL1273 if MFD_WL1273_CORE
|
||||
select SND_SOC_WM0010 if SPI_MASTER
|
||||
select SND_SOC_WM1250_EV1 if I2C
|
||||
@ -1334,6 +1334,7 @@ config SND_SOC_WCD9335
|
||||
|
||||
config SND_SOC_WCD934X
|
||||
tristate "WCD9340/WCD9341 Codec"
|
||||
depends on COMMON_CLK
|
||||
depends on MFD_WCD934X
|
||||
help
|
||||
The WCD9340/9341 is a audio codec IC Integrated in
|
||||
|
@ -52,7 +52,8 @@ static void max98090_shdn_restore_locked(struct max98090_priv *max98090)
|
||||
|
||||
static void max98090_shdn_save(struct max98090_priv *max98090)
|
||||
{
|
||||
mutex_lock(&max98090->component->card->dapm_mutex);
|
||||
mutex_lock_nested(&max98090->component->card->dapm_mutex,
|
||||
SND_SOC_DAPM_CLASS_RUNTIME);
|
||||
max98090_shdn_save_locked(max98090);
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ static const char * const rt1015_boost_mode[] = {
|
||||
"Bypass", "Adaptive", "Fixed Adaptive"
|
||||
};
|
||||
|
||||
static const SOC_ENUM_SINGLE_DECL(rt1015_boost_mode_enum, 0, 0,
|
||||
static SOC_ENUM_SINGLE_DECL(rt1015_boost_mode_enum, 0, 0,
|
||||
rt1015_boost_mode);
|
||||
|
||||
static int rt1015_boost_mode_get(struct snd_kcontrol *kcontrol,
|
||||
|
@ -673,7 +673,7 @@ static const struct sdw_device_id rt1308_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, rt1308_id);
|
||||
|
||||
static int rt1308_dev_suspend(struct device *dev)
|
||||
static int __maybe_unused rt1308_dev_suspend(struct device *dev)
|
||||
{
|
||||
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
|
||||
|
||||
@ -687,7 +687,7 @@ static int rt1308_dev_suspend(struct device *dev)
|
||||
|
||||
#define RT1308_PROBE_TIMEOUT 2000
|
||||
|
||||
static int rt1308_dev_resume(struct device *dev)
|
||||
static int __maybe_unused rt1308_dev_resume(struct device *dev)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(dev);
|
||||
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
|
||||
|
@ -486,7 +486,7 @@ static const struct sdw_device_id rt700_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, rt700_id);
|
||||
|
||||
static int rt700_dev_suspend(struct device *dev)
|
||||
static int __maybe_unused rt700_dev_suspend(struct device *dev)
|
||||
{
|
||||
struct rt700_priv *rt700 = dev_get_drvdata(dev);
|
||||
|
||||
@ -500,7 +500,7 @@ static int rt700_dev_suspend(struct device *dev)
|
||||
|
||||
#define RT700_PROBE_TIMEOUT 2000
|
||||
|
||||
static int rt700_dev_resume(struct device *dev)
|
||||
static int __maybe_unused rt700_dev_resume(struct device *dev)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(dev);
|
||||
struct rt700_priv *rt700 = dev_get_drvdata(dev);
|
||||
|
@ -487,7 +487,7 @@ static const struct sdw_device_id rt711_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, rt711_id);
|
||||
|
||||
static int rt711_dev_suspend(struct device *dev)
|
||||
static int __maybe_unused rt711_dev_suspend(struct device *dev)
|
||||
{
|
||||
struct rt711_priv *rt711 = dev_get_drvdata(dev);
|
||||
|
||||
@ -501,7 +501,7 @@ static int rt711_dev_suspend(struct device *dev)
|
||||
|
||||
#define RT711_PROBE_TIMEOUT 2000
|
||||
|
||||
static int rt711_dev_resume(struct device *dev)
|
||||
static int __maybe_unused rt711_dev_resume(struct device *dev)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(dev);
|
||||
struct rt711_priv *rt711 = dev_get_drvdata(dev);
|
||||
|
@ -549,7 +549,7 @@ static const struct sdw_device_id rt715_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdw, rt715_id);
|
||||
|
||||
static int rt715_dev_suspend(struct device *dev)
|
||||
static int __maybe_unused rt715_dev_suspend(struct device *dev)
|
||||
{
|
||||
struct rt715_priv *rt715 = dev_get_drvdata(dev);
|
||||
|
||||
@ -563,7 +563,7 @@ static int rt715_dev_suspend(struct device *dev)
|
||||
|
||||
#define RT715_PROBE_TIMEOUT 2000
|
||||
|
||||
static int rt715_dev_resume(struct device *dev)
|
||||
static int __maybe_unused rt715_dev_resume(struct device *dev)
|
||||
{
|
||||
struct sdw_slave *slave = dev_to_sdw_dev(dev);
|
||||
struct rt715_priv *rt715 = dev_get_drvdata(dev);
|
||||
|
@ -617,12 +617,15 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
|
||||
snd_soc_dapm_add_routes(&card->dapm, broxton_map,
|
||||
ARRAY_SIZE(broxton_map));
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->common_hdmi_codec_drv)
|
||||
if (ctx->common_hdmi_codec_drv) {
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
return hda_dsp_hdmi_build_controls(card, component);
|
||||
}
|
||||
|
||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||
component = pcm->codec_dai->component;
|
||||
@ -643,9 +646,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!component)
|
||||
return -EINVAL;
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
||||
|
@ -529,12 +529,15 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
|
||||
int err, i = 0;
|
||||
char jack_name[NAME_SIZE];
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->common_hdmi_codec_drv)
|
||||
if (ctx->common_hdmi_codec_drv) {
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct bxt_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
return hda_dsp_hdmi_build_controls(card, component);
|
||||
}
|
||||
|
||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||
component = pcm->codec_dai->component;
|
||||
@ -555,9 +558,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!component)
|
||||
return -EINVAL;
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
||||
|
@ -241,12 +241,15 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
struct hdmi_pcm *pcm;
|
||||
int ret, i = 0;
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->common_hdmi_codec_drv)
|
||||
if (ctx->common_hdmi_codec_drv) {
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
return hda_dsp_hdmi_build_controls(card, component);
|
||||
}
|
||||
|
||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||
component = pcm->codec_dai->component;
|
||||
@ -265,8 +268,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
|
||||
i++;
|
||||
}
|
||||
if (!component)
|
||||
return -EINVAL;
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
@ -534,15 +534,18 @@ static int glk_card_late_probe(struct snd_soc_card *card)
|
||||
struct snd_soc_component *component = NULL;
|
||||
char jack_name[NAME_SIZE];
|
||||
struct glk_hdmi_pcm *pcm;
|
||||
int err = 0;
|
||||
int err;
|
||||
int i = 0;
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct glk_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->common_hdmi_codec_drv)
|
||||
if (ctx->common_hdmi_codec_drv) {
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct glk_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
return hda_dsp_hdmi_build_controls(card, component);
|
||||
}
|
||||
|
||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||
component = pcm->codec_dai->component;
|
||||
@ -563,9 +566,6 @@ static int glk_card_late_probe(struct snd_soc_card *card)
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!component)
|
||||
return -EINVAL;
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
||||
|
@ -273,19 +273,22 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
struct snd_soc_component *component = NULL;
|
||||
char jack_name[NAME_SIZE];
|
||||
struct sof_hdmi_pcm *pcm;
|
||||
int err = 0;
|
||||
int err;
|
||||
int i = 0;
|
||||
|
||||
/* HDMI is not supported by SOF on Baytrail/CherryTrail */
|
||||
if (is_legacy_cpu)
|
||||
return 0;
|
||||
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
if (list_empty(&ctx->hdmi_pcm_list))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->common_hdmi_codec_drv)
|
||||
if (ctx->common_hdmi_codec_drv) {
|
||||
pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
|
||||
head);
|
||||
component = pcm->codec_dai->component;
|
||||
return hda_dsp_hdmi_build_controls(card, component);
|
||||
}
|
||||
|
||||
list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
|
||||
component = pcm->codec_dai->component;
|
||||
@ -305,8 +308,6 @@ static int sof_card_late_probe(struct snd_soc_card *card)
|
||||
|
||||
i++;
|
||||
}
|
||||
if (!component)
|
||||
return -EINVAL;
|
||||
|
||||
return hdac_hdmi_jack_port_init(component, &card->dapm);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ static const u64 rt1308_2_adr[] = {
|
||||
};
|
||||
|
||||
static const u64 rt715_3_adr[] = {
|
||||
0x000310025D715000
|
||||
0x000310025D071500
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr icl_3_in_1_default[] = {
|
||||
|
@ -224,12 +224,12 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev,
|
||||
"error: failed to register DSP DAI driver %d\n", ret);
|
||||
goto fw_run_err;
|
||||
goto fw_trace_err;
|
||||
}
|
||||
|
||||
ret = snd_sof_machine_register(sdev, plat_data);
|
||||
if (ret < 0)
|
||||
goto fw_run_err;
|
||||
goto fw_trace_err;
|
||||
|
||||
/*
|
||||
* Some platforms in SOF, ex: BYT, may not have their platform PM
|
||||
@ -244,7 +244,8 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
||||
|
||||
return 0;
|
||||
|
||||
#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
|
||||
fw_trace_err:
|
||||
snd_sof_free_trace(sdev);
|
||||
fw_run_err:
|
||||
snd_sof_fw_unload(sdev);
|
||||
fw_load_err:
|
||||
@ -253,21 +254,10 @@ static int sof_probe_continue(struct snd_sof_dev *sdev)
|
||||
snd_sof_free_debug(sdev);
|
||||
dbg_err:
|
||||
snd_sof_remove(sdev);
|
||||
#else
|
||||
|
||||
/*
|
||||
* when the probe_continue is handled in a work queue, the
|
||||
* probe does not fail so we don't release resources here.
|
||||
* They will be released with an explicit call to
|
||||
* snd_sof_device_remove() when the PCI/ACPI device is removed
|
||||
*/
|
||||
|
||||
fw_run_err:
|
||||
fw_load_err:
|
||||
ipc_err:
|
||||
dbg_err:
|
||||
|
||||
#endif
|
||||
/* all resources freed, update state to match */
|
||||
sdev->fw_state = SOF_FW_BOOT_NOT_STARTED;
|
||||
sdev->first_boot = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -350,10 +340,12 @@ int snd_sof_device_remove(struct device *dev)
|
||||
if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE))
|
||||
cancel_work_sync(&sdev->probe_work);
|
||||
|
||||
snd_sof_fw_unload(sdev);
|
||||
snd_sof_ipc_free(sdev);
|
||||
snd_sof_free_debug(sdev);
|
||||
snd_sof_free_trace(sdev);
|
||||
if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) {
|
||||
snd_sof_fw_unload(sdev);
|
||||
snd_sof_ipc_free(sdev);
|
||||
snd_sof_free_debug(sdev);
|
||||
snd_sof_free_trace(sdev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregister machine driver. This will unbind the snd_card which
|
||||
@ -361,13 +353,15 @@ int snd_sof_device_remove(struct device *dev)
|
||||
* before freeing the snd_card.
|
||||
*/
|
||||
snd_sof_machine_unregister(sdev, pdata);
|
||||
|
||||
/*
|
||||
* Unregistering the machine driver results in unloading the topology.
|
||||
* Some widgets, ex: scheduler, attempt to power down the core they are
|
||||
* scheduled on, when they are unloaded. Therefore, the DSP must be
|
||||
* removed only after the topology has been unloaded.
|
||||
*/
|
||||
snd_sof_remove(sdev);
|
||||
if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED)
|
||||
snd_sof_remove(sdev);
|
||||
|
||||
/* release firmware */
|
||||
release_firmware(pdata->fw);
|
||||
|
@ -170,23 +170,14 @@ EXPORT_SYMBOL_NS(hda_codec_probe_bus, SND_SOC_SOF_HDA_AUDIO_CODEC);
|
||||
#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) || \
|
||||
IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)
|
||||
|
||||
void hda_codec_i915_get(struct snd_sof_dev *sdev)
|
||||
void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
|
||||
{
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
|
||||
dev_dbg(bus->dev, "Turning i915 HDAC power on\n");
|
||||
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
|
||||
dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
|
||||
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(hda_codec_i915_get, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
|
||||
|
||||
void hda_codec_i915_put(struct snd_sof_dev *sdev)
|
||||
{
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
|
||||
dev_dbg(bus->dev, "Turning i915 HDAC power off\n");
|
||||
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(hda_codec_i915_put, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
|
||||
EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
|
||||
|
||||
int hda_codec_i915_init(struct snd_sof_dev *sdev)
|
||||
{
|
||||
@ -198,7 +189,7 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hda_codec_i915_get(sdev);
|
||||
hda_codec_i915_display_power(sdev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -209,7 +200,7 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
int ret;
|
||||
|
||||
hda_codec_i915_put(sdev);
|
||||
hda_codec_i915_display_power(sdev, false);
|
||||
|
||||
ret = snd_hdac_i915_exit(bus);
|
||||
|
||||
|
@ -380,7 +380,8 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
|
||||
/* create codec instances */
|
||||
hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
|
||||
|
||||
hda_codec_i915_put(sdev);
|
||||
if (!HDA_IDISP_CODEC(bus->codec_mask))
|
||||
hda_codec_i915_display_power(sdev, false);
|
||||
|
||||
/*
|
||||
* we are done probing so decrement link counts
|
||||
|
@ -586,15 +586,14 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev);
|
||||
(IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) || \
|
||||
IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
|
||||
|
||||
void hda_codec_i915_get(struct snd_sof_dev *sdev);
|
||||
void hda_codec_i915_put(struct snd_sof_dev *sdev);
|
||||
void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable);
|
||||
int hda_codec_i915_init(struct snd_sof_dev *sdev);
|
||||
int hda_codec_i915_exit(struct snd_sof_dev *sdev);
|
||||
|
||||
#else
|
||||
|
||||
static inline void hda_codec_i915_get(struct snd_sof_dev *sdev) { }
|
||||
static inline void hda_codec_i915_put(struct snd_sof_dev *sdev) { }
|
||||
static inline void hda_codec_i915_display_power(struct snd_sof_dev *sdev,
|
||||
bool enable) { }
|
||||
static inline int hda_codec_i915_init(struct snd_sof_dev *sdev) { return 0; }
|
||||
static inline int hda_codec_i915_exit(struct snd_sof_dev *sdev) { return 0; }
|
||||
|
||||
|
@ -591,6 +591,11 @@ static int sof_pcm_new(struct snd_soc_component *component,
|
||||
"spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
|
||||
caps->name, caps->buffer_size_min, caps->buffer_size_max);
|
||||
|
||||
if (!pcm->streams[stream].substream) {
|
||||
dev_err(component->dev, "error: NULL playback substream!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
|
||||
SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
|
||||
le32_to_cpu(caps->buffer_size_min),
|
||||
@ -609,6 +614,11 @@ static int sof_pcm_new(struct snd_soc_component *component,
|
||||
"spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
|
||||
caps->name, caps->buffer_size_min, caps->buffer_size_max);
|
||||
|
||||
if (!pcm->streams[stream].substream) {
|
||||
dev_err(component->dev, "error: NULL capture substream!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_pcm_set_managed_buffer(pcm->streams[stream].substream,
|
||||
SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
|
||||
le32_to_cpu(caps->buffer_size_min),
|
||||
|
@ -56,6 +56,10 @@ static int sof_resume(struct device *dev, bool runtime_resume)
|
||||
if (!sof_ops(sdev)->resume || !sof_ops(sdev)->runtime_resume)
|
||||
return 0;
|
||||
|
||||
/* DSP was never successfully started, nothing to resume */
|
||||
if (sdev->first_boot)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if the runtime_resume flag is set, call the runtime_resume routine
|
||||
* or else call the system resume routine
|
||||
|
@ -235,6 +235,7 @@ static const struct sof_dev_desc jsl_desc = {
|
||||
.chip_info = &jsl_chip_info,
|
||||
.default_fw_path = "intel/sof",
|
||||
.default_tplg_path = "intel/sof-tplg",
|
||||
.default_fw_filename = "sof-jsl.ri",
|
||||
.nocodec_tplg_filename = "sof-jsl-nocodec.tplg",
|
||||
.ops = &sof_cnl_ops,
|
||||
};
|
||||
@ -416,6 +417,8 @@ static const struct pci_device_id sof_pci_ids[] = {
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
|
||||
{ PCI_DEVICE(0x8086, 0x38c8),
|
||||
.driver_data = (unsigned long)&jsl_desc},
|
||||
{ PCI_DEVICE(0x8086, 0x4dc8),
|
||||
.driver_data = (unsigned long)&jsl_desc},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
|
||||
{ PCI_DEVICE(0x8086, 0x02c8),
|
||||
|
@ -343,7 +343,10 @@ void snd_sof_free_trace(struct snd_sof_dev *sdev)
|
||||
|
||||
snd_sof_release_trace(sdev);
|
||||
|
||||
snd_dma_free_pages(&sdev->dmatb);
|
||||
snd_dma_free_pages(&sdev->dmatp);
|
||||
if (sdev->dma_trace_pages) {
|
||||
snd_dma_free_pages(&sdev->dmatb);
|
||||
snd_dma_free_pages(&sdev->dmatp);
|
||||
sdev->dma_trace_pages = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(snd_sof_free_trace);
|
||||
|
@ -127,7 +127,7 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct device *dev = dai->dev;
|
||||
struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||
unsigned int mask, val, reg;
|
||||
int ret, sample_size, srate, i2sclock, bitcnt, audio_bits;
|
||||
int ret, sample_size, srate, i2sclock, bitcnt;
|
||||
struct tegra30_ahub_cif_conf cif_conf;
|
||||
|
||||
if (params_channels(params) != 2)
|
||||
@ -137,19 +137,8 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
val = TEGRA30_I2S_CTRL_BIT_SIZE_16;
|
||||
audio_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
sample_size = 16;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
val = TEGRA30_I2S_CTRL_BIT_SIZE_24;
|
||||
audio_bits = TEGRA30_AUDIOCIF_BITS_24;
|
||||
sample_size = 24;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
val = TEGRA30_I2S_CTRL_BIT_SIZE_32;
|
||||
audio_bits = TEGRA30_AUDIOCIF_BITS_32;
|
||||
sample_size = 32;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -181,8 +170,8 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
cif_conf.threshold = 0;
|
||||
cif_conf.audio_channels = 2;
|
||||
cif_conf.client_channels = 2;
|
||||
cif_conf.audio_bits = audio_bits;
|
||||
cif_conf.client_bits = audio_bits;
|
||||
cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
|
||||
cif_conf.expand = 0;
|
||||
cif_conf.stereo_conv = 0;
|
||||
cif_conf.replicate = 0;
|
||||
@ -317,18 +306,14 @@ static const struct snd_soc_dai_driver tegra30_i2s_dai_template = {
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "Capture",
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_96000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.ops = &tegra30_i2s_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
|
@ -558,11 +558,11 @@ static const struct scarlett2_config
|
||||
|
||||
/* proprietary request/response format */
|
||||
struct scarlett2_usb_packet {
|
||||
u32 cmd;
|
||||
u16 size;
|
||||
u16 seq;
|
||||
u32 error;
|
||||
u32 pad;
|
||||
__le32 cmd;
|
||||
__le16 size;
|
||||
__le16 seq;
|
||||
__le32 error;
|
||||
__le32 pad;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
@ -664,11 +664,11 @@ static int scarlett2_usb(
|
||||
"Scarlett Gen 2 USB invalid response; "
|
||||
"cmd tx/rx %d/%d seq %d/%d size %d/%d "
|
||||
"error %d pad %d\n",
|
||||
le16_to_cpu(req->cmd), le16_to_cpu(resp->cmd),
|
||||
le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd),
|
||||
le16_to_cpu(req->seq), le16_to_cpu(resp->seq),
|
||||
resp_size, le16_to_cpu(resp->size),
|
||||
le16_to_cpu(resp->error),
|
||||
le16_to_cpu(resp->pad));
|
||||
le32_to_cpu(resp->error),
|
||||
le32_to_cpu(resp->pad));
|
||||
err = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
@ -687,7 +687,7 @@ static int scarlett2_usb(
|
||||
/* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */
|
||||
static void scarlett2_config_save(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
u32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
|
||||
__le32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
|
||||
|
||||
scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
|
||||
&req, sizeof(u32),
|
||||
@ -713,11 +713,11 @@ static int scarlett2_usb_set_config(
|
||||
const struct scarlett2_config config_item =
|
||||
scarlett2_config_items[config_item_num];
|
||||
struct {
|
||||
u32 offset;
|
||||
u32 bytes;
|
||||
s32 value;
|
||||
__le32 offset;
|
||||
__le32 bytes;
|
||||
__le32 value;
|
||||
} __packed req;
|
||||
u32 req2;
|
||||
__le32 req2;
|
||||
int err;
|
||||
struct scarlett2_mixer_data *private = mixer->private_data;
|
||||
|
||||
@ -753,8 +753,8 @@ static int scarlett2_usb_get(
|
||||
int offset, void *buf, int size)
|
||||
{
|
||||
struct {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
__le32 offset;
|
||||
__le32 size;
|
||||
} __packed req;
|
||||
|
||||
req.offset = cpu_to_le32(offset);
|
||||
@ -794,8 +794,8 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer,
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
|
||||
struct {
|
||||
u16 mix_num;
|
||||
u16 data[SCARLETT2_INPUT_MIX_MAX];
|
||||
__le16 mix_num;
|
||||
__le16 data[SCARLETT2_INPUT_MIX_MAX];
|
||||
} __packed req;
|
||||
|
||||
int i, j;
|
||||
@ -850,9 +850,9 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer)
|
||||
};
|
||||
|
||||
struct {
|
||||
u16 pad;
|
||||
u16 num;
|
||||
u32 data[SCARLETT2_MUX_MAX];
|
||||
__le16 pad;
|
||||
__le16 num;
|
||||
__le32 data[SCARLETT2_MUX_MAX];
|
||||
} __packed req;
|
||||
|
||||
req.pad = 0;
|
||||
@ -911,9 +911,9 @@ static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer,
|
||||
u16 *levels)
|
||||
{
|
||||
struct {
|
||||
u16 pad;
|
||||
u16 num_meters;
|
||||
u32 magic;
|
||||
__le16 pad;
|
||||
__le16 num_meters;
|
||||
__le32 magic;
|
||||
} __packed req;
|
||||
u32 resp[SCARLETT2_NUM_METERS];
|
||||
int i, err;
|
||||
|
@ -110,7 +110,7 @@ static bool validate_processing_unit(const void *p,
|
||||
default:
|
||||
if (v->type == UAC1_EXTENSION_UNIT)
|
||||
return true; /* OK */
|
||||
switch (d->wProcessType) {
|
||||
switch (le16_to_cpu(d->wProcessType)) {
|
||||
case UAC_PROCESS_UP_DOWNMIX:
|
||||
case UAC_PROCESS_DOLBY_PROLOGIC:
|
||||
if (d->bLength < len + 1) /* bNrModes */
|
||||
@ -125,7 +125,7 @@ static bool validate_processing_unit(const void *p,
|
||||
case UAC_VERSION_2:
|
||||
if (v->type == UAC2_EXTENSION_UNIT_V2)
|
||||
return true; /* OK */
|
||||
switch (d->wProcessType) {
|
||||
switch (le16_to_cpu(d->wProcessType)) {
|
||||
case UAC2_PROCESS_UP_DOWNMIX:
|
||||
case UAC2_PROCESS_DOLBY_PROLOCIC: /* SiC! */
|
||||
if (d->bLength < len + 1) /* bNrModes */
|
||||
@ -142,7 +142,7 @@ static bool validate_processing_unit(const void *p,
|
||||
len += 2; /* wClusterDescrID */
|
||||
break;
|
||||
}
|
||||
switch (d->wProcessType) {
|
||||
switch (le16_to_cpu(d->wProcessType)) {
|
||||
case UAC3_PROCESS_UP_DOWNMIX:
|
||||
if (d->bLength < len + 1) /* bNrModes */
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user