2014-02-28 15:41:22 -08:00
/*
* Common functionality for the alsa driver code base for HD Audio .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*/
# 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>
# include "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 */
# define AZX_DCAPS_RIRB_DELAY (1 << 13) /* Long delay in read loop */
# define AZX_DCAPS_RIRB_PRE_DELAY (1 << 14) /* Put a delay before read */
# define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */
# define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */
# define AZX_DCAPS_POSFIX_VIA (1 << 17) /* Use VIACOMBO as default */
# define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
# define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
# 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 */
# define AZX_DCAPS_REVERSE_ASSIGN (1 << 24) /* Assign devices in reverse order */
# define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */
# define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */
# define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */
# 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 ;
unsigned int prepared : 1 ;
/*
* For VIA :
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
unsigned int insufficient : 1 ;
unsigned int wc_marked : 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
/* CORB/RIRB */
struct azx_rb {
u32 * buf ; /* CORB/RIRB buffer
* Each CORB entry is 4 byte , RIRB is 8 byte
*/
dma_addr_t addr ; /* physical address of CORB/RIRB buffer */
/* for RIRB */
unsigned short rp , wp ; /* read/write pointers */
int cmds [ AZX_MAX_CODECS ] ; /* number of pending requests */
u32 res [ AZX_MAX_CODECS ] ; /* last read value */
} ;
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 * ) ;
int ( * substream_alloc_pages ) ( struct azx * chip ,
struct snd_pcm_substream * substream ,
size_t size ) ;
int ( * substream_free_pages ) ( struct azx * chip ,
struct snd_pcm_substream * substream ) ;
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 ) ;
} ;
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 {
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 ;
const int * jackpoll_ms ; /* per-card jack poll interval */
/* Register interaction. */
const struct hda_controller_ops * ops ;
2015-04-14 17:26:00 +02:00
const struct hdac_io_ops * io_ops ;
2015-02-19 18:04:17 +01:00
/* position adjustment callbacks */
azx_get_pos_callback_t get_position [ 2 ] ;
azx_get_delay_callback_t get_delay [ 2 ] ;
/* pci resources */
unsigned long addr ;
void __iomem * remap_addr ;
int irq ;
/* locks */
spinlock_t reg_lock ;
struct mutex open_mutex ; /* Prevents concurrent open/close operations */
/* PCM */
struct list_head pcm_list ; /* azx_pcm list */
/* HD codec */
unsigned short codec_mask ;
int codec_probe_mask ; /* copied from probe_mask option */
struct hda_bus * bus ;
unsigned int beep_mode ;
/* CORB/RIRB */
struct azx_rb corb ;
struct azx_rb rirb ;
/* CORB/RIRB and position buffers */
struct snd_dma_buffer rb ;
struct snd_dma_buffer posbuf ;
# ifdef CONFIG_SND_HDA_PATCH_LOADER
const struct firmware * fw ;
# endif
/* flags */
const int * bdl_pos_adj ;
int poll_count ;
unsigned int running : 1 ;
unsigned int initialized : 1 ;
unsigned int single_cmd : 1 ;
unsigned int polling_mode : 1 ;
unsigned int msi : 1 ;
unsigned int probing : 1 ; /* codec probing phase */
unsigned int snoop : 1 ;
unsigned int align_buffer_size : 1 ;
unsigned int region_requested : 1 ;
unsigned int disabled : 1 ; /* disabled by VGA-switcher */
/* for debugging */
unsigned int last_cmd [ AZX_MAX_CODECS ] ;
# ifdef CONFIG_SND_HDA_DSP_LOADER
struct azx_dev saved_azx_dev ;
# endif
} ;
2015-04-14 17:26:00 +02:00
# define azx_bus(chip) (&(chip)->bus->core)
2015-02-19 18:04:17 +01:00
# ifdef CONFIG_X86
# define azx_snoop(chip) ((chip)->snoop)
# else
# define azx_snoop(chip) true
# endif
/*
* macros for easy use
*/
# define azx_writel(chip, reg, value) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_writel ( value , ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_readl(chip, reg) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_readl ( ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_writew(chip, reg, value) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_writew ( value , ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_readw(chip, reg) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_readw ( ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_writeb(chip, reg, value) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_writeb ( value , ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_readb(chip, reg) \
2015-04-14 17:26:00 +02:00
( ( chip ) - > io_ops - > reg_readb ( ( chip ) - > remap_addr + AZX_REG_ # # reg ) )
2015-02-19 18:04:17 +01:00
# define azx_sd_writel(chip, dev, reg, value) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_writel ( & ( dev ) - > core , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_sd_readl(chip, dev, reg) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_readl ( & ( dev ) - > core , reg )
2015-02-19 18:04:17 +01:00
# define azx_sd_writew(chip, dev, reg, value) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_writew ( & ( dev ) - > core , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_sd_readw(chip, dev, reg) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_readw ( & ( dev ) - > core , reg )
2015-02-19 18:04:17 +01:00
# define azx_sd_writeb(chip, dev, reg, value) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_writeb ( & ( dev ) - > core , reg , value )
2015-02-19 18:04:17 +01:00
# define azx_sd_readb(chip, dev, reg) \
2015-04-14 18:13:13 +02:00
snd_hdac_stream_readb ( & ( dev ) - > core , reg )
2015-02-19 18:04:17 +01:00
# define azx_has_pm_runtime(chip) \
( ! AZX_DCAPS_PM_RUNTIME | | ( ( 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. */
int azx_alloc_stream_pages ( struct azx * chip ) ;
void azx_free_stream_pages ( struct azx * chip ) ;
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 ) ;
void azx_enter_link_reset ( struct azx * 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 */
2015-02-20 09:26:04 +01:00
int azx_bus_create ( 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 ) ;
int azx_init_stream ( struct azx * chip ) ;
2014-02-28 15:41:22 -08:00
# endif /* __SOUND_HDA_CONTROLLER_H */