Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (214 commits)
  ALSA: hda - Add pin-fix for HP dc5750
  ALSA: als4000: Fix potentially invalid DMA mode setup
  ALSA: als4000: enable burst mode
  ALSA: hda - Fix initial capsrc selection in patch_alc269()
  ASoC: TWL4030: Capture route runtime DAPM ordering fix
  ALSA: hda - Add PC-beep whitelist for an Intel board
  ALSA: hda - More relax for pending period handling
  ALSA: hda - Define AC_FMT_* constants
  ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs
  ALSA: hda - Add support for HDMI HBR passthrough
  ALSA: hda - Set Stream Type in Stream Format according to AES0
  ALSA: hda - Fix Thinkpad X300 so SPDIF is not exposed
  ALSA: hda - FIX to not expose SPDIF on Thinkpad X301, since it does not have the ability to use SPDIF
  ASoC: wm9081: fix resource reclaim in wm9081_register error path
  ASoC: wm8978: fix a memory leak if a wm8978_register fail
  ASoC: wm8974: fix a memory leak if another WM8974 is registered
  ASoC: wm8961: fix resource reclaim in wm8961_register error path
  ASoC: wm8955: fix resource reclaim in wm8955_register error path
  ASoC: wm8940: fix a memory leak if wm8940_register return error
  ASoC: wm8904: fix resource reclaim in wm8904_register error path
  ...
This commit is contained in:
Linus Torvalds 2010-08-07 17:07:31 -07:00
commit faa38b5e0e
194 changed files with 11087 additions and 1507 deletions

View File

@ -281,19 +281,12 @@ and is between 256 and 4096 characters. It is defined in the file
no: ACPI OperationRegions are not marked as reserved,
no further checks are performed.
ad1848= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<type>
add_efi_memmap [EFI; X86] Include EFI memory map in
kernel's map of available physical RAM.
advansys= [HW,SCSI]
See header of drivers/scsi/advansys.c.
aedsp16= [HW,OSS] Audio Excel DSP 16
Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
See also header of sound/oss/aedsp16.c.
agp= [AGP]
{ off | try_unsupported }
off: disable AGP support
@ -312,6 +305,9 @@ and is between 256 and 4096 characters. It is defined in the file
aic79xx= [HW,SCSI]
See Documentation/scsi/aic79xx.txt.
ALSA [HW,ALSA]
See Documentation/sound/alsa/alsa-parameters.txt
alignment= [KNL,ARM]
Allow the default userspace alignment fault handler
behaviour to be specified. Bit 0 enables warnings,
@ -656,8 +652,6 @@ and is between 256 and 4096 characters. It is defined in the file
Disable PIN 1 of APIC timer
Can be useful to work around chipset bugs.
dmasound= [HW,OSS] Sound subsystem buffers
dma_debug=off If the kernel is compiled with DMA_API_DEBUG support,
this option disables the debugging code at boot.
@ -1527,9 +1521,6 @@ and is between 256 and 4096 characters. It is defined in the file
that the amount of memory usable for all allocations
is not too small.
mpu401= [HW,OSS]
Format: <io>,<irq>
MTD_Partition= [MTD]
Format: <name>,<region-number>,<size>,<offset>
@ -1854,9 +1845,6 @@ and is between 256 and 4096 characters. It is defined in the file
For example, to override I2C bus2:
omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100
opl3= [HW,OSS]
Format: <io>
oprofile.timer= [HW]
Use timer interrupt instead of performance counters
@ -1868,6 +1856,9 @@ and is between 256 and 4096 characters. It is defined in the file
perfmon on Intel CPUs instead of the
CPU specific event set.
OSS [HW,OSS]
See Documentation/sound/oss/oss-parameters.txt
osst= [HW,SCSI] SCSI Tape Driver
Format: <buffer_size>,<write_threshold>
See also Documentation/scsi/st.txt.
@ -1904,9 +1895,6 @@ and is between 256 and 4096 characters. It is defined in the file
Currently this function knows 686a and 8231 chips.
Format: [spp|ps2|epp|ecp|ecpepp]
pas2= [HW,OSS] Format:
<io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
pas16= [HW,SCSI]
See header of drivers/scsi/pas16.c.
@ -2178,10 +2166,6 @@ and is between 256 and 4096 characters. It is defined in the file
[HW,MOUSE] Controls Logitech smartscroll autorepeat.
0 = disabled, 1 = enabled (default).
pss= [HW,OSS] Personal Sound System (ECHO ESC614)
Format:
<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
pt. [PARIDE]
See Documentation/blockdev/paride.txt.
@ -2397,128 +2381,6 @@ and is between 256 and 4096 characters. It is defined in the file
1: Fast pin select (default)
2: ATC IRMode
snd-ad1816a= [HW,ALSA]
snd-ad1848= [HW,ALSA]
snd-ali5451= [HW,ALSA]
snd-als100= [HW,ALSA]
snd-als4000= [HW,ALSA]
snd-azt2320= [HW,ALSA]
snd-cmi8330= [HW,ALSA]
snd-cmipci= [HW,ALSA]
snd-cs4231= [HW,ALSA]
snd-cs4232= [HW,ALSA]
snd-cs4236= [HW,ALSA]
snd-cs4281= [HW,ALSA]
snd-cs46xx= [HW,ALSA]
snd-dt019x= [HW,ALSA]
snd-dummy= [HW,ALSA]
snd-emu10k1= [HW,ALSA]
snd-ens1370= [HW,ALSA]
snd-ens1371= [HW,ALSA]
snd-es968= [HW,ALSA]
snd-es1688= [HW,ALSA]
snd-es18xx= [HW,ALSA]
snd-es1938= [HW,ALSA]
snd-es1968= [HW,ALSA]
snd-fm801= [HW,ALSA]
snd-gusclassic= [HW,ALSA]
snd-gusextreme= [HW,ALSA]
snd-gusmax= [HW,ALSA]
snd-hdsp= [HW,ALSA]
snd-ice1712= [HW,ALSA]
snd-intel8x0= [HW,ALSA]
snd-interwave= [HW,ALSA]
snd-interwave-stb=
[HW,ALSA]
snd-korg1212= [HW,ALSA]
snd-maestro3= [HW,ALSA]
snd-mpu401= [HW,ALSA]
snd-mtpav= [HW,ALSA]
snd-nm256= [HW,ALSA]
snd-opl3sa2= [HW,ALSA]
snd-opti92x-ad1848=
[HW,ALSA]
snd-opti92x-cs4231=
[HW,ALSA]
snd-opti93x= [HW,ALSA]
snd-pmac= [HW,ALSA]
snd-rme32= [HW,ALSA]
snd-rme96= [HW,ALSA]
snd-rme9652= [HW,ALSA]
snd-sb8= [HW,ALSA]
snd-sb16= [HW,ALSA]
snd-sbawe= [HW,ALSA]
snd-serial= [HW,ALSA]
snd-sgalaxy= [HW,ALSA]
snd-sonicvibes= [HW,ALSA]
snd-sun-amd7930=
[HW,ALSA]
snd-sun-cs4231= [HW,ALSA]
snd-trident= [HW,ALSA]
snd-usb-audio= [HW,ALSA,USB]
snd-via82xx= [HW,ALSA]
snd-virmidi= [HW,ALSA]
snd-wavefront= [HW,ALSA]
snd-ymfpci= [HW,ALSA]
softlockup_panic=
[KNL] Should the soft-lockup detector generate panics.
@ -2533,9 +2395,6 @@ and is between 256 and 4096 characters. It is defined in the file
spia_pedr=
spia_peddr=
sscape= [HW,OSS]
Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
st= [HW,SCSI] SCSI tape parameters (buffers, etc.)
See Documentation/scsi/st.txt.
@ -2675,10 +2534,6 @@ and is between 256 and 4096 characters. It is defined in the file
to facilitate early boot debugging.
See also Documentation/trace/events.txt
trix= [HW,OSS] MediaTrix AudioTrix Pro
Format:
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
tsc= Disable clocksource-must-verify flag for TSC.
Format: <string>
[x86] reliable: mark tsc clocksource as reliable, this
@ -2695,12 +2550,6 @@ and is between 256 and 4096 characters. It is defined in the file
u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter
See header of drivers/scsi/u14-34f.c.
uart401= [HW,OSS]
Format: <io>,<irq>
uart6850= [HW,OSS]
Format: <io>,<irq>
uhash_entries= [KNL,NET]
Set number of hash buckets for UDP/UDP-Lite connections
@ -2866,9 +2715,6 @@ and is between 256 and 4096 characters. It is defined in the file
overridden by individual drivers. 0 will hide
cursors, 1 will display them.
waveartist= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>
wd33c93= [HW,SCSI]
See header of drivers/scsi/wd33c93.c.
@ -2911,5 +2757,4 @@ ______________________________________________________________________
TODO:
Add documentation for ALSA options.
Add more DRM drivers.

View File

@ -114,6 +114,11 @@ ALC662/663/272
samsung-nc10 Samsung NC10 mini notebook
auto auto-config reading BIOS (default)
ALC680
======
base Base model (ASUS NX90)
auto auto-config reading BIOS (default)
ALC882/883/885/888/889
======================
3stack-dig 3-jack with SPDIF I/O
@ -282,6 +287,7 @@ Conexant 5051
hp HP Spartan laptop
hp-dv6736 HP dv6736
hp-f700 HP Compaq Presario F700
ideapad Lenovo IdeaPad laptop
lenovo-x200 Lenovo X200 laptop
toshiba Toshiba Satellite M300

View File

@ -103,6 +103,8 @@ card*/pcm*/xrun_debug
bit 2 = Enable additional jiffies check
bit 3 = Log hwptr update at each period interrupt
bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
bit 5 = Show last 10 positions on error
bit 6 = Do above only once
When the bit 0 is set, the driver will show the messages to
kernel log when an xrun is detected. The debug message is
@ -122,6 +124,12 @@ card*/pcm*/xrun_debug
Bits 3 and 4 are for logging the hwptr records. Note that
these will give flood of kernel messages.
When bit 5 is set, the driver logs the last 10 xrun errors and
the proc file shows each jiffies, position, period_size,
buffer_size, old_hw_ptr, and hw_ptr_base values.
When bit 6 is set, the full xrun log is shown only once.
card*/pcm*/sub*/info
The general information of this PCM sub-stream.

View File

@ -0,0 +1,135 @@
ALSA Kernel Parameters
~~~~~~~~~~~~~~~~~~~~~~
See Documentation/kernel-parameters.txt for general information on
specifying module parameters.
This document may not be entirely up to date and comprehensive. The command
"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
module. Loadable modules, after being loaded into the running kernel, also
reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
parameters may be changed at runtime by the command
"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
snd-ad1816a= [HW,ALSA]
snd-ad1848= [HW,ALSA]
snd-ali5451= [HW,ALSA]
snd-als100= [HW,ALSA]
snd-als4000= [HW,ALSA]
snd-azt2320= [HW,ALSA]
snd-cmi8330= [HW,ALSA]
snd-cmipci= [HW,ALSA]
snd-cs4231= [HW,ALSA]
snd-cs4232= [HW,ALSA]
snd-cs4236= [HW,ALSA]
snd-cs4281= [HW,ALSA]
snd-cs46xx= [HW,ALSA]
snd-dt019x= [HW,ALSA]
snd-dummy= [HW,ALSA]
snd-emu10k1= [HW,ALSA]
snd-ens1370= [HW,ALSA]
snd-ens1371= [HW,ALSA]
snd-es968= [HW,ALSA]
snd-es1688= [HW,ALSA]
snd-es18xx= [HW,ALSA]
snd-es1938= [HW,ALSA]
snd-es1968= [HW,ALSA]
snd-fm801= [HW,ALSA]
snd-gusclassic= [HW,ALSA]
snd-gusextreme= [HW,ALSA]
snd-gusmax= [HW,ALSA]
snd-hdsp= [HW,ALSA]
snd-ice1712= [HW,ALSA]
snd-intel8x0= [HW,ALSA]
snd-interwave= [HW,ALSA]
snd-interwave-stb=
[HW,ALSA]
snd-korg1212= [HW,ALSA]
snd-maestro3= [HW,ALSA]
snd-mpu401= [HW,ALSA]
snd-mtpav= [HW,ALSA]
snd-nm256= [HW,ALSA]
snd-opl3sa2= [HW,ALSA]
snd-opti92x-ad1848=
[HW,ALSA]
snd-opti92x-cs4231=
[HW,ALSA]
snd-opti93x= [HW,ALSA]
snd-pmac= [HW,ALSA]
snd-rme32= [HW,ALSA]
snd-rme96= [HW,ALSA]
snd-rme9652= [HW,ALSA]
snd-sb8= [HW,ALSA]
snd-sb16= [HW,ALSA]
snd-sbawe= [HW,ALSA]
snd-serial= [HW,ALSA]
snd-sgalaxy= [HW,ALSA]
snd-sonicvibes= [HW,ALSA]
snd-sun-amd7930=
[HW,ALSA]
snd-sun-cs4231= [HW,ALSA]
snd-trident= [HW,ALSA]
snd-usb-audio= [HW,ALSA,USB]
snd-via82xx= [HW,ALSA]
snd-virmidi= [HW,ALSA]
snd-wavefront= [HW,ALSA]
snd-ymfpci= [HW,ALSA]

View File

@ -0,0 +1,51 @@
OSS Kernel Parameters
~~~~~~~~~~~~~~~~~~~~~
See Documentation/kernel-parameters.txt for general information on
specifying module parameters.
This document may not be entirely up to date and comprehensive. The command
"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
module. Loadable modules, after being loaded into the running kernel, also
reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
parameters may be changed at runtime by the command
"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
ad1848= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<type>
aedsp16= [HW,OSS] Audio Excel DSP 16
Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
See also header of sound/oss/aedsp16.c.
dmasound= [HW,OSS] Sound subsystem buffers
mpu401= [HW,OSS]
Format: <io>,<irq>
opl3= [HW,OSS]
Format: <io>
pas2= [HW,OSS] Format:
<io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
pss= [HW,OSS] Personal Sound System (ECHO ESC614)
Format:
<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
sscape= [HW,OSS]
Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
trix= [HW,OSS] MediaTrix AudioTrix Pro
Format:
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
uart401= [HW,OSS]
Format: <io>,<irq>
uart6850= [HW,OSS]
Format: <io>,<irq>
waveartist= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>

View File

@ -208,7 +208,7 @@ static struct snd_platform_data da830_evm_snd_data = {
.num_serializer = ARRAY_SIZE(da830_iis_serializer_direction),
.tdm_slots = 2,
.serial_dir = da830_iis_serializer_direction,
.eventq_no = EVENTQ_0,
.asp_chan_q = EVENTQ_0,
.version = MCASP_VERSION_2,
.txnumevt = 1,
.rxnumevt = 1,

View File

@ -343,7 +343,7 @@ static struct snd_platform_data da850_evm_snd_data = {
.num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
.tdm_slots = 2,
.serial_dir = da850_iis_serializer_direction,
.eventq_no = EVENTQ_1,
.asp_chan_q = EVENTQ_1,
.version = MCASP_VERSION_2,
.txnumevt = 1,
.rxnumevt = 1,

View File

@ -323,7 +323,7 @@ static struct snd_platform_data dm646x_evm_snd_data[] = {
.num_serializer = ARRAY_SIZE(dm646x_iis_serializer_direction),
.tdm_slots = 2,
.serial_dir = dm646x_iis_serializer_direction,
.eventq_no = EVENTQ_0,
.asp_chan_q = EVENTQ_0,
},
{
.tx_dma_offset = 0x400,
@ -332,7 +332,7 @@ static struct snd_platform_data dm646x_evm_snd_data[] = {
.num_serializer = ARRAY_SIZE(dm646x_dit_serializer_direction),
.tdm_slots = 32,
.serial_dir = dm646x_dit_serializer_direction,
.eventq_no = EVENTQ_0,
.asp_chan_q = EVENTQ_0,
},
};

View File

@ -52,7 +52,8 @@
struct snd_platform_data {
u32 tx_dma_offset;
u32 rx_dma_offset;
enum dma_event_q eventq_no; /* event queue number */
enum dma_event_q asp_chan_q; /* event queue number for ASP channel */
enum dma_event_q ram_chan_q; /* event queue number for RAM channel */
unsigned int codec_fmt;
/*
* Allowing this is more efficient and eliminates left and right swaps
@ -63,6 +64,49 @@ struct snd_platform_data {
unsigned sram_size_playback;
unsigned sram_size_capture;
/*
* If McBSP peripheral gets the clock from an external pin,
* there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR
* and MCBSP_CLKS.
* Depending on different hardware connections it is possible
* to use this setting to change the behaviour of McBSP
* driver. The dm365_clk_input_pin enum is available for dm365
*/
int clk_input_pin;
/*
* This flag works when both clock and FS are outputs for the cpu
* and makes clock more accurate (FS is not symmetrical and the
* clock is very fast.
* The clock becoming faster is named
* i2s continuous serial clock (I2S_SCK) and it is an externally
* visible bit clock.
*
* first line : WordSelect
* second line : ContinuousSerialClock
* third line: SerialData
*
* SYMMETRICAL APPROACH:
* _______________________ LEFT
* _| RIGHT |______________________|
* _ _ _ _ _ _ _ _
* _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_
* _ _ _ _ _ _ _ _
* _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_
* \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
*
* ACCURATE CLOCK APPROACH:
* ______________ LEFT
* _| RIGHT |_______________________________|
* _ _ _ _ _ _ _ _ _
* _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| |
* _ _ _ _ dummy cycles
* _/ \_ ... _/ \_/ \_ ... _/ \__________________
* \_/ \_/ \_/ \_/
*
*/
bool i2s_accurate_sck;
/* McASP specific fields */
int tdm_slots;
u8 op_mode;
@ -78,6 +122,11 @@ enum {
MCASP_VERSION_2, /* DA8xx/OMAPL1x */
};
enum dm365_clk_input_pin {
MCBSP_CLKR = 0, /* DM365 */
MCBSP_CLKS,
};
#define INACTIVE_MODE 0
#define TX_MODE 1
#define RX_MODE 2

View File

@ -43,7 +43,8 @@ static unsigned long get_uart_rate(struct clk *clk);
static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
static int set_div_rate(struct clk *clk, unsigned long rate);
static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate);
static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate);
static struct clk clk_xtali = {
.rate = EP93XX_EXT_CLK_RATE,
@ -112,6 +113,29 @@ static struct clk clk_video = {
.set_rate = set_div_rate,
};
static struct clk clk_i2s_mclk = {
.sw_locked = 1,
.enable_reg = EP93XX_SYSCON_I2SCLKDIV,
.enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
.set_rate = set_div_rate,
};
static struct clk clk_i2s_sclk = {
.sw_locked = 1,
.parent = &clk_i2s_mclk,
.enable_reg = EP93XX_SYSCON_I2SCLKDIV,
.enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
.set_rate = set_i2s_sclk_rate,
};
static struct clk clk_i2s_lrclk = {
.sw_locked = 1,
.parent = &clk_i2s_sclk,
.enable_reg = EP93XX_SYSCON_I2SCLKDIV,
.enable_mask = EP93XX_SYSCON_I2SCLKDIV_SENA,
.set_rate = set_i2s_lrclk_rate,
};
/* DMA Clocks */
static struct clk clk_m2p0 = {
.parent = &clk_h,
@ -191,6 +215,9 @@ static struct clk_lookup clocks[] = {
INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
INIT_CK("ep93xx-fb", NULL, &clk_video),
INIT_CK("ep93xx-spi.0", NULL, &clk_spi),
INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk),
INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk),
INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk),
INIT_CK(NULL, "pwm_clk", &clk_pwm),
INIT_CK(NULL, "m2p0", &clk_m2p0),
INIT_CK(NULL, "m2p1", &clk_m2p1),
@ -401,6 +428,44 @@ static int set_div_rate(struct clk *clk, unsigned long rate)
return 0;
}
static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate)
{
unsigned val = __raw_readl(clk->enable_reg);
if (rate == clk_i2s_mclk.rate / 2)
ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV,
clk->enable_reg);
else if (rate == clk_i2s_mclk.rate / 4)
ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV,
clk->enable_reg);
else
return -EINVAL;
clk_i2s_sclk.rate = rate;
return 0;
}
static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate)
{
unsigned val = __raw_readl(clk->enable_reg) &
~EP93XX_I2SCLKDIV_LRDIV_MASK;
if (rate == clk_i2s_sclk.rate / 32)
ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32,
clk->enable_reg);
else if (rate == clk_i2s_sclk.rate / 64)
ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64,
clk->enable_reg);
else if (rate == clk_i2s_sclk.rate / 128)
ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128,
clk->enable_reg);
else
return -EINVAL;
clk_i2s_lrclk.rate = rate;
return 0;
}
int clk_set_rate(struct clk *clk, unsigned long rate)
{
if (clk->set_rate)

View File

@ -758,6 +758,73 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev)
}
EXPORT_SYMBOL(ep93xx_keypad_release_gpio);
/*************************************************************************
* EP93xx I2S audio peripheral handling
*************************************************************************/
static struct resource ep93xx_i2s_resource[] = {
{
.start = EP93XX_I2S_PHYS_BASE,
.end = EP93XX_I2S_PHYS_BASE + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device ep93xx_i2s_device = {
.name = "ep93xx-i2s",
.id = -1,
.num_resources = ARRAY_SIZE(ep93xx_i2s_resource),
.resource = ep93xx_i2s_resource,
};
void __init ep93xx_register_i2s(void)
{
platform_device_register(&ep93xx_i2s_device);
}
#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
EP93XX_SYSCON_DEVCFG_I2SONAC97)
#define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
EP93XX_SYSCON_I2SCLKDIV_SPOL)
int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
{
unsigned val;
/* Sanity check */
if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
return -EINVAL;
if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
return -EINVAL;
/* Must have only one of I2SONSSP/I2SONAC97 set */
if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
(i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
return -EINVAL;
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
ep93xx_devcfg_set_bits(i2s_pins);
/*
* This is potentially racy with the clock api for i2s_mclk, sclk and
* lrclk. Since the i2s driver is the only user of those clocks we
* rely on it to prevent parallel use of this function and the
* clock api for the i2s clocks.
*/
val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
val &= ~EP93XX_I2SCLKDIV_MASK;
val |= i2s_config;
ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
return 0;
}
EXPORT_SYMBOL(ep93xx_i2s_acquire);
void ep93xx_i2s_release(void)
{
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
}
EXPORT_SYMBOL(ep93xx_i2s_release);
extern void ep93xx_gpio_init(void);

View File

@ -93,6 +93,7 @@
/* APB peripherals */
#define EP93XX_TIMER_BASE EP93XX_APB_IOMEM(0x00010000)
#define EP93XX_I2S_PHYS_BASE EP93XX_APB_PHYS(0x00020000)
#define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000)
#define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000)
@ -194,6 +195,15 @@
#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
#define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c)
#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31)
#define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29)
#define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19)
#define EP93XX_I2SCLKDIV_SDIV (1 << 16)
#define EP93XX_I2SCLKDIV_LRDIV32 (0 << 17)
#define EP93XX_I2SCLKDIV_LRDIV64 (1 << 17)
#define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17)
#define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17)
#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31)
#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16)

View File

@ -58,6 +58,9 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev);
void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
void ep93xx_keypad_release_gpio(struct platform_device *pdev);
void ep93xx_register_i2s(void);
int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
void ep93xx_i2s_release(void);
void ep93xx_init_devices(void);
extern struct sys_timer ep93xx_timer;

View File

@ -157,6 +157,7 @@ static void __init snappercl15_init_machine(void)
ep93xx_register_i2c(&snappercl15_i2c_gpio_data, snappercl15_i2c_data,
ARRAY_SIZE(snappercl15_i2c_data));
ep93xx_register_fb(&snappercl15_fb_info);
ep93xx_register_i2s();
platform_device_register(&snappercl15_nand_device);
}

View File

@ -25,6 +25,7 @@
#include <asm/mach/time.h>
#include <mach/kirkwood.h>
#include <mach/bridge-regs.h>
#include <plat/audio.h>
#include <plat/cache-feroceon-l2.h>
#include <plat/ehci-orion.h>
#include <plat/mvsdio.h>
@ -871,6 +872,42 @@ struct sys_timer kirkwood_timer = {
.init = kirkwood_timer_init,
};
/*****************************************************************************
* Audio
****************************************************************************/
static struct resource kirkwood_i2s_resources[] = {
[0] = {
.start = AUDIO_PHYS_BASE,
.end = AUDIO_PHYS_BASE + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_KIRKWOOD_I2S,
.end = IRQ_KIRKWOOD_I2S,
.flags = IORESOURCE_IRQ,
},
};
static struct kirkwood_asoc_platform_data kirkwood_i2s_data = {
.dram = &kirkwood_mbus_dram_info,
.burst = 128,
};
static struct platform_device kirkwood_i2s_device = {
.name = "kirkwood-i2s",
.id = -1,
.num_resources = ARRAY_SIZE(kirkwood_i2s_resources),
.resource = kirkwood_i2s_resources,
.dev = {
.platform_data = &kirkwood_i2s_data,
},
};
void __init kirkwood_audio_init(void)
{
kirkwood_clk_ctrl |= CGC_AUDIO;
platform_device_register(&kirkwood_i2s_device);
}
/*****************************************************************************
* General
@ -939,6 +976,7 @@ void __init kirkwood_init(void)
kirkwood_spi_plat_data.tclk = kirkwood_tclk;
kirkwood_uart0_data[0].uartclk = kirkwood_tclk;
kirkwood_uart1_data[0].uartclk = kirkwood_tclk;
kirkwood_i2s_data.tclk = kirkwood_tclk;
/*
* Disable propagation of mbus errors to the CPU local bus,

View File

@ -17,6 +17,7 @@ struct mv_sata_platform_data;
struct mvsdio_platform_data;
struct mtd_partition;
struct mtd_info;
struct kirkwood_asoc_platform_data;
#define KW_PCIE0 (1 << 0)
#define KW_PCIE1 (1 << 1)
@ -46,6 +47,7 @@ void kirkwood_uart0_init(void);
void kirkwood_uart1_init(void);
void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay);
void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts, int (*dev_ready)(struct mtd_info *));
void kirkwood_audio_init(void);
extern int kirkwood_tclk;
extern struct sys_timer kirkwood_timer;

View File

@ -111,6 +111,9 @@
#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
#define AUDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0xA0000)
#define AUDIO_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0xA0000)
/*
* Supported devices and revisions.
*/

View File

@ -15,6 +15,7 @@
#include <linux/mtd/partitions.h>
#include <linux/ata_platform.h>
#include <linux/mv643xx_eth.h>
#include <linux/i2c.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/kirkwood.h>
@ -60,6 +61,12 @@ static unsigned int openrd_mpp_config[] __initdata = {
0
};
static struct i2c_board_info i2c_board_info[] __initdata = {
{
I2C_BOARD_INFO("cs42l51", 0x4a),
},
};
static void __init openrd_init(void)
{
/*
@ -86,6 +93,12 @@ static void __init openrd_init(void)
kirkwood_sdio_init(&openrd_mvsdio_data);
kirkwood_i2c_init();
if (machine_is_openrd_client()) {
i2c_register_board_info(0, i2c_board_info,
ARRAY_SIZE(i2c_board_info));
kirkwood_audio_init();
}
}
static int __init openrd_pci_init(void)

View File

@ -133,7 +133,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
.ops = &omap2_mcbsp_ops,
.buffer_size = 0x6F,
.buffer_size = 0x80, /* The FIFO has 128 locations */
},
{
.phys_base = OMAP34XX_MCBSP2_BASE,
@ -143,7 +143,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
.ops = &omap2_mcbsp_ops,
.buffer_size = 0x3FF,
.buffer_size = 0x500, /* The FIFO has 1024 + 256 locations */
},
{
.phys_base = OMAP34XX_MCBSP3_BASE,
@ -153,7 +153,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP3_IRQ_RX,
.tx_irq = INT_24XX_MCBSP3_IRQ_TX,
.ops = &omap2_mcbsp_ops,
.buffer_size = 0x6F,
.buffer_size = 0x80, /* The FIFO has 128 locations */
},
{
.phys_base = OMAP34XX_MCBSP4_BASE,
@ -162,7 +162,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP4_IRQ_RX,
.tx_irq = INT_24XX_MCBSP4_IRQ_TX,
.ops = &omap2_mcbsp_ops,
.buffer_size = 0x6F,
.buffer_size = 0x80, /* The FIFO has 128 locations */
},
{
.phys_base = OMAP34XX_MCBSP5_BASE,
@ -171,7 +171,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP5_IRQ_RX,
.tx_irq = INT_24XX_MCBSP5_IRQ_TX,
.ops = &omap2_mcbsp_ops,
.buffer_size = 0x6F,
.buffer_size = 0x80, /* The FIFO has 128 locations */
},
};
#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)

View File

@ -10,6 +10,9 @@ struct imx_ssi_platform_data {
unsigned int flags;
#define IMX_SSI_DMA (1 << 0)
#define IMX_SSI_USE_AC97 (1 << 1)
#define IMX_SSI_NET (1 << 2)
#define IMX_SSI_SYN (1 << 3)
#define IMX_SSI_USE_I2S_SLAVE (1 << 4)
void (*ac97_reset) (struct snd_ac97 *ac97);
void (*ac97_warm_reset)(struct snd_ac97 *ac97);
};

View File

@ -473,6 +473,7 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
u16 omap_mcbsp_get_fifo_size(unsigned int id);
u16 omap_mcbsp_get_tx_delay(unsigned int id);
u16 omap_mcbsp_get_rx_delay(unsigned int id);
int omap_mcbsp_get_dma_op_mode(unsigned int id);
@ -483,6 +484,7 @@ static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
{ }
static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_fifo_size(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_tx_delay(unsigned int id) { return 0; }
static inline u16 omap_mcbsp_get_rx_delay(unsigned int id) { return 0; }
static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }

View File

@ -481,9 +481,9 @@ int omap_st_is_enabled(unsigned int id)
EXPORT_SYMBOL(omap_st_is_enabled);
/*
* omap_mcbsp_set_tx_threshold configures how to deal
* with transmit threshold. the threshold value and handler can be
* configure in here.
* omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH2 register.
*/
void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
{
@ -498,14 +498,15 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
}
mcbsp = id_to_mcbsp_ptr(id);
MCBSP_WRITE(mcbsp, THRSH2, threshold);
if (threshold && threshold <= mcbsp->max_tx_thres)
MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
}
EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
/*
* omap_mcbsp_set_rx_threshold configures how to deal
* with receive threshold. the threshold value and handler can be
* configure in here.
* omap_mcbsp_set_rx_threshold configures the receive threshold in words.
* The threshold parameter is 1 based, and it is converted (threshold - 1)
* for the THRSH1 register.
*/
void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
{
@ -520,7 +521,8 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
}
mcbsp = id_to_mcbsp_ptr(id);
MCBSP_WRITE(mcbsp, THRSH1, threshold);
if (threshold && threshold <= mcbsp->max_rx_thres)
MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
}
EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
@ -560,8 +562,20 @@ u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
}
EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
#define MCBSP2_FIFO_SIZE 0x500 /* 1024 + 256 locations */
#define MCBSP1345_FIFO_SIZE 0x80 /* 128 locations */
u16 omap_mcbsp_get_fifo_size(unsigned int id)
{
struct omap_mcbsp *mcbsp;
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
return -ENODEV;
}
mcbsp = id_to_mcbsp_ptr(id);
return mcbsp->pdata->buffer_size;
}
EXPORT_SYMBOL(omap_mcbsp_get_fifo_size);
/*
* omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
*/
@ -580,10 +594,7 @@ u16 omap_mcbsp_get_tx_delay(unsigned int id)
buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
/* Number of slots are different in McBSP ports */
if (mcbsp->id == 2)
return MCBSP2_FIFO_SIZE - buffstat;
else
return MCBSP1345_FIFO_SIZE - buffstat;
return mcbsp->pdata->buffer_size - buffstat;
}
EXPORT_SYMBOL(omap_mcbsp_get_tx_delay);
@ -1683,8 +1694,16 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
{
mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
if (cpu_is_omap34xx()) {
mcbsp->max_tx_thres = max_thres(mcbsp);
mcbsp->max_rx_thres = max_thres(mcbsp);
/*
* Initially configure the maximum thresholds to a safe value.
* The McBSP FIFO usage with these values should not go under
* 16 locations.
* If the whole FIFO without safety buffer is used, than there
* is a possibility that the DMA will be not able to push the
* new data on time, causing channel shifts in runtime.
*/
mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
/*
* REVISIT: Set dmap_op_mode to THRESHOLD as default
* for mcbsp2 instances.

View File

@ -0,0 +1,11 @@
#ifndef __PLAT_AUDIO_H
#define __PLAT_AUDIO_H
#include <linux/mbus.h>
struct kirkwood_asoc_platform_data {
u32 tclk;
struct mbus_dram_target_info *dram;
int burst;
};
#endif

View File

@ -8,6 +8,7 @@
#include "linux/slab.h"
#include "linux/sound.h"
#include "linux/soundcard.h"
#include "linux/smp_lock.h"
#include "asm/uaccess.h"
#include "init.h"
#include "os.h"
@ -198,7 +199,10 @@ static int hostaudio_open(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
w = 1;
lock_kernel();
ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
unlock_kernel();
if (ret < 0) {
kfree(state);
return ret;
@ -254,7 +258,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
w = 1;
lock_kernel();
ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
unlock_kernel();
if (ret < 0) {
printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "

View File

@ -61,7 +61,7 @@ DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
+ UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
/* B.3.2 Class-Specific AC Interface Descriptor */
static struct uac_ac_header_descriptor_v1_2 ac_header_desc = {
static struct uac1_ac_header_descriptor_2 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_LENGTH,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_HEADER,
@ -125,7 +125,7 @@ static struct usb_audio_control_selector feature_unit = {
};
#define OUTPUT_TERMINAL_ID 3
static struct uac_output_terminal_descriptor_v1 output_terminal_desc = {
static struct uac1_output_terminal_descriptor output_terminal_desc = {
.bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
@ -155,7 +155,7 @@ static struct usb_interface_descriptor as_interface_alt_1_desc = {
};
/* B.4.2 Class-Specific AS Interface Descriptor */
static struct uac_as_header_descriptor_v1 as_header_desc = {
static struct uac1_as_header_descriptor as_header_desc = {
.bLength = UAC_DT_AS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_AS_GENERAL,

View File

@ -238,7 +238,7 @@ static const struct usb_interface_descriptor ac_interface_desc = {
};
/* B.3.2 Class-Specific AC Interface Descriptor */
static const struct uac_ac_header_descriptor_v1_1 ac_header_desc = {
static const struct uac1_ac_header_descriptor_1 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,

View File

@ -18,6 +18,21 @@
/* v1.0 and v2.0 of this standard have many things in common. For the rest
* of the definitions, please refer to audio.h */
/*
* bmControl field decoders
*
* From the USB Audio spec v2.0:
*
* bmaControls() is a (ch+1)-element array of 4-byte bitmaps,
* each containing a set of bit pairs. If a Control is present,
* it must be Host readable. If a certain Control is not
* present then the bit pair must be set to 0b00.
* If a Control is present but read-only, the bit pair must be
* set to 0b01. If a Control is also Host programmable, the bit
* pair must be set to 0b11. The value 0b10 is not allowed.
*
*/
static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
{
return (bmControls >> (control * 2)) & 0x1;
@ -121,7 +136,7 @@ struct uac2_feature_unit_descriptor {
/* 4.9.2 Class-Specific AS Interface Descriptor */
struct uac_as_header_descriptor_v2 {
struct uac2_as_header_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;

View File

@ -39,8 +39,8 @@
#define UAC_MIXER_UNIT 0x04
#define UAC_SELECTOR_UNIT 0x05
#define UAC_FEATURE_UNIT 0x06
#define UAC_PROCESSING_UNIT_V1 0x07
#define UAC_EXTENSION_UNIT_V1 0x08
#define UAC1_PROCESSING_UNIT 0x07
#define UAC1_EXTENSION_UNIT 0x08
/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
#define UAC_AS_GENERAL 0x01
@ -151,7 +151,7 @@
/* Terminal Control Selectors */
/* 4.3.2 Class-Specific AC Interface Descriptor */
struct uac_ac_header_descriptor_v1 {
struct uac1_ac_header_descriptor {
__u8 bLength; /* 8 + n */
__u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
__u8 bDescriptorSubtype; /* UAC_MS_HEADER */
@ -165,7 +165,7 @@ struct uac_ac_header_descriptor_v1 {
/* As above, but more useful for defining your own descriptors: */
#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \
struct uac_ac_header_descriptor_v1_##n { \
struct uac1_ac_header_descriptor_##n { \
__u8 bLength; \
__u8 bDescriptorType; \
__u8 bDescriptorSubtype; \
@ -205,7 +205,7 @@ struct uac_input_terminal_descriptor {
#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01
/* 4.3.2.2 Output Terminal Descriptor */
struct uac_output_terminal_descriptor_v1 {
struct uac1_output_terminal_descriptor {
__u8 bLength; /* in bytes: 9 */
__u8 bDescriptorType; /* CS_INTERFACE descriptor type */
__u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */
@ -395,7 +395,7 @@ static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_desc
}
/* 4.5.2 Class-Specific AS Interface Descriptor */
struct uac_as_header_descriptor_v1 {
struct uac1_as_header_descriptor {
__u8 bLength; /* in bytes: 7 */
__u8 bDescriptorType; /* USB_DT_CS_INTERFACE */
__u8 bDescriptorSubtype; /* AS_GENERAL */

View File

@ -212,7 +212,11 @@ typedef int __bitwise snd_pcm_format_t;
#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
#ifdef SNDRV_LITTLE_ENDIAN
#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE

View File

@ -174,6 +174,10 @@ struct snd_pcm_ops {
#define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE)
#define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE)
#define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE)
#define SNDRV_PCM_FMTBIT_G723_24 (1ULL << SNDRV_PCM_FORMAT_G723_24)
#define SNDRV_PCM_FMTBIT_G723_24_1B (1ULL << SNDRV_PCM_FORMAT_G723_24_1B)
#define SNDRV_PCM_FMTBIT_G723_40 (1ULL << SNDRV_PCM_FORMAT_G723_40)
#define SNDRV_PCM_FMTBIT_G723_40_1B (1ULL << SNDRV_PCM_FORMAT_G723_40_1B)
#ifdef SNDRV_LITTLE_ENDIAN
#define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE
@ -313,7 +317,7 @@ struct snd_pcm_runtime {
struct snd_pcm_mmap_control *control;
/* -- locking / scheduling -- */
unsigned int twake: 1; /* do transfer (!poll) wakeup */
snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */
wait_queue_head_t sleep; /* poll sleep */
wait_queue_head_t tsleep; /* transfer sleep */
struct fasync_struct *fasync;

View File

@ -12,6 +12,9 @@
* published by the Free Software Foundation.
*/
#define FSI_PORT_A 0
#define FSI_PORT_B 1
/* flags format
* 0xABCDEEFF
@ -55,12 +58,14 @@
#define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK)
#define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK)
#define SH_FSI_FMT_MONO (1 << 0)
#define SH_FSI_FMT_MONO_DELAY (1 << 1)
#define SH_FSI_FMT_PCM (1 << 2)
#define SH_FSI_FMT_I2S (1 << 3)
#define SH_FSI_FMT_TDM (1 << 4)
#define SH_FSI_FMT_TDM_DELAY (1 << 5)
#define SH_FSI_FMT_MONO 0
#define SH_FSI_FMT_MONO_DELAY 1
#define SH_FSI_FMT_PCM 2
#define SH_FSI_FMT_I2S 3
#define SH_FSI_FMT_TDM 4
#define SH_FSI_FMT_TDM_DELAY 5
#define SH_FSI_FMT_SPDIF 6
#define SH_FSI_IFMT_TDM_CH(x) \
(SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x))
@ -72,9 +77,41 @@
#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
(SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x))
/*
* set_rate return value
*
* see ACKMD/BPFMD on
* ACK_MD (FSI2)
* CKG1 (FSI)
*
* err: return value < 0
*
* 0x-00000AB
*
* A: ACKMD value
* B: BPFMD value
*/
#define SH_FSI_ACKMD_MASK (0xF << 0)
#define SH_FSI_ACKMD_512 (1 << 0)
#define SH_FSI_ACKMD_256 (2 << 0)
#define SH_FSI_ACKMD_128 (3 << 0)
#define SH_FSI_ACKMD_64 (4 << 0)
#define SH_FSI_ACKMD_32 (5 << 0)
#define SH_FSI_BPFMD_MASK (0xF << 4)
#define SH_FSI_BPFMD_512 (1 << 4)
#define SH_FSI_BPFMD_256 (2 << 4)
#define SH_FSI_BPFMD_128 (3 << 4)
#define SH_FSI_BPFMD_64 (4 << 4)
#define SH_FSI_BPFMD_32 (5 << 4)
#define SH_FSI_BPFMD_16 (6 << 4)
struct sh_fsi_platform_info {
unsigned long porta_flags;
unsigned long portb_flags;
int (*set_rate)(int is_porta, int rate); /* for master mode */
};
extern struct snd_soc_dai fsi_soc_dai[2];

View File

@ -273,6 +273,8 @@
#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
#define SND_SOC_DAPM_PRE_POST_PMD \
(SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
/* convenience event type detection */
#define SND_SOC_DAPM_EVENT_ON(e) \

View File

@ -170,6 +170,21 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&xenum }
#define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\
xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw_2r_sx, \
.get = snd_soc_get_volsw_2r_sx, \
.put = snd_soc_put_volsw_2r_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg_left, \
.rreg = xreg_right, .shift = xshift, \
.min = xmin, .max = xmax} }
/*
* Simplified versions of above macros, declaring a struct and calculating
* ARRAY_SIZE internally
@ -329,6 +344,12 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_limit_volume(struct snd_soc_codec *codec,
const char *name, int max);
int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
/**
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection

View File

@ -15,6 +15,8 @@
struct tlv320dac33_platform_data {
int power_gpio;
int mode1_latency; /* latency caused by the i2c writes in us */
int auto_fifo_config; /* FIFO config based on the period size */
int keep_bclk; /* Keep the BCLK running in FIFO modes */
u8 burst_bclkdiv;
};

View File

@ -18,6 +18,18 @@ struct uda134x_platform_data {
struct l3_pins l3;
void (*power) (int);
int model;
/*
ALSA SOC usually puts the device in standby mode when it's not used
for sometime. If you unset is_powered_on_standby the driver will
turn off the ADC/DAC when this callback is invoked and turn it back
on when needed. Unfortunately this will result in a very light bump
(it can be audible only with good earphones). If this bothers you
set is_powered_on_standby, you will have slightly higher power
consumption. Please note that sending the L3 command for ADC is
enough to make the bump, so it doesn't make difference if you
completely take off power from the codec.
*/
int is_powered_on_standby;
#define UDA134X_UDA1340 1
#define UDA134X_UDA1341 2
#define UDA134X_UDA1344 3

View File

@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
} else {
if (new_hw_ptr == ULONG_MAX) { /* initialization */
snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
if (avail > runtime->buffer_size)
avail = runtime->buffer_size;
runtime->silence_filled = avail > 0 ? avail : 0;
runtime->silence_start = (runtime->status->hw_ptr +
runtime->silence_filled) %
@ -287,8 +289,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
return -EPIPE;
}
}
if (avail >= runtime->control->avail_min)
wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
if (runtime->twake) {
if (avail >= runtime->twake)
wake_up(&runtime->tsleep);
} else if (avail >= runtime->control->avail_min)
wake_up(&runtime->sleep);
return 0;
}
@ -1707,7 +1712,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed);
* The available space is stored on availp. When err = 0 and avail = 0
* on the capture stream, it indicates the stream is in DRAINING state.
*/
static int wait_for_avail_min(struct snd_pcm_substream *substream,
static int wait_for_avail(struct snd_pcm_substream *substream,
snd_pcm_uframes_t *availp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -1757,7 +1762,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
if (avail >= runtime->control->avail_min)
if (avail >= runtime->twake)
break;
}
_endloop:
@ -1820,7 +1825,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
goto _end_unlock;
}
runtime->twake = 1;
runtime->twake = runtime->control->avail_min ? : 1;
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
@ -1833,7 +1838,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
err = -EAGAIN;
goto _end_unlock;
}
err = wait_for_avail_min(substream, &avail);
runtime->twake = min_t(snd_pcm_uframes_t, size,
runtime->control->avail_min ? : 1);
err = wait_for_avail(substream, &avail);
if (err < 0)
goto _end_unlock;
}
@ -2042,7 +2049,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
goto _end_unlock;
}
runtime->twake = 1;
runtime->twake = runtime->control->avail_min ? : 1;
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
@ -2060,7 +2067,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
err = -EAGAIN;
goto _end_unlock;
}
err = wait_for_avail_min(substream, &avail);
runtime->twake = min_t(snd_pcm_uframes_t, size,
runtime->control->avail_min ? : 1);
err = wait_for_avail(substream, &avail);
if (err < 0)
goto _end_unlock;
if (!avail)

View File

@ -128,6 +128,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
.width = 4, .phys = 4, .le = -1, .signd = -1,
.silence = {},
},
[SNDRV_PCM_FORMAT_G723_24] = {
.width = 3, .phys = 3, .le = -1, .signd = -1,
.silence = {},
},
[SNDRV_PCM_FORMAT_G723_40] = {
.width = 5, .phys = 5, .le = -1, .signd = -1,
.silence = {},
},
/* FIXME: the following three formats are not defined properly yet */
[SNDRV_PCM_FORMAT_MPEG] = {
.le = -1, .signd = -1,
@ -186,6 +194,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
.width = 18, .phys = 24, .le = 0, .signd = 0,
.silence = { 0x02, 0x00, 0x00 },
},
[SNDRV_PCM_FORMAT_G723_24_1B] = {
.width = 3, .phys = 8, .le = -1, .signd = -1,
.silence = {},
},
[SNDRV_PCM_FORMAT_G723_40_1B] = {
.width = 5, .phys = 8, .le = -1, .signd = -1,
.silence = {},
},
};

View File

@ -170,9 +170,25 @@ config SND_AC97_POWER_SAVE
AC97 codecs. In this mode, the power-mode is dynamically
controlled at each open/close.
The mode is activated by passing power_save=1 option to
snd-ac97-codec driver. You can toggle it dynamically over
sysfs, too.
The mode is activated by passing 'power_save=X' to the
snd-ac97-codec driver module, where 'X' is the time-out
value, a nonnegative integer that specifies how many
seconds of idle time the driver must count before it may
put the AC97 into power-save mode; a value of 0 (zero)
disables the use of this power-save mode.
After the snd-ac97-codec driver module has been loaded,
the 'power_save' parameter can be set via sysfs as follows:
echo 10 > /sys/module/snd_ac97_codec/parameters/power_save
In this case, the time-out is set to 10 seconds; setting
the time-out to 1 second (the minimum activation value)
isn't recommended because many applications try to reopen
the device frequently. A value of 10 seconds would be a
good choice for normal operations.
See Documentation/sound/alsa/powersave.txt for more details.
config SND_AC97_POWER_SAVE_DEFAULT
int "Default time-out for AC97 power-save mode"
@ -182,4 +198,6 @@ config SND_AC97_POWER_SAVE_DEFAULT
The default time-out value in seconds for AC97 automatic
power-save mode. 0 means to disable the power-save mode.
See SND_AC97_POWER_SAVE for more details.
endif # SND_DRIVERS

View File

@ -549,7 +549,10 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
return err;
}
request_region(chip->io, DSP_NUMIO, card->shortname);
if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
free_irq(chip->irq, chip);
return -EBUSY;
}
if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
printk(KERN_ERR LOGNAME

View File

@ -433,7 +433,8 @@ static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned sh
while (count > 0) {
unsigned short sval;
CHECK_SCHEDULER();
get_user(sval, buf);
if (get_user(sval, buf))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
buf++;
count--;
@ -525,12 +526,14 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
while (count-- > 0) {
unsigned short sval;
CHECK_SCHEDULER();
get_user(sval, buf);
if (get_user(sval, buf))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
buf++;
if (rec->voices > 1) {
CHECK_SCHEDULER();
get_user(sval, buf);
if (get_user(sval, buf))
return -EFAULT;
EMU8000_SMRD_WRITE(emu, sval);
buf++;
}

View File

@ -43,6 +43,7 @@
#include <linux/sound.h>
#include <linux/slab.h>
#include <linux/soundcard.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@ -162,19 +163,10 @@ ld2(unsigned int x)
static void
au1550_delay(int msec)
{
unsigned long tmo;
signed long tmo2;
if (in_interrupt())
return;
tmo = jiffies + (msec * HZ) / 1000;
for (;;) {
tmo2 = tmo - jiffies;
if (tmo2 <= 0)
break;
schedule_timeout(tmo2);
}
schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
}
static u16
@ -807,7 +799,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
static int
au1550_open_mixdev(struct inode *inode, struct file *file)
{
lock_kernel();
file->private_data = &au1550_state;
unlock_kernel();
return 0;
}
@ -824,22 +818,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
return codec->mixer_ioctl(codec, cmd, arg);
}
static int
au1550_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long
au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
{
struct au1550_state *s = (struct au1550_state *)file->private_data;
struct ac97_codec *codec = s->codec;
int ret;
return mixdev_ioctl(codec, cmd, arg);
lock_kernel();
ret = mixdev_ioctl(codec, cmd, arg);
unlock_kernel();
return ret;
}
static /*const */ struct file_operations au1550_mixer_fops = {
owner:THIS_MODULE,
llseek:au1550_llseek,
ioctl:au1550_ioctl_mixdev,
open:au1550_open_mixdev,
release:au1550_release_mixdev,
.owner = THIS_MODULE,
.llseek = au1550_llseek,
.unlocked_ioctl = au1550_ioctl_mixdev,
.open = au1550_open_mixdev,
.release = au1550_release_mixdev,
};
static int
@ -1343,8 +1341,7 @@ dma_count_done(struct dmabuf *db)
static int
au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct au1550_state *s = (struct au1550_state *)file->private_data;
unsigned long flags;
@ -1780,6 +1777,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return mixdev_ioctl(s->codec, cmd, arg);
}
static long
au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
lock_kernel();
ret = au1550_ioctl(file, cmd, arg);
unlock_kernel();
return ret;
}
static int
au1550_open(struct inode *inode, struct file *file)
@ -1797,21 +1805,22 @@ au1550_open(struct inode *inode, struct file *file)
#endif
file->private_data = s;
lock_kernel();
/* wait for device to become free */
mutex_lock(&s->open_mutex);
while (s->open_mode & file->f_mode) {
if (file->f_flags & O_NONBLOCK) {
mutex_unlock(&s->open_mutex);
return -EBUSY;
}
ret = -EBUSY;
if (file->f_flags & O_NONBLOCK)
goto out;
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
mutex_unlock(&s->open_mutex);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
ret = -ERESTARTSYS;
if (signal_pending(current))
return -ERESTARTSYS;
goto out2;
mutex_lock(&s->open_mutex);
}
@ -1840,17 +1849,21 @@ au1550_open(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_READ) {
if ((ret = prog_dmabuf_adc(s)))
return ret;
goto out;
}
if (file->f_mode & FMODE_WRITE) {
if ((ret = prog_dmabuf_dac(s)))
return ret;
goto out;
}
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
mutex_unlock(&s->open_mutex);
mutex_init(&s->sem);
return 0;
ret = 0;
out:
mutex_unlock(&s->open_mutex);
out2:
unlock_kernel();
return ret;
}
static int
@ -1885,15 +1898,15 @@ au1550_release(struct inode *inode, struct file *file)
}
static /*const */ struct file_operations au1550_audio_fops = {
owner: THIS_MODULE,
llseek: au1550_llseek,
read: au1550_read,
write: au1550_write,
poll: au1550_poll,
ioctl: au1550_ioctl,
mmap: au1550_mmap,
open: au1550_open,
release: au1550_release,
.owner = THIS_MODULE,
.llseek = au1550_llseek,
.read = au1550_read,
.write = au1550_write,
.poll = au1550_poll,
.unlocked_ioctl = au1550_unlocked_ioctl,
.mmap = au1550_mmap,
.open = au1550_open,
.release = au1550_release,
};
MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");

View File

@ -323,9 +323,13 @@ static struct {
static int mixer_open(struct inode *inode, struct file *file)
{
if (!try_module_get(dmasound.mach.owner))
lock_kernel();
if (!try_module_get(dmasound.mach.owner)) {
unlock_kernel();
return -ENODEV;
}
mixer.busy = 1;
unlock_kernel();
return 0;
}
@ -337,8 +341,8 @@ static int mixer_release(struct inode *inode, struct file *file)
unlock_kernel();
return 0;
}
static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
static int mixer_ioctl(struct file *file, u_int cmd, u_long arg)
{
if (_SIOC_DIR(cmd) & _SIOC_WRITE)
mixer.modify_counter++;
@ -362,11 +366,22 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
return -EINVAL;
}
static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{
int ret;
lock_kernel();
ret = mixer_ioctl(file, cmd, arg);
unlock_kernel();
return ret;
}
static const struct file_operations mixer_fops =
{
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = mixer_ioctl,
.unlocked_ioctl = mixer_unlocked_ioctl,
.open = mixer_open,
.release = mixer_release,
};
@ -737,8 +752,11 @@ static int sq_open(struct inode *inode, struct file *file)
{
int rc;
if (!try_module_get(dmasound.mach.owner))
lock_kernel();
if (!try_module_get(dmasound.mach.owner)) {
unlock_kernel();
return -ENODEV;
}
rc = write_sq_open(file); /* checks the f_mode */
if (rc)
@ -781,10 +799,11 @@ static int sq_open(struct inode *inode, struct file *file)
sound_set_format(AFMT_MU_LAW);
}
#endif
unlock_kernel();
return 0;
out:
module_put(dmasound.mach.owner);
unlock_kernel();
return rc;
}
@ -955,8 +974,7 @@ printk("dmasound_core: tried to set_queue_frags on a locked queue\n") ;
return 0 ;
}
static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
static int sq_ioctl(struct file *file, u_int cmd, u_long arg)
{
int val, result;
u_long fmt;
@ -1114,18 +1132,29 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
return IOCTL_OUT(arg,val);
default:
return mixer_ioctl(inode, file, cmd, arg);
return mixer_ioctl(file, cmd, arg);
}
return -EINVAL;
}
static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{
int ret;
lock_kernel();
ret = sq_ioctl(file, cmd, arg);
unlock_kernel();
return ret;
}
static const struct file_operations sq_fops =
{
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = sq_write,
.poll = sq_poll,
.ioctl = sq_ioctl,
.unlocked_ioctl = sq_unlocked_ioctl,
.open = sq_open,
.release = sq_release,
};
@ -1226,12 +1255,17 @@ static int state_open(struct inode *inode, struct file *file)
{
char *buffer = state.buf;
int len = 0;
int ret;
lock_kernel();
ret = -EBUSY;
if (state.busy)
return -EBUSY;
goto out;
ret = -ENODEV;
if (!try_module_get(dmasound.mach.owner))
return -ENODEV;
goto out;
state.ptr = 0;
state.busy = 1;
@ -1293,7 +1327,10 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n");
state.len = len;
return 0;
ret = 0;
out:
unlock_kernel();
return ret;
}
static int state_release(struct inode *inode, struct file *file)

View File

@ -523,7 +523,9 @@ midi_synth_load_patch(int dev, int format, const char __user *addr,
{
unsigned char data;
get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i]));
if (get_user(data,
(unsigned char __user *)(addr + hdr_size + i)))
return -EFAULT;
eox_seen = (i > 0 && data & 0x80); /* End of sysex */

View File

@ -639,21 +639,26 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
return -EINVAL;
}
static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int minor = iminor(inode);
int minor = iminor(file->f_path.dentry->d_inode);
int ret;
if (cmd == OSS_GETVERSION) {
int sound_version = SOUND_VERSION;
return put_user(sound_version, (int __user *)arg);
}
if (minor == dev.dsp_minor)
return dsp_ioctl(file, cmd, arg);
else if (minor == dev.mixer_minor)
return mixer_ioctl(cmd, arg);
ret = -EINVAL;
return -EINVAL;
lock_kernel();
if (minor == dev.dsp_minor)
ret = dsp_ioctl(file, cmd, arg);
else if (minor == dev.mixer_minor)
ret = mixer_ioctl(cmd, arg);
unlock_kernel();
return ret;
}
static void dsp_write_flush(void)
@ -756,12 +761,15 @@ static int dev_open(struct inode *inode, struct file *file)
int minor = iminor(inode);
int err = 0;
lock_kernel();
if (minor == dev.dsp_minor) {
if ((file->f_mode & FMODE_WRITE &&
test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
(file->f_mode & FMODE_READ &&
test_bit(F_AUDIO_READ_INUSE, &dev.flags)))
return -EBUSY;
test_bit(F_AUDIO_READ_INUSE, &dev.flags))) {
err = -EBUSY;
goto out;
}
if ((err = dsp_open(file)) >= 0) {
dev.nresets = 0;
@ -782,7 +790,8 @@ static int dev_open(struct inode *inode, struct file *file)
/* nothing */
} else
err = -EINVAL;
out:
unlock_kernel();
return err;
}
@ -1105,7 +1114,7 @@ static const struct file_operations dev_fileops = {
.owner = THIS_MODULE,
.read = dev_read,
.write = dev_write,
.ioctl = dev_ioctl,
.unlocked_ioctl = dev_ioctl,
.open = dev_open,
.release = dev_release,
};
@ -1391,9 +1400,13 @@ static int __init attach_multisound(void)
printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);
return err;
}
request_region(dev.io, dev.numio, dev.name);
if (request_region(dev.io, dev.numio, dev.name) == NULL) {
free_irq(dev.irq, &dev);
return -EBUSY;
}
if ((err = dsp_full_reset()) < 0) {
err = dsp_full_reset();
if (err < 0) {
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
return err;

View File

@ -15,7 +15,9 @@
#include <linux/linkage.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/smp_lock.h>
#include <linux/sound.h>
#include <linux/smp_lock.h>
#include <linux/soundcard.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
@ -92,7 +94,7 @@ static void dac_audio_set_rate(void)
wakeups_per_second = ktime_set(0, 1000000000 / rate);
}
static int dac_audio_ioctl(struct inode *inode, struct file *file,
static int dac_audio_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int val;
@ -158,6 +160,17 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{
int ret;
lock_kernel();
ret = dac_audio_ioctl(file, cmd, arg);
unlock_kernel();
return ret;
}
static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
loff_t * ppos)
{
@ -216,13 +229,17 @@ static int dac_audio_open(struct inode *inode, struct file *file)
{
if (file->f_mode & FMODE_READ)
return -ENODEV;
if (in_use)
lock_kernel();
if (in_use) {
unlock_kernel();
return -EBUSY;
}
in_use = 1;
dac_audio_start();
unlock_kernel();
return 0;
}
@ -237,8 +254,8 @@ static int dac_audio_release(struct inode *inode, struct file *file)
const struct file_operations dac_audio_fops = {
.read = dac_audio_read,
.write = dac_audio_write,
.ioctl = dac_audio_ioctl,
.write = dac_audio_write,
.unlocked_ioctl = dac_audio_unlocked_ioctl,
.open = dac_audio_open,
.release = dac_audio_release,
};

View File

@ -210,42 +210,44 @@ static int sound_open(struct inode *inode, struct file *file)
printk(KERN_ERR "Invalid minor device %d\n", dev);
return -ENXIO;
}
lock_kernel();
switch (dev & 0x0f) {
case SND_DEV_CTL:
dev >>= 4;
if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
request_module("mixer%d", dev);
}
retval = -ENXIO;
if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
return -ENXIO;
break;
if (!try_module_get(mixer_devs[dev]->owner))
return -ENXIO;
break;
retval = 0;
break;
case SND_DEV_SEQ:
case SND_DEV_SEQ2:
if ((retval = sequencer_open(dev, file)) < 0)
return retval;
retval = sequencer_open(dev, file);
break;
case SND_DEV_MIDIN:
if ((retval = MIDIbuf_open(dev, file)) < 0)
return retval;
retval = MIDIbuf_open(dev, file);
break;
case SND_DEV_DSP:
case SND_DEV_DSP16:
case SND_DEV_AUDIO:
if ((retval = audio_open(dev, file)) < 0)
return retval;
retval = audio_open(dev, file);
break;
default:
printk(KERN_ERR "Invalid minor device %d\n", dev);
return -ENXIO;
retval = -ENXIO;
}
unlock_kernel();
return 0;
}

View File

@ -68,6 +68,7 @@
#include <linux/delay.h>
#include <linux/sound.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/soundcard.h>
#include <linux/ac97_codec.h>
#include <linux/pci.h>
@ -1534,6 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
lock_kernel();
list_for_each(entry, &cs4297a_devs)
{
s = list_entry(entry, struct cs4297a_state, list);
@ -1544,6 +1546,8 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
{
CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
unlock_kernel();
return -ENODEV;
}
VALIDATE_STATE(s);
@ -1551,6 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
unlock_kernel();
return nonseekable_open(inode, file);
}
@ -1566,11 +1571,15 @@ static int cs4297a_release_mixdev(struct inode *inode, struct file *file)
}
static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,
static int cs4297a_ioctl_mixdev(struct file *file,
unsigned int cmd, unsigned long arg)
{
return mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
int ret;
lock_kernel();
ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
arg);
unlock_kernel();
return ret;
}
@ -1580,7 +1589,7 @@ static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,
static const struct file_operations cs4297a_mixer_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = cs4297a_ioctl_mixdev,
.unlocked_ioctl = cs4297a_ioctl_mixdev,
.open = cs4297a_open_mixdev,
.release = cs4297a_release_mixdev,
};
@ -1944,7 +1953,7 @@ static int cs4297a_mmap(struct file *file, struct vm_area_struct *vma)
}
static int cs4297a_ioctl(struct inode *inode, struct file *file,
static int cs4297a_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct cs4297a_state *s =
@ -2337,6 +2346,16 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file,
return mixer_ioctl(s, cmd, arg);
}
static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{
int ret;
lock_kernel();
ret = cs4297a_ioctl(file, cmd, arg);
unlock_kernel();
return ret;
}
static int cs4297a_release(struct inode *inode, struct file *file)
{
@ -2369,7 +2388,7 @@ static int cs4297a_release(struct inode *inode, struct file *file)
return 0;
}
static int cs4297a_open(struct inode *inode, struct file *file)
static int cs4297a_locked_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
struct cs4297a_state *s=NULL;
@ -2486,6 +2505,16 @@ static int cs4297a_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file);
}
static int cs4297a_open(struct inode *inode, struct file *file)
{
int ret;
lock_kernel();
ret = cs4297a_open(inode, file);
unlock_kernel();
return ret;
}
// ******************************************************************************************
// Wave (audio) file operations struct.
@ -2496,7 +2525,7 @@ static const struct file_operations cs4297a_audio_fops = {
.read = cs4297a_read,
.write = cs4297a_write,
.poll = cs4297a_poll,
.ioctl = cs4297a_ioctl,
.unlocked_ioctl = cs4297a_unlocked_ioctl,
.mmap = cs4297a_mmap,
.open = cs4297a_open,
.release = cs4297a_release,

View File

@ -491,9 +491,6 @@ static void __init attach_vidc(struct address_info *hw_config)
vidc_adev = adev;
vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
softoss_dev = adev;
#endif
return;
irq_failed:

View File

@ -2429,8 +2429,7 @@ static unsigned int vwsnd_audio_poll(struct file *file,
return mask;
}
static int vwsnd_audio_do_ioctl(struct inode *inode,
struct file *file,
static int vwsnd_audio_do_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
@ -2446,8 +2445,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
int ival;
DBGEV("(inode=0x%p, file=0x%p, cmd=0x%x, arg=0x%lx)\n",
inode, file, cmd, arg);
DBGEV("(file=0x%p, cmd=0x%x, arg=0x%lx)\n",
file, cmd, arg);
switch (cmd) {
case OSS_GETVERSION: /* _SIOR ('M', 118, int) */
DBGX("OSS_GETVERSION\n");
@ -2885,17 +2884,19 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
return -EINVAL;
}
static int vwsnd_audio_ioctl(struct inode *inode,
struct file *file,
static long vwsnd_audio_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
int ret;
lock_kernel();
mutex_lock(&devc->io_mutex);
ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg);
ret = vwsnd_audio_do_ioctl(file, cmd, arg);
mutex_unlock(&devc->io_mutex);
unlock_kernel();
return ret;
}
@ -2921,6 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
lock_kernel();
INC_USE_COUNT;
for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
@ -2928,6 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
if (devc == NULL) {
DEC_USE_COUNT;
unlock_kernel();
return -ENODEV;
}
@ -2936,11 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
mutex_unlock(&devc->open_mutex);
if (file->f_flags & O_NONBLOCK) {
DEC_USE_COUNT;
unlock_kernel();
return -EBUSY;
}
interruptible_sleep_on(&devc->open_wait);
if (signal_pending(current)) {
DEC_USE_COUNT;
unlock_kernel();
return -ERESTARTSYS;
}
mutex_lock(&devc->open_mutex);
@ -2993,6 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
file->private_data = devc;
DBGRV();
unlock_kernel();
return 0;
}
@ -3044,7 +3050,7 @@ static const struct file_operations vwsnd_audio_fops = {
.read = vwsnd_audio_read,
.write = vwsnd_audio_write,
.poll = vwsnd_audio_poll,
.ioctl = vwsnd_audio_ioctl,
.unlocked_ioctl = vwsnd_audio_ioctl,
.mmap = vwsnd_audio_mmap,
.open = vwsnd_audio_open,
.release = vwsnd_audio_release,
@ -3062,15 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
INC_USE_COUNT;
lock_kernel();
for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
if (devc->mixer_minor == iminor(inode))
break;
if (devc == NULL) {
DEC_USE_COUNT;
unlock_kernel();
return -ENODEV;
}
file->private_data = devc;
unlock_kernel();
return 0;
}
@ -3203,8 +3212,7 @@ static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *ar
/* This is the ioctl entry to the mixer driver. */
static int vwsnd_mixer_ioctl(struct inode *ioctl,
struct file *file,
static long vwsnd_mixer_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
@ -3215,6 +3223,7 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
lock_kernel();
mutex_lock(&devc->mix_mutex);
{
if ((cmd & ~nrmask) == MIXER_READ(0))
@ -3225,13 +3234,14 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
retval = -EINVAL;
}
mutex_unlock(&devc->mix_mutex);
unlock_kernel();
return retval;
}
static const struct file_operations vwsnd_mixer_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.ioctl = vwsnd_mixer_ioctl,
.unlocked_ioctl = vwsnd_mixer_ioctl,
.open = vwsnd_mixer_open,
.release = vwsnd_mixer_release,
};

View File

@ -184,14 +184,8 @@ waveartist_iack(wavnc_info *devc)
static inline int
waveartist_sleep(int timeout_ms)
{
unsigned int timeout = timeout_ms * 10 * HZ / 100;
do {
set_current_state(TASK_INTERRUPTIBLE);
timeout = schedule_timeout(timeout);
} while (timeout);
return 0;
unsigned int timeout = msecs_to_jiffies(timeout_ms*100);
return schedule_timeout_interruptible(timeout);
}
static int

View File

@ -763,9 +763,9 @@ static void snd_als4000_configure(struct snd_sb *chip)
/* SPECS_PAGE: 39 */
for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i)
snd_als4k_gcr_write(chip, i, 0);
/* enable burst mode to prevent dropouts during high PCI bus usage */
snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL,
snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL));
(snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL) & ~0x07) | 0x04);
spin_unlock_irq(&chip->reg_lock);
}

View File

@ -460,6 +460,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
int err;
u16 format;
int width;
unsigned int bytes_per_sec;
print_hwparams(params);
@ -512,9 +513,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
dpcm->hpi_buffer_attached);
}
bytes_per_sec = params_rate(params) * params_channels(params);
bytes_per_sec *= snd_pcm_format_width(params_format(params));
width = snd_pcm_format_width(params_format(params));
bytes_per_sec *= width;
bytes_per_sec /= 8;
if (bytes_per_sec <= 0)
if (width < 0 || bytes_per_sec == 0)
return -EINVAL;
dpcm->bytes_per_sec = bytes_per_sec;
@ -1383,7 +1385,7 @@ static char *asihpi_src_names[] =
compile_time_assert(
(ARRAY_SIZE(asihpi_src_names) ==
(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_BASE+1)),
(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),
assert_src_names_size);
#if ASI_STYLE_NAMES
@ -1414,7 +1416,7 @@ static char *asihpi_dst_names[] =
compile_time_assert(
(ARRAY_SIZE(asihpi_dst_names) ==
(HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_BASE+1)),
(HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)),
assert_dst_names_size);
static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
@ -2171,7 +2173,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
&src_node_type, &src_node_index);
sprintf(uinfo->value.enumerated.name, "%s %d",
asihpi_src_names[src_node_type - HPI_SOURCENODE_BASE],
asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE],
src_node_index);
return 0;
}
@ -2603,8 +2605,8 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
}
hpi_ctl.src_node_type -= HPI_SOURCENODE_BASE;
hpi_ctl.dst_node_type -= HPI_DESTNODE_BASE;
hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE;
hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE;
/* ASI50xx in SSX mode has multiple meters on the same node.
Use subindex to create distinct ALSA controls

View File

@ -50,7 +50,8 @@ i.e 3.05.02 is a development version
#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
/* Use single digits for versions less that 10 to avoid octal. */
#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 25)
#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 4, 1)
#define HPI_VER_STRING "4.04.01"
/* Library version as documented in hpi-api-versions.txt */
#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0)
@ -203,8 +204,6 @@ enum HPI_SOURCENODES {
exists on a destination node can be searched for using a source
node value of either 0, or HPI_SOURCENODE_NONE */
HPI_SOURCENODE_NONE = 100,
/** \deprecated Use HPI_SOURCENODE_NONE instead. */
HPI_SOURCENODE_BASE = 100,
/** Out Stream (Play) node. */
HPI_SOURCENODE_OSTREAM = 101,
/** Line in node - could be analog, AES/EBU or network. */
@ -235,8 +234,6 @@ enum HPI_DESTNODES {
exists on a source node can be searched for using a destination
node value of either 0, or HPI_DESTNODE_NONE */
HPI_DESTNODE_NONE = 200,
/** \deprecated Use HPI_DESTNODE_NONE instead. */
HPI_DESTNODE_BASE = 200,
/** In Stream (Record) node. */
HPI_DESTNODE_ISTREAM = 201,
HPI_DESTNODE_LINEOUT = 202, /**< line out node. */
@ -432,7 +429,18 @@ Property 2 - adapter can do stream grouping (supports SSX2)
Property 1 - adapter can do samplerate conversion (MRX)
Property 2 - adapter can do timestretch (TSX)
*/
HPI_ADAPTER_PROPERTY_CAPS2 = 269
HPI_ADAPTER_PROPERTY_CAPS2 = 269,
/** Readonly adapter sync header connection count.
*/
HPI_ADAPTER_PROPERTY_SYNC_HEADER_CONNECTIONS = 270,
/** Readonly supports SSX2 property.
Indicates the adapter supports SSX2 in some mode setting. The
return value is true (1) or false (0). If the current adapter
mode is MONO SSX2 is disabled, even though this property will
return true.
*/
HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271
};
/** Adapter mode commands
@ -813,8 +821,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
/** The sampleclock output is derived from its local samplerate generator.
The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */
HPI_SAMPLECLOCK_SOURCE_LOCAL = 1,
/** \deprecated Use HPI_SAMPLECLOCK_SOURCE_LOCAL instead */
HPI_SAMPLECLOCK_SOURCE_ADAPTER = 1,
/** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/
HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2,
/** From external wordclock connector */
@ -825,10 +831,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
HPI_SAMPLECLOCK_SOURCE_SMPTE = 5,
/** One of the aesebu inputs */
HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6,
/** \deprecated The first aesebu input with a valid signal
Superseded by separate Auto enable flag
*/
HPI_SAMPLECLOCK_SOURCE_AESEBU_AUTO = 7,
/** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */
HPI_SAMPLECLOCK_SOURCE_NETWORK = 8,
/** From previous adjacent module (ASI2416 only)*/
@ -1015,8 +1017,6 @@ enum HPI_ERROR_CODES {
HPI_ERROR_CONTROL_DISABLED = 404,
/** I2C transaction failed due to a missing ACK. */
HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
/** Control attribute is valid, but not supported by this hardware. */
HPI_ERROR_UNSUPPORTED_CONTROL_ATTRIBUTE = 406,
/** Control is busy, or coming out of
reset and cannot be accessed at this time. */
HPI_ERROR_CONTROL_NOT_READY = 407,
@ -1827,13 +1827,41 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
Compressor Expander control
*******************************/
u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 attack, u16 decay, short ratio100, short threshold0_01dB,
short makeup_gain0_01dB);
u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 on);
u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB);
u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pon);
u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
u32 h_control, short makeup_gain0_01dB);
u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
u32 h_control, short *pn_makeup_gain0_01dB);
u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
*ph_subsys, u32 h_control, u32 index, u32 attack);
u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
*ph_subsys, u32 h_control, u32 index, u32 *pw_attack);
u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 decay);
u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 *pw_decay);
u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, short threshold0_01dB);
u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, short *pn_threshold0_01dB);
u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 ratio100);
u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 *pw_ratio100);
/*******************************
Cobranet HMI control

View File

@ -687,6 +687,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
switch (pao->pci.subsys_device_id) {
case 0x5100:
case 0x5110: /* ASI5100 revB or higher with C6711D */
case 0x5200: /* ASI5200 PC_ie version of ASI5100 */
case 0x6100:
case 0x6200:
boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
@ -1133,6 +1134,12 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
subsys_device_id) ==
HPI_ADAPTER_FAMILY_ASI(0x5100))
mask = 0x00000000L;
/* ASI5200 uses AX6 code, */
/* but has no PLD r/w register to test */
if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
subsys_device_id) ==
HPI_ADAPTER_FAMILY_ASI(0x5200))
mask = 0x00000000L;
break;
case HPI_ADAPTER_FAMILY_ASI(0x8800):
/* ASI8800 has 16bit path to FPGA */

View File

@ -104,9 +104,9 @@ typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *);
#define STR_ROLE_FIELD_MAX 255U
struct hpi_entity_str {
uint16_t size;
uint8_t type;
uint8_t role;
u16 size;
u8 type;
u8 role;
};
#if defined(_MSC_VER)
@ -119,11 +119,11 @@ struct hpi_entity {
#if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
/* DSP C6000 compiler v6.0.8 and lower
do not support flexible array member */
uint8_t value[];
u8 value[];
#else
/* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
#define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
uint8_t value[1];
u8 value[1];
#endif
};
@ -142,12 +142,15 @@ enum HPI_BUSES {
/******************************************* CONTROL ATTRIBUTES ****/
/* (in order of control type ID */
/* This allows for 255 control types, 256 unique attributes each */
/* This allows for 255 control types, 256 unique attributes each */
#define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
/* Get the sub-index of the attribute for a control type */
#define HPI_CTL_ATTR_INDEX(i) (i&0xff)
/* Extract the control from the control attribute */
#define HPI_CTL_ATTR_CONTROL(i) (i>>8)
/* Generic control attributes. */
/** Enable a control.
@ -311,8 +314,7 @@ Used for HPI_ChannelModeSet/Get()
/* Microphone control attributes */
#define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
/** Equalizer control attributes
*/
/** Equalizer control attributes */
/** Used to get number of filters in an EQ. (Can't set) */
#define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
/** Set/get the filter by type, freq, Q, gain */
@ -320,13 +322,15 @@ Used for HPI_ChannelModeSet/Get()
/** Get the biquad coefficients */
#define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1)
/* Note compander also uses HPI_GENERIC_ENABLE */
#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1)
#define HPI_COMPANDER_MAKEUPGAIN HPI_CTL_ATTR(COMPANDER, 2)
#define HPI_COMPANDER_THRESHOLD HPI_CTL_ATTR(COMPANDER, 3)
#define HPI_COMPANDER_RATIO HPI_CTL_ATTR(COMPANDER, 4)
#define HPI_COMPANDER_ATTACK HPI_CTL_ATTR(COMPANDER, 5)
#define HPI_COMPANDER_DECAY HPI_CTL_ATTR(COMPANDER, 6)
/* Cobranet control attributes.
MUST be distinct from all other control attributes.
This is so that host side processing can easily identify a Cobranet control
and apply additional host side operations (like copying data) as required.
*/
/* Cobranet control attributes. */
#define HPI_COBRANET_SET HPI_CTL_ATTR(COBRANET, 1)
#define HPI_COBRANET_GET HPI_CTL_ATTR(COBRANET, 2)
#define HPI_COBRANET_SET_DATA HPI_CTL_ATTR(COBRANET, 3)
@ -1512,11 +1516,11 @@ struct hpi_control_cache_single {
struct hpi_control_cache_info i;
union {
struct { /* volume */
u16 an_log[2];
short an_log[2];
} v;
struct { /* peak meter */
u16 an_log_peak[2];
u16 an_logRMS[2];
short an_log_peak[2];
short an_logRMS[2];
} p;
struct { /* channel mode */
u16 mode;
@ -1526,7 +1530,7 @@ struct hpi_control_cache_single {
u16 source_node_index;
} x;
struct { /* level/trim */
u16 an_log[2];
short an_log[2];
} l;
struct { /* tuner - partial caching.
some attributes go to the DSP. */

View File

@ -353,7 +353,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
phr->u.c.param1 = pC->u.t.band;
else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
phr->u.c.param1 = pC->u.t.level;
if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
phr->u.c.param1 = 0;
phr->error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
} else
phr->u.c.param1 = pC->u.t.level;
else
found = 0;
break;
@ -397,7 +402,8 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
if (pC->u.clk.source_index ==
HPI_ERROR_ILLEGAL_CACHE_VALUE) {
phr->u.c.param1 = 0;
phr->error = HPI_ERROR_INVALID_OPERATION;
phr->error =
HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
} else
phr->u.c.param1 = pC->u.clk.source_index;
} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)

View File

@ -111,7 +111,7 @@ make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
&hpi_profile_strings,\
&hpi_control_strings, \
&hpi_asyncevent_strings \
};
}
make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);

View File

@ -356,7 +356,7 @@ compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
"HPI_SOURCENODE_ADAPTER" \
}
compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) ==
(12), sourcenode_strings_match_defs);
#define HPI_DESTNODE_STRINGS \
@ -370,7 +370,7 @@ compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
"HPI_DESTNODE_COBRANET", \
"HPI_DESTNODE_ANALOG" \
}
compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_BASE + 1) == (8),
compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8),
destnode_strings_match_defs);
#define HPI_CONTROL_CHANNEL_MODE_STRINGS \

View File

@ -96,8 +96,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR)
static struct hpi_hsubsys gh_subsys;
struct hpi_hsubsys *hpi_subsys_create(void
)
struct hpi_hsubsys *hpi_subsys_create(void)
{
struct hpi_message hm;
struct hpi_response hr;
@ -302,6 +301,7 @@ u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_SET_MODE);
hm.adapter_index = adapter_index;
@ -510,7 +510,7 @@ u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
hm.adapter_index = adapter_index;
hm.u.ax.debug_read.dsp_address = dsp_address;
if (*count_bytes > sizeof(hr.u.bytes))
if (*count_bytes > (int)sizeof(hr.u.bytes))
*count_bytes = sizeof(hr.u.bytes);
hm.u.ax.debug_read.count_bytes = *count_bytes;
@ -976,6 +976,7 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
HPI_OSTREAM_ANC_READ);
u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
@ -1581,6 +1582,7 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -1591,6 +1593,22 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
return hr.error;
}
static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0,
short sv1)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.attribute = attrib;
hm.u.c.an_log_value[0] = sv0;
hm.u.c.an_log_value[1] = sv1;
hpi_send_recv(&hm, &hr);
return hr.error;
}
static
u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
const u32 h_control, const u16 attrib, u32 param1, u32 param2,
@ -1598,6 +1616,7 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -1605,8 +1624,8 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
hm.u.c.param1 = param1;
hm.u.c.param2 = param2;
hpi_send_recv(&hm, &hr);
if (pparam1)
*pparam1 = hr.u.c.param1;
*pparam1 = hr.u.c.param1;
if (pparam2)
*pparam2 = hr.u.c.param2;
@ -1617,10 +1636,23 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
#define hpi_control_param2_get(s, h, a, p1, p2) \
hpi_control_param_get(s, h, a, 0, 0, p1, p2)
#define hpi_control_ex_param1_get(s, h, a, p1) \
hpi_control_ex_param_get(s, h, a, 0, 0, p1, NULL)
#define hpi_control_ex_param2_get(s, h, a, p1, p2) \
hpi_control_ex_param_get(s, h, a, 0, 0, p1, p2)
static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u16 attrib, short *sv0, short *sv1)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.attribute = attrib;
hpi_send_recv(&hm, &hr);
*sv0 = hr.u.c.an_log_value[0];
if (sv1)
*sv1 = hr.u.c.an_log_value[1];
return hr.error;
}
static
u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
@ -1629,6 +1661,7 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_INFO);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -1643,9 +1676,8 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
return hr.error;
}
static u16 hpi_control_get_string(const struct hpi_hsubsys *ph_subsys,
const u32 h_control, const u16 attribute, char *psz_string,
const u32 string_length)
static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
char *psz_string, const u32 string_length)
{
unsigned int sub_string_index = 0, j = 0;
char c = 0;
@ -1916,6 +1948,7 @@ u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -1941,6 +1974,7 @@ u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -1980,6 +2014,7 @@ u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2006,6 +2041,7 @@ u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
u32 byte_count;
u32 iP;
u16 error;
error = hpi_cobranet_hmi_read(ph_subsys, h_control,
HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
(u8 *)&iP);
@ -2082,6 +2118,7 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
u32 byte_count;
u16 error;
u32 mAC;
error = hpi_cobranet_hmi_read(ph_subsys, h_control,
HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
(u8 *)&mAC);
@ -2103,60 +2140,119 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
return error;
}
u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 attack, u16 decay, short ratio100, short threshold0_01dB,
short makeup_gain0_01dB)
u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 enable)
{
return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
enable, 0);
}
u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *enable)
{
return hpi_control_param1_get(ph_subsys, h_control,
HPI_GENERIC_ENABLE, enable);
}
u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
u32 h_control, short makeup_gain0_01dB)
{
return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN,
makeup_gain0_01dB, 0);
}
u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
u32 h_control, short *makeup_gain0_01dB)
{
return hpi_control_log_get2(ph_subsys, h_control,
HPI_COMPANDER_MAKEUPGAIN, makeup_gain0_01dB, NULL);
}
u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
*ph_subsys, u32 h_control, unsigned int index, u32 attack)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_COMPANDER_ATTACK, attack, index);
}
u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
*ph_subsys, u32 h_control, unsigned int index, u32 *attack)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_COMPANDER_ATTACK, 0, index, attack, NULL);
}
u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
u32 h_control, unsigned int index, u32 decay)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_COMPANDER_DECAY, decay, index);
}
u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
u32 h_control, unsigned int index, u32 *decay)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_COMPANDER_DECAY, 0, index, decay, NULL);
}
u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, unsigned int index, short threshold0_01dB)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.param1 = attack + ((u32)ratio100 << 16);
hm.u.c.param2 = (decay & 0xFFFFL);
hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
hm.u.c.param2 = index;
hm.u.c.an_log_value[0] = threshold0_01dB;
hm.u.c.an_log_value[1] = makeup_gain0_01dB;
hm.u.c.attribute = HPI_COMPANDER_PARAMS;
hpi_send_recv(&hm, &hr);
return hr.error;
}
u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB)
u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, unsigned int index, short *threshold0_01dB)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.attribute = HPI_COMPANDER_PARAMS;
hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
hm.u.c.param2 = index;
hpi_send_recv(&hm, &hr);
if (pw_attack)
*pw_attack = (short)(hr.u.c.param1 & 0xFFFF);
if (pw_decay)
*pw_decay = (short)(hr.u.c.param2 & 0xFFFF);
if (pw_ratio100)
*pw_ratio100 = (short)(hr.u.c.param1 >> 16);
if (pn_threshold0_01dB)
*pn_threshold0_01dB = hr.u.c.an_log_value[0];
if (pn_makeup_gain0_01dB)
*pn_makeup_gain0_01dB = hr.u.c.an_log_value[1];
*threshold0_01dB = hr.u.c.an_log_value[0];
return hr.error;
}
u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 ratio100)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_COMPANDER_RATIO, ratio100, index);
}
u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 index, u32 *ratio100)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_COMPANDER_RATIO, 0, index, ratio100, NULL);
}
u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2181,37 +2277,16 @@ u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
short an_gain0_01dB[HPI_MAX_CHANNELS]
)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
memcpy(hm.u.c.an_log_value, an_gain0_01dB,
sizeof(short) * HPI_MAX_CHANNELS);
hm.u.c.attribute = HPI_LEVEL_GAIN;
hpi_send_recv(&hm, &hr);
return hr.error;
return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN,
an_gain0_01dB[0], an_gain0_01dB[1]);
}
u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
short an_gain0_01dB[HPI_MAX_CHANNELS]
)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.attribute = HPI_LEVEL_GAIN;
hpi_send_recv(&hm, &hr);
memcpy(an_gain0_01dB, hr.u.c.an_log_value,
sizeof(short) * HPI_MAX_CHANNELS);
return hr.error;
return hpi_control_log_get2(ph_subsys, h_control, HPI_LEVEL_GAIN,
&an_gain0_01dB[0], &an_gain0_01dB[1]);
}
u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
@ -2413,6 +2488,7 @@ u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2439,6 +2515,7 @@ u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2460,6 +2537,7 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2623,8 +2701,8 @@ u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *state)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_TONEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_TONEDETECTOR_STATE, state);
}
u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@ -2637,8 +2715,8 @@ u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *enable)
{
return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
0, 0, (u32 *)enable, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_GENERIC_ENABLE, enable);
}
u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
@ -2651,8 +2729,8 @@ u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *event_enable)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_GENERIC_EVENT_ENABLE, event_enable);
}
u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
@ -2665,15 +2743,15 @@ u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, int *threshold)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_TONEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_TONEDETECTOR_THRESHOLD, (u32 *)threshold);
}
u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *state)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_STATE, state);
}
u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@ -2686,50 +2764,50 @@ u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *enable)
{
return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
0, 0, (u32 *)enable, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_GENERIC_ENABLE, enable);
}
u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 event_enable)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0);
HPI_GENERIC_EVENT_ENABLE, event_enable, 0);
}
u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *event_enable)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_GENERIC_EVENT_ENABLE, event_enable);
}
u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 delay)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_SILENCEDETECTOR_DELAY, (u32)delay, 0);
HPI_SILENCEDETECTOR_DELAY, delay, 0);
}
u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *delay)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_DELAY, 0, 0, (u32 *)delay, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_DELAY, delay);
}
u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, int threshold)
{
return hpi_control_param_set(ph_subsys, h_control,
HPI_SILENCEDETECTOR_THRESHOLD, (u32)threshold, 0);
HPI_SILENCEDETECTOR_THRESHOLD, threshold, 0);
}
u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
u32 h_control, int *threshold)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold);
}
u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
@ -2822,6 +2900,7 @@ u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2838,6 +2917,7 @@ u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2894,14 +2974,14 @@ u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
u32 h_control, char *psz_dsp_version, const u32 string_size)
{
return hpi_control_get_string(ph_subsys, h_control,
return hpi_control_get_string(h_control,
HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
}
u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
u32 h_control, char *psz_sdk_version, const u32 string_size)
{
return hpi_control_get_string(ph_subsys, h_control,
return hpi_control_get_string(h_control,
HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
}
@ -2942,15 +3022,15 @@ u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pquality)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pquality, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality);
}
u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *pblend)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_TUNER_HDRADIO_BLEND, 0, 0, pblend, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_TUNER_HDRADIO_BLEND, pblend);
}
u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
@ -2965,6 +3045,7 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -2981,43 +3062,43 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
u32 h_control, char *psz_string, const u32 data_length)
{
return hpi_control_get_string(ph_subsys, h_control,
HPI_PAD_CHANNEL_NAME, psz_string, data_length);
return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME,
psz_string, data_length);
}
u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
char *psz_string, const u32 data_length)
{
return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_ARTIST,
psz_string, data_length);
return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string,
data_length);
}
u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
char *psz_string, const u32 data_length)
{
return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_TITLE,
psz_string, data_length);
return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string,
data_length);
}
u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
char *psz_string, const u32 data_length)
{
return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_COMMENT,
psz_string, data_length);
return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string,
data_length);
}
u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
u32 h_control, u32 *ppTY)
{
return hpi_control_param_get(ph_subsys, h_control,
HPI_PAD_PROGRAM_TYPE, 0, 0, ppTY, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_PAD_PROGRAM_TYPE, ppTY);
}
u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
u32 *ppI)
{
return hpi_control_param_get(ph_subsys, h_control, HPI_PAD_PROGRAM_ID,
0, 0, ppI, NULL);
return hpi_control_param1_get(ph_subsys, h_control,
HPI_PAD_PROGRAM_ID, ppI);
}
u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
@ -3031,36 +3112,16 @@ u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
short an_log_gain[HPI_MAX_CHANNELS]
)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
memcpy(hm.u.c.an_log_value, an_log_gain,
sizeof(short) * HPI_MAX_CHANNELS);
hm.u.c.attribute = HPI_VOLUME_GAIN;
hpi_send_recv(&hm, &hr);
return hr.error;
return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN,
an_log_gain[0], an_log_gain[1]);
}
u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
short an_log_gain[HPI_MAX_CHANNELS]
)
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
hm.u.c.attribute = HPI_VOLUME_GAIN;
hpi_send_recv(&hm, &hr);
memcpy(an_log_gain, hr.u.c.an_log_value,
sizeof(short) * HPI_MAX_CHANNELS);
return hr.error;
return hpi_control_log_get2(ph_subsys, h_control, HPI_VOLUME_GAIN,
&an_log_gain[0], &an_log_gain[1]);
}
u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
@ -3068,6 +3129,7 @@ u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_GET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -3094,6 +3156,7 @@ u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
{
struct hpi_message hm;
struct hpi_response hr;
hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
HPI_CONTROL_SET_STATE);
u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@ -3170,43 +3233,42 @@ static size_t entity_type_to_size[LAST_ENTITY_TYPE] = {
6 * sizeof(char),
};
inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
{
return entity_ptr->header.size;
}
inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
static inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
{
return sizeof(entity_ptr->header);
}
inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
{
return hpi_entity_size(entity_ptr) -
hpi_entity_header_size(entity_ptr);
}
inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
static inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
{
return hpi_entity_value_size(entity_ptr) /
entity_type_to_size[entity_ptr->header.type];
}
inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
*entity_ptr)
{
return (void *)(((uint8_t *) entity_ptr) +
hpi_entity_size(entity_ptr));
return (void *)(((u8 *)entity_ptr) + hpi_entity_size(entity_ptr));
}
inline u16 hpi_entity_check_type(const enum e_entity_type t)
static inline u16 hpi_entity_check_type(const enum e_entity_type t)
{
if (t >= 0 && t < STR_TYPE_FIELD_MAX)
return 0;
return HPI_ERROR_ENTITY_TYPE_INVALID;
}
inline u16 hpi_entity_check_role(const enum e_entity_role r)
static inline u16 hpi_entity_check_role(const enum e_entity_role r)
{
if (r >= 0 && r < STR_ROLE_FIELD_MAX)
return 0;
@ -3624,6 +3686,7 @@ u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
u16 maximum_events, struct hpi_async_event *p_events,
u16 *pw_number_returned)
{
return 0;
}

View File

@ -741,7 +741,7 @@ static void HPIMSGX__reset(u16 adapter_index)
hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
HPI_SUBSYS_FIND_ADAPTERS, 0);
memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS));
sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {

View File

@ -121,11 +121,17 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
/* Read the message and response pointers from user space. */
get_user(puhm, &phpi_ioctl_data->phm);
get_user(puhr, &phpi_ioctl_data->phr);
if (get_user(puhm, &phpi_ioctl_data->phm) ||
get_user(puhr, &phpi_ioctl_data->phr)) {
err = -EFAULT;
goto out;
}
/* Now read the message size and data from user space. */
get_user(hm->h.size, (u16 __user *)puhm);
if (get_user(hm->h.size, (u16 __user *)puhm)) {
err = -EFAULT;
goto out;
}
if (hm->h.size > sizeof(*hm))
hm->h.size = sizeof(*hm);
@ -138,7 +144,10 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out;
}
get_user(res_max_size, (u16 __user *)puhr);
if (get_user(res_max_size, (u16 __user *)puhr)) {
err = -EFAULT;
goto out;
}
/* printk(KERN_INFO "user response size %d\n", res_max_size); */
if (res_max_size < sizeof(struct hpi_response_header)) {
HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
@ -464,9 +473,7 @@ void __init asihpi_init(void)
memset(adapters, 0, sizeof(adapters));
printk(KERN_INFO "ASIHPI driver %d.%02d.%02d\n",
HPI_VER_MAJOR(HPI_VER), HPI_VER_MINOR(HPI_VER),
HPI_VER_RELEASE(HPI_VER));
printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n");
hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
HPI_SUBSYS_DRIVER_LOAD);

View File

@ -2250,6 +2250,8 @@ static int snd_echo_resume(struct pci_dev *pci)
DE_INIT(("resume start\n"));
pci_restore_state(pci);
commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
if (commpage_bak == NULL)
return -ENOMEM;
commpage = chip->comm_page;
memcpy(commpage_bak, commpage, sizeof(struct comm_page));

View File

@ -396,15 +396,18 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
for (n = prev_nid + 1; n <= val; n++) {
if (conns >= max_conns) {
snd_printk(KERN_ERR
"Too many connections\n");
snd_printk(KERN_ERR "hda_codec: "
"Too many connections %d for NID 0x%x\n",
conns, nid);
return -EINVAL;
}
conn_list[conns++] = n;
}
} else {
if (conns >= max_conns) {
snd_printk(KERN_ERR "Too many connections\n");
snd_printk(KERN_ERR "hda_codec: "
"Too many connections %d for NID 0x%x\n",
conns, nid);
return -EINVAL;
}
conn_list[conns++] = val;
@ -730,15 +733,17 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
for (i = 0; i < total_nodes; i++, nid++) {
function_id = snd_hda_param_read(codec, nid,
AC_PAR_FUNCTION_TYPE) & 0xff;
switch (function_id) {
AC_PAR_FUNCTION_TYPE);
switch (function_id & 0xff) {
case AC_GRP_AUDIO_FUNCTION:
codec->afg = nid;
codec->function_id = function_id;
codec->afg_function_id = function_id & 0xff;
codec->afg_unsol = (function_id >> 8) & 1;
break;
case AC_GRP_MODEM_FUNCTION:
codec->mfg = nid;
codec->function_id = function_id;
codec->mfg_function_id = function_id & 0xff;
codec->mfg_unsol = (function_id >> 8) & 1;
break;
default:
break;
@ -1565,6 +1570,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
#endif /* SND_HDA_NEEDS_RESUME */
static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int ofs)
{
u32 caps = query_amp_caps(codec, nid, dir);
/* get num steps */
caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
if (ofs < caps)
caps -= ofs;
return caps;
}
/**
* snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
*
@ -1579,23 +1595,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
u8 chs = get_amp_channels(kcontrol);
int dir = get_amp_direction(kcontrol);
unsigned int ofs = get_amp_offset(kcontrol);
u32 caps;
caps = query_amp_caps(codec, nid, dir);
/* num steps */
caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
if (!caps) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = chs == 3 ? 2 : 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
if (!uinfo->value.integer.max) {
printk(KERN_WARNING "hda_codec: "
"num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
kcontrol->id.name);
return -EINVAL;
}
if (ofs < caps)
caps -= ofs;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = chs == 3 ? 2 : 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = caps;
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
@ -1620,8 +1630,14 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
int ch, int dir, int idx, unsigned int ofs,
unsigned int val)
{
unsigned int maxval;
if (val > 0)
val += ofs;
/* ofs = 0: raw max value */
maxval = get_amp_max_value(codec, nid, dir, 0);
if (val > maxval)
val = maxval;
return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
HDA_AMP_VOLMASK, val);
}
@ -2999,26 +3015,31 @@ struct hda_rate_tbl {
unsigned int hda_fmt;
};
/* rate = base * mult / div */
#define HDA_RATE(base, mult, div) \
(AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
(((div) - 1) << AC_FMT_DIV_SHIFT))
static struct hda_rate_tbl rate_bits[] = {
/* rate in Hz, ALSA rate bitmask, HDA format value */
/* autodetected value used in snd_hda_query_supported_pcm */
{ 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
{ 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
{ 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
{ 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
{ 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
{ 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
{ 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
{ 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
{ 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
{ 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
{ 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
{ 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
{ 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
{ 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
{ 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
{ 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
{ 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
{ 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
{ 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
{ 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
#define AC_PAR_PCM_RATE_BITS 11
/* up to bits 10, 384kHZ isn't supported properly */
/* not autodetected value */
{ 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
{ 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
{ 0 } /* terminator */
};
@ -3037,7 +3058,8 @@ static struct hda_rate_tbl rate_bits[] = {
unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps)
unsigned int maxbps,
unsigned short spdif_ctls)
{
int i;
unsigned int val = 0;
@ -3060,20 +3082,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
switch (snd_pcm_format_width(format)) {
case 8:
val |= 0x00;
val |= AC_FMT_BITS_8;
break;
case 16:
val |= 0x10;
val |= AC_FMT_BITS_16;
break;
case 20:
case 24:
case 32:
if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
val |= 0x40;
val |= AC_FMT_BITS_32;
else if (maxbps >= 24)
val |= 0x30;
val |= AC_FMT_BITS_24;
else
val |= 0x20;
val |= AC_FMT_BITS_20;
break;
default:
snd_printdd("invalid format width %d\n",
@ -3081,6 +3103,9 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return 0;
}
if (spdif_ctls & AC_DIG1_NONAUDIO)
val |= AC_FMT_TYPE_NON_PCM;
return val;
}
EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);

View File

@ -224,6 +224,27 @@ enum {
/* Input converter SDI select */
#define AC_SDI_SELECT (0xf<<0)
/* stream format id */
#define AC_FMT_CHAN_SHIFT 0
#define AC_FMT_CHAN_MASK (0x0f << 0)
#define AC_FMT_BITS_SHIFT 4
#define AC_FMT_BITS_MASK (7 << 4)
#define AC_FMT_BITS_8 (0 << 4)
#define AC_FMT_BITS_16 (1 << 4)
#define AC_FMT_BITS_20 (2 << 4)
#define AC_FMT_BITS_24 (3 << 4)
#define AC_FMT_BITS_32 (4 << 4)
#define AC_FMT_DIV_SHIFT 8
#define AC_FMT_DIV_MASK (7 << 8)
#define AC_FMT_MULT_SHIFT 11
#define AC_FMT_MULT_MASK (7 << 11)
#define AC_FMT_BASE_SHIFT 14
#define AC_FMT_BASE_48K (0 << 14)
#define AC_FMT_BASE_44K (1 << 14)
#define AC_FMT_TYPE_SHIFT 15
#define AC_FMT_TYPE_PCM (0 << 15)
#define AC_FMT_TYPE_NON_PCM (1 << 15)
/* Unsolicited response control */
#define AC_UNSOL_TAG (0x3f<<0)
#define AC_UNSOL_ENABLED (1<<7)
@ -364,6 +385,9 @@ enum {
#define AC_DIG2_CC (0x7f<<0)
/* Pin widget control - 8bit */
#define AC_PINCTL_EPT (0x3<<0)
#define AC_PINCTL_EPT_NATIVE 0
#define AC_PINCTL_EPT_HBR 3
#define AC_PINCTL_VREFEN (0x7<<0)
#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
#define AC_PINCTL_VREF_50 1 /* 50% */
@ -760,7 +784,10 @@ struct hda_codec {
hda_nid_t mfg; /* MFG node id */
/* ids */
u32 function_id;
u8 afg_function_id;
u8 mfg_function_id;
u8 afg_unsol;
u8 mfg_unsol;
u32 vendor_id;
u32 subsystem_id;
u32 revision_id;
@ -928,7 +955,8 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid);
unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps);
unsigned int maxbps,
unsigned short spdif_ctls);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);

View File

@ -649,7 +649,9 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus,
*codecp = NULL;
if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
list_for_each_entry(codec, &bus->codec_list, list) {
if (codec->addr == caddr) {
if (codec->vendor_id == vendorid &&
codec->subsystem_id == subid &&
codec->addr == caddr) {
*codecp = codec;
break;
}

View File

@ -1653,7 +1653,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
format_val = snd_hda_calc_stream_format(runtime->rate,
runtime->channels,
runtime->format,
hinfo->maxbps);
hinfo->maxbps,
apcm->codec->spdif_ctls);
if (!format_val) {
snd_printk(KERN_ERR SFX
"invalid format_val, rate=%d, ch=%d, format=%d\n",
@ -1960,7 +1961,7 @@ static void azx_irq_pending_work(struct work_struct *work)
spin_unlock_irq(&chip->reg_lock);
if (!pending)
return;
cond_resched();
msleep(1);
}
}

View File

@ -557,7 +557,12 @@ static void print_codec_info(struct snd_info_entry *entry,
else
snd_iprintf(buffer, "Not Set\n");
snd_iprintf(buffer, "Address: %d\n", codec->addr);
snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
if (codec->afg)
snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
codec->afg_function_id, codec->afg_unsol);
if (codec->mfg)
snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
codec->mfg_function_id, codec->mfg_unsol);
snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);

View File

@ -3662,7 +3662,12 @@ static int patch_ad1984(struct hda_codec *codec)
codec->patch_ops.build_pcms = ad1984_build_pcms;
break;
case AD1984_THINKPAD:
spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
if (codec->subsystem_id == 0x17aa20fb) {
/* Thinpad X300 does not have the ability to do SPDIF,
or attach to docking station to use SPDIF */
spec->multiout.dig_out_nid = 0;
} else
spec->multiout.dig_out_nid = AD1884_SPDIF_OUT;
spec->input_mux = &ad1984_thinkpad_capture_source;
spec->mixers[0] = ad1984_thinkpad_mixers;
spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs;

View File

@ -131,6 +131,8 @@ struct conexant_spec {
unsigned int dc_enable;
unsigned int dc_input_bias; /* offset into cxt5066_olpc_dc_bias */
unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
unsigned int beep_amp;
};
static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
@ -515,6 +517,15 @@ static struct snd_kcontrol_new cxt_capture_mixers[] = {
{}
};
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
static struct snd_kcontrol_new cxt_beep_mixer[] = {
HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
{ } /* end */
};
#endif
static const char *slave_vols[] = {
"Headphone Playback Volume",
"Speaker Playback Volume",
@ -580,16 +591,52 @@ static int conexant_build_controls(struct hda_codec *codec)
return err;
}
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* create beep controls if needed */
if (spec->beep_amp) {
struct snd_kcontrol_new *knew;
for (knew = cxt_beep_mixer; knew->name; knew++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(knew, codec);
if (!kctl)
return -ENOMEM;
kctl->private_value = spec->beep_amp;
err = snd_hda_ctl_add(codec, 0, kctl);
if (err < 0)
return err;
}
}
#endif
return 0;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
static int conexant_suspend(struct hda_codec *codec, pm_message_t state)
{
snd_hda_shutup_pins(codec);
return 0;
}
#endif
static struct hda_codec_ops conexant_patch_ops = {
.build_controls = conexant_build_controls,
.build_pcms = conexant_build_pcms,
.init = conexant_init,
.free = conexant_free,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.suspend = conexant_suspend,
#endif
.reboot_notify = snd_hda_shutup_pins,
};
#ifdef CONFIG_SND_HDA_INPUT_BEEP
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
#else
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
#endif
/*
* EAPD control
* the private value = nid | (invert << 8)
@ -1130,9 +1177,10 @@ static int patch_cxt5045(struct hda_codec *codec)
spec->num_init_verbs = 1;
spec->init_verbs[0] = cxt5045_init_verbs;
spec->spdif_route = 0;
spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes),
spec->channel_mode = cxt5045_modes,
spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
spec->channel_mode = cxt5045_modes;
set_beep_amp(spec, 0x16, 0, 1);
codec->patch_ops = conexant_patch_ops;
@ -1211,6 +1259,9 @@ static int patch_cxt5045(struct hda_codec *codec)
break;
}
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
return 0;
}
@ -1632,6 +1683,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl);
/* on ideapad there is an aditional speaker (subwoofer) to mute */
if (spec->ideapad)
snd_hda_codec_write(codec, 0x1b, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl);
}
/* turn on/off EAPD (+ mute HP) as a master switch */
@ -1888,6 +1944,13 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
#endif
}
static struct hda_verb cxt5051_ideapad_init_verbs[] = {
/* Subwoofer */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
{ } /* end */
};
/* initialize jack-sensing, too */
static int cxt5051_init(struct hda_codec *codec)
{
@ -1917,6 +1980,7 @@ enum {
CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
CXT5051_F700, /* HP Compaq Presario F700 */
CXT5051_TOSHIBA, /* Toshiba M300 & co */
CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
CXT5051_MODELS
};
@ -1927,6 +1991,7 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
[CXT5051_LENOVO_X200] = "lenovo-x200",
[CXT5051_F700] = "hp-700",
[CXT5051_TOSHIBA] = "toshiba",
[CXT5051_IDEAPAD] = "ideapad",
};
static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
@ -1938,6 +2003,7 @@ static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
CXT5051_LAPTOP),
SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
{}
};
@ -1972,6 +2038,8 @@ static int patch_cxt5051(struct hda_codec *codec)
spec->cur_adc = 0;
spec->cur_adc_idx = 0;
set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
@ -1989,6 +2057,10 @@ static int patch_cxt5051(struct hda_codec *codec)
break;
case CXT5051_LENOVO_X200:
spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
/* Thinkpad X301 does not have S/PDIF wired and no ability
to use a docking station. */
if (codec->subsystem_id == 0x17aa211f)
spec->multiout.dig_out_nid = 0;
break;
case CXT5051_F700:
spec->init_verbs[0] = cxt5051_f700_init_verbs;
@ -1999,8 +2071,16 @@ static int patch_cxt5051(struct hda_codec *codec)
spec->mixers[0] = cxt5051_toshiba_mixers;
spec->auto_mic = AUTO_MIC_PORTB;
break;
case CXT5051_IDEAPAD:
spec->init_verbs[spec->num_init_verbs++] =
cxt5051_ideapad_init_verbs;
spec->ideapad = 1;
break;
}
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
return 0;
}
@ -2616,7 +2696,6 @@ static struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
.put = cxt5066_mic_boost_mux_enum_put,
.private_value = 0x23 | 0x100,
},
HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT),
{}
};
@ -2977,8 +3056,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G series (AMD)", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
{}
};
@ -3014,6 +3095,8 @@ static int patch_cxt5066(struct hda_codec *codec)
spec->cur_adc = 0;
spec->cur_adc_idx = 0;
set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
cxt5066_models, cxt5066_cfg_tbl);
switch (board_config) {
@ -3062,7 +3145,6 @@ static int patch_cxt5066(struct hda_codec *codec)
spec->port_d_mode = 0;
spec->dell_vostro = 1;
spec->mic_boost = 3; /* default 30dB gain */
snd_hda_attach_beep_device(codec, 0x13);
/* no S/PDIF out */
spec->multiout.dig_out_nid = 0;
@ -3104,6 +3186,9 @@ static int patch_cxt5066(struct hda_codec *codec)
break;
}
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
return 0;
}

View File

@ -698,11 +698,51 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
* Callbacks
*/
static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
/* HBR should be Non-PCM, 8 channels */
#define is_hbr_format(format) \
((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag, int format)
{
struct hdmi_spec *spec = codec->spec;
int tag;
int fmt;
int pinctl;
int new_pinctl = 0;
int i;
for (i = 0; i < spec->num_pins; i++) {
if (spec->pin_cvt[i] != nid)
continue;
if (!(snd_hda_query_pin_caps(codec, spec->pin[i]) & AC_PINCAP_HBR))
continue;
pinctl = snd_hda_codec_read(codec, spec->pin[i], 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
new_pinctl = pinctl & ~AC_PINCTL_EPT;
if (is_hbr_format(format))
new_pinctl |= AC_PINCTL_EPT_HBR;
else
new_pinctl |= AC_PINCTL_EPT_NATIVE;
snd_printdd("hdmi_setup_stream: "
"NID=0x%x, %spinctl=0x%x\n",
spec->pin[i],
pinctl == new_pinctl ? "" : "new-",
new_pinctl);
if (pinctl != new_pinctl)
snd_hda_codec_write(codec, spec->pin[i], 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
new_pinctl);
}
if (is_hbr_format(format) && !new_pinctl) {
snd_printdd("hdmi_setup_stream: HBR is not supported\n");
return -EINVAL;
}
tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
@ -722,6 +762,7 @@ static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
if (fmt != format)
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_STREAM_FORMAT, format);
return 0;
}
/*

View File

@ -66,8 +66,7 @@ static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
return 0;
return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
}
static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,

View File

@ -202,8 +202,7 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
return 0;
return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
}
static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,

File diff suppressed because it is too large Load Diff

View File

@ -202,6 +202,7 @@ struct sigmatel_spec {
unsigned int spdif_mute: 1;
unsigned int check_volume_offset:1;
unsigned int auto_mic:1;
unsigned int linear_tone_beep:1;
/* gpio lines */
unsigned int eapd_mask;
@ -3802,7 +3803,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
return err;
if (codec->beep) {
/* IDT/STAC codecs have linear beep tone parameter */
codec->beep->linear_tone = 1;
codec->beep->linear_tone = spec->linear_tone_beep;
/* if no beep switch is available, make its own one */
caps = query_amp_caps(codec, nid, HDA_OUTPUT);
if (!(caps & AC_AMPCAP_MUTE)) {
@ -5005,6 +5006,7 @@ static int patch_stac9200(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
@ -5068,6 +5070,7 @@ static int patch_stac925x(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids;
@ -5153,6 +5156,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 0;
codec->slave_dig_outs = stac92hd73xx_slave_dig_outs;
spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids);
spec->pin_nids = stac92hd73xx_pin_nids;
@ -5300,6 +5304,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
spec->digbeep_nid = 0x21;
spec->mux_nids = stac92hd83xxx_mux_nids;
@ -5522,6 +5527,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 0;
codec->patch_ops = stac92xx_patch_ops;
spec->num_pins = STAC92HD71BXX_NUM_PINS;
switch (codec->vendor_id) {
@ -5779,6 +5785,7 @@ static int patch_stac922x(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac922x_pin_nids);
spec->pin_nids = stac922x_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
@ -5883,6 +5890,7 @@ static int patch_stac927x(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
codec->slave_dig_outs = stac927x_slave_dig_outs;
spec->num_pins = ARRAY_SIZE(stac927x_pin_nids);
spec->pin_nids = stac927x_pin_nids;
@ -6018,6 +6026,7 @@ static int patch_stac9205(struct hda_codec *codec)
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac9205_pin_nids);
spec->pin_nids = stac9205_pin_nids;
spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
@ -6174,6 +6183,7 @@ static int patch_stac9872(struct hda_codec *codec)
return -ENOMEM;
codec->no_trigger_sense = 1;
codec->spec = spec;
spec->linear_tone_beep = 1;
spec->num_pins = ARRAY_SIZE(stac9872_pin_nids);
spec->pin_nids = stac9872_pin_nids;

View File

@ -552,24 +552,30 @@ static void via_auto_init_hp_out(struct hda_codec *codec)
}
}
static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
static void via_auto_init_analog_input(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
unsigned int ctl;
int i;
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i];
if (!nid)
continue;
if (spec->smart51_enabled && is_smart51_pins(spec, nid))
ctl = PIN_OUT;
else if (i <= AUTO_PIN_FRONT_MIC)
ctl = PIN_VREF50;
else
ctl = PIN_IN;
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
(i <= AUTO_PIN_FRONT_MIC ?
PIN_VREF50 : PIN_IN));
AC_VERB_SET_PIN_WIDGET_CONTROL, ctl);
}
}
static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int *affected_parm)
{
@ -658,6 +664,8 @@ static void set_jack_power_state(struct hda_codec *codec)
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x19, &parm);
if (spec->smart51_enabled)
parm = AC_PWRST_D0;
snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
parm);
snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
@ -667,6 +675,8 @@ static void set_jack_power_state(struct hda_codec *codec)
if (is_8ch) {
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x22, &parm);
if (spec->smart51_enabled)
parm = AC_PWRST_D0;
snd_hda_codec_write(codec, 0x26, 0,
AC_VERB_SET_POWER_STATE, parm);
snd_hda_codec_write(codec, 0x24, 0,
@ -3915,6 +3925,13 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
}
}
/* for Smart 5.1, line/mic inputs double as output pins */
if (cfg->line_outs == 1) {
spec->multiout.num_dacs = 3;
spec->multiout.dac_nids[AUTO_SEQ_SURROUND] = 0x11;
spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24;
}
return 0;
}
@ -3932,7 +3949,8 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
nid = cfg->line_out_pins[i];
if (!nid)
/* for Smart 5.1, there are always at least six channels */
if (!nid && i > AUTO_SEQ_CENLFE)
continue;
nid_vol = nid_vols[i];

View File

@ -97,6 +97,7 @@
#include <linux/gameport.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <sound/core.h>
#include <sound/info.h>
@ -667,13 +668,12 @@ static u32 atoh(const unsigned char *in, unsigned int len)
unsigned char c;
while (len) {
int value;
c = in[len - 1];
if ((c >= '0') && (c <= '9'))
sum += mult * (c - '0');
else if ((c >= 'A') && (c <= 'F'))
sum += mult * (c - ('A' - 10));
else if ((c >= 'a') && (c <= 'f'))
sum += mult * (c - ('a' - 10));
value = hex_to_bin(c);
if (value >= 0)
sum += mult * value;
mult *= 16;
--len;
}
@ -1615,7 +1615,10 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
chip->playback_substream[sub_num] = substream;
runtime->hw = snd_riptide_playback;
data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
data->paths = lbus_play_paths[sub_num];
data->id = play_ids[sub_num];
data->source = play_sources[sub_num];
@ -1635,7 +1638,10 @@ static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
chip->capture_substream = substream;
runtime->hw = snd_riptide_capture;
data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
data->paths = lbus_rec_path;
data->id = PADC;
data->source = ACLNK2PADC;

View File

@ -264,11 +264,13 @@ static void sis_update_voice(struct voice *voice)
* if using small periods.
*
* If we're less than 9 samples behind, we're on target.
* Otherwise, shorten the next vperiod by the amount we've
* been delayed.
*/
if (sync > -9)
voice->vperiod = voice->sync_period_size + 1;
else
voice->vperiod = voice->sync_period_size - 4;
voice->vperiod = voice->sync_period_size + sync + 10;
if (voice->vperiod < voice->buffer_size) {
sis_update_sso(voice, voice->vperiod);
@ -736,7 +738,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
period_size = buffer_size;
/* Initially, we want to interrupt just a bit behind the end of
* the period we're clocking out. 10 samples seems to give a good
* the period we're clocking out. 12 samples seems to give a good
* delay.
*
* We want to spread our interrupts throughout the virtual period,
@ -747,7 +749,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
*
* This is all moot if we don't need to use virtual periods.
*/
vperiod = runtime->period_size + 10;
vperiod = runtime->period_size + 12;
if (vperiod > period_size) {
u16 tail = vperiod % period_size;
u16 quarter_period = period_size / 4;
@ -776,7 +778,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
*/
timing->flags |= VOICE_SYNC_TIMING;
timing->sync_base = voice->ctrl_base;
timing->sync_cso = runtime->period_size - 1;
timing->sync_cso = runtime->period_size;
timing->sync_period_size = runtime->period_size;
timing->sync_buffer_size = runtime->buffer_size;
timing->period_size = period_size;
@ -1047,7 +1049,7 @@ static int sis_chip_free(struct sis7019 *sis)
/* Reset the chip, and disable all interrputs.
*/
outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
udelay(10);
udelay(25);
outl(0, sis->ioport + SIS_GCR);
outl(0, sis->ioport + SIS_GIER);
@ -1083,7 +1085,7 @@ static int sis_chip_init(struct sis7019 *sis)
/* Reset the audio controller
*/
outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
udelay(10);
udelay(25);
outl(0, io + SIS_GCR);
/* Get the AC-link semaphore, and reset the codecs
@ -1096,7 +1098,7 @@ static int sis_chip_init(struct sis7019 *sis)
return -EIO;
outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
udelay(10);
udelay(250);
count = 0xffff;
while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)

View File

@ -85,6 +85,7 @@ static int joystick;
static int ac97_clock = 48000;
static char *ac97_quirk;
static int dxs_support;
static int dxs_init_volume = 31;
static int nodelay;
module_param(index, int, 0444);
@ -103,6 +104,8 @@ module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param(dxs_support, int, 0444);
MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
module_param(dxs_init_volume, int, 0644);
MODULE_PARM_DESC(dxs_init_volume, "initial DXS volume (0-31)");
module_param(nodelay, int, 0444);
MODULE_PARM_DESC(nodelay, "Disable 500ms init delay");
@ -1245,8 +1248,10 @@ static int snd_via8233_playback_open(struct snd_pcm_substream *substream)
return err;
stream = viadev->reg_offset / 0x10;
if (chip->dxs_controls[stream]) {
chip->playback_volume[stream][0] = 0;
chip->playback_volume[stream][1] = 0;
chip->playback_volume[stream][0] =
VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
chip->playback_volume[stream][1] =
VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
chip->dxs_controls[stream]->vd[0].access &=
~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |

View File

@ -28,9 +28,13 @@ source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
source "sound/soc/blackfin/Kconfig"
source "sound/soc/davinci/Kconfig"
source "sound/soc/ep93xx/Kconfig"
source "sound/soc/fsl/Kconfig"
source "sound/soc/imx/Kconfig"
source "sound/soc/jz4740/Kconfig"
source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/kirkwood/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig"
source "sound/soc/s6000/Kconfig"

View File

@ -6,9 +6,13 @@ obj-$(CONFIG_SND_SOC) += atmel/
obj-$(CONFIG_SND_SOC) += au1x/
obj-$(CONFIG_SND_SOC) += blackfin/
obj-$(CONFIG_SND_SOC) += davinci/
obj-$(CONFIG_SND_SOC) += ep93xx/
obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += imx/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += omap/
obj-$(CONFIG_SND_SOC) += kirkwood/
obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += s3c24xx/
obj-$(CONFIG_SND_SOC) += s6000/

View File

@ -77,7 +77,6 @@ struct atmel_runtime_data {
size_t period_size;
dma_addr_t period_ptr; /* physical address of next period */
int periods; /* period index of period_ptr */
/* PDC register save */
u32 pdc_xpr_save;

View File

@ -549,7 +549,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
ssc_p->daifmt);
return -EINVAL;
break;
}
pr_debug("atmel_ssc_hw_params: "
"RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",

View File

@ -375,12 +375,10 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
}
ret = -EBUSY;
wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
"au1xpsc_ac97");
if (!wd->ioarea)
if (!request_mem_region(r->start, resource_size(r), pdev->name))
goto out0;
wd->mmio = ioremap(r->start, 0xffff);
wd->mmio = ioremap(r->start, resource_size(r));
if (!wd->mmio)
goto out1;
@ -410,8 +408,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
snd_soc_unregister_dai(&au1xpsc_ac97_dai);
out1:
release_resource(wd->ioarea);
kfree(wd->ioarea);
release_mem_region(r->start, resource_size(r));
out0:
kfree(wd);
return ret;
@ -420,6 +417,7 @@ out0:
static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (wd->dmapd)
au1xpsc_pcm_destroy(wd->dmapd);
@ -433,8 +431,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
au_sync();
iounmap(wd->mmio);
release_resource(wd->ioarea);
kfree(wd->ioarea);
release_mem_region(r->start, resource_size(r));
kfree(wd);
au1xpsc_ac97_workdata = NULL; /* MDEV */

View File

@ -321,12 +321,10 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
}
ret = -EBUSY;
wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
"au1xpsc_i2s");
if (!wd->ioarea)
if (!request_mem_region(r->start, resource_size(r), pdev->name))
goto out0;
wd->mmio = ioremap(r->start, 0xffff);
wd->mmio = ioremap(r->start, resource_size(r));
if (!wd->mmio)
goto out1;
@ -362,8 +360,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
snd_soc_unregister_dai(&au1xpsc_i2s_dai);
out1:
release_resource(wd->ioarea);
kfree(wd->ioarea);
release_mem_region(r->start, resource_size(r));
out0:
kfree(wd);
return ret;
@ -372,6 +369,7 @@ out0:
static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (wd->dmapd)
au1xpsc_pcm_destroy(wd->dmapd);
@ -384,8 +382,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
au_sync();
iounmap(wd->mmio);
release_resource(wd->ioarea);
kfree(wd->ioarea);
release_mem_region(r->start, resource_size(r));
kfree(wd);
au1xpsc_i2s_workdata = NULL; /* MDEV */

View File

@ -32,7 +32,6 @@ struct au1xpsc_audio_data {
unsigned long rate;
unsigned long pm[2];
struct resource *ioarea;
struct mutex lock;
struct platform_device *dmapd;
};

View File

@ -255,8 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
#ifdef CONFIG_PM
static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
struct sport_device *sport = dai->private_data;
pr_debug("%s : sport %d\n", __func__, dai->id);
if (!dai->active)
@ -271,8 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport =
(struct sport_device *)dai->private_data;
struct sport_device *sport = dai->private_data;
pr_debug("%s : sport %d\n", __func__, dai->id);
if (!dai->active)

View File

@ -210,8 +210,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
#ifdef CONFIG_PM
static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
struct sport_device *sport = dai->private_data;
if (!dai->active)
return 0;
@ -225,8 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport =
(struct sport_device *)dai->private_data;
struct sport_device *sport = dai->private_data;
if (!dai->active)
return 0;

View File

@ -22,9 +22,11 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AK4642 if I2C
select SND_SOC_AK4671 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_DA7210 if I2C
select SND_SOC_JZ4740 if SOC_JZ4740
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
select SND_SOC_SPDIF
select SND_SOC_SSM2602 if I2C
@ -48,6 +50,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8727
select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8741 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
@ -120,13 +123,13 @@ config SND_SOC_AK4671
config SND_SOC_CQ0093VC
tristate
config SND_SOC_CS42L51
tristate
# Cirrus Logic CS4270 Codec
config SND_SOC_CS4270
tristate
config SND_SOC_DA7210
tristate
# Cirrus Logic CS4270 Codec VD = 3.3V Errata
# Select if you are affected by the errata where the part will not function
# if MCLK divide-by-1.5 is selected and VD is set to 3.3V. The driver will
@ -138,9 +141,15 @@ config SND_SOC_CS4270_VD33_ERRATA
config SND_SOC_CX20442
tristate
config SND_SOC_JZ4740_CODEC
tristate
config SND_SOC_L3
tristate
config SND_SOC_DA7210
tristate
config SND_SOC_PCM3008
tristate
@ -206,6 +215,9 @@ config SND_SOC_WM8728
config SND_SOC_WM8731
tristate
config SND_SOC_WM8741
tristate
config SND_SOC_WM8750
tristate

View File

@ -9,6 +9,7 @@ snd-soc-ak4535-objs := ak4535.o
snd-soc-ak4642-objs := ak4642.o
snd-soc-ak4671-objs := ak4671.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
@ -34,6 +35,7 @@ snd-soc-wm8711-objs := wm8711.o
snd-soc-wm8727-objs := wm8727.o
snd-soc-wm8728-objs := wm8728.o
snd-soc-wm8731-objs := wm8731.o
snd-soc-wm8741-objs := wm8741.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
snd-soc-wm8776-objs := wm8776.o
@ -56,6 +58,7 @@ snd-soc-wm9705-objs := wm9705.o
snd-soc-wm9712-objs := wm9712.o
snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
snd-soc-jz4740-codec-objs := jz4740.o
# Amp
snd-soc-max9877-objs := max9877.o
@ -74,10 +77,12 @@ obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@ -99,6 +104,7 @@ obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o

View File

@ -272,6 +272,7 @@ static int ad1836_register(struct ad1836_priv *ad1836)
if (ad1836_codec) {
dev_err(codec->dev, "Another ad1836 is registered\n");
kfree(ad1836);
return -EINVAL;
}

View File

@ -24,6 +24,7 @@
/* codec private data */
struct ad193x_priv {
unsigned int sysclk;
struct snd_soc_codec codec;
u8 reg_cache[AD193X_NUM_REGS];
};
@ -251,15 +252,32 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
static int ad193x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
switch (freq) {
case 12288000:
case 18432000:
case 24576000:
case 36864000:
ad193x->sysclk = freq;
return 0;
}
return -EINVAL;
}
static int ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
int word_len = 0, reg = 0;
int word_len = 0, reg = 0, master_rate = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
/* bit size */
switch (params_format(params)) {
@ -275,6 +293,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
switch (ad193x->sysclk) {
case 12288000:
master_rate = AD193X_PLL_INPUT_256;
break;
case 18432000:
master_rate = AD193X_PLL_INPUT_384;
break;
case 24576000:
master_rate = AD193X_PLL_INPUT_512;
break;
case 36864000:
master_rate = AD193X_PLL_INPUT_768;
break;
}
reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
reg = (reg & (~AD193X_DAC_WORD_LEN_MASK)) | word_len;
snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
@ -348,6 +385,7 @@ static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
/* pll input: mclki/xi */
snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
ad193x->sysclk = 12288000;
ret = snd_soc_register_codec(codec);
if (ret != 0) {
@ -383,6 +421,7 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
.set_tdm_slot = ad193x_set_tdm_slot,
.set_sysclk = ad193x_set_dai_sysclk,
.set_fmt = ad193x_set_dai_fmt,
};

View File

@ -11,6 +11,11 @@
#define AD193X_PLL_CLK_CTRL0 0x800
#define AD193X_PLL_POWERDOWN 0x01
#define AD193X_PLL_INPUT_MASK (~0x6)
#define AD193X_PLL_INPUT_256 (0 << 1)
#define AD193X_PLL_INPUT_384 (1 << 1)
#define AD193X_PLL_INPUT_512 (2 << 1)
#define AD193X_PLL_INPUT_768 (3 << 1)
#define AD193X_PLL_CLK_CTRL1 0x801
#define AD193X_DAC_CTRL0 0x802
#define AD193X_DAC_POWERDOWN 0x01

View File

@ -22,20 +22,13 @@
* AK4643 is tested.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "ak4642.h"
@ -111,6 +104,23 @@
struct snd_soc_codec_device soc_codec_dev_ak4642;
/*
* Playback Volume (table 39)
*
* max : 0x00 : +12.0 dB
* ( 0.5 dB step )
* min : 0xFE : -115.0 dB
* mute: 0xFF
*/
static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1);
static const struct snd_kcontrol_new ak4642_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
0, 0xFF, 1, out_tlv),
};
/* codec private data */
struct ak4642_priv {
struct snd_soc_codec codec;
@ -204,7 +214,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
*
* PLL, Master Mode
* Audio I/F Format :MSB justified (ADC & DAC)
* Digital Volume: -8dB
* Bass Boost Level : Middle
*
* This operation came from example code of
@ -214,8 +223,6 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
ak4642_write(codec, 0x0e, 0x19);
ak4642_write(codec, 0x09, 0x91);
ak4642_write(codec, 0x0c, 0x91);
ak4642_write(codec, 0x0a, 0x28);
ak4642_write(codec, 0x0d, 0x28);
ak4642_write(codec, 0x00, 0x64);
snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
@ -491,8 +498,10 @@ static int ak4642_i2c_probe(struct i2c_client *i2c,
codec->control_data = i2c;
ret = ak4642_init(ak4642);
if (ret < 0)
if (ret < 0) {
printk(KERN_ERR "failed to initialise AK4642\n");
kfree(ak4642);
}
return ret;
}
@ -548,6 +557,9 @@ static int ak4642_probe(struct platform_device *pdev)
goto pcm_err;
}
snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
ARRAY_SIZE(ak4642_snd_controls));
dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
return ret;

763
sound/soc/codecs/cs42l51.c Normal file
View File

@ -0,0 +1,763 @@
/*
* cs42l51.c
*
* ASoC Driver for Cirrus Logic CS42L51 codecs
*
* Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com>
*
* Based on cs4270.c - Copyright (c) Freescale Semiconductor
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
* For now:
* - Only I2C is support. Not SPI
* - master mode *NOT* supported
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
#include <linux/i2c.h>
#include "cs42l51.h"
enum master_slave_mode {
MODE_SLAVE,
MODE_SLAVE_AUTO,
MODE_MASTER,
};
struct cs42l51_private {
unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
struct snd_soc_codec codec;
u8 reg_cache[CS42L51_NUMREGS];
};
static struct snd_soc_codec *cs42l51_codec;
#define CS42L51_FORMATS ( \
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
static int cs42l51_fill_cache(struct snd_soc_codec *codec)
{
u8 *cache = codec->reg_cache + 1;
struct i2c_client *i2c_client = codec->control_data;
s32 length;
length = i2c_smbus_read_i2c_block_data(i2c_client,
CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache);
if (length != CS42L51_NUMREGS) {
dev_err(&i2c_client->dev,
"I2C read failure, addr=0x%x (ret=%d vs %d)\n",
i2c_client->addr, length, CS42L51_NUMREGS);
return -EIO;
}
return 0;
}
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id)
{
struct snd_soc_codec *codec;
struct cs42l51_private *cs42l51;
int ret = 0;
int reg;
if (cs42l51_codec)
return -EBUSY;
/* Verify that we have a CS42L51 */
ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
if (ret < 0) {
dev_err(&i2c_client->dev, "failed to read I2C\n");
goto error;
}
if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
(ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
dev_err(&i2c_client->dev, "Invalid chip id\n");
ret = -ENODEV;
goto error;
}
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
ret & 7);
cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
if (!cs42l51) {
dev_err(&i2c_client->dev, "could not allocate codec\n");
return -ENOMEM;
}
codec = &cs42l51->codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
codec->dev = &i2c_client->dev;
codec->name = "CS42L51";
codec->owner = THIS_MODULE;
codec->dai = &cs42l51_dai;
codec->num_dai = 1;
snd_soc_codec_set_drvdata(codec, cs42l51);
codec->control_data = i2c_client;
codec->reg_cache = cs42l51->reg_cache;
codec->reg_cache_size = CS42L51_NUMREGS;
i2c_set_clientdata(i2c_client, codec);
ret = cs42l51_fill_cache(codec);
if (ret < 0) {
dev_err(&i2c_client->dev, "failed to fill register cache\n");
goto error_alloc;
}
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
goto error_alloc;
}
/*
* DAC configuration
* - Use signal processor
* - auto mute
* - vol changes immediate
* - no de-emphasize
*/
reg = CS42L51_DAC_CTL_DATA_SEL(1)
| CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
if (ret < 0)
goto error_alloc;
cs42l51_dai.dev = codec->dev;
cs42l51_codec = codec;
ret = snd_soc_register_codec(codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
goto error_alloc;
}
ret = snd_soc_register_dai(&cs42l51_dai);
if (ret < 0) {
dev_err(&i2c_client->dev, "failed to register DAIe\n");
goto error_reg;
}
return 0;
error_reg:
snd_soc_unregister_codec(codec);
error_alloc:
kfree(cs42l51);
error:
return ret;
}
static int cs42l51_i2c_remove(struct i2c_client *client)
{
struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
snd_soc_unregister_dai(&cs42l51_dai);
snd_soc_unregister_codec(cs42l51_codec);
cs42l51_codec = NULL;
kfree(cs42l51);
return 0;
}
static const struct i2c_device_id cs42l51_id[] = {
{"cs42l51", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cs42l51_id);
static struct i2c_driver cs42l51_i2c_driver = {
.driver = {
.name = "CS42L51 I2C",
.owner = THIS_MODULE,
},
.id_table = cs42l51_id,
.probe = cs42l51_i2c_probe,
.remove = cs42l51_i2c_remove,
};
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3;
switch (value) {
default:
case 0:
ucontrol->value.integer.value[0] = 0;
break;
/* same value : (L+R)/2 and (R+L)/2 */
case 1:
case 2:
ucontrol->value.integer.value[0] = 1;
break;
case 3:
ucontrol->value.integer.value[0] = 2;
break;
}
return 0;
}
#define CHAN_MIX_NORMAL 0x00
#define CHAN_MIX_BOTH 0x55
#define CHAN_MIX_SWAP 0xFF
static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned char val;
switch (ucontrol->value.integer.value[0]) {
default:
case 0:
val = CHAN_MIX_NORMAL;
break;
case 1:
val = CHAN_MIX_BOTH;
break;
case 2:
val = CHAN_MIX_SWAP;
break;
}
snd_soc_write(codec, CS42L51_PCM_MIXER, val);
return 1;
}
static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0);
static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0);
/* This is a lie. after -102 db, it stays at -102 */
/* maybe a range would be better */
static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0);
static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0);
static const char *chan_mix[] = {
"L R",
"L+R",
"R L",
};
static const struct soc_enum cs42l51_chan_mix =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix);
static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
SOC_DOUBLE_R_SX_TLV("PCM Playback Volume",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL,
7, 0xffffff99, 0x18, adc_pcm_tlv),
SOC_DOUBLE_R("PCM Playback Switch",
CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1),
SOC_DOUBLE_R_SX_TLV("Analog Playback Volume",
CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL,
8, 0xffffff19, 0x18, aout_tlv),
SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL,
7, 0xffffff99, 0x18, adc_pcm_tlv),
SOC_DOUBLE_R("ADC Mixer Switch",
CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1),
SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0),
SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0),
SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0),
SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0),
SOC_DOUBLE_TLV("Mic Boost Volume",
CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv),
SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv),
SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv),
SOC_ENUM_EXT("PCM channel mixer",
cs42l51_chan_mix,
cs42l51_get_chan_mix, cs42l51_set_chan_mix),
};
/*
* to power down, one must:
* 1.) Enable the PDN bit
* 2.) enable power-down for the select channels
* 3.) disable the PDN bit.
*/
static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
unsigned long value;
value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
value &= ~CS42L51_POWER_CTL1_PDN;
switch (event) {
case SND_SOC_DAPM_PRE_PMD:
value |= CS42L51_POWER_CTL1_PDN;
break;
default:
case SND_SOC_DAPM_POST_PMD:
break;
}
snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
CS42L51_POWER_CTL1_PDN, value);
return 0;
}
static const char *cs42l51_dac_names[] = {"Direct PCM",
"DSP PCM", "ADC"};
static const struct soc_enum cs42l51_dac_mux_enum =
SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names);
static const struct snd_kcontrol_new cs42l51_dac_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum);
static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left",
"MIC Left", "MIC+preamp Left"};
static const struct soc_enum cs42l51_adcl_mux_enum =
SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names);
static const struct snd_kcontrol_new cs42l51_adcl_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum);
static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right",
"MIC Right", "MIC+preamp Right"};
static const struct soc_enum cs42l51_adcr_mux_enum =
SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names);
static const struct snd_kcontrol_new cs42l51_adcr_mux_controls =
SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum);
static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = {
SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1),
SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture",
CS42L51_POWER_CTL1, 1, 1,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture",
CS42L51_POWER_CTL1, 2, 1,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback",
CS42L51_POWER_CTL1, 5, 1,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback",
CS42L51_POWER_CTL1, 6, 1,
cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD),
/* analog/mic */
SND_SOC_DAPM_INPUT("AIN1L"),
SND_SOC_DAPM_INPUT("AIN1R"),
SND_SOC_DAPM_INPUT("AIN2L"),
SND_SOC_DAPM_INPUT("AIN2R"),
SND_SOC_DAPM_INPUT("MICL"),
SND_SOC_DAPM_INPUT("MICR"),
SND_SOC_DAPM_MIXER("Mic Preamp Left",
CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0),
SND_SOC_DAPM_MIXER("Mic Preamp Right",
CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0),
/* HP */
SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
/* mux */
SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0,
&cs42l51_dac_mux_controls),
SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0,
&cs42l51_adcl_mux_controls),
SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0,
&cs42l51_adcr_mux_controls),
};
static const struct snd_soc_dapm_route cs42l51_routes[] = {
{"HPL", NULL, "Left DAC"},
{"HPR", NULL, "Right DAC"},
{"Left ADC", NULL, "Left PGA"},
{"Right ADC", NULL, "Right PGA"},
{"Mic Preamp Left", NULL, "MICL"},
{"Mic Preamp Right", NULL, "MICR"},
{"PGA-ADC Mux Left", "AIN1 Left", "AIN1L" },
{"PGA-ADC Mux Left", "AIN2 Left", "AIN2L" },
{"PGA-ADC Mux Left", "MIC Left", "MICL" },
{"PGA-ADC Mux Left", "MIC+preamp Left", "Mic Preamp Left" },
{"PGA-ADC Mux Right", "AIN1 Right", "AIN1R" },
{"PGA-ADC Mux Right", "AIN2 Right", "AIN2R" },
{"PGA-ADC Mux Right", "MIC Right", "MICR" },
{"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" },
{"Left PGA", NULL, "PGA-ADC Mux Left"},
{"Right PGA", NULL, "PGA-ADC Mux Right"},
};
static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_LEFT_J:
case SND_SOC_DAIFMT_RIGHT_J:
cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK;
break;
default:
dev_err(codec->dev, "invalid DAI format\n");
ret = -EINVAL;
}
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
cs42l51->func = MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
cs42l51->func = MODE_SLAVE_AUTO;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
struct cs42l51_ratios {
unsigned int ratio;
unsigned char speed_mode;
unsigned char mclk;
};
static struct cs42l51_ratios slave_ratios[] = {
{ 512, CS42L51_QSM_MODE, 0 }, { 768, CS42L51_QSM_MODE, 0 },
{ 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
{ 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 },
{ 256, CS42L51_HSM_MODE, 0 }, { 384, CS42L51_HSM_MODE, 0 },
{ 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
{ 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 },
{ 128, CS42L51_SSM_MODE, 0 }, { 192, CS42L51_SSM_MODE, 0 },
{ 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
{ 512, CS42L51_SSM_MODE, 0 }, { 768, CS42L51_SSM_MODE, 0 },
{ 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
{ 256, CS42L51_DSM_MODE, 0 }, { 384, CS42L51_DSM_MODE, 0 },
};
static struct cs42l51_ratios slave_auto_ratios[] = {
{ 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 },
{ 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 },
{ 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 },
{ 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 },
{ 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 },
{ 512, CS42L51_SSM_MODE, 1 }, { 768, CS42L51_SSM_MODE, 1 },
{ 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 },
{ 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 },
};
static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
struct cs42l51_ratios *ratios = NULL;
int nr_ratios = 0;
unsigned int rates = 0;
unsigned int rate_min = -1;
unsigned int rate_max = 0;
int i;
cs42l51->mclk = freq;
switch (cs42l51->func) {
case MODE_MASTER:
return -EINVAL;
case MODE_SLAVE:
ratios = slave_ratios;
nr_ratios = ARRAY_SIZE(slave_ratios);
break;
case MODE_SLAVE_AUTO:
ratios = slave_auto_ratios;
nr_ratios = ARRAY_SIZE(slave_auto_ratios);
break;
}
for (i = 0; i < nr_ratios; i++) {
unsigned int rate = freq / ratios[i].ratio;
rates |= snd_pcm_rate_to_rate_bit(rate);
if (rate < rate_min)
rate_min = rate;
if (rate > rate_max)
rate_max = rate;
}
rates &= ~SNDRV_PCM_RATE_KNOT;
if (!rates) {
dev_err(codec->dev, "could not find a valid sample rate\n");
return -EINVAL;
}
codec_dai->playback.rates = rates;
codec_dai->playback.rate_min = rate_min;
codec_dai->playback.rate_max = rate_max;
codec_dai->capture.rates = rates;
codec_dai->capture.rate_min = rate_min;
codec_dai->capture.rate_max = rate_max;
return 0;
}
static int cs42l51_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret;
unsigned int i;
unsigned int rate;
unsigned int ratio;
struct cs42l51_ratios *ratios = NULL;
int nr_ratios = 0;
int intf_ctl, power_ctl, fmt;
switch (cs42l51->func) {
case MODE_MASTER:
return -EINVAL;
case MODE_SLAVE:
ratios = slave_ratios;
nr_ratios = ARRAY_SIZE(slave_ratios);
break;
case MODE_SLAVE_AUTO:
ratios = slave_auto_ratios;
nr_ratios = ARRAY_SIZE(slave_auto_ratios);
break;
}
/* Figure out which MCLK/LRCK ratio to use */
rate = params_rate(params); /* Sampling rate, in Hz */
ratio = cs42l51->mclk / rate; /* MCLK/LRCK ratio */
for (i = 0; i < nr_ratios; i++) {
if (ratios[i].ratio == ratio)
break;
}
if (i == nr_ratios) {
/* We did not find a matching ratio */
dev_err(codec->dev, "could not find matching ratio\n");
return -EINVAL;
}
intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL);
power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL);
intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S
| CS42L51_INTF_CTL_DAC_FORMAT(7));
power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3)
| CS42L51_MIC_POWER_CTL_MCLK_DIV2);
switch (cs42l51->func) {
case MODE_MASTER:
intf_ctl |= CS42L51_INTF_CTL_MASTER;
power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
break;
case MODE_SLAVE:
power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode);
break;
case MODE_SLAVE_AUTO:
power_ctl |= CS42L51_MIC_POWER_CTL_AUTO;
break;
}
switch (cs42l51->audio_mode) {
case SND_SOC_DAIFMT_I2S:
intf_ctl |= CS42L51_INTF_CTL_ADC_I2S;
intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S);
break;
case SND_SOC_DAIFMT_LEFT_J:
intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24);
break;
case SND_SOC_DAIFMT_RIGHT_J:
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
case SNDRV_PCM_FORMAT_S16_BE:
fmt = CS42L51_DAC_DIF_RJ16;
break;
case SNDRV_PCM_FORMAT_S18_3LE:
case SNDRV_PCM_FORMAT_S18_3BE:
fmt = CS42L51_DAC_DIF_RJ18;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
fmt = CS42L51_DAC_DIF_RJ20;
break;
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
fmt = CS42L51_DAC_DIF_RJ24;
break;
default:
dev_err(codec->dev, "unknown format\n");
return -EINVAL;
}
intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt);
break;
default:
dev_err(codec->dev, "unknown format\n");
return -EINVAL;
}
if (ratios[i].mclk)
power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2;
ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl);
if (ret < 0)
return ret;
ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl);
if (ret < 0)
return ret;
return 0;
}
static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
int reg;
int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE;
reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL);
if (mute)
reg |= mask;
else
reg &= ~mask;
return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
}
static struct snd_soc_dai_ops cs42l51_dai_ops = {
.hw_params = cs42l51_hw_params,
.set_sysclk = cs42l51_set_dai_sysclk,
.set_fmt = cs42l51_set_dai_fmt,
.digital_mute = cs42l51_dai_mute,
};
struct snd_soc_dai cs42l51_dai = {
.name = "CS42L51 HiFi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = CS42L51_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = CS42L51_FORMATS,
},
.ops = &cs42l51_dai_ops,
};
EXPORT_SYMBOL_GPL(cs42l51_dai);
static int cs42l51_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
int ret = 0;
if (!cs42l51_codec) {
dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
return -EINVAL;
}
socdev->card->codec = cs42l51_codec;
codec = socdev->card->codec;
/* Register PCMs */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to create PCMs\n");
return ret;
}
snd_soc_add_controls(codec, cs42l51_snd_controls,
ARRAY_SIZE(cs42l51_snd_controls));
snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
ARRAY_SIZE(cs42l51_dapm_widgets));
snd_soc_dapm_add_routes(codec, cs42l51_routes,
ARRAY_SIZE(cs42l51_routes));
return 0;
}
static int cs42l51_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0;
}
struct snd_soc_codec_device soc_codec_device_cs42l51 = {
.probe = cs42l51_probe,
.remove = cs42l51_remove
};
EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
static int __init cs42l51_init(void)
{
int ret;
ret = i2c_add_driver(&cs42l51_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "%s: can't add i2c driver\n", __func__);
return ret;
}
return 0;
}
module_init(cs42l51_init);
static void __exit cs42l51_exit(void)
{
i2c_del_driver(&cs42l51_i2c_driver);
}
module_exit(cs42l51_exit);
MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");

163
sound/soc/codecs/cs42l51.h Normal file
View File

@ -0,0 +1,163 @@
/*
* cs42l51.h
*
* ASoC Driver for Cirrus Logic CS42L51 codecs
*
* Copyright (c) 2010 Arnaud Patard <apatard@mandriva.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.
*/
#ifndef _CS42L51_H
#define _CS42L51_H
#define CS42L51_CHIP_ID 0x1B
#define CS42L51_CHIP_REV_A 0x00
#define CS42L51_CHIP_REV_B 0x01
#define CS42L51_CHIP_REV_ID 0x01
#define CS42L51_MK_CHIP_REV(a, b) ((a)<<3|(b))
#define CS42L51_POWER_CTL1 0x02
#define CS42L51_POWER_CTL1_PDN_DACB (1<<6)
#define CS42L51_POWER_CTL1_PDN_DACA (1<<5)
#define CS42L51_POWER_CTL1_PDN_PGAB (1<<4)
#define CS42L51_POWER_CTL1_PDN_PGAA (1<<3)
#define CS42L51_POWER_CTL1_PDN_ADCB (1<<2)
#define CS42L51_POWER_CTL1_PDN_ADCA (1<<1)
#define CS42L51_POWER_CTL1_PDN (1<<0)
#define CS42L51_MIC_POWER_CTL 0x03
#define CS42L51_MIC_POWER_CTL_AUTO (1<<7)
#define CS42L51_MIC_POWER_CTL_SPEED(x) (((x)&3)<<5)
#define CS42L51_QSM_MODE 3
#define CS42L51_HSM_MODE 2
#define CS42L51_SSM_MODE 1
#define CS42L51_DSM_MODE 0
#define CS42L51_MIC_POWER_CTL_3ST_SP (1<<4)
#define CS42L51_MIC_POWER_CTL_PDN_MICB (1<<3)
#define CS42L51_MIC_POWER_CTL_PDN_MICA (1<<2)
#define CS42L51_MIC_POWER_CTL_PDN_BIAS (1<<1)
#define CS42L51_MIC_POWER_CTL_MCLK_DIV2 (1<<0)
#define CS42L51_INTF_CTL 0x04
#define CS42L51_INTF_CTL_LOOPBACK (1<<7)
#define CS42L51_INTF_CTL_MASTER (1<<6)
#define CS42L51_INTF_CTL_DAC_FORMAT(x) (((x)&7)<<3)
#define CS42L51_DAC_DIF_LJ24 0x00
#define CS42L51_DAC_DIF_I2S 0x01
#define CS42L51_DAC_DIF_RJ24 0x02
#define CS42L51_DAC_DIF_RJ20 0x03
#define CS42L51_DAC_DIF_RJ18 0x04
#define CS42L51_DAC_DIF_RJ16 0x05
#define CS42L51_INTF_CTL_ADC_I2S (1<<2)
#define CS42L51_INTF_CTL_DIGMIX (1<<1)
#define CS42L51_INTF_CTL_MICMIX (1<<0)
#define CS42L51_MIC_CTL 0x05
#define CS42L51_MIC_CTL_ADC_SNGVOL (1<<7)
#define CS42L51_MIC_CTL_ADCD_DBOOST (1<<6)
#define CS42L51_MIC_CTL_ADCA_DBOOST (1<<5)
#define CS42L51_MIC_CTL_MICBIAS_SEL (1<<4)
#define CS42L51_MIC_CTL_MICBIAS_LVL(x) (((x)&3)<<2)
#define CS42L51_MIC_CTL_MICB_BOOST (1<<1)
#define CS42L51_MIC_CTL_MICA_BOOST (1<<0)
#define CS42L51_ADC_CTL 0x06
#define CS42L51_ADC_CTL_ADCB_HPFEN (1<<7)
#define CS42L51_ADC_CTL_ADCB_HPFRZ (1<<6)
#define CS42L51_ADC_CTL_ADCA_HPFEN (1<<5)
#define CS42L51_ADC_CTL_ADCA_HPFRZ (1<<4)
#define CS42L51_ADC_CTL_SOFTB (1<<3)
#define CS42L51_ADC_CTL_ZCROSSB (1<<2)
#define CS42L51_ADC_CTL_SOFTA (1<<1)
#define CS42L51_ADC_CTL_ZCROSSA (1<<0)
#define CS42L51_ADC_INPUT 0x07
#define CS42L51_ADC_INPUT_AINB_MUX(x) (((x)&3)<<6)
#define CS42L51_ADC_INPUT_AINA_MUX(x) (((x)&3)<<4)
#define CS42L51_ADC_INPUT_INV_ADCB (1<<3)
#define CS42L51_ADC_INPUT_INV_ADCA (1<<2)
#define CS42L51_ADC_INPUT_ADCB_MUTE (1<<1)
#define CS42L51_ADC_INPUT_ADCA_MUTE (1<<0)
#define CS42L51_DAC_OUT_CTL 0x08
#define CS42L51_DAC_OUT_CTL_HP_GAIN(x) (((x)&7)<<5)
#define CS42L51_DAC_OUT_CTL_DAC_SNGVOL (1<<4)
#define CS42L51_DAC_OUT_CTL_INV_PCMB (1<<3)
#define CS42L51_DAC_OUT_CTL_INV_PCMA (1<<2)
#define CS42L51_DAC_OUT_CTL_DACB_MUTE (1<<1)
#define CS42L51_DAC_OUT_CTL_DACA_MUTE (1<<0)
#define CS42L51_DAC_CTL 0x09
#define CS42L51_DAC_CTL_DATA_SEL(x) (((x)&3)<<6)
#define CS42L51_DAC_CTL_FREEZE (1<<5)
#define CS42L51_DAC_CTL_DEEMPH (1<<3)
#define CS42L51_DAC_CTL_AMUTE (1<<2)
#define CS42L51_DAC_CTL_DACSZ(x) (((x)&3)<<0)
#define CS42L51_ALC_PGA_CTL 0x0A
#define CS42L51_ALC_PGB_CTL 0x0B
#define CS42L51_ALC_PGX_ALCX_SRDIS (1<<7)
#define CS42L51_ALC_PGX_ALCX_ZCDIS (1<<6)
#define CS42L51_ALC_PGX_PGX_VOL(x) (((x)&0x1f)<<0)
#define CS42L51_ADCA_ATT 0x0C
#define CS42L51_ADCB_ATT 0x0D
#define CS42L51_ADCA_VOL 0x0E
#define CS42L51_ADCB_VOL 0x0F
#define CS42L51_PCMA_VOL 0x10
#define CS42L51_PCMB_VOL 0x11
#define CS42L51_MIX_MUTE_ADCMIX (1<<7)
#define CS42L51_MIX_VOLUME(x) (((x)&0x7f)<<0)
#define CS42L51_BEEP_FREQ 0x12
#define CS42L51_BEEP_VOL 0x13
#define CS42L51_BEEP_CONF 0x14
#define CS42L51_TONE_CTL 0x15
#define CS42L51_TONE_CTL_TREB(x) (((x)&0xf)<<4)
#define CS42L51_TONE_CTL_BASS(x) (((x)&0xf)<<0)
#define CS42L51_AOUTA_VOL 0x16
#define CS42L51_AOUTB_VOL 0x17
#define CS42L51_PCM_MIXER 0x18
#define CS42L51_LIMIT_THRES_DIS 0x19
#define CS42L51_LIMIT_REL 0x1A
#define CS42L51_LIMIT_ATT 0x1B
#define CS42L51_ALC_EN 0x1C
#define CS42L51_ALC_REL 0x1D
#define CS42L51_ALC_THRES 0x1E
#define CS42L51_NOISE_CONF 0x1F
#define CS42L51_STATUS 0x20
#define CS42L51_STATUS_SP_CLKERR (1<<6)
#define CS42L51_STATUS_SPEA_OVFL (1<<5)
#define CS42L51_STATUS_SPEB_OVFL (1<<4)
#define CS42L51_STATUS_PCMA_OVFL (1<<3)
#define CS42L51_STATUS_PCMB_OVFL (1<<2)
#define CS42L51_STATUS_ADCA_OVFL (1<<1)
#define CS42L51_STATUS_ADCB_OVFL (1<<0)
#define CS42L51_CHARGE_FREQ 0x21
#define CS42L51_FIRSTREG 0x01
/*
* Hack: with register 0x21, it makes 33 registers. Looks like someone in the
* i2c layer doesn't like i2c smbus block read of 33 regs. Workaround by using
* 32 regs
*/
#define CS42L51_LASTREG 0x20
#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
extern struct snd_soc_dai cs42l51_dai;
extern struct snd_soc_codec_device soc_codec_device_cs42l51;
#endif

View File

@ -15,23 +15,15 @@
* option) any later version.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include <sound/initval.h>
#include <asm/div64.h>
#include <sound/tlv.h>
#include "da7210.h"
@ -145,6 +137,29 @@
#define DA7210_VERSION "0.0.1"
/*
* Playback Volume
*
* max : 0x3F (+15.0 dB)
* (1.5 dB step)
* min : 0x11 (-54.0 dB)
* mute : 0x10
* reserved : 0x00 - 0x0F
*
* ** FIXME **
*
* Reserved area are considered as "mute".
* -> min = -79.5 dB
*/
static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
static const struct snd_kcontrol_new da7210_snd_controls[] = {
SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
DA7210_HP_L_VOL, DA7210_HP_R_VOL,
0, 0x3F, 0, hp_out_tlv),
};
/* Codec private data */
struct da7210_priv {
struct snd_soc_codec codec;
@ -227,10 +242,6 @@ static int da7210_startup(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
if (is_play) {
/* PlayBack Volume 40 */
snd_soc_update_bits(codec, DA7210_HP_L_VOL, 0x3F, 40);
snd_soc_update_bits(codec, DA7210_HP_R_VOL, 0x3F, 40);
/* Enable Out */
snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
@ -488,7 +499,7 @@ static int da7210_init(struct da7210_priv *da7210)
ret = snd_soc_register_dai(&da7210_dai);
if (ret) {
dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
goto init_err;
goto codec_err;
}
/* FIXME
@ -574,6 +585,8 @@ static int da7210_init(struct da7210_priv *da7210)
return ret;
codec_err:
snd_soc_unregister_codec(codec);
init_err:
kfree(codec->reg_cache);
codec->reg_cache = NULL;
@ -601,8 +614,10 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
codec->control_data = i2c;
ret = da7210_init(da7210);
if (ret < 0)
if (ret < 0) {
pr_err("Failed to initialise da7210 audio codec\n");
kfree(da7210);
}
return ret;
}
@ -656,6 +671,9 @@ static int da7210_probe(struct platform_device *pdev)
if (ret < 0)
goto pcm_err;
snd_soc_add_controls(da7210_codec, da7210_snd_controls,
ARRAY_SIZE(da7210_snd_controls));
dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
pcm_err:

511
sound/soc/codecs/jz4740.c Normal file
View File

@ -0,0 +1,511 @@
/*
* Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc-dapm.h>
#include <sound/soc.h>
#define JZ4740_REG_CODEC_1 0x0
#define JZ4740_REG_CODEC_2 0x1
#define JZ4740_CODEC_1_LINE_ENABLE BIT(29)
#define JZ4740_CODEC_1_MIC_ENABLE BIT(28)
#define JZ4740_CODEC_1_SW1_ENABLE BIT(27)
#define JZ4740_CODEC_1_ADC_ENABLE BIT(26)
#define JZ4740_CODEC_1_SW2_ENABLE BIT(25)
#define JZ4740_CODEC_1_DAC_ENABLE BIT(24)
#define JZ4740_CODEC_1_VREF_DISABLE BIT(20)
#define JZ4740_CODEC_1_VREF_AMP_DISABLE BIT(19)
#define JZ4740_CODEC_1_VREF_PULLDOWN BIT(18)
#define JZ4740_CODEC_1_VREF_LOW_CURRENT BIT(17)
#define JZ4740_CODEC_1_VREF_HIGH_CURRENT BIT(16)
#define JZ4740_CODEC_1_HEADPHONE_DISABLE BIT(14)
#define JZ4740_CODEC_1_HEADPHONE_AMP_CHANGE_ANY BIT(13)
#define JZ4740_CODEC_1_HEADPHONE_CHARGE BIT(12)
#define JZ4740_CODEC_1_HEADPHONE_PULLDOWN (BIT(11) | BIT(10))
#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M BIT(9)
#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN BIT(8)
#define JZ4740_CODEC_1_SUSPEND BIT(1)
#define JZ4740_CODEC_1_RESET BIT(0)
#define JZ4740_CODEC_1_LINE_ENABLE_OFFSET 29
#define JZ4740_CODEC_1_MIC_ENABLE_OFFSET 28
#define JZ4740_CODEC_1_SW1_ENABLE_OFFSET 27
#define JZ4740_CODEC_1_ADC_ENABLE_OFFSET 26
#define JZ4740_CODEC_1_SW2_ENABLE_OFFSET 25
#define JZ4740_CODEC_1_DAC_ENABLE_OFFSET 24
#define JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET 14
#define JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET 8
#define JZ4740_CODEC_2_INPUT_VOLUME_MASK 0x1f0000
#define JZ4740_CODEC_2_SAMPLE_RATE_MASK 0x000f00
#define JZ4740_CODEC_2_MIC_BOOST_GAIN_MASK 0x000030
#define JZ4740_CODEC_2_HEADPHONE_VOLUME_MASK 0x000003
#define JZ4740_CODEC_2_INPUT_VOLUME_OFFSET 16
#define JZ4740_CODEC_2_SAMPLE_RATE_OFFSET 8
#define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4
#define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0
static const uint32_t jz4740_codec_regs[] = {
0x021b2302, 0x00170803,
};
struct jz4740_codec {
void __iomem *base;
struct resource *mem;
uint32_t reg_cache[2];
struct snd_soc_codec codec;
};
static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
{
return container_of(codec, struct jz4740_codec, codec);
}
static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
unsigned int reg)
{
struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
return readl(jz4740_codec->base + (reg << 2));
}
static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val)
{
struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
jz4740_codec->reg_cache[reg] = val;
writel(val, jz4740_codec->base + (reg << 2));
return 0;
}
static const struct snd_kcontrol_new jz4740_codec_controls[] = {
SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0),
SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0),
SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1),
SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0),
};
static const struct snd_kcontrol_new jz4740_codec_output_controls[] = {
SOC_DAPM_SINGLE("Bypass Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW1_ENABLE_OFFSET, 1, 0),
SOC_DAPM_SINGLE("DAC Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW2_ENABLE_OFFSET, 1, 0),
};
static const struct snd_kcontrol_new jz4740_codec_input_controls[] = {
SOC_DAPM_SINGLE("Line Capture Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_LINE_ENABLE_OFFSET, 1, 0),
SOC_DAPM_SINGLE("Mic Capture Switch", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_MIC_ENABLE_OFFSET, 1, 0),
};
static const struct snd_soc_dapm_widget jz4740_codec_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADC", "Capture", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_ADC_ENABLE_OFFSET, 0),
SND_SOC_DAPM_DAC("DAC", "Playback", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_DAC_ENABLE_OFFSET, 0),
SND_SOC_DAPM_MIXER("Output Mixer", JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_OFFSET, 1,
jz4740_codec_output_controls,
ARRAY_SIZE(jz4740_codec_output_controls)),
SND_SOC_DAPM_MIXER_NAMED_CTL("Input Mixer", SND_SOC_NOPM, 0, 0,
jz4740_codec_input_controls,
ARRAY_SIZE(jz4740_codec_input_controls)),
SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("LOUT"),
SND_SOC_DAPM_OUTPUT("ROUT"),
SND_SOC_DAPM_INPUT("MIC"),
SND_SOC_DAPM_INPUT("LIN"),
SND_SOC_DAPM_INPUT("RIN"),
};
static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = {
{"Line Input", NULL, "LIN"},
{"Line Input", NULL, "RIN"},
{"Input Mixer", "Line Capture Switch", "Line Input"},
{"Input Mixer", "Mic Capture Switch", "MIC"},
{"ADC", NULL, "Input Mixer"},
{"Output Mixer", "Bypass Switch", "Input Mixer"},
{"Output Mixer", "DAC Switch", "DAC"},
{"LOUT", NULL, "Output Mixer"},
{"ROUT", NULL, "Output Mixer"},
};
static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
uint32_t val;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
switch (params_rate(params)) {
case 8000:
val = 0;
break;
case 11025:
val = 1;
break;
case 12000:
val = 2;
break;
case 16000:
val = 3;
break;
case 22050:
val = 4;
break;
case 24000:
val = 5;
break;
case 32000:
val = 6;
break;
case 44100:
val = 7;
break;
case 48000:
val = 8;
break;
default:
return -EINVAL;
}
val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_2,
JZ4740_CODEC_2_SAMPLE_RATE_MASK, val);
return 0;
}
static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
.hw_params = jz4740_codec_hw_params,
};
struct snd_soc_dai jz4740_codec_dai = {
.name = "jz4740",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
},
.ops = &jz4740_codec_dai_ops,
.symmetric_rates = 1,
};
EXPORT_SYMBOL_GPL(jz4740_codec_dai);
static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
{
int i;
uint32_t *cache = codec->reg_cache;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET);
udelay(2);
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0);
for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i)
jz4740_codec_write(codec, i, cache[i]);
}
static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
unsigned int mask;
unsigned int value;
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
mask = JZ4740_CODEC_1_VREF_DISABLE |
JZ4740_CODEC_1_VREF_AMP_DISABLE |
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
value = 0;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_STANDBY:
/* The only way to clear the suspend flag is to reset the codec */
if (codec->bias_level == SND_SOC_BIAS_OFF)
jz4740_codec_wakeup(codec);
mask = JZ4740_CODEC_1_VREF_DISABLE |
JZ4740_CODEC_1_VREF_AMP_DISABLE |
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
value = JZ4740_CODEC_1_VREF_DISABLE |
JZ4740_CODEC_1_VREF_AMP_DISABLE |
JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
break;
case SND_SOC_BIAS_OFF:
mask = JZ4740_CODEC_1_SUSPEND;
value = JZ4740_CODEC_1_SUSPEND;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value);
break;
default:
break;
}
codec->bias_level = level;
return 0;
}
static struct snd_soc_codec *jz4740_codec_codec;
static int jz4740_codec_dev_probe(struct platform_device *pdev)
{
int ret;
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = jz4740_codec_codec;
BUG_ON(!codec);
socdev->card->codec = codec;
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret) {
dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
return ret;
}
snd_soc_add_controls(codec, jz4740_codec_controls,
ARRAY_SIZE(jz4740_codec_controls));
snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
ARRAY_SIZE(jz4740_codec_dapm_widgets));
snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
ARRAY_SIZE(jz4740_codec_dapm_routes));
snd_soc_dapm_new_widgets(codec);
return 0;
}
static int jz4740_codec_dev_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int jz4740_codec_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
#else
#define jz4740_codec_suspend NULL
#define jz4740_codec_resume NULL
#endif
struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
.probe = jz4740_codec_dev_probe,
.remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
static int __devinit jz4740_codec_probe(struct platform_device *pdev)
{
int ret;
struct jz4740_codec *jz4740_codec;
struct snd_soc_codec *codec;
struct resource *mem;
jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
if (!jz4740_codec)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
ret = -ENOENT;
goto err_free_codec;
}
mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
if (!mem) {
dev_err(&pdev->dev, "Failed to request mmio memory region\n");
ret = -EBUSY;
goto err_free_codec;
}
jz4740_codec->base = ioremap(mem->start, resource_size(mem));
if (!jz4740_codec->base) {
dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
ret = -EBUSY;
goto err_release_mem_region;
}
jz4740_codec->mem = mem;
jz4740_codec_dai.dev = &pdev->dev;
codec = &jz4740_codec->codec;
codec->dev = &pdev->dev;
codec->name = "jz4740";
codec->owner = THIS_MODULE;
codec->read = jz4740_codec_read;
codec->write = jz4740_codec_write;
codec->set_bias_level = jz4740_codec_set_bias_level;
codec->bias_level = SND_SOC_BIAS_OFF;
codec->dai = &jz4740_codec_dai;
codec->num_dai = 1;
codec->reg_cache = jz4740_codec->reg_cache;
codec->reg_cache_size = 2;
memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
jz4740_codec_codec = codec;
snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
platform_set_drvdata(pdev, jz4740_codec);
ret = snd_soc_register_codec(codec);
if (ret) {
dev_err(&pdev->dev, "Failed to register codec\n");
goto err_iounmap;
}
ret = snd_soc_register_dai(&jz4740_codec_dai);
if (ret) {
dev_err(&pdev->dev, "Failed to register codec dai\n");
goto err_unregister_codec;
}
jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
err_unregister_codec:
snd_soc_unregister_codec(codec);
err_iounmap:
iounmap(jz4740_codec->base);
err_release_mem_region:
release_mem_region(mem->start, resource_size(mem));
err_free_codec:
kfree(jz4740_codec);
return ret;
}
static int __devexit jz4740_codec_remove(struct platform_device *pdev)
{
struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
struct resource *mem = jz4740_codec->mem;
snd_soc_unregister_dai(&jz4740_codec_dai);
snd_soc_unregister_codec(&jz4740_codec->codec);
iounmap(jz4740_codec->base);
release_mem_region(mem->start, resource_size(mem));
platform_set_drvdata(pdev, NULL);
kfree(jz4740_codec);
return 0;
}
static struct platform_driver jz4740_codec_driver = {
.probe = jz4740_codec_probe,
.remove = __devexit_p(jz4740_codec_remove),
.driver = {
.name = "jz4740-codec",
.owner = THIS_MODULE,
},
};
static int __init jz4740_codec_init(void)
{
return platform_driver_register(&jz4740_codec_driver);
}
module_init(jz4740_codec_init);
static void __exit jz4740_codec_exit(void)
{
platform_driver_unregister(&jz4740_codec_driver);
}
module_exit(jz4740_codec_exit);
MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:jz4740-codec");

20
sound/soc/codecs/jz4740.h Normal file
View File

@ -0,0 +1,20 @@
/*
* Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
#define __SND_SOC_CODECS_JZ4740_CODEC_H__
extern struct snd_soc_dai jz4740_codec_dai;
extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
#endif

View File

@ -16,8 +16,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/initval.h>
#include "spdif_transciever.h"
@ -26,6 +28,48 @@ MODULE_LICENSE("GPL");
#define STUB_RATES SNDRV_PCM_RATE_8000_96000
#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
static struct snd_soc_codec *spdif_dit_codec;
static int spdif_dit_codec_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
int ret;
if (spdif_dit_codec == NULL) {
dev_err(&pdev->dev, "Codec device not registered\n");
return -ENODEV;
}
socdev->card->codec = spdif_dit_codec;
codec = spdif_dit_codec;
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
dev_err(codec->dev, "failed to create pcms: %d\n", ret);
goto err_create_pcms;
}
return 0;
err_create_pcms:
return ret;
}
static int spdif_dit_codec_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
snd_soc_free_pcms(socdev);
return 0;
}
struct snd_soc_codec_device soc_codec_dev_spdif_dit = {
.probe = spdif_dit_codec_probe,
.remove = spdif_dit_codec_remove,
}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
struct snd_soc_dai dit_stub_dai = {
.name = "DIT",
.playback = {
@ -40,13 +84,61 @@ EXPORT_SYMBOL_GPL(dit_stub_dai);
static int spdif_dit_probe(struct platform_device *pdev)
{
struct snd_soc_codec *codec;
int ret;
if (spdif_dit_codec) {
dev_err(&pdev->dev, "Another Codec is registered\n");
ret = -EINVAL;
goto err_reg_codec;
}
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
codec->dev = &pdev->dev;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
codec->name = "spdif-dit";
codec->owner = THIS_MODULE;
codec->dai = &dit_stub_dai;
codec->num_dai = 1;
spdif_dit_codec = codec;
ret = snd_soc_register_codec(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
goto err_reg_codec;
}
dit_stub_dai.dev = &pdev->dev;
return snd_soc_register_dai(&dit_stub_dai);
ret = snd_soc_register_dai(&dit_stub_dai);
if (ret < 0) {
dev_err(codec->dev, "Failed to register dai: %d\n", ret);
goto err_reg_dai;
}
return 0;
err_reg_dai:
snd_soc_unregister_codec(codec);
err_reg_codec:
kfree(spdif_dit_codec);
return ret;
}
static int spdif_dit_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&dit_stub_dai);
snd_soc_unregister_codec(spdif_dit_codec);
kfree(spdif_dit_codec);
spdif_dit_codec = NULL;
return 0;
}

View File

@ -12,6 +12,7 @@
#ifndef CODEC_STUBS_H
#define CODEC_STUBS_H
extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
extern struct snd_soc_dai dit_stub_dai;
#endif /* CODEC_STUBS_H */

Some files were not shown because too many files have changed in this diff Show More