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:
commit
faa38b5e0e
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
135
Documentation/sound/alsa/alsa-parameters.txt
Normal file
135
Documentation/sound/alsa/alsa-parameters.txt
Normal 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]
|
51
Documentation/sound/oss/oss-parameters.txt
Normal file
51
Documentation/sound/oss/oss-parameters.txt
Normal 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>
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
11
arch/arm/plat-orion/include/plat/audio.h
Normal file
11
arch/arm/plat-orion/include/plat/audio.h
Normal 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
|
@ -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', "
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 = {},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
@ -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
@ -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;
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 |
|
||||
|
@ -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"
|
||||
|
@ -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/
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
763
sound/soc/codecs/cs42l51.c
Normal 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
163
sound/soc/codecs/cs42l51.h
Normal 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
|
@ -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
511
sound/soc/codecs/jz4740.c
Normal 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
20
sound/soc/codecs/jz4740.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user