freebsd-dev/sys/dev/sound/pci/hda/hdaa.h
Alexander Motin 7c6b05d280 Major snd_hda driver rewrite:
- Huge old hdac driver was split into three independent pieces: HDA
controller driver (hdac), HDA CODEC driver (hdacc) and HDA sudio function
driver (hdaa).
 - Support for multichannel recording was added. Now, as specification
defines, driver checks input associations for pins with sequence numbers
14 and 15, and if found (usually) -- works as before, mixing signals
together. If it doesn't, it configures input association as multichannel.
 - Signal tracer was improved to look for cases where several DACs/ADCs in
CODEC can work with the same audio signal. If such case found, driver
registers additional playback/record stream (channel) for the pcm device.
 - New controller streams reservation mechanism was implemented. That
allows to have more pcm devices then streams supported by the controller
(usually 4 in each direction). Now it limits only number of simultaneously
transferred audio streams, that is rarely reachable and properly reported
if happens.
 - Codec pins and GPIO signals configuration was exported via set of
writable sysctls. Another sysctl dev.hdaa.X.reconfig allows to trigger
driver reconfiguration in run-time.
 - Driver now decodes pins location and connector type names. In some cases
it allows to hint user where on the system case connectors, related to the
pcm device, are located. Number of channels supported by pcm device,
reported now (if it is not 2), should also make search easier.
 - Added workaround for digital mic on some Asus laptops/netbooks.

MFC after:	2 months
Sponsored by:	iXsystems, Inc.
2012-01-15 13:21:36 +00:00

231 lines
6.3 KiB
C

/*-7
* Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
* Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
* Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
*/
#ifndef _HDAA_QUIRKS_H_
#define _HDAA_QUIRKS_H_
#define HDAA_GPIO_SHIFT(n) (n * 3)
#define HDAA_GPIO_MASK(n) (0x7 << (n * 3))
#define HDAA_GPIO_KEEP(n) (0x0 << (n * 3))
#define HDAA_GPIO_SET(n) (0x1 << (n * 3))
#define HDAA_GPIO_CLEAR(n) (0x2 << (n * 3))
#define HDAA_GPIO_DISABLE(n) (0x3 << (n * 3))
#define HDAA_GPIO_INPUT(n) (0x4 << (n * 3))
/* 9 - 25 = anything else */
#define HDAA_QUIRK_SOFTPCMVOL (1 << 9)
#define HDAA_QUIRK_FIXEDRATE (1 << 10)
#define HDAA_QUIRK_FORCESTEREO (1 << 11)
#define HDAA_QUIRK_EAPDINV (1 << 12)
#define HDAA_QUIRK_SENSEINV (1 << 14)
/* 26 - 31 = vrefs */
#define HDAA_QUIRK_IVREF50 (1 << 26)
#define HDAA_QUIRK_IVREF80 (1 << 27)
#define HDAA_QUIRK_IVREF100 (1 << 28)
#define HDAA_QUIRK_OVREF50 (1 << 29)
#define HDAA_QUIRK_OVREF80 (1 << 30)
#define HDAA_QUIRK_OVREF100 (1 << 31)
#define HDAA_QUIRK_IVREF (HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF80 | \
HDAA_QUIRK_IVREF100)
#define HDAA_QUIRK_OVREF (HDAA_QUIRK_OVREF50 | HDAA_QUIRK_OVREF80 | \
HDAA_QUIRK_OVREF100)
#define HDAA_QUIRK_VREF (HDAA_QUIRK_IVREF | HDAA_QUIRK_OVREF)
#define HDAA_AMP_VOL_DEFAULT (-1)
#define HDAA_AMP_MUTE_DEFAULT (0xffffffff)
#define HDAA_AMP_MUTE_NONE (0)
#define HDAA_AMP_MUTE_LEFT (1 << 0)
#define HDAA_AMP_MUTE_RIGHT (1 << 1)
#define HDAA_AMP_MUTE_ALL (HDAA_AMP_MUTE_LEFT | HDAA_AMP_MUTE_RIGHT)
#define HDAA_AMP_LEFT_MUTED(v) ((v) & (HDAA_AMP_MUTE_LEFT))
#define HDAA_AMP_RIGHT_MUTED(v) (((v) & HDAA_AMP_MUTE_RIGHT) >> 1)
#define HDAA_ADC_MONITOR (1 << 0)
#define HDAA_CTL_OUT 1
#define HDAA_CTL_IN 2
#define HDA_MAX_CONNS 32
#define HDA_MAX_NAMELEN 32
struct hdaa_widget {
nid_t nid;
int type;
int enable;
int nconns, selconn;
int waspin;
uint32_t pflags;
int bindas;
int bindseqmask;
int ossdev;
uint32_t ossmask;
nid_t conns[HDA_MAX_CONNS];
u_char connsenable[HDA_MAX_CONNS];
char name[HDA_MAX_NAMELEN];
struct hdaa_devinfo *devinfo;
struct {
uint32_t widget_cap;
uint32_t outamp_cap;
uint32_t inamp_cap;
uint32_t supp_stream_formats;
uint32_t supp_pcm_size_rate;
uint32_t eapdbtl;
} param;
union {
struct {
uint32_t config;
uint32_t original;
uint32_t newconf;
uint32_t cap;
uint32_t ctrl;
} pin;
} wclass;
};
struct hdaa_audio_ctl {
struct hdaa_widget *widget, *childwidget;
int enable;
int index, dir, ndir;
int mute, step, size, offset;
int left, right, forcemute;
uint32_t muted;
uint32_t ossmask, possmask;
};
/* Association is a group of pins bound for some special function. */
struct hdaa_audio_as {
u_char enable;
u_char index;
u_char dir;
u_char pincnt;
u_char fakeredir;
u_char digital;
uint16_t pinset;
nid_t hpredir;
nid_t pins[16];
nid_t dacs[2][16];
int num_chans;
int chans[2];
int unsol;
int location; /* Pins location, if all have the same */
int mixed; /* Mixed/multiplexed recording, not multichannel. */
};
struct hdaa_pcm_devinfo {
device_t dev;
struct hdaa_devinfo *devinfo;
int index;
int registered;
int playas, recas;
u_char left[SOUND_MIXER_NRDEVICES];
u_char right[SOUND_MIXER_NRDEVICES];
int chan_size;
int chan_blkcnt;
u_char digital;
};
struct hdaa_devinfo {
device_t dev;
struct mtx *lock;
nid_t nid;
nid_t startnode, endnode;
uint32_t outamp_cap;
uint32_t inamp_cap;
uint32_t supp_stream_formats;
uint32_t supp_pcm_size_rate;
uint32_t gpio_cap;
uint32_t quirks;
uint32_t newquirks;
uint32_t gpio;
uint32_t newgpio;
uint32_t gpo;
uint32_t newgpo;
int nodecnt;
int ctlcnt;
int ascnt;
int num_devs;
int num_chans;
struct hdaa_widget *widget;
struct hdaa_audio_ctl *ctl;
struct hdaa_audio_as *as;
struct hdaa_pcm_devinfo *devs;
struct hdaa_chan *chans;
struct callout poll_jack;
int poll_ival;
};
#define HDAA_CHN_RUNNING 0x00000001
#define HDAA_CHN_SUSPEND 0x00000002
struct hdaa_chan {
struct snd_dbuf *b;
struct pcm_channel *c;
struct pcmchan_caps caps;
struct hdaa_devinfo *devinfo;
struct hdaa_pcm_devinfo *pdevinfo;
uint32_t spd, fmt, fmtlist[16], pcmrates[16];
uint32_t supp_stream_formats, supp_pcm_size_rate;
uint32_t ptr, prevptr, blkcnt, blksz;
uint32_t *dmapos;
uint32_t flags;
int dir;
int off;
int sid;
int bit16, bit32;
int channels; /* Number of audio channels. */
int as; /* Number of association. */
int asindex; /* Index within association. */
nid_t io[16];
};
#define hdaa_codec_id(devinfo) \
(((uint32_t)hda_get_vendor_id(devinfo->dev) << 16) + \
hda_get_device_id(devinfo->dev))
#define hdaa_subvendor_id(devinfo) \
(((uint32_t)hda_get_subvendor_id(devinfo->dev) << 16) + \
hda_get_subdevice_id(devinfo->dev))
struct hdaa_widget *hdaa_widget_get(struct hdaa_devinfo *, nid_t);
uint32_t hdaa_widget_pin_patch(uint32_t config, const char *str);
uint32_t hdaa_gpio_patch(uint32_t gpio, const char *str);
void hdaa_patch(struct hdaa_devinfo *devinfo);
void hdaa_patch_direct(struct hdaa_devinfo *devinfo);
#endif