2019-05-27 08:55:06 +02:00
/* SPDX-License-Identifier: GPL-2.0-or-later */
2014-02-28 15:41:22 -08:00
/*
* Common functionality for the alsa driver code base for HD Audio .
*/
# ifndef __SOUND_HDA_CONTROLLER_H
# define __SOUND_HDA_CONTROLLER_H
2015-02-19 18:04:17 +01:00
# include <linux/timecounter.h>
# include <linux/interrupt.h>
2014-02-28 15:41:22 -08:00
# include <sound/core.h>
2015-02-19 18:04:17 +01:00
# include <sound/pcm.h>
2014-02-28 15:41:22 -08:00
# include <sound/initval.h>
2018-08-22 15:24:57 -05:00
# include <sound/hda_codec.h>
2015-04-14 12:15:47 +02:00
# include <sound/hda_register.h>
2015-02-19 18:04:17 +01:00
2015-04-14 12:15:47 +02:00
# define AZX_MAX_CODECS HDA_MAX_CODECS
2015-02-19 18:04:17 +01:00
# define AZX_DEFAULT_CODECS 4
/* driver quirks (capabilities) */
/* bits 0-7 are used for indicating driver type */
# define AZX_DCAPS_NO_TCSEL (1 << 8) /* No Intel TCSEL bit */
# define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */
# define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */
# define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */
2017-06-29 16:18:12 +02:00
# ifdef CONFIG_SND_HDA_I915
# define AZX_DCAPS_I915_COMPONENT (1 << 13) /* bind with i915 gfx */
# else
# define AZX_DCAPS_I915_COMPONENT 0 /* NOP */
# endif
2018-12-31 19:02:01 +01:00
/* 14 unused */
2015-02-19 18:04:17 +01:00
# define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
# define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
ALSA: hda - Workaround for crackled sound on AMD controller (1022:1457)
A long-time problem on the recent AMD chip (X370, X470, B450, etc with
PCI ID 1022:1457) with Realtek codecs is the crackled or distorted
sound for capture streams, as well as occasional playback hiccups.
After lengthy debugging sessions, the workarounds we've found are like
the following:
- Set up the proper driver caps for this controller, similar as the
other AMD controller.
- Correct the DMA position reporting with the fixed FIFO size, which
is similar like as workaround used for VIA chip set.
- Even after the position correction, PulseAudio still shows
mysterious stalls of playback streams when a capture is triggered in
timer-scheduled mode. Since we have no clear way to eliminate the
stall, pass the BATCH PCM flag for PA to suppress the tsched mode as
a temporary workaround.
This patch implements the workarounds. For the driver caps, it
defines a new preset, AXZ_DCAPS_PRESET_AMD_SB. It enables the FIFO-
corrected position reporting (corresponding to the new position_fix=6)
and enforces the SNDRV_PCM_INFO_BATCH flag.
Note that the current implementation is merely a workaround.
Hopefully we'll find a better alternative in future, especially about
removing the BATCH flag hack again.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=195303
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2019-08-06 17:31:48 +02:00
# define AZX_DCAPS_AMD_WORKAROUND (1 << 17) /* AMD-specific workaround */
2015-02-19 18:04:17 +01:00
# define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
2020-06-18 16:40:51 +02:00
/* 19 unused */
2015-02-19 18:04:17 +01:00
# define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
# define AZX_DCAPS_NO_ALIGN_BUFSIZE (1 << 21) /* no buffer size alignment */
/* 22 unused */
# define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */
2015-12-17 08:31:45 +01:00
/* 24 unused */
2015-02-19 18:04:17 +01:00
# define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
# define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
2020-10-27 21:00:37 +08:00
/* 27 unused */
2015-02-19 18:04:17 +01:00
# define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */
# define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */
# define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */
enum {
AZX_SNOOP_TYPE_NONE ,
AZX_SNOOP_TYPE_SCH ,
AZX_SNOOP_TYPE_ATI ,
AZX_SNOOP_TYPE_NVIDIA ,
} ;
struct azx_dev {
2015-04-14 18:13:13 +02:00
struct hdac_stream core ;
2015-02-19 18:04:17 +01:00
unsigned int irq_pending : 1 ;
/*
* For VIA :
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
unsigned int insufficient : 1 ;
} ;
2015-04-14 18:13:13 +02:00
# define azx_stream(dev) (&(dev)->core)
# define stream_to_azx_dev(s) container_of(s, struct azx_dev, core)
2015-02-19 18:04:17 +01:00
struct azx ;
/* Functions to read/write to hda registers. */
struct hda_controller_ops {
/* Disable msi if supported, PCI only */
int ( * disable_msi_reset_irq ) ( struct azx * ) ;
void ( * pcm_mmap_prepare ) ( struct snd_pcm_substream * substream ,
struct vm_area_struct * area ) ;
/* Check if current position is acceptable */
int ( * position_check ) ( struct azx * chip , struct azx_dev * azx_dev ) ;
2015-04-29 17:43:29 +08:00
/* enable/disable the link power */
int ( * link_power ) ( struct azx * chip , bool enable ) ;
2015-02-19 18:04:17 +01:00
} ;
struct azx_pcm {
struct azx * chip ;
struct snd_pcm * pcm ;
struct hda_codec * codec ;
2015-02-20 12:50:46 +01:00
struct hda_pcm * info ;
2015-02-19 18:04:17 +01:00
struct list_head list ;
} ;
typedef unsigned int ( * azx_get_pos_callback_t ) ( struct azx * , struct azx_dev * ) ;
typedef int ( * azx_get_delay_callback_t ) ( struct azx * , struct azx_dev * , unsigned int pos ) ;
struct azx {
2015-04-14 22:13:18 +02:00
struct hda_bus bus ;
2015-02-19 18:04:17 +01:00
struct snd_card * card ;
struct pci_dev * pci ;
int dev_index ;
/* chip type specific */
int driver_type ;
unsigned int driver_caps ;
int playback_streams ;
int playback_index_offset ;
int capture_streams ;
int capture_index_offset ;
int num_streams ;
2018-08-30 07:58:50 +02:00
int jackpoll_interval ; /* jack poll interval in jiffies */
2015-02-19 18:04:17 +01:00
/* Register interaction. */
const struct hda_controller_ops * ops ;
/* position adjustment callbacks */
azx_get_pos_callback_t get_position [ 2 ] ;
azx_get_delay_callback_t get_delay [ 2 ] ;
/* locks */
struct mutex open_mutex ; /* Prevents concurrent open/close operations */
/* PCM */
struct list_head pcm_list ; /* azx_pcm list */
/* HD codec */
int codec_probe_mask ; /* copied from probe_mask option */
unsigned int beep_mode ;
# ifdef CONFIG_SND_HDA_PATCH_LOADER
const struct firmware * fw ;
# endif
/* flags */
2015-12-10 16:44:08 +01:00
int bdl_pos_adj ;
2015-02-19 18:04:17 +01:00
unsigned int running : 1 ;
2017-01-12 17:13:21 +01:00
unsigned int fallback_to_single_cmd : 1 ;
2015-02-19 18:04:17 +01:00
unsigned int single_cmd : 1 ;
unsigned int msi : 1 ;
unsigned int probing : 1 ; /* codec probing phase */
unsigned int snoop : 1 ;
2018-08-11 23:33:34 +02:00
unsigned int uc_buffer : 1 ; /* non-cached pages for stream buffers */
2015-02-19 18:04:17 +01:00
unsigned int align_buffer_size : 1 ;
unsigned int region_requested : 1 ;
2015-09-04 20:49:36 +02:00
unsigned int disabled : 1 ; /* disabled by vga_switcheroo */
2020-10-27 21:00:37 +08:00
unsigned int pm_prepared : 1 ;
2015-02-19 18:04:17 +01:00
2016-08-04 15:46:03 +05:30
/* GTS present */
unsigned int gts_present : 1 ;
2015-02-19 18:04:17 +01:00
# ifdef CONFIG_SND_HDA_DSP_LOADER
struct azx_dev saved_azx_dev ;
# endif
} ;
2015-04-14 22:13:18 +02:00
# define azx_bus(chip) (&(chip)->bus.core)
# define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core)
2015-04-14 17:26:00 +02:00
2018-09-11 16:18:36 +02:00
static inline bool azx_snoop ( struct azx * chip )
{
return ! IS_ENABLED ( CONFIG_X86 ) | | chip - > snoop ;
}
2015-02-19 18:04:17 +01:00
/*
* macros for easy use
*/
# define azx_writel(chip, reg, value) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_writel ( azx_bus ( chip ) , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_readl(chip, reg) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_readl ( azx_bus ( chip ) , reg )
2015-02-19 18:04:17 +01:00
# define azx_writew(chip, reg, value) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_writew ( azx_bus ( chip ) , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_readw(chip, reg) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_readw ( azx_bus ( chip ) , reg )
2015-02-19 18:04:17 +01:00
# define azx_writeb(chip, reg, value) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_writeb ( azx_bus ( chip ) , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_readb(chip, reg) \
2015-04-14 22:13:18 +02:00
snd_hdac_chip_readb ( azx_bus ( chip ) , reg )
2015-02-19 18:04:17 +01:00
# define azx_has_pm_runtime(chip) \
2015-04-15 13:29:05 +02:00
( ( chip ) - > driver_caps & AZX_DCAPS_PM_RUNTIME )
2014-02-28 15:41:22 -08:00
/* PCM setup */
static inline struct azx_dev * get_azx_dev ( struct snd_pcm_substream * substream )
{
return substream - > runtime - > private_data ;
}
2014-06-26 16:50:16 +02:00
unsigned int azx_get_position ( struct azx * chip , struct azx_dev * azx_dev ) ;
unsigned int azx_get_pos_lpib ( struct azx * chip , struct azx_dev * azx_dev ) ;
unsigned int azx_get_pos_posbuf ( struct azx * chip , struct azx_dev * azx_dev ) ;
2014-02-28 15:41:22 -08:00
/* Stream control. */
2015-04-14 18:13:13 +02:00
void azx_stop_all_streams ( struct azx * chip ) ;
2014-02-28 15:41:22 -08:00
2014-02-28 15:41:23 -08:00
/* Allocation functions. */
2015-04-14 22:13:18 +02:00
# define azx_alloc_stream_pages(chip) \
snd_hdac_bus_alloc_stream_pages ( azx_bus ( chip ) )
# define azx_free_stream_pages(chip) \
snd_hdac_bus_free_stream_pages ( azx_bus ( chip ) )
2014-02-28 15:41:23 -08:00
2014-02-28 15:41:27 -08:00
/* Low level azx interface */
2014-04-09 12:30:57 +02:00
void azx_init_chip ( struct azx * chip , bool full_reset ) ;
2014-02-28 15:41:27 -08:00
void azx_stop_chip ( struct azx * chip ) ;
2015-04-14 22:13:18 +02:00
# define azx_enter_link_reset(chip) \
snd_hdac_bus_enter_link_reset ( azx_bus ( chip ) )
2014-02-28 15:41:29 -08:00
irqreturn_t azx_interrupt ( int irq , void * dev_id ) ;
2014-02-28 15:41:27 -08:00
2014-02-28 15:41:30 -08:00
/* Codec interface */
2019-08-07 20:32:08 +02:00
int azx_bus_init ( struct azx * chip , const char * model ) ;
2015-02-19 18:12:22 +01:00
int azx_probe_codecs ( struct azx * chip , unsigned int max_slots ) ;
2014-02-28 15:41:30 -08:00
int azx_codec_configure ( struct azx * chip ) ;
2015-04-14 22:13:18 +02:00
int azx_init_streams ( struct azx * chip ) ;
void azx_free_streams ( struct azx * chip ) ;
2014-02-28 15:41:30 -08:00
2014-02-28 15:41:22 -08:00
# endif /* __SOUND_HDA_CONTROLLER_H */