Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Upstream
linux-stable
Commits
86e1d57e
Commit
86e1d57e
authored
15 years ago
by
Takashi Iwai
Browse files
Options
Download
Plain Diff
Merge branch 'topic/hda' into for-linus
parents
baf92266
ac2c92e0
Changes
48
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
Documentation/sound/alsa/ALSA-Configuration.txt
+3
-0
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/HD-Audio-Models.txt
+1
-0
Documentation/sound/alsa/HD-Audio-Models.txt
include/sound/ak4113.h
+321
-0
include/sound/ak4113.h
include/sound/ak4114.h
+6
-6
include/sound/ak4114.h
include/sound/ak4xxx-adda.h
+4
-1
include/sound/ak4xxx-adda.h
sound/i2c/other/Makefile
+2
-1
sound/i2c/other/Makefile
sound/i2c/other/ak4113.c
+639
-0
sound/i2c/other/ak4113.c
sound/i2c/other/ak4xxx-adda.c
+104
-32
sound/i2c/other/ak4xxx-adda.c
sound/pci/hda/Kconfig
+12
-1
sound/pci/hda/Kconfig
sound/pci/hda/hda_beep.c
+96
-18
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_beep.h
+10
-0
sound/pci/hda/hda_beep.h
sound/pci/hda/hda_codec.c
+515
-92
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
+11
-0
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_eld.c
+11
-9
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
+11
-6
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_hwdep.c
+38
-0
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
+34
-16
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
+64
-5
sound/pci/hda/hda_local.h
sound/pci/hda/hda_proc.c
+70
-0
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_analog.c
+28
-33
sound/pci/hda/patch_analog.c
with
1980 additions
and
220 deletions
+1980
-220
Documentation/sound/alsa/ALSA-Configuration.txt
View file @
86e1d57e
...
...
@@ -798,6 +798,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
setup before initializing the codecs. This option is
available only when CONFIG_SND_HDA_PATCH_LOADER=y is set.
See HD-Audio.txt for details.
beep_mode - Selects the beep registration mode (0=off, 1=on, 2=
dynamic registration via mute switch on/off); the default
value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig.
[Single (global) options]
single_cmd - Use single immediate commands to communicate with
...
...
This diff is collapsed.
Click to expand it.
Documentation/sound/alsa/HD-Audio-Models.txt
View file @
86e1d57e
...
...
@@ -391,6 +391,7 @@ STAC92HD83*
ref Reference board
mic-ref Reference board with power management for ports
dell-s14 Dell laptop
hp HP laptops with (inverted) mute-LED
auto BIOS setup (default)
STAC9872
...
...
This diff is collapsed.
Click to expand it.
include/sound/ak4113.h
0 → 100644
View file @
86e1d57e
#ifndef __SOUND_AK4113_H
#define __SOUND_AK4113_H
/*
* Routines for Asahi Kasei AK4113
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>,
*
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* AK4113 registers */
/* power down */
#define AK4113_REG_PWRDN 0x00
/* format control */
#define AK4113_REG_FORMAT 0x01
/* input/output control */
#define AK4113_REG_IO0 0x02
/* input/output control */
#define AK4113_REG_IO1 0x03
/* interrupt0 mask */
#define AK4113_REG_INT0_MASK 0x04
/* interrupt1 mask */
#define AK4113_REG_INT1_MASK 0x05
/* DAT mask & DTS select */
#define AK4113_REG_DATDTS 0x06
/* receiver status 0 */
#define AK4113_REG_RCS0 0x07
/* receiver status 1 */
#define AK4113_REG_RCS1 0x08
/* receiver status 2 */
#define AK4113_REG_RCS2 0x09
/* RX channel status byte 0 */
#define AK4113_REG_RXCSB0 0x0a
/* RX channel status byte 1 */
#define AK4113_REG_RXCSB1 0x0b
/* RX channel status byte 2 */
#define AK4113_REG_RXCSB2 0x0c
/* RX channel status byte 3 */
#define AK4113_REG_RXCSB3 0x0d
/* RX channel status byte 4 */
#define AK4113_REG_RXCSB4 0x0e
/* burst preamble Pc byte 0 */
#define AK4113_REG_Pc0 0x0f
/* burst preamble Pc byte 1 */
#define AK4113_REG_Pc1 0x10
/* burst preamble Pd byte 0 */
#define AK4113_REG_Pd0 0x11
/* burst preamble Pd byte 1 */
#define AK4113_REG_Pd1 0x12
/* Q-subcode address + control */
#define AK4113_REG_QSUB_ADDR 0x13
/* Q-subcode track */
#define AK4113_REG_QSUB_TRACK 0x14
/* Q-subcode index */
#define AK4113_REG_QSUB_INDEX 0x15
/* Q-subcode minute */
#define AK4113_REG_QSUB_MINUTE 0x16
/* Q-subcode second */
#define AK4113_REG_QSUB_SECOND 0x17
/* Q-subcode frame */
#define AK4113_REG_QSUB_FRAME 0x18
/* Q-subcode zero */
#define AK4113_REG_QSUB_ZERO 0x19
/* Q-subcode absolute minute */
#define AK4113_REG_QSUB_ABSMIN 0x1a
/* Q-subcode absolute second */
#define AK4113_REG_QSUB_ABSSEC 0x1b
/* Q-subcode absolute frame */
#define AK4113_REG_QSUB_ABSFRM 0x1c
/* sizes */
#define AK4113_REG_RXCSB_SIZE ((AK4113_REG_RXCSB4-AK4113_REG_RXCSB0)+1)
#define AK4113_REG_QSUB_SIZE ((AK4113_REG_QSUB_ABSFRM-AK4113_REG_QSUB_ADDR)\
+1)
#define AK4113_WRITABLE_REGS (AK4113_REG_DATDTS + 1)
/* AK4113_REG_PWRDN bits */
/* Channel Status Select */
#define AK4113_CS12 (1<<7)
/* Block Start & C/U Output Mode */
#define AK4113_BCU (1<<6)
/* Master Clock Operation Select */
#define AK4113_CM1 (1<<5)
/* Master Clock Operation Select */
#define AK4113_CM0 (1<<4)
/* Master Clock Frequency Select */
#define AK4113_OCKS1 (1<<3)
/* Master Clock Frequency Select */
#define AK4113_OCKS0 (1<<2)
/* 0 = power down, 1 = normal operation */
#define AK4113_PWN (1<<1)
/* 0 = reset & initialize (except thisregister), 1 = normal operation */
#define AK4113_RST (1<<0)
/* AK4113_REQ_FORMAT bits */
/* V/TX Output select: 0 = Validity Flag Output, 1 = TX */
#define AK4113_VTX (1<<7)
/* Audio Data Control */
#define AK4113_DIF2 (1<<6)
/* Audio Data Control */
#define AK4113_DIF1 (1<<5)
/* Audio Data Control */
#define AK4113_DIF0 (1<<4)
/* Deemphasis Autodetect Enable (1 = enable) */
#define AK4113_DEAU (1<<3)
/* 32kHz-48kHz Deemphasis Control */
#define AK4113_DEM1 (1<<2)
/* 32kHz-48kHz Deemphasis Control */
#define AK4113_DEM0 (1<<1)
#define AK4113_DEM_OFF (AK4113_DEM0)
#define AK4113_DEM_44KHZ (0)
#define AK4113_DEM_48KHZ (AK4113_DEM1)
#define AK4113_DEM_32KHZ (AK4113_DEM0|AK4113_DEM1)
/* STDO: 16-bit, right justified */
#define AK4113_DIF_16R (0)
/* STDO: 18-bit, right justified */
#define AK4113_DIF_18R (AK4113_DIF0)
/* STDO: 20-bit, right justified */
#define AK4113_DIF_20R (AK4113_DIF1)
/* STDO: 24-bit, right justified */
#define AK4113_DIF_24R (AK4113_DIF1|AK4113_DIF0)
/* STDO: 24-bit, left justified */
#define AK4113_DIF_24L (AK4113_DIF2)
/* STDO: I2S */
#define AK4113_DIF_24I2S (AK4113_DIF2|AK4113_DIF0)
/* STDO: 24-bit, left justified; LRCLK, BICK = Input */
#define AK4113_DIF_I24L (AK4113_DIF2|AK4113_DIF1)
/* STDO: I2S; LRCLK, BICK = Input */
#define AK4113_DIF_I24I2S (AK4113_DIF2|AK4113_DIF1|AK4113_DIF0)
/* AK4113_REG_IO0 */
/* XTL1=0,XTL0=0 -> 11.2896Mhz; XTL1=0,XTL0=1 -> 12.288Mhz */
#define AK4113_XTL1 (1<<6)
/* XTL1=1,XTL0=0 -> 24.576Mhz; XTL1=1,XTL0=1 -> use channel status */
#define AK4113_XTL0 (1<<5)
/* Block Start Signal Output: 0 = U-bit, 1 = C-bit (req. BCU = 1) */
#define AK4113_UCE (1<<4)
/* TX Output Enable (1 = enable) */
#define AK4113_TXE (1<<3)
/* Output Through Data Selector for TX pin */
#define AK4113_OPS2 (1<<2)
/* Output Through Data Selector for TX pin */
#define AK4113_OPS1 (1<<1)
/* Output Through Data Selector for TX pin */
#define AK4113_OPS0 (1<<0)
/* 11.2896 MHz ref. Xtal freq. */
#define AK4113_XTL_11_2896M (0)
/* 12.288 MHz ref. Xtal freq. */
#define AK4113_XTL_12_288M (AK4113_XTL0)
/* 24.576 MHz ref. Xtal freq. */
#define AK4113_XTL_24_576M (AK4113_XTL1)
/* AK4113_REG_IO1 */
/* Interrupt 0 pin Hold */
#define AK4113_EFH1 (1<<7)
/* Interrupt 0 pin Hold */
#define AK4113_EFH0 (1<<6)
#define AK4113_EFH_512LRCLK (0)
#define AK4113_EFH_1024LRCLK (AK4113_EFH0)
#define AK4113_EFH_2048LRCLK (AK4113_EFH1)
#define AK4113_EFH_4096LRCLK (AK4113_EFH1|AK4113_EFH0)
/* PLL Lock Time: 0 = 384/fs, 1 = 1/fs */
#define AK4113_FAST (1<<5)
/* MCKO2 Output Select: 0 = CMx/OCKSx, 1 = Xtal */
#define AK4113_XMCK (1<<4)
/* MCKO2 Output Freq. Select: 0 = x1, 1 = x0.5 (req. XMCK = 1) */
#define AK4113_DIV (1<<3)
/* Input Recovery Data Select */
#define AK4113_IPS2 (1<<2)
/* Input Recovery Data Select */
#define AK4113_IPS1 (1<<1)
/* Input Recovery Data Select */
#define AK4113_IPS0 (1<<0)
#define AK4113_IPS(x) ((x)&7)
/* AK4113_REG_INT0_MASK && AK4113_REG_INT1_MASK*/
/* mask enable for QINT bit */
#define AK4113_MQI (1<<7)
/* mask enable for AUTO bit */
#define AK4113_MAUT (1<<6)
/* mask enable for CINT bit */
#define AK4113_MCIT (1<<5)
/* mask enable for UNLOCK bit */
#define AK4113_MULK (1<<4)
/* mask enable for V bit */
#define AK4113_V (1<<3)
/* mask enable for STC bit */
#define AK4113_STC (1<<2)
/* mask enable for AUDN bit */
#define AK4113_MAN (1<<1)
/* mask enable for PAR bit */
#define AK4113_MPR (1<<0)
/* AK4113_REG_DATDTS */
/* DAT Start ID Counter */
#define AK4113_DCNT (1<<4)
/* DTS-CD 16-bit Sync Word Detect */
#define AK4113_DTS16 (1<<3)
/* DTS-CD 14-bit Sync Word Detect */
#define AK4113_DTS14 (1<<2)
/* mask enable for DAT bit (if 1, no INT1 effect */
#define AK4113_MDAT1 (1<<1)
/* mask enable for DAT bit (if 1, no INT0 effect */
#define AK4113_MDAT0 (1<<0)
/* AK4113_REG_RCS0 */
/* Q-subcode buffer interrupt, 0 = no change, 1 = changed */
#define AK4113_QINT (1<<7)
/* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */
#define AK4113_AUTO (1<<6)
/* channel status buffer interrupt, 0 = no change, 1 = change */
#define AK4113_CINT (1<<5)
/* PLL lock status, 0 = lock, 1 = unlock */
#define AK4113_UNLCK (1<<4)
/* Validity bit, 0 = valid, 1 = invalid */
#define AK4113_V (1<<3)
/* sampling frequency or Pre-emphasis change, 0 = no detect, 1 = detect */
#define AK4113_STC (1<<2)
/* audio bit output, 0 = audio, 1 = non-audio */
#define AK4113_AUDION (1<<1)
/* parity error or biphase error status, 0 = no error, 1 = error */
#define AK4113_PAR (1<<0)
/* AK4113_REG_RCS1 */
/* sampling frequency detection */
#define AK4113_FS3 (1<<7)
#define AK4113_FS2 (1<<6)
#define AK4113_FS1 (1<<5)
#define AK4113_FS0 (1<<4)
/* Pre-emphasis detect, 0 = OFF, 1 = ON */
#define AK4113_PEM (1<<3)
/* DAT Start ID Detect, 0 = no detect, 1 = detect */
#define AK4113_DAT (1<<2)
/* DTS-CD bit audio stream detect, 0 = no detect, 1 = detect */
#define AK4113_DTSCD (1<<1)
/* Non-PCM bit stream detection, 0 = no detect, 1 = detect */
#define AK4113_NPCM (1<<0)
#define AK4113_FS_8000HZ (AK4113_FS3|AK4113_FS0)
#define AK4113_FS_11025HZ (AK4113_FS2|AK4113_FS0)
#define AK4113_FS_16000HZ (AK4113_FS2|AK4113_FS1|AK4113_FS0)
#define AK4113_FS_22050HZ (AK4113_FS2)
#define AK4113_FS_24000HZ (AK4113_FS2|AK4113_FS1)
#define AK4113_FS_32000HZ (AK4113_FS1|AK4113_FS0)
#define AK4113_FS_44100HZ (0)
#define AK4113_FS_48000HZ (AK4113_FS1)
#define AK4113_FS_64000HZ (AK4113_FS3|AK4113_FS1|AK4113_FS0)
#define AK4113_FS_88200HZ (AK4113_FS3)
#define AK4113_FS_96000HZ (AK4113_FS3|AK4113_FS1)
#define AK4113_FS_176400HZ (AK4113_FS3|AK4113_FS2)
#define AK4113_FS_192000HZ (AK4113_FS3|AK4113_FS2|AK4113_FS1)
/* AK4113_REG_RCS2 */
/* CRC for Q-subcode, 0 = no error, 1 = error */
#define AK4113_QCRC (1<<1)
/* CRC for channel status, 0 = no error, 1 = error */
#define AK4113_CCRC (1<<0)
/* flags for snd_ak4113_check_rate_and_errors() */
#define AK4113_CHECK_NO_STAT (1<<0)
/* no statistics */
#define AK4113_CHECK_NO_RATE (1<<1)
/* no rate check */
#define AK4113_CONTROLS 13
typedef
void
(
ak4113_write_t
)(
void
*
private_data
,
unsigned
char
addr
,
unsigned
char
data
);
typedef
unsigned
char
(
ak4113_read_t
)(
void
*
private_data
,
unsigned
char
addr
);
struct
ak4113
{
struct
snd_card
*
card
;
ak4113_write_t
*
write
;
ak4113_read_t
*
read
;
void
*
private_data
;
unsigned
int
init
:
1
;
spinlock_t
lock
;
unsigned
char
regmap
[
AK4113_WRITABLE_REGS
];
struct
snd_kcontrol
*
kctls
[
AK4113_CONTROLS
];
struct
snd_pcm_substream
*
substream
;
unsigned
long
parity_errors
;
unsigned
long
v_bit_errors
;
unsigned
long
qcrc_errors
;
unsigned
long
ccrc_errors
;
unsigned
char
rcs0
;
unsigned
char
rcs1
;
unsigned
char
rcs2
;
struct
delayed_work
work
;
unsigned
int
check_flags
;
void
*
change_callback_private
;
void
(
*
change_callback
)(
struct
ak4113
*
ak4113
,
unsigned
char
c0
,
unsigned
char
c1
);
};
int
snd_ak4113_create
(
struct
snd_card
*
card
,
ak4113_read_t
*
read
,
ak4113_write_t
*
write
,
const
unsigned
char
pgm
[
AK4113_WRITABLE_REGS
],
void
*
private_data
,
struct
ak4113
**
r_ak4113
);
void
snd_ak4113_reg_write
(
struct
ak4113
*
ak4113
,
unsigned
char
reg
,
unsigned
char
mask
,
unsigned
char
val
);
void
snd_ak4113_reinit
(
struct
ak4113
*
ak4113
);
int
snd_ak4113_build
(
struct
ak4113
*
ak4113
,
struct
snd_pcm_substream
*
capture_substream
);
int
snd_ak4113_external_rate
(
struct
ak4113
*
ak4113
);
int
snd_ak4113_check_rate_and_errors
(
struct
ak4113
*
ak4113
,
unsigned
int
flags
);
#endif
/* __SOUND_AK4113_H */
This diff is collapsed.
Click to expand it.
include/sound/ak4114.h
View file @
86e1d57e
...
...
@@ -95,13 +95,13 @@
/* AK4114_REG_IO0 */
#define AK4114_TX1E (1<<7)
/* TX1 Output Enable (1 = enable) */
#define AK4114_OPS12 (1<<
2
)
/* Output
Though
Data Selector for TX1 pin */
#define AK4114_OPS11 (1<<
1
)
/* Output
Though
Data Selector for TX1 pin */
#define AK4114_OPS10 (1<<
0
)
/* Output
Though
Data Selector for TX1 pin */
#define AK4114_OPS12 (1<<
6
)
/* Output Data Selector for TX1 pin */
#define AK4114_OPS11 (1<<
5
)
/* Output Data Selector for TX1 pin */
#define AK4114_OPS10 (1<<
4
)
/* Output Data Selector for TX1 pin */
#define AK4114_TX0E (1<<3)
/* TX0 Output Enable (1 = enable) */
#define AK4114_OPS02 (1<<2)
/* Output
Though
Data Selector for TX0 pin */
#define AK4114_OPS01 (1<<1)
/* Output
Though
Data Selector for TX0 pin */
#define AK4114_OPS00 (1<<0)
/* Output
Though
Data Selector for TX0 pin */
#define AK4114_OPS02 (1<<2)
/* Output Data Selector for TX0 pin */
#define AK4114_OPS01 (1<<1)
/* Output Data Selector for TX0 pin */
#define AK4114_OPS00 (1<<0)
/* Output Data Selector for TX0 pin */
/* AK4114_REG_IO1 */
#define AK4114_EFH1 (1<<7)
/* Interrupt 0 pin Hold */
...
...
This diff is collapsed.
Click to expand it.
include/sound/ak4xxx-adda.h
View file @
86e1d57e
...
...
@@ -68,7 +68,7 @@ struct snd_akm4xxx {
enum
{
SND_AK4524
,
SND_AK4528
,
SND_AK4529
,
SND_AK4355
,
SND_AK4358
,
SND_AK4381
,
SND_AK5365
SND_AK5365
,
SND_AK4620
,
}
type
;
/* (array) information of combined codecs */
...
...
@@ -76,6 +76,9 @@ struct snd_akm4xxx {
const
struct
snd_akm4xxx_adc_channel
*
adc_info
;
struct
snd_ak4xxx_ops
ops
;
unsigned
int
num_chips
;
unsigned
int
total_regs
;
const
char
*
name
;
};
void
snd_akm4xxx_write
(
struct
snd_akm4xxx
*
ak
,
int
chip
,
unsigned
char
reg
,
...
...
This diff is collapsed.
Click to expand it.
sound/i2c/other/Makefile
View file @
86e1d57e
...
...
@@ -5,6 +5,7 @@
snd-ak4114-objs
:=
ak4114.o
snd-ak4117-objs
:=
ak4117.o
snd-ak4113-objs
:=
ak4113.o
snd-ak4xxx-adda-objs
:=
ak4xxx-adda.o
snd-pt2258-objs
:=
pt2258.o
snd-tea575x-tuner-objs
:=
tea575x-tuner.o
...
...
@@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
# Module Dependency
obj-$(CONFIG_SND_PDAUDIOCF)
+=
snd-ak4117.o
obj-$(CONFIG_SND_ICE1712)
+=
snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724)
+=
snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_ICE1724)
+=
snd-ak4114.o
snd-ak4113.o
snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_FM801_TEA575X)
+=
snd-tea575x-tuner.o
This diff is collapsed.
Click to expand it.
sound/i2c/other/ak4113.c
0 → 100644
View file @
86e1d57e
/*
* Routines for control of the AK4113 via I2C/4-wire serial interface
* IEC958 (S/PDIF) receiver by Asahi Kasei
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
* Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>
*
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/slab.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/ak4113.h>
#include <sound/asoundef.h>
#include <sound/info.h>
MODULE_AUTHOR
(
"Pavel Hofman <pavel.hofman@ivitera.com>"
);
MODULE_DESCRIPTION
(
"AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei"
);
MODULE_LICENSE
(
"GPL"
);
#define AK4113_ADDR 0x00
/* fixed address */
static
void
ak4113_stats
(
struct
work_struct
*
work
);
static
void
ak4113_init_regs
(
struct
ak4113
*
chip
);
static
void
reg_write
(
struct
ak4113
*
ak4113
,
unsigned
char
reg
,
unsigned
char
val
)
{
ak4113
->
write
(
ak4113
->
private_data
,
reg
,
val
);
if
(
reg
<
sizeof
(
ak4113
->
regmap
))
ak4113
->
regmap
[
reg
]
=
val
;
}
static
inline
unsigned
char
reg_read
(
struct
ak4113
*
ak4113
,
unsigned
char
reg
)
{
return
ak4113
->
read
(
ak4113
->
private_data
,
reg
);
}
static
void
snd_ak4113_free
(
struct
ak4113
*
chip
)
{
chip
->
init
=
1
;
/* don't schedule new work */
mb
();
cancel_delayed_work
(
&
chip
->
work
);
flush_scheduled_work
();
kfree
(
chip
);
}
static
int
snd_ak4113_dev_free
(
struct
snd_device
*
device
)
{
struct
ak4113
*
chip
=
device
->
device_data
;
snd_ak4113_free
(
chip
);
return
0
;
}
int
snd_ak4113_create
(
struct
snd_card
*
card
,
ak4113_read_t
*
read
,
ak4113_write_t
*
write
,
const
unsigned
char
pgm
[
5
],
void
*
private_data
,
struct
ak4113
**
r_ak4113
)
{
struct
ak4113
*
chip
;
int
err
=
0
;
unsigned
char
reg
;
static
struct
snd_device_ops
ops
=
{
.
dev_free
=
snd_ak4113_dev_free
,
};
chip
=
kzalloc
(
sizeof
(
*
chip
),
GFP_KERNEL
);
if
(
chip
==
NULL
)
return
-
ENOMEM
;
spin_lock_init
(
&
chip
->
lock
);
chip
->
card
=
card
;
chip
->
read
=
read
;
chip
->
write
=
write
;
chip
->
private_data
=
private_data
;
INIT_DELAYED_WORK
(
&
chip
->
work
,
ak4113_stats
);
for
(
reg
=
0
;
reg
<
AK4113_WRITABLE_REGS
;
reg
++
)
chip
->
regmap
[
reg
]
=
pgm
[
reg
];
ak4113_init_regs
(
chip
);
chip
->
rcs0
=
reg_read
(
chip
,
AK4113_REG_RCS0
)
&
~
(
AK4113_QINT
|
AK4113_CINT
|
AK4113_STC
);
chip
->
rcs1
=
reg_read
(
chip
,
AK4113_REG_RCS1
);
chip
->
rcs2
=
reg_read
(
chip
,
AK4113_REG_RCS2
);
err
=
snd_device_new
(
card
,
SNDRV_DEV_LOWLEVEL
,
chip
,
&
ops
);
if
(
err
<
0
)
goto
__fail
;
if
(
r_ak4113
)
*
r_ak4113
=
chip
;
return
0
;
__fail:
snd_ak4113_free
(
chip
);
return
err
<
0
?
err
:
-
EIO
;
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_create
);
void
snd_ak4113_reg_write
(
struct
ak4113
*
chip
,
unsigned
char
reg
,
unsigned
char
mask
,
unsigned
char
val
)
{
if
(
reg
>=
AK4113_WRITABLE_REGS
)
return
;
reg_write
(
chip
,
reg
,
(
chip
->
regmap
[
reg
]
&
~
mask
)
|
val
);
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_reg_write
);
static
void
ak4113_init_regs
(
struct
ak4113
*
chip
)
{
unsigned
char
old
=
chip
->
regmap
[
AK4113_REG_PWRDN
],
reg
;
/* bring the chip to reset state and powerdown state */
reg_write
(
chip
,
AK4113_REG_PWRDN
,
old
&
~
(
AK4113_RST
|
AK4113_PWN
));
udelay
(
200
);
/* release reset, but leave powerdown */
reg_write
(
chip
,
AK4113_REG_PWRDN
,
(
old
|
AK4113_RST
)
&
~
AK4113_PWN
);
udelay
(
200
);
for
(
reg
=
1
;
reg
<
AK4113_WRITABLE_REGS
;
reg
++
)
reg_write
(
chip
,
reg
,
chip
->
regmap
[
reg
]);
/* release powerdown, everything is initialized now */
reg_write
(
chip
,
AK4113_REG_PWRDN
,
old
|
AK4113_RST
|
AK4113_PWN
);
}
void
snd_ak4113_reinit
(
struct
ak4113
*
chip
)
{
chip
->
init
=
1
;
mb
();
flush_scheduled_work
();
ak4113_init_regs
(
chip
);
/* bring up statistics / event queing */
chip
->
init
=
0
;
if
(
chip
->
kctls
[
0
])
schedule_delayed_work
(
&
chip
->
work
,
HZ
/
10
);
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_reinit
);
static
unsigned
int
external_rate
(
unsigned
char
rcs1
)
{
switch
(
rcs1
&
(
AK4113_FS0
|
AK4113_FS1
|
AK4113_FS2
|
AK4113_FS3
))
{
case
AK4113_FS_8000HZ
:
return
8000
;
case
AK4113_FS_11025HZ
:
return
11025
;
case
AK4113_FS_16000HZ
:
return
16000
;
case
AK4113_FS_22050HZ
:
return
22050
;
case
AK4113_FS_24000HZ
:
return
24000
;
case
AK4113_FS_32000HZ
:
return
32000
;
case
AK4113_FS_44100HZ
:
return
44100
;
case
AK4113_FS_48000HZ
:
return
48000
;
case
AK4113_FS_64000HZ
:
return
64000
;
case
AK4113_FS_88200HZ
:
return
88200
;
case
AK4113_FS_96000HZ
:
return
96000
;
case
AK4113_FS_176400HZ
:
return
176400
;
case
AK4113_FS_192000HZ
:
return
192000
;
default:
return
0
;
}
}
static
int
snd_ak4113_in_error_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
1
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
LONG_MAX
;
return
0
;
}
static
int
snd_ak4113_in_error_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
long
*
ptr
;
spin_lock_irq
(
&
chip
->
lock
);
ptr
=
(
long
*
)(((
char
*
)
chip
)
+
kcontrol
->
private_value
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
*
ptr
;
*
ptr
=
0
;
spin_unlock_irq
(
&
chip
->
lock
);
return
0
;
}
#define snd_ak4113_in_bit_info snd_ctl_boolean_mono_info
static
int
snd_ak4113_in_bit_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
char
reg
=
kcontrol
->
private_value
&
0xff
;
unsigned
char
bit
=
(
kcontrol
->
private_value
>>
8
)
&
0xff
;
unsigned
char
inv
=
(
kcontrol
->
private_value
>>
31
)
&
1
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
((
reg_read
(
chip
,
reg
)
&
(
1
<<
bit
))
?
1
:
0
)
^
inv
;
return
0
;
}
static
int
snd_ak4113_rx_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
1
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
5
;
return
0
;
}
static
int
snd_ak4113_rx_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
(
AK4113_IPS
(
chip
->
regmap
[
AK4113_REG_IO1
]));
return
0
;
}
static
int
snd_ak4113_rx_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
int
change
;
u8
old_val
;
spin_lock_irq
(
&
chip
->
lock
);
old_val
=
chip
->
regmap
[
AK4113_REG_IO1
];
change
=
ucontrol
->
value
.
integer
.
value
[
0
]
!=
AK4113_IPS
(
old_val
);
if
(
change
)
reg_write
(
chip
,
AK4113_REG_IO1
,
(
old_val
&
(
~
AK4113_IPS
(
0xff
)))
|
(
AK4113_IPS
(
ucontrol
->
value
.
integer
.
value
[
0
])));
spin_unlock_irq
(
&
chip
->
lock
);
return
change
;
}
static
int
snd_ak4113_rate_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
1
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
192000
;
return
0
;
}
static
int
snd_ak4113_rate_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
external_rate
(
reg_read
(
chip
,
AK4113_REG_RCS1
));
return
0
;
}
static
int
snd_ak4113_spdif_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_IEC958
;
uinfo
->
count
=
1
;
return
0
;
}
static
int
snd_ak4113_spdif_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
i
;
for
(
i
=
0
;
i
<
AK4113_REG_RXCSB_SIZE
;
i
++
)
ucontrol
->
value
.
iec958
.
status
[
i
]
=
reg_read
(
chip
,
AK4113_REG_RXCSB0
+
i
);
return
0
;
}
static
int
snd_ak4113_spdif_mask_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_IEC958
;
uinfo
->
count
=
1
;
return
0
;
}
static
int
snd_ak4113_spdif_mask_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
memset
(
ucontrol
->
value
.
iec958
.
status
,
0xff
,
AK4113_REG_RXCSB_SIZE
);
return
0
;
}
static
int
snd_ak4113_spdif_pinfo
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
0xffff
;
uinfo
->
count
=
4
;
return
0
;
}
static
int
snd_ak4113_spdif_pget
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
short
tmp
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
0xf8f2
;
ucontrol
->
value
.
integer
.
value
[
1
]
=
0x4e1f
;
tmp
=
reg_read
(
chip
,
AK4113_REG_Pc0
)
|
(
reg_read
(
chip
,
AK4113_REG_Pc1
)
<<
8
);
ucontrol
->
value
.
integer
.
value
[
2
]
=
tmp
;
tmp
=
reg_read
(
chip
,
AK4113_REG_Pd0
)
|
(
reg_read
(
chip
,
AK4113_REG_Pd1
)
<<
8
);
ucontrol
->
value
.
integer
.
value
[
3
]
=
tmp
;
return
0
;
}
static
int
snd_ak4113_spdif_qinfo
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_BYTES
;
uinfo
->
count
=
AK4113_REG_QSUB_SIZE
;
return
0
;
}
static
int
snd_ak4113_spdif_qget
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
ak4113
*
chip
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
i
;
for
(
i
=
0
;
i
<
AK4113_REG_QSUB_SIZE
;
i
++
)
ucontrol
->
value
.
bytes
.
data
[
i
]
=
reg_read
(
chip
,
AK4113_REG_QSUB_ADDR
+
i
);
return
0
;
}
/* Don't forget to change AK4113_CONTROLS define!!! */
static
struct
snd_kcontrol_new
snd_ak4113_iec958_controls
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Parity Errors"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_error_info
,
.
get
=
snd_ak4113_in_error_get
,
.
private_value
=
offsetof
(
struct
ak4113
,
parity_errors
),
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 V-Bit Errors"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_error_info
,
.
get
=
snd_ak4113_in_error_get
,
.
private_value
=
offsetof
(
struct
ak4113
,
v_bit_errors
),
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 C-CRC Errors"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_error_info
,
.
get
=
snd_ak4113_in_error_get
,
.
private_value
=
offsetof
(
struct
ak4113
,
ccrc_errors
),
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Q-CRC Errors"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_error_info
,
.
get
=
snd_ak4113_in_error_get
,
.
private_value
=
offsetof
(
struct
ak4113
,
qcrc_errors
),
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 External Rate"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_rate_info
,
.
get
=
snd_ak4113_rate_get
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
SNDRV_CTL_NAME_IEC958
(
""
,
CAPTURE
,
MASK
),
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
,
.
info
=
snd_ak4113_spdif_mask_info
,
.
get
=
snd_ak4113_spdif_mask_get
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
SNDRV_CTL_NAME_IEC958
(
""
,
CAPTURE
,
DEFAULT
),
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_spdif_info
,
.
get
=
snd_ak4113_spdif_get
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Preample Capture Default"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_spdif_pinfo
,
.
get
=
snd_ak4113_spdif_pget
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Q-subcode Capture Default"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_spdif_qinfo
,
.
get
=
snd_ak4113_spdif_qget
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Audio"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_bit_info
,
.
get
=
snd_ak4113_in_bit_get
,
.
private_value
=
(
1
<<
31
)
|
(
1
<<
8
)
|
AK4113_REG_RCS0
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 Non-PCM Bitstream"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_bit_info
,
.
get
=
snd_ak4113_in_bit_get
,
.
private_value
=
(
0
<<
8
)
|
AK4113_REG_RCS1
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"IEC958 DTS Bitstream"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_VOLATILE
,
.
info
=
snd_ak4113_in_bit_info
,
.
get
=
snd_ak4113_in_bit_get
,
.
private_value
=
(
1
<<
8
)
|
AK4113_REG_RCS1
,
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_PCM
,
.
name
=
"AK4113 Input Select"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READ
|
SNDRV_CTL_ELEM_ACCESS_WRITE
,
.
info
=
snd_ak4113_rx_info
,
.
get
=
snd_ak4113_rx_get
,
.
put
=
snd_ak4113_rx_put
,
}
};
static
void
snd_ak4113_proc_regs_read
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
struct
ak4113
*
ak4113
=
entry
->
private_data
;
int
reg
,
val
;
/* all ak4113 registers 0x00 - 0x1c */
for
(
reg
=
0
;
reg
<
0x1d
;
reg
++
)
{
val
=
reg_read
(
ak4113
,
reg
);
snd_iprintf
(
buffer
,
"0x%02x = 0x%02x
\n
"
,
reg
,
val
);
}
}
static
void
snd_ak4113_proc_init
(
struct
ak4113
*
ak4113
)
{
struct
snd_info_entry
*
entry
;
if
(
!
snd_card_proc_new
(
ak4113
->
card
,
"ak4113"
,
&
entry
))
snd_info_set_text_ops
(
entry
,
ak4113
,
snd_ak4113_proc_regs_read
);
}
int
snd_ak4113_build
(
struct
ak4113
*
ak4113
,
struct
snd_pcm_substream
*
cap_substream
)
{
struct
snd_kcontrol
*
kctl
;
unsigned
int
idx
;
int
err
;
if
(
snd_BUG_ON
(
!
cap_substream
))
return
-
EINVAL
;
ak4113
->
substream
=
cap_substream
;
for
(
idx
=
0
;
idx
<
AK4113_CONTROLS
;
idx
++
)
{
kctl
=
snd_ctl_new1
(
&
snd_ak4113_iec958_controls
[
idx
],
ak4113
);
if
(
kctl
==
NULL
)
return
-
ENOMEM
;
kctl
->
id
.
device
=
cap_substream
->
pcm
->
device
;
kctl
->
id
.
subdevice
=
cap_substream
->
number
;
err
=
snd_ctl_add
(
ak4113
->
card
,
kctl
);
if
(
err
<
0
)
return
err
;
ak4113
->
kctls
[
idx
]
=
kctl
;
}
snd_ak4113_proc_init
(
ak4113
);
/* trigger workq */
schedule_delayed_work
(
&
ak4113
->
work
,
HZ
/
10
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_build
);
int
snd_ak4113_external_rate
(
struct
ak4113
*
ak4113
)
{
unsigned
char
rcs1
;
rcs1
=
reg_read
(
ak4113
,
AK4113_REG_RCS1
);
return
external_rate
(
rcs1
);
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_external_rate
);
int
snd_ak4113_check_rate_and_errors
(
struct
ak4113
*
ak4113
,
unsigned
int
flags
)
{
struct
snd_pcm_runtime
*
runtime
=
ak4113
->
substream
?
ak4113
->
substream
->
runtime
:
NULL
;
unsigned
long
_flags
;
int
res
=
0
;
unsigned
char
rcs0
,
rcs1
,
rcs2
;
unsigned
char
c0
,
c1
;
rcs1
=
reg_read
(
ak4113
,
AK4113_REG_RCS1
);
if
(
flags
&
AK4113_CHECK_NO_STAT
)
goto
__rate
;
rcs0
=
reg_read
(
ak4113
,
AK4113_REG_RCS0
);
rcs2
=
reg_read
(
ak4113
,
AK4113_REG_RCS2
);
spin_lock_irqsave
(
&
ak4113
->
lock
,
_flags
);
if
(
rcs0
&
AK4113_PAR
)
ak4113
->
parity_errors
++
;
if
(
rcs0
&
AK4113_V
)
ak4113
->
v_bit_errors
++
;
if
(
rcs2
&
AK4113_CCRC
)
ak4113
->
ccrc_errors
++
;
if
(
rcs2
&
AK4113_QCRC
)
ak4113
->
qcrc_errors
++
;
c0
=
(
ak4113
->
rcs0
&
(
AK4113_QINT
|
AK4113_CINT
|
AK4113_STC
|
AK4113_AUDION
|
AK4113_AUTO
|
AK4113_UNLCK
))
^
(
rcs0
&
(
AK4113_QINT
|
AK4113_CINT
|
AK4113_STC
|
AK4113_AUDION
|
AK4113_AUTO
|
AK4113_UNLCK
));
c1
=
(
ak4113
->
rcs1
&
(
AK4113_DTSCD
|
AK4113_NPCM
|
AK4113_PEM
|
AK4113_DAT
|
0xf0
))
^
(
rcs1
&
(
AK4113_DTSCD
|
AK4113_NPCM
|
AK4113_PEM
|
AK4113_DAT
|
0xf0
));
ak4113
->
rcs0
=
rcs0
&
~
(
AK4113_QINT
|
AK4113_CINT
|
AK4113_STC
);
ak4113
->
rcs1
=
rcs1
;
ak4113
->
rcs2
=
rcs2
;
spin_unlock_irqrestore
(
&
ak4113
->
lock
,
_flags
);
if
(
rcs0
&
AK4113_PAR
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
0
]
->
id
);
if
(
rcs0
&
AK4113_V
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
1
]
->
id
);
if
(
rcs2
&
AK4113_CCRC
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
2
]
->
id
);
if
(
rcs2
&
AK4113_QCRC
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
3
]
->
id
);
/* rate change */
if
(
c1
&
0xf0
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
4
]
->
id
);
if
((
c1
&
AK4113_PEM
)
|
(
c0
&
AK4113_CINT
))
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
6
]
->
id
);
if
(
c0
&
AK4113_QINT
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
8
]
->
id
);
if
(
c0
&
AK4113_AUDION
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
9
]
->
id
);
if
(
c1
&
AK4113_NPCM
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
10
]
->
id
);
if
(
c1
&
AK4113_DTSCD
)
snd_ctl_notify
(
ak4113
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
&
ak4113
->
kctls
[
11
]
->
id
);
if
(
ak4113
->
change_callback
&&
(
c0
|
c1
)
!=
0
)
ak4113
->
change_callback
(
ak4113
,
c0
,
c1
);
__rate:
/* compare rate */
res
=
external_rate
(
rcs1
);
if
(
!
(
flags
&
AK4113_CHECK_NO_RATE
)
&&
runtime
&&
(
runtime
->
rate
!=
res
))
{
snd_pcm_stream_lock_irqsave
(
ak4113
->
substream
,
_flags
);
if
(
snd_pcm_running
(
ak4113
->
substream
))
{
/*printk(KERN_DEBUG "rate changed (%i <- %i)\n",
* runtime->rate, res); */
snd_pcm_stop
(
ak4113
->
substream
,
SNDRV_PCM_STATE_DRAINING
);
wake_up
(
&
runtime
->
sleep
);
res
=
1
;
}
snd_pcm_stream_unlock_irqrestore
(
ak4113
->
substream
,
_flags
);
}
return
res
;
}
EXPORT_SYMBOL_GPL
(
snd_ak4113_check_rate_and_errors
);
static
void
ak4113_stats
(
struct
work_struct
*
work
)
{
struct
ak4113
*
chip
=
container_of
(
work
,
struct
ak4113
,
work
.
work
);
if
(
!
chip
->
init
)
snd_ak4113_check_rate_and_errors
(
chip
,
chip
->
check_flags
);
schedule_delayed_work
(
&
chip
->
work
,
HZ
/
10
);
}
This diff is collapsed.
Click to expand it.
sound/i2c/other/ak4xxx-adda.c
View file @
86e1d57e
...
...
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
*/
#include <asm/io.h>
#include <linux/delay.h>
...
...
@@ -29,6 +29,7 @@
#include <sound/control.h>
#include <sound/tlv.h>
#include <sound/ak4xxx-adda.h>
#include <sound/info.h>
MODULE_AUTHOR
(
"Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"
);
MODULE_DESCRIPTION
(
"Routines for control of AK452x / AK43xx AD/DA converters"
);
...
...
@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write);
static
void
ak4524_reset
(
struct
snd_akm4xxx
*
ak
,
int
state
)
{
unsigned
int
chip
;
unsigned
char
reg
,
maxreg
;
unsigned
char
reg
;
if
(
ak
->
type
==
SND_AK4528
)
maxreg
=
0x06
;
else
maxreg
=
0x08
;
for
(
chip
=
0
;
chip
<
ak
->
num_dacs
/
2
;
chip
++
)
{
snd_akm4xxx_write
(
ak
,
chip
,
0x01
,
state
?
0x00
:
0x03
);
if
(
state
)
continue
;
/* DAC volumes */
for
(
reg
=
0x04
;
reg
<
max
reg
;
reg
++
)
for
(
reg
=
0x04
;
reg
<
ak
->
total_
reg
s
;
reg
++
)
snd_akm4xxx_write
(
ak
,
chip
,
reg
,
snd_akm4xxx_get
(
ak
,
chip
,
reg
));
}
}
/* reset procedure for AK4355 and AK4358 */
static
void
ak435X_reset
(
struct
snd_akm4xxx
*
ak
,
int
state
,
unsigned
char
total_regs
)
static
void
ak435X_reset
(
struct
snd_akm4xxx
*
ak
,
int
state
)
{
unsigned
char
reg
;
...
...
@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state,
snd_akm4xxx_write
(
ak
,
0
,
0x01
,
0x02
);
/* reset and soft-mute */
return
;
}
for
(
reg
=
0x00
;
reg
<
total_regs
;
reg
++
)
for
(
reg
=
0x00
;
reg
<
ak
->
total_regs
;
reg
++
)
if
(
reg
!=
0x01
)
snd_akm4xxx_write
(
ak
,
0
,
reg
,
snd_akm4xxx_get
(
ak
,
0
,
reg
));
...
...
@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state)
{
unsigned
int
chip
;
unsigned
char
reg
;
for
(
chip
=
0
;
chip
<
ak
->
num_dacs
/
2
;
chip
++
)
{
snd_akm4xxx_write
(
ak
,
chip
,
0x00
,
state
?
0x0c
:
0x0f
);
if
(
state
)
continue
;
for
(
reg
=
0x01
;
reg
<
0x05
;
reg
++
)
for
(
reg
=
0x01
;
reg
<
ak
->
total_regs
;
reg
++
)
snd_akm4xxx_write
(
ak
,
chip
,
reg
,
snd_akm4xxx_get
(
ak
,
chip
,
reg
));
}
...
...
@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
switch
(
ak
->
type
)
{
case
SND_AK4524
:
case
SND_AK4528
:
case
SND_AK4620
:
ak4524_reset
(
ak
,
state
);
break
;
case
SND_AK4529
:
/* FIXME: needed for ak4529? */
break
;
case
SND_AK4355
:
ak435X_reset
(
ak
,
state
,
0x0b
);
ak435X_reset
(
ak
,
state
);
break
;
case
SND_AK4358
:
ak435X_reset
(
ak
,
state
,
0x10
);
ak435X_reset
(
ak
,
state
);
break
;
case
SND_AK4381
:
ak4381_reset
(
ak
,
state
);
...
...
@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
* Volume conversion table for non-linear volumes
* from -63.5dB (mute) to 0dB step 0.5dB
*
* Used for AK4524 input/ouput attenuation, AK4528, and
* Used for AK4524
/AK4620
input/ouput attenuation, AK4528, and
* AK5365 input attenuation
*/
static
const
unsigned
char
vol_cvt_datt
[
128
]
=
{
...
...
@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
0x00
,
0x0f
,
/* 0: power-up, un-reset */
0xff
,
0xff
};
static
const
unsigned
char
inits_ak4620
[]
=
{
0x00
,
0x07
,
/* 0: normal */
0x01
,
0x00
,
/* 0: reset */
0x01
,
0x02
,
/* 1: RSTAD */
0x01
,
0x03
,
/* 1: RSTDA */
0x01
,
0x0f
,
/* 1: normal */
0x02
,
0x60
,
/* 2: 24bit I2S */
0x03
,
0x01
,
/* 3: deemphasis off */
0x04
,
0x00
,
/* 4: LIN muted */
0x05
,
0x00
,
/* 5: RIN muted */
0x06
,
0x00
,
/* 6: LOUT muted */
0x07
,
0x00
,
/* 7: ROUT muted */
0xff
,
0xff
};
int
chip
,
num_chips
;
int
chip
;
const
unsigned
char
*
ptr
,
*
inits
;
unsigned
char
reg
,
data
;
...
...
@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
switch
(
ak
->
type
)
{
case
SND_AK4524
:
inits
=
inits_ak4524
;
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
name
=
"ak4524"
;
ak
->
total_regs
=
0x08
;
break
;
case
SND_AK4528
:
inits
=
inits_ak4528
;
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
name
=
"ak4528"
;
ak
->
total_regs
=
0x06
;
break
;
case
SND_AK4529
:
inits
=
inits_ak4529
;
num_chips
=
1
;
ak
->
num_chips
=
1
;
ak
->
name
=
"ak4529"
;
ak
->
total_regs
=
0x0d
;
break
;
case
SND_AK4355
:
inits
=
inits_ak4355
;
num_chips
=
1
;
ak
->
num_chips
=
1
;
ak
->
name
=
"ak4355"
;
ak
->
total_regs
=
0x0b
;
break
;
case
SND_AK4358
:
inits
=
inits_ak4358
;
num_chips
=
1
;
ak
->
num_chips
=
1
;
ak
->
name
=
"ak4358"
;
ak
->
total_regs
=
0x10
;
break
;
case
SND_AK4381
:
inits
=
inits_ak4381
;
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
name
=
"ak4381"
;
ak
->
total_regs
=
0x05
;
break
;
case
SND_AK5365
:
/* FIXME: any init sequence? */
ak
->
num_chips
=
1
;
ak
->
name
=
"ak5365"
;
ak
->
total_regs
=
0x08
;
return
;
case
SND_AK4620
:
inits
=
inits_ak4620
;
ak
->
num_chips
=
ak
->
num_dacs
/
2
;
ak
->
name
=
"ak4620"
;
ak
->
total_regs
=
0x08
;
break
;
default:
snd_BUG
();
return
;
}
for
(
chip
=
0
;
chip
<
num_chips
;
chip
++
)
{
for
(
chip
=
0
;
chip
<
ak
->
num_chips
;
chip
++
)
{
ptr
=
inits
;
while
(
*
ptr
!=
0xff
)
{
reg
=
*
ptr
++
;
data
=
*
ptr
++
;
snd_akm4xxx_write
(
ak
,
chip
,
reg
,
data
);
udelay
(
10
);
}
}
}
...
...
@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
AK_COMPOSE
(
idx
/
2
,
(
idx
%
2
)
+
3
,
0
,
255
);
knew
.
tlv
.
p
=
db_scale_linear
;
break
;
case
SND_AK4620
:
/* register 6 & 7 */
knew
.
private_value
=
AK_COMPOSE
(
idx
/
2
,
(
idx
%
2
)
+
6
,
0
,
255
);
knew
.
tlv
.
p
=
db_scale_linear
;
break
;
default:
return
-
EINVAL
;
}
...
...
@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
static
int
build_adc_controls
(
struct
snd_akm4xxx
*
ak
)
{
int
idx
,
err
,
mixer_ch
,
num_stereo
;
int
idx
,
err
,
mixer_ch
,
num_stereo
,
max_steps
;
struct
snd_kcontrol_new
knew
;
mixer_ch
=
0
;
if
(
ak
->
type
==
SND_AK4528
)
return
0
;
/* no controls */
for
(
idx
=
0
;
idx
<
ak
->
num_adcs
;)
{
memset
(
&
knew
,
0
,
sizeof
(
knew
));
if
(
!
ak
->
adc_info
||
!
ak
->
adc_info
[
mixer_ch
].
name
)
{
...
...
@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
}
/* register 4 & 5 */
if
(
ak
->
type
==
SND_AK5365
)
knew
.
private_value
=
AK_COMPOSE
(
idx
/
2
,
(
idx
%
2
)
+
4
,
0
,
151
)
|
AK_VOL_CVT
|
AK_IPGA
;
max_steps
=
152
;
else
knew
.
private_value
=
AK_COMPOSE
(
idx
/
2
,
(
idx
%
2
)
+
4
,
0
,
163
)
|
AK_VOL_CVT
|
AK_IPGA
;
max_steps
=
164
;
knew
.
private_value
=
AK_COMPOSE
(
idx
/
2
,
(
idx
%
2
)
+
4
,
0
,
max_steps
)
|
AK_VOL_CVT
|
AK_IPGA
;
knew
.
tlv
.
p
=
db_scale_vol_datt
;
err
=
snd_ctl_add
(
ak
->
card
,
snd_ctl_new1
(
&
knew
,
ak
));
if
(
err
<
0
)
...
...
@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
switch
(
ak
->
type
)
{
case
SND_AK4524
:
case
SND_AK4528
:
case
SND_AK4620
:
/* register 3 */
knew
.
private_value
=
AK_COMPOSE
(
idx
,
3
,
0
,
0
);
break
;
...
...
@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
return
0
;
}
#ifdef CONFIG_PROC_FS
static
void
proc_regs_read
(
struct
snd_info_entry
*
entry
,
struct
snd_info_buffer
*
buffer
)
{
struct
snd_akm4xxx
*
ak
=
(
struct
snd_akm4xxx
*
)
entry
->
private_data
;
int
reg
,
val
,
chip
;
for
(
chip
=
0
;
chip
<
ak
->
num_chips
;
chip
++
)
{
for
(
reg
=
0
;
reg
<
ak
->
total_regs
;
reg
++
)
{
val
=
snd_akm4xxx_get
(
ak
,
chip
,
reg
);
snd_iprintf
(
buffer
,
"chip %d: 0x%02x = 0x%02x
\n
"
,
chip
,
reg
,
val
);
}
}
}
static
int
proc_init
(
struct
snd_akm4xxx
*
ak
)
{
struct
snd_info_entry
*
entry
;
int
err
;
err
=
snd_card_proc_new
(
ak
->
card
,
ak
->
name
,
&
entry
);
if
(
err
<
0
)
return
err
;
snd_info_set_text_ops
(
entry
,
ak
,
proc_regs_read
);
return
0
;
}
#else
/* !CONFIG_PROC_FS */
static
int
proc_init
(
struct
snd_akm4xxx
*
ak
)
{}
#endif
int
snd_akm4xxx_build_controls
(
struct
snd_akm4xxx
*
ak
)
{
int
err
,
num_emphs
;
...
...
@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
err
=
build_adc_controls
(
ak
);
if
(
err
<
0
)
return
err
;
if
(
ak
->
type
==
SND_AK4355
||
ak
->
type
==
SND_AK4358
)
num_emphs
=
1
;
else
if
(
ak
->
type
==
SND_AK4620
)
num_emphs
=
0
;
else
num_emphs
=
ak
->
num_dacs
/
2
;
err
=
build_deemphasis
(
ak
,
num_emphs
);
if
(
err
<
0
)
return
err
;
err
=
proc_init
(
ak
);
if
(
err
<
0
)
return
err
;
return
0
;
}
EXPORT_SYMBOL
(
snd_akm4xxx_build_controls
);
static
int
__init
alsa_akm4xxx_module_init
(
void
)
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/Kconfig
View file @
86e1d57e
...
...
@@ -38,9 +38,20 @@ config SND_HDA_INPUT_BEEP
Say Y here to build a digital beep interface for HD-audio
driver. This interface is used to generate digital beeps.
config SND_HDA_INPUT_BEEP_MODE
int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)"
depends on SND_HDA_INPUT_BEEP=y
default "1"
range 0 2
help
Set 0 to disable the digital beep interface for HD-audio by default.
Set 1 to always enable the digital beep interface for HD-audio by
default. Set 2 to control the beep device registration to input
layer using a "Beep Switch" in mixer applications.
config SND_HDA_INPUT_JACK
bool "Support jack plugging notification via input layer"
depends on INPUT=y || INPUT=SND
_HDA_INTEL
depends on INPUT=y || INPUT=SND
select SND_JACK
help
Say Y here to enable the jack plugging notification via
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_beep.c
View file @
86e1d57e
...
...
@@ -113,23 +113,25 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
return
0
;
}
int
snd_hda_attach_beep_device
(
struct
hda_codec
*
codec
,
int
nid
)
static
void
snd_hda_do_detach
(
struct
hda_beep
*
beep
)
{
input_unregister_device
(
beep
->
dev
);
beep
->
dev
=
NULL
;
cancel_work_sync
(
&
beep
->
beep_work
);
/* turn off beep for sure */
snd_hda_codec_write_cache
(
beep
->
codec
,
beep
->
nid
,
0
,
AC_VERB_SET_BEEP_CONTROL
,
0
);
}
static
int
snd_hda_do_attach
(
struct
hda_beep
*
beep
)
{
struct
input_dev
*
input_dev
;
struct
hda_
beep
*
beep
;
struct
hda_
codec
*
codec
=
beep
->
codec
;
int
err
;
if
(
!
snd_hda_get_bool_hint
(
codec
,
"beep"
))
return
0
;
/* disabled explicitly */
beep
=
kzalloc
(
sizeof
(
*
beep
),
GFP_KERNEL
);
if
(
beep
==
NULL
)
return
-
ENOMEM
;
snprintf
(
beep
->
phys
,
sizeof
(
beep
->
phys
),
"card%d/codec#%d/beep0"
,
codec
->
bus
->
card
->
number
,
codec
->
addr
);
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
{
kfree
(
beep
);
printk
(
KERN_INFO
"hda_beep: unable to allocate input device
\n
"
);
return
-
ENOMEM
;
}
...
...
@@ -151,21 +153,96 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
err
=
input_register_device
(
input_dev
);
if
(
err
<
0
)
{
input_free_device
(
input_dev
);
kfree
(
beep
);
printk
(
KERN_INFO
"hda_beep: unable to register input device
\n
"
);
return
err
;
}
beep
->
dev
=
input_dev
;
return
0
;
}
static
void
snd_hda_do_register
(
struct
work_struct
*
work
)
{
struct
hda_beep
*
beep
=
container_of
(
work
,
struct
hda_beep
,
register_work
);
mutex_lock
(
&
beep
->
mutex
);
if
(
beep
->
enabled
&&
!
beep
->
dev
)
snd_hda_do_attach
(
beep
);
mutex_unlock
(
&
beep
->
mutex
);
}
static
void
snd_hda_do_unregister
(
struct
work_struct
*
work
)
{
struct
hda_beep
*
beep
=
container_of
(
work
,
struct
hda_beep
,
unregister_work
.
work
);
mutex_lock
(
&
beep
->
mutex
);
if
(
!
beep
->
enabled
&&
beep
->
dev
)
snd_hda_do_detach
(
beep
);
mutex_unlock
(
&
beep
->
mutex
);
}
int
snd_hda_enable_beep_device
(
struct
hda_codec
*
codec
,
int
enable
)
{
struct
hda_beep
*
beep
=
codec
->
beep
;
enable
=
!!
enable
;
if
(
beep
==
NULL
)
return
0
;
if
(
beep
->
enabled
!=
enable
)
{
beep
->
enabled
=
enable
;
if
(
!
enable
)
{
/* turn off beep */
snd_hda_codec_write_cache
(
beep
->
codec
,
beep
->
nid
,
0
,
AC_VERB_SET_BEEP_CONTROL
,
0
);
}
if
(
beep
->
mode
==
HDA_BEEP_MODE_SWREG
)
{
if
(
enable
)
{
cancel_delayed_work
(
&
beep
->
unregister_work
);
schedule_work
(
&
beep
->
register_work
);
}
else
{
schedule_delayed_work
(
&
beep
->
unregister_work
,
HZ
);
}
}
return
1
;
}
return
0
;
}
EXPORT_SYMBOL_HDA
(
snd_hda_enable_beep_device
);
int
snd_hda_attach_beep_device
(
struct
hda_codec
*
codec
,
int
nid
)
{
struct
hda_beep
*
beep
;
if
(
!
snd_hda_get_bool_hint
(
codec
,
"beep"
))
return
0
;
/* disabled explicitly by hints */
if
(
codec
->
beep_mode
==
HDA_BEEP_MODE_OFF
)
return
0
;
/* disabled by module option */
beep
=
kzalloc
(
sizeof
(
*
beep
),
GFP_KERNEL
);
if
(
beep
==
NULL
)
return
-
ENOMEM
;
snprintf
(
beep
->
phys
,
sizeof
(
beep
->
phys
),
"card%d/codec#%d/beep0"
,
codec
->
bus
->
card
->
number
,
codec
->
addr
);
/* enable linear scale */
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_DIGI_CONVERT_2
,
0x01
);
beep
->
nid
=
nid
;
beep
->
dev
=
input_dev
;
beep
->
codec
=
codec
;
beep
->
enabled
=
1
;
beep
->
mode
=
codec
->
beep_mode
;
codec
->
beep
=
beep
;
INIT_WORK
(
&
beep
->
register_work
,
&
snd_hda_do_register
);
INIT_DELAYED_WORK
(
&
beep
->
unregister_work
,
&
snd_hda_do_unregister
);
INIT_WORK
(
&
beep
->
beep_work
,
&
snd_hda_generate_beep
);
mutex_init
(
&
beep
->
mutex
);
if
(
beep
->
mode
==
HDA_BEEP_MODE_ON
)
{
beep
->
enabled
=
1
;
snd_hda_do_register
(
&
beep
->
register_work
);
}
return
0
;
}
EXPORT_SYMBOL_HDA
(
snd_hda_attach_beep_device
);
...
...
@@ -174,11 +251,12 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
{
struct
hda_beep
*
beep
=
codec
->
beep
;
if
(
beep
)
{
cancel_work_sync
(
&
beep
->
beep
_work
);
i
nput_unregister_device
(
beep
->
dev
);
kfree
(
beep
);
cancel_work_sync
(
&
beep
->
register
_work
);
cancel_delayed_work
(
&
beep
->
unregister_work
);
i
f
(
beep
->
enabled
)
snd_hda_do_detach
(
beep
);
codec
->
beep
=
NULL
;
kfree
(
beep
);
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_detach_beep_device
);
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_beep.h
View file @
86e1d57e
...
...
@@ -24,19 +24,29 @@
#include "hda_codec.h"
#define HDA_BEEP_MODE_OFF 0
#define HDA_BEEP_MODE_ON 1
#define HDA_BEEP_MODE_SWREG 2
/* beep information */
struct
hda_beep
{
struct
input_dev
*
dev
;
struct
hda_codec
*
codec
;
unsigned
int
mode
;
char
phys
[
32
];
int
tone
;
hda_nid_t
nid
;
unsigned
int
enabled
:
1
;
unsigned
int
request_enable
:
1
;
unsigned
int
linear_tone
:
1
;
/* linear tone for IDT/STAC codec */
struct
work_struct
register_work
;
/* registration work */
struct
delayed_work
unregister_work
;
/* unregistration work */
struct
work_struct
beep_work
;
/* scheduled task for beep event */
struct
mutex
mutex
;
};
#ifdef CONFIG_SND_HDA_INPUT_BEEP
int
snd_hda_enable_beep_device
(
struct
hda_codec
*
codec
,
int
enable
);
int
snd_hda_attach_beep_device
(
struct
hda_codec
*
codec
,
int
nid
);
void
snd_hda_detach_beep_device
(
struct
hda_codec
*
codec
);
#else
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_codec.c
View file @
86e1d57e
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_codec.h
View file @
86e1d57e
...
...
@@ -286,6 +286,10 @@ enum {
#define AC_PWRST_D1SUP (1<<1)
#define AC_PWRST_D2SUP (1<<2)
#define AC_PWRST_D3SUP (1<<3)
#define AC_PWRST_D3COLDSUP (1<<4)
#define AC_PWRST_S3D3COLDSUP (1<<29)
#define AC_PWRST_CLKSTOP (1<<30)
#define AC_PWRST_EPSS (1U<<31)
/* Power state values */
#define AC_PWRST_SETTING (0xf<<0)
...
...
@@ -674,6 +678,7 @@ struct hda_codec_ops {
#ifdef CONFIG_SND_HDA_POWER_SAVE
int
(
*
check_power_status
)(
struct
hda_codec
*
codec
,
hda_nid_t
nid
);
#endif
void
(
*
reboot_notify
)(
struct
hda_codec
*
codec
);
};
/* record for amp information cache */
...
...
@@ -771,6 +776,7 @@ struct hda_codec {
/* beep device */
struct
hda_beep
*
beep
;
unsigned
int
beep_mode
;
/* widget capabilities cache */
unsigned
int
num_nodes
;
...
...
@@ -811,6 +817,9 @@ struct hda_codec {
unsigned
int
power_transition
:
1
;
/* power-state in transition */
int
power_count
;
/* current (global) power refcount */
struct
delayed_work
power_work
;
/* delayed task for powerdown */
unsigned
long
power_on_acct
;
unsigned
long
power_off_acct
;
unsigned
long
power_jiffies
;
#endif
/* codec-specific additional proc output */
...
...
@@ -910,6 +919,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
* Misc
*/
void
snd_hda_get_codec_name
(
struct
hda_codec
*
codec
,
char
*
name
,
int
namelen
);
void
snd_hda_bus_reboot_notify
(
struct
hda_bus
*
bus
);
/*
* power management
...
...
@@ -933,6 +943,7 @@ const char *snd_hda_get_jack_location(u32 cfg);
void
snd_hda_power_up
(
struct
hda_codec
*
codec
);
void
snd_hda_power_down
(
struct
hda_codec
*
codec
);
#define snd_hda_codec_needs_resume(codec) codec->power_count
void
snd_hda_update_power_acct
(
struct
hda_codec
*
codec
);
#else
static
inline
void
snd_hda_power_up
(
struct
hda_codec
*
codec
)
{}
static
inline
void
snd_hda_power_down
(
struct
hda_codec
*
codec
)
{}
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_eld.c
View file @
86e1d57e
...
...
@@ -309,17 +309,12 @@ static int hdmi_update_eld(struct hdmi_eld *e,
return
-
EINVAL
;
}
static
int
hdmi_present_sense
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
return
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
);
}
static
int
hdmi_eld_valid
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
int
eldv
;
int
present
;
present
=
hdmi_present
_sense
(
codec
,
nid
);
present
=
snd_hda_pin
_sense
(
codec
,
nid
);
eldv
=
(
present
&
AC_PINSENSE_ELDV
);
present
=
(
present
&
AC_PINSENSE_PRESENCE
);
...
...
@@ -477,6 +472,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
[
4
...
7
]
=
"reserved"
};
snd_iprintf
(
buffer
,
"monitor_present
\t\t
%d
\n
"
,
e
->
monitor_present
);
snd_iprintf
(
buffer
,
"eld_valid
\t\t
%d
\n
"
,
e
->
eld_valid
);
snd_iprintf
(
buffer
,
"monitor_name
\t\t
%s
\n
"
,
e
->
monitor_name
);
snd_iprintf
(
buffer
,
"connection_type
\t\t
%s
\n
"
,
eld_connection_type_names
[
e
->
conn_type
]);
...
...
@@ -518,7 +515,11 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
* monitor_name manufacture_id product_id
* eld_version edid_version
*/
if
(
!
strcmp
(
name
,
"connection_type"
))
if
(
!
strcmp
(
name
,
"monitor_present"
))
e
->
monitor_present
=
val
;
else
if
(
!
strcmp
(
name
,
"eld_valid"
))
e
->
eld_valid
=
val
;
else
if
(
!
strcmp
(
name
,
"connection_type"
))
e
->
conn_type
=
val
;
else
if
(
!
strcmp
(
name
,
"port_id"
))
e
->
port_id
=
val
;
...
...
@@ -560,13 +561,14 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
}
int
snd_hda_eld_proc_new
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
)
int
snd_hda_eld_proc_new
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
,
int
index
)
{
char
name
[
32
];
struct
snd_info_entry
*
entry
;
int
err
;
snprintf
(
name
,
sizeof
(
name
),
"eld#%d"
,
codec
->
addr
);
snprintf
(
name
,
sizeof
(
name
),
"eld#%d
.%d
"
,
codec
->
addr
,
index
);
err
=
snd_card_proc_new
(
codec
->
bus
->
card
,
name
,
&
entry
);
if
(
err
<
0
)
return
err
;
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_generic.c
View file @
86e1d57e
...
...
@@ -727,7 +727,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if
(
is_loopback
)
add_input_loopback
(
codec
,
node
->
nid
,
HDA_INPUT
,
index
);
snd_printdd
(
"[%s] NID=0x%x, DIR=IN, IDX=0x%x
\n
"
,
name
,
node
->
nid
,
index
);
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
knew
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
node
->
nid
,
snd_ctl_new1
(
&
knew
,
codec
));
if
(
err
<
0
)
return
err
;
created
=
1
;
...
...
@@ -737,7 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if
(
is_loopback
)
add_input_loopback
(
codec
,
node
->
nid
,
HDA_OUTPUT
,
0
);
snd_printdd
(
"[%s] NID=0x%x, DIR=OUT
\n
"
,
name
,
node
->
nid
);
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
knew
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
node
->
nid
,
snd_ctl_new1
(
&
knew
,
codec
));
if
(
err
<
0
)
return
err
;
created
=
1
;
...
...
@@ -751,7 +753,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(
node
->
amp_in_caps
&
AC_AMPCAP_NUM_STEPS
))
{
knew
=
(
struct
snd_kcontrol_new
)
HDA_CODEC_VOLUME
(
name
,
node
->
nid
,
index
,
HDA_INPUT
);
snd_printdd
(
"[%s] NID=0x%x, DIR=IN, IDX=0x%x
\n
"
,
name
,
node
->
nid
,
index
);
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
knew
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
node
->
nid
,
snd_ctl_new1
(
&
knew
,
codec
));
if
(
err
<
0
)
return
err
;
created
=
1
;
...
...
@@ -759,7 +762,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(
node
->
amp_out_caps
&
AC_AMPCAP_NUM_STEPS
))
{
knew
=
(
struct
snd_kcontrol_new
)
HDA_CODEC_VOLUME
(
name
,
node
->
nid
,
0
,
HDA_OUTPUT
);
snd_printdd
(
"[%s] NID=0x%x, DIR=OUT
\n
"
,
name
,
node
->
nid
);
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
knew
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
node
->
nid
,
snd_ctl_new1
(
&
knew
,
codec
));
if
(
err
<
0
)
return
err
;
created
=
1
;
...
...
@@ -857,7 +861,7 @@ static int build_input_controls(struct hda_codec *codec)
}
/* create input MUX if multiple sources are available */
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
cap_sel
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
0
,
snd_ctl_new1
(
&
cap_sel
,
codec
));
if
(
err
<
0
)
return
err
;
...
...
@@ -875,7 +879,8 @@ static int build_input_controls(struct hda_codec *codec)
HDA_CODEC_VOLUME
(
name
,
adc_node
->
nid
,
spec
->
input_mux
.
items
[
i
].
index
,
HDA_INPUT
);
err
=
snd_hda_ctl_add
(
codec
,
snd_ctl_new1
(
&
knew
,
codec
));
err
=
snd_hda_ctl_add
(
codec
,
adc_node
->
nid
,
snd_ctl_new1
(
&
knew
,
codec
));
if
(
err
<
0
)
return
err
;
}
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_hwdep.c
View file @
86e1d57e
...
...
@@ -154,6 +154,44 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
return
0
;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
static
ssize_t
power_on_acct_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
snd_hwdep
*
hwdep
=
dev_get_drvdata
(
dev
);
struct
hda_codec
*
codec
=
hwdep
->
private_data
;
snd_hda_update_power_acct
(
codec
);
return
sprintf
(
buf
,
"%u
\n
"
,
jiffies_to_msecs
(
codec
->
power_on_acct
));
}
static
ssize_t
power_off_acct_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
snd_hwdep
*
hwdep
=
dev_get_drvdata
(
dev
);
struct
hda_codec
*
codec
=
hwdep
->
private_data
;
snd_hda_update_power_acct
(
codec
);
return
sprintf
(
buf
,
"%u
\n
"
,
jiffies_to_msecs
(
codec
->
power_off_acct
));
}
static
struct
device_attribute
power_attrs
[]
=
{
__ATTR_RO
(
power_on_acct
),
__ATTR_RO
(
power_off_acct
),
};
int
snd_hda_hwdep_add_power_sysfs
(
struct
hda_codec
*
codec
)
{
struct
snd_hwdep
*
hwdep
=
codec
->
hwdep
;
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
power_attrs
);
i
++
)
snd_add_device_sysfs_file
(
SNDRV_DEVICE_TYPE_HWDEP
,
hwdep
->
card
,
hwdep
->
device
,
&
power_attrs
[
i
]);
return
0
;
}
#endif
/* CONFIG_SND_HDA_POWER_SAVE */
#ifdef CONFIG_SND_HDA_RECONFIG
/*
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_intel.c
View file @
86e1d57e
...
...
@@ -60,10 +60,14 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static
int
probe_mask
[
SNDRV_CARDS
]
=
{[
0
...
(
SNDRV_CARDS
-
1
)]
=
-
1
};
static
int
probe_only
[
SNDRV_CARDS
];
static
int
single_cmd
;
static
int
enable_msi
;
static
int
enable_msi
=
-
1
;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
static
char
*
patch
[
SNDRV_CARDS
];
#endif
#ifdef CONFIG_SND_HDA_INPUT_BEEP
static
int
beep_mode
[
SNDRV_CARDS
]
=
{[
0
...
(
SNDRV_CARDS
-
1
)]
=
CONFIG_SND_HDA_INPUT_BEEP_MODE
};
#endif
module_param_array
(
index
,
int
,
NULL
,
0444
);
MODULE_PARM_DESC
(
index
,
"Index value for Intel HD audio interface."
);
...
...
@@ -91,6 +95,11 @@ MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
module_param_array
(
patch
,
charp
,
NULL
,
0444
);
MODULE_PARM_DESC
(
patch
,
"Patch file for Intel HD audio interface."
);
#endif
#ifdef CONFIG_SND_HDA_INPUT_BEEP
module_param_array
(
beep_mode
,
int
,
NULL
,
0444
);
MODULE_PARM_DESC
(
beep_mode
,
"Select HDA Beep registration mode "
"(0=off, 1=on, 2=mute switch on/off) (default=1)."
);
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE
static
int
power_save
=
CONFIG_SND_HDA_POWER_SAVE_DEFAULT
;
...
...
@@ -404,6 +413,7 @@ struct azx {
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
;
...
...
@@ -677,6 +687,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
}
if
(
!
chip
->
polling_mode
)
{
snd_printk
(
KERN_WARNING
SFX
"azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x
\n
"
,
chip
->
last_cmd
[
addr
]);
chip
->
polling_mode
=
1
;
goto
again
;
}
if
(
chip
->
msi
)
{
snd_printk
(
KERN_WARNING
SFX
"No response from codec, "
"disabling MSI: last cmd=0x%08x
\n
"
,
...
...
@@ -692,14 +710,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
goto
again
;
}
if
(
!
chip
->
polling_mode
)
{
snd_printk
(
KERN_WARNING
SFX
"azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x
\n
"
,
chip
->
last_cmd
[
addr
]);
chip
->
polling_mode
=
1
;
goto
again
;
}
if
(
chip
->
probing
)
{
/* If this critical timeout happens during the codec probing
* phase, this is likely an access to a non-existing codec
...
...
@@ -1404,6 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
err
=
snd_hda_codec_new
(
chip
->
bus
,
c
,
&
codec
);
if
(
err
<
0
)
continue
;
codec
->
beep_mode
=
chip
->
beep_mode
;
codecs
++
;
}
}
...
...
@@ -2154,6 +2165,7 @@ static int azx_resume(struct pci_dev *pci)
static
int
azx_halt
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
buf
)
{
struct
azx
*
chip
=
container_of
(
nb
,
struct
azx
,
reboot_notifier
);
snd_hda_bus_reboot_notify
(
chip
->
bus
);
azx_stop_chip
(
chip
);
return
NOTIFY_OK
;
}
...
...
@@ -2221,7 +2233,9 @@ static int azx_dev_free(struct snd_device *device)
static
struct
snd_pci_quirk
position_fix_list
[]
__devinitdata
=
{
SND_PCI_QUIRK
(
0x1028
,
0x01cc
,
"Dell D820"
,
POS_FIX_LPIB
),
SND_PCI_QUIRK
(
0x1028
,
0x01de
,
"Dell Precision 390"
,
POS_FIX_LPIB
),
SND_PCI_QUIRK
(
0x103c
,
0x306d
,
"HP dv3"
,
POS_FIX_LPIB
),
SND_PCI_QUIRK
(
0x1043
,
0x813d
,
"ASUS P5AD2"
,
POS_FIX_LPIB
),
SND_PCI_QUIRK
(
0x1462
,
0x1002
,
"MSI Wind U115"
,
POS_FIX_LPIB
),
{}
};
...
...
@@ -2304,11 +2318,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
}
/*
* white-list for enable_msi
* white
/black
-list for enable_msi
*/
static
struct
snd_pci_quirk
msi_white_list
[]
__devinitdata
=
{
SND_PCI_QUIRK
(
0x103c
,
0x30f7
,
"HP Pavilion dv4t-1300"
,
1
),
SND_PCI_QUIRK
(
0x103c
,
0x3607
,
"HP Compa CQ40"
,
1
),
static
struct
snd_pci_quirk
msi_black_list
[]
__devinitdata
=
{
{}
};
...
...
@@ -2316,10 +2328,12 @@ static void __devinit check_msi(struct azx *chip)
{
const
struct
snd_pci_quirk
*
q
;
chip
->
msi
=
enable_msi
;
if
(
chip
->
msi
)
if
(
enable_msi
>=
0
)
{
chip
->
msi
=
!!
enable_msi
;
return
;
q
=
snd_pci_quirk_lookup
(
chip
->
pci
,
msi_white_list
);
}
chip
->
msi
=
1
;
/* enable MSI as default */
q
=
snd_pci_quirk_lookup
(
chip
->
pci
,
msi_black_list
);
if
(
q
)
{
printk
(
KERN_INFO
"hda_intel: msi for device %04x:%04x set to %d
\n
"
,
...
...
@@ -2578,6 +2592,10 @@ static int __devinit azx_probe(struct pci_dev *pci,
goto
out_free
;
card
->
private_data
=
chip
;
#ifdef CONFIG_SND_HDA_INPUT_BEEP
chip
->
beep_mode
=
beep_mode
[
dev
];
#endif
/* create codec instances */
err
=
azx_codec_create
(
chip
,
model
[
dev
]);
if
(
err
<
0
)
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_local.h
View file @
86e1d57e
...
...
@@ -23,6 +23,15 @@
#ifndef __SOUND_HDA_LOCAL_H
#define __SOUND_HDA_LOCAL_H
/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
* the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
* snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
*
* Note that the subdevice field is cleared again before the real registration
* in snd_hda_ctl_add(), so that this value won't appear in the outside.
*/
#define HDA_SUBDEV_NID_FLAG (1U << 31)
/*
* for mixer controls
*/
...
...
@@ -33,6 +42,7 @@
/* mono volume with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
...
...
@@ -53,6 +63,7 @@
/* mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get, \
.put = snd_hda_mixer_amp_switch_put, \
...
...
@@ -66,6 +77,28 @@
/* stereo mute switch */
#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get, \
.put = snd_hda_mixer_amp_switch_put_beep, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
#else
/* no digital beep - just the standard one */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir)
#endif
/* CONFIG_SND_HDA_INPUT_BEEP */
/* special beep mono mute switch */
#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction)
/* special beep stereo mute switch */
#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction)
extern
const
char
*
snd_hda_pcm_type_name
[];
int
snd_hda_mixer_amp_volume_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
);
...
...
@@ -81,6 +114,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
);
int
snd_hda_mixer_amp_switch_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
int
snd_hda_mixer_amp_switch_put_beep
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
);
#endif
/* lowlevel accessor with caching; use carefully */
int
snd_hda_codec_amp_read
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
ch
,
int
direction
,
int
index
);
...
...
@@ -424,8 +461,16 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int
snd_hda_override_amp_caps
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
dir
,
unsigned
int
caps
);
u32
snd_hda_query_pin_caps
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
);
u32
snd_hda_pin_sense
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
);
int
snd_hda_jack_detect
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
);
int
snd_hda_ctl_add
(
struct
hda_codec
*
codec
,
struct
snd_kcontrol
*
kctl
);
struct
hda_nid_item
{
struct
snd_kcontrol
*
kctl
;
hda_nid_t
nid
;
};
int
snd_hda_ctl_add
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
struct
snd_kcontrol
*
kctl
);
void
snd_hda_ctls_clear
(
struct
hda_codec
*
codec
);
/*
...
...
@@ -437,6 +482,15 @@ int snd_hda_create_hwdep(struct hda_codec *codec);
static
inline
int
snd_hda_create_hwdep
(
struct
hda_codec
*
codec
)
{
return
0
;
}
#endif
#if defined(CONFIG_SND_HDA_POWER_SAVE) && defined(CONFIG_SND_HDA_HWDEP)
int
snd_hda_hwdep_add_power_sysfs
(
struct
hda_codec
*
codec
);
#else
static
inline
int
snd_hda_hwdep_add_power_sysfs
(
struct
hda_codec
*
codec
)
{
return
0
;
}
#endif
#ifdef CONFIG_SND_HDA_RECONFIG
int
snd_hda_hwdep_add_sysfs
(
struct
hda_codec
*
codec
);
#else
...
...
@@ -490,7 +544,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
* AMP control callbacks
*/
/* retrieve parameters from private_value */
#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
#define get_amp_nid_(pv) ((pv) & 0xffff)
#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
...
...
@@ -516,9 +571,11 @@ struct cea_sad {
* ELD: EDID Like Data
*/
struct
hdmi_eld
{
bool
monitor_present
;
bool
eld_valid
;
int
eld_size
;
int
baseline_len
;
int
eld_ver
;
/* (eld_ver == 0) indicates invalid ELD */
int
eld_ver
;
int
cea_edid_ver
;
char
monitor_name
[
ELD_MAX_MNL
+
1
];
int
manufacture_id
;
...
...
@@ -541,11 +598,13 @@ int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
void
snd_hdmi_show_eld
(
struct
hdmi_eld
*
eld
);
#ifdef CONFIG_PROC_FS
int
snd_hda_eld_proc_new
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
);
int
snd_hda_eld_proc_new
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
,
int
index
);
void
snd_hda_eld_proc_free
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
);
#else
static
inline
int
snd_hda_eld_proc_new
(
struct
hda_codec
*
codec
,
struct
hdmi_eld
*
eld
)
struct
hdmi_eld
*
eld
,
int
index
)
{
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/hda_proc.c
View file @
86e1d57e
...
...
@@ -26,6 +26,21 @@
#include "hda_codec.h"
#include "hda_local.h"
static
char
*
bits_names
(
unsigned
int
bits
,
char
*
names
[],
int
size
)
{
int
i
,
n
;
static
char
buf
[
128
];
for
(
i
=
0
,
n
=
0
;
i
<
size
;
i
++
)
{
if
(
bits
&
(
1U
<<
i
)
&&
names
[
i
])
n
+=
snprintf
(
buf
+
n
,
sizeof
(
buf
)
-
n
,
" %s"
,
names
[
i
]);
}
buf
[
n
]
=
'\0'
;
return
buf
;
}
static
const
char
*
get_wid_type_name
(
unsigned
int
wid_value
)
{
static
char
*
names
[
16
]
=
{
...
...
@@ -46,6 +61,41 @@ static const char *get_wid_type_name(unsigned int wid_value)
return
"UNKNOWN Widget"
;
}
static
void
print_nid_mixers
(
struct
snd_info_buffer
*
buffer
,
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
int
i
;
struct
hda_nid_item
*
items
=
codec
->
mixers
.
list
;
struct
snd_kcontrol
*
kctl
;
for
(
i
=
0
;
i
<
codec
->
mixers
.
used
;
i
++
)
{
if
(
items
[
i
].
nid
==
nid
)
{
kctl
=
items
[
i
].
kctl
;
snd_iprintf
(
buffer
,
" Control: name=
\"
%s
\"
, index=%i, device=%i
\n
"
,
kctl
->
id
.
name
,
kctl
->
id
.
index
,
kctl
->
id
.
device
);
}
}
}
static
void
print_nid_pcms
(
struct
snd_info_buffer
*
buffer
,
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
int
pcm
,
type
;
struct
hda_pcm
*
cpcm
;
for
(
pcm
=
0
;
pcm
<
codec
->
num_pcms
;
pcm
++
)
{
cpcm
=
&
codec
->
pcm_info
[
pcm
];
for
(
type
=
0
;
type
<
2
;
type
++
)
{
if
(
cpcm
->
stream
[
type
].
nid
!=
nid
||
cpcm
->
pcm
==
NULL
)
continue
;
snd_iprintf
(
buffer
,
" Device: name=
\"
%s
\"
, "
"type=
\"
%s
\"
, device=%i
\n
"
,
cpcm
->
name
,
snd_hda_pcm_type_name
[
cpcm
->
pcm_type
],
cpcm
->
pcm
->
device
);
}
}
}
static
void
print_amp_caps
(
struct
snd_info_buffer
*
buffer
,
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
int
dir
)
{
...
...
@@ -363,8 +413,24 @@ static const char *get_pwr_state(u32 state)
static
void
print_power_state
(
struct
snd_info_buffer
*
buffer
,
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
{
static
char
*
names
[]
=
{
[
ilog2
(
AC_PWRST_D0SUP
)]
=
"D0"
,
[
ilog2
(
AC_PWRST_D1SUP
)]
=
"D1"
,
[
ilog2
(
AC_PWRST_D2SUP
)]
=
"D2"
,
[
ilog2
(
AC_PWRST_D3SUP
)]
=
"D3"
,
[
ilog2
(
AC_PWRST_D3COLDSUP
)]
=
"D3cold"
,
[
ilog2
(
AC_PWRST_S3D3COLDSUP
)]
=
"S3D3cold"
,
[
ilog2
(
AC_PWRST_CLKSTOP
)]
=
"CLKSTOP"
,
[
ilog2
(
AC_PWRST_EPSS
)]
=
"EPSS"
,
};
int
sup
=
snd_hda_param_read
(
codec
,
nid
,
AC_PAR_POWER_STATE
);
int
pwr
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
AC_VERB_GET_POWER_STATE
,
0
);
if
(
sup
)
snd_iprintf
(
buffer
,
" Power states: %s
\n
"
,
bits_names
(
sup
,
names
,
ARRAY_SIZE
(
names
)));
snd_iprintf
(
buffer
,
" Power: setting=%s, actual=%s
\n
"
,
get_pwr_state
(
pwr
&
AC_PWRST_SETTING
),
get_pwr_state
((
pwr
&
AC_PWRST_ACTUAL
)
>>
...
...
@@ -457,6 +523,7 @@ static void print_gpio(struct snd_info_buffer *buffer,
(
data
&
(
1
<<
i
))
?
1
:
0
,
(
unsol
&
(
1
<<
i
))
?
1
:
0
);
/* FIXME: add GPO and GPI pin information */
print_nid_mixers
(
buffer
,
codec
,
nid
);
}
static
void
print_codec_info
(
struct
snd_info_entry
*
entry
,
...
...
@@ -536,6 +603,9 @@ static void print_codec_info(struct snd_info_entry *entry,
snd_iprintf
(
buffer
,
" CP"
);
snd_iprintf
(
buffer
,
"
\n
"
);
print_nid_mixers
(
buffer
,
codec
,
nid
);
print_nid_pcms
(
buffer
,
codec
,
nid
);
/* volume knob is a special widget that always have connection
* list
*/
...
...
This diff is collapsed.
Click to expand it.
sound/pci/hda/patch_analog.c
View file @
86e1d57e
...
...
@@ -156,15 +156,19 @@ static const char *ad_slave_sws[] = {
static
void
ad198x_free_kctls
(
struct
hda_codec
*
codec
);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
static
struct
snd_kcontrol_new
ad_beep_mixer
[]
=
{
HDA_CODEC_VOLUME
(
"Beep Playback Volume"
,
0
,
0
,
HDA_OUTPUT
),
HDA_CODEC_MUTE
(
"Beep Playback Switch"
,
0
,
0
,
HDA_OUTPUT
),
HDA_CODEC_MUTE
_BEEP
(
"Beep Playback Switch"
,
0
,
0
,
HDA_OUTPUT
),
{
}
/* end */
};
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
/* mono */
#else
#define set_beep_amp(spec, nid, idx, dir)
/* NOP */
#endif
static
int
ad198x_build_controls
(
struct
hda_codec
*
codec
)
{
...
...
@@ -194,6 +198,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
}
/* create beep controls if needed */
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if
(
spec
->
beep_amp
)
{
struct
snd_kcontrol_new
*
knew
;
for
(
knew
=
ad_beep_mixer
;
knew
->
name
;
knew
++
)
{
...
...
@@ -202,11 +207,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
if
(
!
kctl
)
return
-
ENOMEM
;
kctl
->
private_value
=
spec
->
beep_amp
;
err
=
snd_hda_ctl_add
(
codec
,
kctl
);
err
=
snd_hda_ctl_add
(
codec
,
get_amp_nid_
(
spec
->
beep_amp
),
kctl
);
if
(
err
<
0
)
return
err
;
}
}
#endif
/* if we have no master control, let's create it */
if
(
!
snd_hda_find_mixer_ctl
(
codec
,
"Master Playback Volume"
))
{
...
...
@@ -712,10 +720,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
static
void
ad1986a_automic
(
struct
hda_codec
*
codec
)
{
unsigned
int
present
;
present
=
snd_hda_
codec_read
(
codec
,
0x1f
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
);
present
=
snd_hda_
jack_detect
(
codec
,
0x1f
);
/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
snd_hda_codec_write
(
codec
,
0x0f
,
0
,
AC_VERB_SET_CONNECT_SEL
,
(
present
&
AC_PINSENSE_PRESENCE
)
?
0
:
2
);
present
?
0
:
2
);
}
#define AD1986A_MIC_EVENT 0x36
...
...
@@ -754,10 +762,8 @@ static void ad1986a_update_hp(struct hda_codec *codec)
static
void
ad1986a_hp_automute
(
struct
hda_codec
*
codec
)
{
struct
ad198x_spec
*
spec
=
codec
->
spec
;
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x1a
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
);
spec
->
jack_present
=
!!
(
present
&
0x80000000
);
spec
->
jack_present
=
snd_hda_jack_detect
(
codec
,
0x1a
);
if
(
spec
->
inv_jack_detect
)
spec
->
jack_present
=
!
spec
->
jack_present
;
ad1986a_update_hp
(
codec
);
...
...
@@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec)
{
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x06
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
;
present
=
snd_hda_jack_detect
(
codec
,
0x06
);
snd_hda_codec_amp_stereo
(
codec
,
0x05
,
HDA_OUTPUT
,
0
,
HDA_AMP_MUTE
,
present
?
HDA_AMP_MUTE
:
0
);
}
...
...
@@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec)
};
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x08
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
;
present
=
snd_hda_jack_detect
(
codec
,
0x08
);
if
(
present
)
snd_hda_sequence_write
(
codec
,
mic_jack_on
);
else
...
...
@@ -2524,7 +2528,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
{
if
((
res
>>
26
)
!=
AD1988_HP_EVENT
)
return
;
if
(
snd_hda_
codec_read
(
codec
,
0x11
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
(
1
<<
3
1
))
if
(
snd_hda_
jack_detect
(
codec
,
0x1
1
))
snd_hda_sequence_write
(
codec
,
ad1988_laptop_hp_on
);
else
snd_hda_sequence_write
(
codec
,
ad1988_laptop_hp_off
);
...
...
@@ -2569,6 +2573,8 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
knew
->
name
=
kstrdup
(
name
,
GFP_KERNEL
);
if
(
!
knew
->
name
)
return
-
ENOMEM
;
if
(
get_amp_nid_
(
val
))
knew
->
subdevice
=
HDA_SUBDEV_NID_FLAG
|
get_amp_nid_
(
val
);
knew
->
private_value
=
val
;
return
0
;
}
...
...
@@ -3768,8 +3774,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec)
{
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x11
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
;
present
=
snd_hda_jack_detect
(
codec
,
0x11
);
snd_hda_codec_amp_stereo
(
codec
,
0x16
,
HDA_OUTPUT
,
0
,
HDA_AMP_MUTE
,
present
?
HDA_AMP_MUTE
:
0
);
snd_hda_codec_write
(
codec
,
0x16
,
0
,
AC_VERB_SET_EAPD_BTLENABLE
,
...
...
@@ -3781,8 +3786,7 @@ static void ad1884a_hp_automic(struct hda_codec *codec)
{
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x14
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
;
present
=
snd_hda_jack_detect
(
codec
,
0x14
);
snd_hda_codec_write
(
codec
,
0x0c
,
0
,
AC_VERB_SET_CONNECT_SEL
,
present
?
0
:
1
);
}
...
...
@@ -3817,13 +3821,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec)
{
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x11
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
);
present
&=
AC_PINSENSE_PRESENCE
;
if
(
!
present
)
{
present
=
snd_hda_codec_read
(
codec
,
0x12
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
);
present
&=
AC_PINSENSE_PRESENCE
;
}
present
=
snd_hda_jack_detect
(
codec
,
0x11
);
if
(
!
present
)
present
=
snd_hda_jack_detect
(
codec
,
0x12
);
snd_hda_codec_amp_stereo
(
codec
,
0x16
,
HDA_OUTPUT
,
0
,
HDA_AMP_MUTE
,
present
?
HDA_AMP_MUTE
:
0
);
snd_hda_codec_write
(
codec
,
0x16
,
0
,
AC_VERB_SET_EAPD_BTLENABLE
,
...
...
@@ -3835,11 +3835,9 @@ static void ad1884a_laptop_automic(struct hda_codec *codec)
{
unsigned
int
idx
;
if
(
snd_hda_codec_read
(
codec
,
0x14
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
AC_PINSENSE_PRESENCE
)
if
(
snd_hda_jack_detect
(
codec
,
0x14
))
idx
=
0
;
else
if
(
snd_hda_codec_read
(
codec
,
0x1c
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
AC_PINSENSE_PRESENCE
)
else
if
(
snd_hda_jack_detect
(
codec
,
0x1c
))
idx
=
4
;
else
idx
=
1
;
...
...
@@ -4008,8 +4006,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec)
{
unsigned
int
present
;
present
=
snd_hda_codec_read
(
codec
,
0x11
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
AC_PINSENSE_PRESENCE
;
present
=
snd_hda_jack_detect
(
codec
,
0x11
);
snd_hda_codec_amp_stereo
(
codec
,
0x12
,
HDA_OUTPUT
,
0
,
HDA_AMP_MUTE
,
present
?
HDA_AMP_MUTE
:
0
);
}
...
...
@@ -4117,14 +4114,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
/* switch to external mic if plugged */
static
void
ad1984a_touchsmart_automic
(
struct
hda_codec
*
codec
)
{
if
(
snd_hda_codec_read
(
codec
,
0x1c
,
0
,
AC_VERB_GET_PIN_SENSE
,
0
)
&
0x80000000
)
{
if
(
snd_hda_jack_detect
(
codec
,
0x1c
))
snd_hda_codec_write
(
codec
,
0x0c
,
0
,
AC_VERB_SET_CONNECT_SEL
,
0x4
);
}
else
{
else
snd_hda_codec_write
(
codec
,
0x0c
,
0
,
AC_VERB_SET_CONNECT_SEL
,
0x5
);
}
}
...
...
This diff is collapsed.
Click to expand it.
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment