Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
02e5fbf6
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 大约 4 年
通知
14
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
02e5fbf6
编写于
5月 22, 2011
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/misc' into for-linus
上级
b759b3ac
bfe9fc8a
变更
48
展开全部
隐藏空白更改
内联
并排
Showing
48 changed file
with
1722 addition
and
1297 deletion
+1722
-1297
MAINTAINERS
MAINTAINERS
+7
-0
drivers/media/radio/Kconfig
drivers/media/radio/Kconfig
+0
-15
drivers/media/radio/Makefile
drivers/media/radio/Makefile
+0
-1
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maestro.c
+0
-452
include/sound/control.h
include/sound/control.h
+1
-0
include/sound/tea575x-tuner.h
include/sound/tea575x-tuner.h
+17
-9
sound/core/control.c
sound/core/control.c
+64
-0
sound/core/init.c
sound/core/init.c
+1
-1
sound/core/pcm_lib.c
sound/core/pcm_lib.c
+9
-5
sound/firewire/Kconfig
sound/firewire/Kconfig
+11
-0
sound/firewire/Makefile
sound/firewire/Makefile
+2
-0
sound/firewire/isight.c
sound/firewire/isight.c
+755
-0
sound/firewire/iso-resources.c
sound/firewire/iso-resources.c
+5
-0
sound/firewire/packets-buffer.c
sound/firewire/packets-buffer.c
+2
-0
sound/i2c/other/Makefile
sound/i2c/other/Makefile
+1
-1
sound/i2c/other/tea575x-tuner.c
sound/i2c/other/tea575x-tuner.c
+112
-41
sound/pci/Kconfig
sound/pci/Kconfig
+13
-5
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/asihpi.c
+142
-186
sound/pci/asihpi/hpi6000.c
sound/pci/asihpi/hpi6000.c
+15
-24
sound/pci/asihpi/hpi6205.c
sound/pci/asihpi/hpi6205.c
+48
-47
sound/pci/asihpi/hpi_internal.h
sound/pci/asihpi/hpi_internal.h
+8
-11
sound/pci/asihpi/hpicmn.c
sound/pci/asihpi/hpicmn.c
+7
-3
sound/pci/asihpi/hpicmn.h
sound/pci/asihpi/hpicmn.h
+2
-0
sound/pci/asihpi/hpifunc.c
sound/pci/asihpi/hpifunc.c
+0
-27
sound/pci/asihpi/hpimsgx.c
sound/pci/asihpi/hpimsgx.c
+13
-18
sound/pci/asihpi/hpioctl.c
sound/pci/asihpi/hpioctl.c
+31
-32
sound/pci/au88x0/au8810.h
sound/pci/au88x0/au8810.h
+1
-1
sound/pci/au88x0/au8820.h
sound/pci/au88x0/au8820.h
+1
-1
sound/pci/au88x0/au8830.h
sound/pci/au88x0/au8830.h
+1
-1
sound/pci/au88x0/au88x0_pcm.c
sound/pci/au88x0/au88x0_pcm.c
+7
-6
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emufx.c
+5
-0
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emumixer.c
+8
-2
sound/pci/es1968.c
sound/pci/es1968.c
+78
-0
sound/pci/fm801.c
sound/pci/fm801.c
+79
-292
sound/pci/intel8x0m.c
sound/pci/intel8x0m.c
+2
-2
sound/ppc/tumbler.c
sound/ppc/tumbler.c
+1
-1
sound/usb/6fire/control.c
sound/usb/6fire/control.c
+105
-0
sound/usb/6fire/control.h
sound/usb/6fire/control.h
+17
-0
sound/usb/6fire/firmware.c
sound/usb/6fire/firmware.c
+33
-40
sound/usb/6fire/pcm.c
sound/usb/6fire/pcm.c
+38
-59
sound/usb/Kconfig
sound/usb/Kconfig
+4
-6
sound/usb/clock.c
sound/usb/clock.c
+10
-1
sound/usb/debug.h
sound/usb/debug.h
+1
-1
sound/usb/format.c
sound/usb/format.c
+1
-0
sound/usb/mixer.c
sound/usb/mixer.c
+6
-4
sound/usb/mixer_quirks.c
sound/usb/mixer_quirks.c
+12
-0
sound/usb/quirks-table.h
sound/usb/quirks-table.h
+45
-2
sound/usb/quirks.c
sound/usb/quirks.c
+1
-0
未找到文件。
MAINTAINERS
浏览文件 @
02e5fbf6
...
@@ -4264,6 +4264,13 @@ M: Tim Hockin <thockin@hockin.org>
...
@@ -4264,6 +4264,13 @@ M: Tim Hockin <thockin@hockin.org>
S: Maintained
S: Maintained
F: drivers/net/natsemi.c
F: drivers/net/natsemi.c
NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
M: Daniel Mack <zonque@gmail.com>
S: Maintained
L: alsa-devel@alsa-project.org
W: http://www.native-instruments.com
F: sound/usb/caiaq/
NCP FILESYSTEM
NCP FILESYSTEM
M: Petr Vandrovec <petr@vandrovec.name>
M: Petr Vandrovec <petr@vandrovec.name>
S: Odd Fixes
S: Odd Fixes
...
...
drivers/media/radio/Kconfig
浏览文件 @
02e5fbf6
...
@@ -166,21 +166,6 @@ config RADIO_MAXIRADIO
...
@@ -166,21 +166,6 @@ config RADIO_MAXIRADIO
To compile this driver as a module, choose M here: the
To compile this driver as a module, choose M here: the
module will be called radio-maxiradio.
module will be called radio-maxiradio.
config RADIO_MAESTRO
tristate "Maestro on board radio"
depends on VIDEO_V4L2 && PCI
---help---
Say Y here to directly support the on-board radio tuner on the
Maestro 2 or 2E sound card.
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
this API and pointers to "v4l" programs may be found at
<file:Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called radio-maestro.
config RADIO_MIROPCM20
config RADIO_MIROPCM20
tristate "miroSOUND PCM20 radio"
tristate "miroSOUND PCM20 radio"
depends on ISA && VIDEO_V4L2 && SND
depends on ISA && VIDEO_V4L2 && SND
...
...
drivers/media/radio/Makefile
浏览文件 @
02e5fbf6
...
@@ -16,7 +16,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
...
@@ -16,7 +16,6 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
obj-$(CONFIG_RADIO_TRUST)
+=
radio-trust.o
obj-$(CONFIG_RADIO_TRUST)
+=
radio-trust.o
obj-$(CONFIG_I2C_SI4713)
+=
si4713-i2c.o
obj-$(CONFIG_I2C_SI4713)
+=
si4713-i2c.o
obj-$(CONFIG_RADIO_SI4713)
+=
radio-si4713.o
obj-$(CONFIG_RADIO_SI4713)
+=
radio-si4713.o
obj-$(CONFIG_RADIO_MAESTRO)
+=
radio-maestro.o
obj-$(CONFIG_RADIO_MIROPCM20)
+=
radio-miropcm20.o
obj-$(CONFIG_RADIO_MIROPCM20)
+=
radio-miropcm20.o
obj-$(CONFIG_USB_DSBR)
+=
dsbr100.o
obj-$(CONFIG_USB_DSBR)
+=
dsbr100.o
obj-$(CONFIG_RADIO_SI470X)
+=
si470x/
obj-$(CONFIG_RADIO_SI470X)
+=
si470x/
...
...
drivers/media/radio/radio-maestro.c
已删除
100644 → 0
浏览文件 @
b759b3ac
/* Maestro PCI sound card radio driver for Linux support
* (c) 2000 A. Tlalka, atlka@pg.gda.pl
* Notes on the hardware
*
* + Frequency control is done digitally
* + No volume control - only mute/unmute - you have to use Aux line volume
* control on Maestro card to set the volume
* + Radio status (tuned/not_tuned and stereo/mono) is valid some time after
* frequency setting (>100ms) and only when the radio is unmuted.
* version 0.02
* + io port is automatically detected - only the first radio is used
* version 0.03
* + thread access locking additions
* version 0.04
* + code improvements
* + VIDEO_TUNER_LOW is permanent
*
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/version.h>
/* for KERNEL_VERSION MACRO */
#include <linux/pci.h>
#include <linux/videodev2.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
MODULE_AUTHOR
(
"Adam Tlalka, atlka@pg.gda.pl"
);
MODULE_DESCRIPTION
(
"Radio driver for the Maestro PCI sound card radio."
);
MODULE_LICENSE
(
"GPL"
);
static
int
radio_nr
=
-
1
;
module_param
(
radio_nr
,
int
,
0
);
#define RADIO_VERSION KERNEL_VERSION(0, 0, 6)
#define DRIVER_VERSION "0.06"
#define GPIO_DATA 0x60
/* port offset from ESS_IO_BASE */
#define IO_MASK 4
/* mask register offset from GPIO_DATA
bits 1=unmask write to given bit */
#define IO_DIR 8
/* direction register offset from GPIO_DATA
bits 0/1=read/write direction */
#define GPIO6 0x0040
/* mask bits for GPIO lines */
#define GPIO7 0x0080
#define GPIO8 0x0100
#define GPIO9 0x0200
#define STR_DATA GPIO6
/* radio TEA5757 pins and GPIO bits */
#define STR_CLK GPIO7
#define STR_WREN GPIO8
#define STR_MOST GPIO9
#define FREQ_LO 50*16000
#define FREQ_HI 150*16000
#define FREQ_IF 171200
/* 10.7*16000 */
#define FREQ_STEP 200
/* 12.5*16 */
#define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
/(FREQ_STEP<<2))<<2)
/* (x==fmhz*16*1000) -> bits */
#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
struct
maestro
{
struct
v4l2_device
v4l2_dev
;
struct
video_device
vdev
;
struct
pci_dev
*
pdev
;
struct
mutex
lock
;
u16
io
;
/* base of Maestro card radio io (GPIO_DATA)*/
u16
muted
;
/* VIDEO_AUDIO_MUTE */
u16
stereo
;
/* VIDEO_TUNER_STEREO_ON */
u16
tuned
;
/* signal strength (0 or 0xffff) */
};
static
inline
struct
maestro
*
to_maestro
(
struct
v4l2_device
*
v4l2_dev
)
{
return
container_of
(
v4l2_dev
,
struct
maestro
,
v4l2_dev
);
}
static
u32
radio_bits_get
(
struct
maestro
*
dev
)
{
u16
io
=
dev
->
io
,
l
,
rdata
;
u32
data
=
0
;
u16
omask
;
omask
=
inw
(
io
+
IO_MASK
);
outw
(
~
(
STR_CLK
|
STR_WREN
),
io
+
IO_MASK
);
outw
(
0
,
io
);
udelay
(
16
);
for
(
l
=
24
;
l
--
;)
{
outw
(
STR_CLK
,
io
);
/* HI state */
udelay
(
2
);
if
(
!
l
)
dev
->
tuned
=
inw
(
io
)
&
STR_MOST
?
0
:
0xffff
;
outw
(
0
,
io
);
/* LO state */
udelay
(
2
);
data
<<=
1
;
/* shift data */
rdata
=
inw
(
io
);
if
(
!
l
)
dev
->
stereo
=
(
rdata
&
STR_MOST
)
?
0
:
1
;
else
if
(
rdata
&
STR_DATA
)
data
++
;
udelay
(
2
);
}
if
(
dev
->
muted
)
outw
(
STR_WREN
,
io
);
udelay
(
4
);
outw
(
omask
,
io
+
IO_MASK
);
return
data
&
0x3ffe
;
}
static
void
radio_bits_set
(
struct
maestro
*
dev
,
u32
data
)
{
u16
io
=
dev
->
io
,
l
,
bits
;
u16
omask
,
odir
;
omask
=
inw
(
io
+
IO_MASK
);
odir
=
(
inw
(
io
+
IO_DIR
)
&
~
STR_DATA
)
|
(
STR_CLK
|
STR_WREN
);
outw
(
odir
|
STR_DATA
,
io
+
IO_DIR
);
outw
(
~
(
STR_DATA
|
STR_CLK
|
STR_WREN
),
io
+
IO_MASK
);
udelay
(
16
);
for
(
l
=
25
;
l
;
l
--
)
{
bits
=
((
data
>>
18
)
&
STR_DATA
)
|
STR_WREN
;
data
<<=
1
;
/* shift data */
outw
(
bits
,
io
);
/* start strobe */
udelay
(
2
);
outw
(
bits
|
STR_CLK
,
io
);
/* HI level */
udelay
(
2
);
outw
(
bits
,
io
);
/* LO level */
udelay
(
4
);
}
if
(
!
dev
->
muted
)
outw
(
0
,
io
);
udelay
(
4
);
outw
(
omask
,
io
+
IO_MASK
);
outw
(
odir
,
io
+
IO_DIR
);
msleep
(
125
);
}
static
int
vidioc_querycap
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_capability
*
v
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
strlcpy
(
v
->
driver
,
"radio-maestro"
,
sizeof
(
v
->
driver
));
strlcpy
(
v
->
card
,
"Maestro Radio"
,
sizeof
(
v
->
card
));
snprintf
(
v
->
bus_info
,
sizeof
(
v
->
bus_info
),
"PCI:%s"
,
pci_name
(
dev
->
pdev
));
v
->
version
=
RADIO_VERSION
;
v
->
capabilities
=
V4L2_CAP_TUNER
|
V4L2_CAP_RADIO
;
return
0
;
}
static
int
vidioc_g_tuner
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_tuner
*
v
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
if
(
v
->
index
>
0
)
return
-
EINVAL
;
mutex_lock
(
&
dev
->
lock
);
radio_bits_get
(
dev
);
strlcpy
(
v
->
name
,
"FM"
,
sizeof
(
v
->
name
));
v
->
type
=
V4L2_TUNER_RADIO
;
v
->
rangelow
=
FREQ_LO
;
v
->
rangehigh
=
FREQ_HI
;
v
->
rxsubchans
=
V4L2_TUNER_SUB_MONO
|
V4L2_TUNER_SUB_STEREO
;
v
->
capability
=
V4L2_TUNER_CAP_LOW
;
if
(
dev
->
stereo
)
v
->
audmode
=
V4L2_TUNER_MODE_STEREO
;
else
v
->
audmode
=
V4L2_TUNER_MODE_MONO
;
v
->
signal
=
dev
->
tuned
;
mutex_unlock
(
&
dev
->
lock
);
return
0
;
}
static
int
vidioc_s_tuner
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_tuner
*
v
)
{
return
v
->
index
?
-
EINVAL
:
0
;
}
static
int
vidioc_s_frequency
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_frequency
*
f
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
||
f
->
type
!=
V4L2_TUNER_RADIO
)
return
-
EINVAL
;
if
(
f
->
frequency
<
FREQ_LO
||
f
->
frequency
>
FREQ_HI
)
return
-
EINVAL
;
mutex_lock
(
&
dev
->
lock
);
radio_bits_set
(
dev
,
FREQ2BITS
(
f
->
frequency
));
mutex_unlock
(
&
dev
->
lock
);
return
0
;
}
static
int
vidioc_g_frequency
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_frequency
*
f
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
)
return
-
EINVAL
;
f
->
type
=
V4L2_TUNER_RADIO
;
mutex_lock
(
&
dev
->
lock
);
f
->
frequency
=
BITS2FREQ
(
radio_bits_get
(
dev
));
mutex_unlock
(
&
dev
->
lock
);
return
0
;
}
static
int
vidioc_queryctrl
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_queryctrl
*
qc
)
{
switch
(
qc
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
return
v4l2_ctrl_query_fill
(
qc
,
0
,
1
,
1
,
1
);
}
return
-
EINVAL
;
}
static
int
vidioc_g_ctrl
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_control
*
ctrl
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
ctrl
->
value
=
dev
->
muted
;
return
0
;
}
return
-
EINVAL
;
}
static
int
vidioc_s_ctrl
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_control
*
ctrl
)
{
struct
maestro
*
dev
=
video_drvdata
(
file
);
u16
io
=
dev
->
io
;
u16
omask
;
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
mutex_lock
(
&
dev
->
lock
);
omask
=
inw
(
io
+
IO_MASK
);
outw
(
~
STR_WREN
,
io
+
IO_MASK
);
dev
->
muted
=
ctrl
->
value
;
outw
(
dev
->
muted
?
STR_WREN
:
0
,
io
);
udelay
(
4
);
outw
(
omask
,
io
+
IO_MASK
);
msleep
(
125
);
mutex_unlock
(
&
dev
->
lock
);
return
0
;
}
return
-
EINVAL
;
}
static
int
vidioc_g_input
(
struct
file
*
filp
,
void
*
priv
,
unsigned
int
*
i
)
{
*
i
=
0
;
return
0
;
}
static
int
vidioc_s_input
(
struct
file
*
filp
,
void
*
priv
,
unsigned
int
i
)
{
return
i
?
-
EINVAL
:
0
;
}
static
int
vidioc_g_audio
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_audio
*
a
)
{
a
->
index
=
0
;
strlcpy
(
a
->
name
,
"Radio"
,
sizeof
(
a
->
name
));
a
->
capability
=
V4L2_AUDCAP_STEREO
;
return
0
;
}
static
int
vidioc_s_audio
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_audio
*
a
)
{
return
a
->
index
?
-
EINVAL
:
0
;
}
static
const
struct
v4l2_file_operations
maestro_fops
=
{
.
owner
=
THIS_MODULE
,
.
unlocked_ioctl
=
video_ioctl2
,
};
static
const
struct
v4l2_ioctl_ops
maestro_ioctl_ops
=
{
.
vidioc_querycap
=
vidioc_querycap
,
.
vidioc_g_tuner
=
vidioc_g_tuner
,
.
vidioc_s_tuner
=
vidioc_s_tuner
,
.
vidioc_g_audio
=
vidioc_g_audio
,
.
vidioc_s_audio
=
vidioc_s_audio
,
.
vidioc_g_input
=
vidioc_g_input
,
.
vidioc_s_input
=
vidioc_s_input
,
.
vidioc_g_frequency
=
vidioc_g_frequency
,
.
vidioc_s_frequency
=
vidioc_s_frequency
,
.
vidioc_queryctrl
=
vidioc_queryctrl
,
.
vidioc_g_ctrl
=
vidioc_g_ctrl
,
.
vidioc_s_ctrl
=
vidioc_s_ctrl
,
};
static
u16
__devinit
radio_power_on
(
struct
maestro
*
dev
)
{
register
u16
io
=
dev
->
io
;
register
u32
ofreq
;
u16
omask
,
odir
;
omask
=
inw
(
io
+
IO_MASK
);
odir
=
(
inw
(
io
+
IO_DIR
)
&
~
STR_DATA
)
|
(
STR_CLK
|
STR_WREN
);
outw
(
odir
&
~
STR_WREN
,
io
+
IO_DIR
);
dev
->
muted
=
inw
(
io
)
&
STR_WREN
?
0
:
1
;
outw
(
odir
,
io
+
IO_DIR
);
outw
(
~
(
STR_WREN
|
STR_CLK
),
io
+
IO_MASK
);
outw
(
dev
->
muted
?
0
:
STR_WREN
,
io
);
udelay
(
16
);
outw
(
omask
,
io
+
IO_MASK
);
ofreq
=
radio_bits_get
(
dev
);
if
((
ofreq
<
FREQ2BITS
(
FREQ_LO
))
||
(
ofreq
>
FREQ2BITS
(
FREQ_HI
)))
ofreq
=
FREQ2BITS
(
FREQ_LO
);
radio_bits_set
(
dev
,
ofreq
);
return
(
ofreq
==
radio_bits_get
(
dev
));
}
static
int
__devinit
maestro_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
maestro
*
dev
;
struct
v4l2_device
*
v4l2_dev
;
int
retval
;
retval
=
pci_enable_device
(
pdev
);
if
(
retval
)
{
dev_err
(
&
pdev
->
dev
,
"enabling pci device failed!
\n
"
);
goto
err
;
}
retval
=
-
ENOMEM
;
dev
=
kzalloc
(
sizeof
(
*
dev
),
GFP_KERNEL
);
if
(
dev
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"not enough memory
\n
"
);
goto
err
;
}
v4l2_dev
=
&
dev
->
v4l2_dev
;
mutex_init
(
&
dev
->
lock
);
dev
->
pdev
=
pdev
;
strlcpy
(
v4l2_dev
->
name
,
"maestro"
,
sizeof
(
v4l2_dev
->
name
));
retval
=
v4l2_device_register
(
&
pdev
->
dev
,
v4l2_dev
);
if
(
retval
<
0
)
{
v4l2_err
(
v4l2_dev
,
"Could not register v4l2_device
\n
"
);
goto
errfr
;
}
dev
->
io
=
pci_resource_start
(
pdev
,
0
)
+
GPIO_DATA
;
strlcpy
(
dev
->
vdev
.
name
,
v4l2_dev
->
name
,
sizeof
(
dev
->
vdev
.
name
));
dev
->
vdev
.
v4l2_dev
=
v4l2_dev
;
dev
->
vdev
.
fops
=
&
maestro_fops
;
dev
->
vdev
.
ioctl_ops
=
&
maestro_ioctl_ops
;
dev
->
vdev
.
release
=
video_device_release_empty
;
video_set_drvdata
(
&
dev
->
vdev
,
dev
);
if
(
!
radio_power_on
(
dev
))
{
retval
=
-
EIO
;
goto
errfr1
;
}
retval
=
video_register_device
(
&
dev
->
vdev
,
VFL_TYPE_RADIO
,
radio_nr
);
if
(
retval
)
{
v4l2_err
(
v4l2_dev
,
"can't register video device!
\n
"
);
goto
errfr1
;
}
v4l2_info
(
v4l2_dev
,
"version "
DRIVER_VERSION
"
\n
"
);
return
0
;
errfr1:
v4l2_device_unregister
(
v4l2_dev
);
errfr:
kfree
(
dev
);
err:
return
retval
;
}
static
void
__devexit
maestro_remove
(
struct
pci_dev
*
pdev
)
{
struct
v4l2_device
*
v4l2_dev
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
maestro
*
dev
=
to_maestro
(
v4l2_dev
);
video_unregister_device
(
&
dev
->
vdev
);
v4l2_device_unregister
(
&
dev
->
v4l2_dev
);
}
static
struct
pci_device_id
maestro_r_pci_tbl
[]
=
{
{
PCI_DEVICE
(
PCI_VENDOR_ID_ESS
,
PCI_DEVICE_ID_ESS_ESS1968
),
.
class
=
PCI_CLASS_MULTIMEDIA_AUDIO
<<
8
,
.
class_mask
=
0xffff00
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_ESS
,
PCI_DEVICE_ID_ESS_ESS1978
),
.
class
=
PCI_CLASS_MULTIMEDIA_AUDIO
<<
8
,
.
class_mask
=
0xffff00
},
{
0
}
};
MODULE_DEVICE_TABLE
(
pci
,
maestro_r_pci_tbl
);
static
struct
pci_driver
maestro_r_driver
=
{
.
name
=
"maestro_radio"
,
.
id_table
=
maestro_r_pci_tbl
,
.
probe
=
maestro_probe
,
.
remove
=
__devexit_p
(
maestro_remove
),
};
static
int
__init
maestro_radio_init
(
void
)
{
int
retval
=
pci_register_driver
(
&
maestro_r_driver
);
if
(
retval
)
printk
(
KERN_ERR
"error during registration pci driver
\n
"
);
return
retval
;
}
static
void
__exit
maestro_radio_exit
(
void
)
{
pci_unregister_driver
(
&
maestro_r_driver
);
}
module_init
(
maestro_radio_init
);
module_exit
(
maestro_radio_exit
);
include/sound/control.h
浏览文件 @
02e5fbf6
...
@@ -113,6 +113,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, v
...
@@ -113,6 +113,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, v
void
snd_ctl_free_one
(
struct
snd_kcontrol
*
kcontrol
);
void
snd_ctl_free_one
(
struct
snd_kcontrol
*
kcontrol
);
int
snd_ctl_add
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
);
int
snd_ctl_add
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
);
int
snd_ctl_remove
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
);
int
snd_ctl_remove
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
);
int
snd_ctl_replace
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
,
bool
add_on_replace
);
int
snd_ctl_remove_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
id
);
int
snd_ctl_remove_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
id
);
int
snd_ctl_rename_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
src_id
,
struct
snd_ctl_elem_id
*
dst_id
);
int
snd_ctl_rename_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
src_id
,
struct
snd_ctl_elem_id
*
dst_id
);
int
snd_ctl_activate_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
id
,
int
snd_ctl_activate_id
(
struct
snd_card
*
card
,
struct
snd_ctl_elem_id
*
id
,
...
...
include/sound/tea575x-tuner.h
浏览文件 @
02e5fbf6
...
@@ -26,29 +26,37 @@
...
@@ -26,29 +26,37 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ioctl.h>
#define TEA575X_FMIF 10700
#define TEA575X_DATA (1 << 0)
#define TEA575X_CLK (1 << 1)
#define TEA575X_WREN (1 << 2)
#define TEA575X_MOST (1 << 3)
struct
snd_tea575x
;
struct
snd_tea575x
;
struct
snd_tea575x_ops
{
struct
snd_tea575x_ops
{
void
(
*
write
)(
struct
snd_tea575x
*
tea
,
unsigned
int
val
);
void
(
*
set_pins
)(
struct
snd_tea575x
*
tea
,
u8
pins
);
u
nsigned
int
(
*
read
)(
struct
snd_tea575x
*
tea
);
u
8
(
*
get_pins
)(
struct
snd_tea575x
*
tea
);
void
(
*
mute
)(
struct
snd_tea575x
*
tea
,
unsigned
int
mute
);
void
(
*
set_direction
)(
struct
snd_tea575x
*
tea
,
bool
output
);
};
};
struct
snd_tea575x
{
struct
snd_tea575x
{
struct
snd_card
*
card
;
struct
video_device
*
vd
;
/* video device */
struct
video_device
*
vd
;
/* video device */
int
dev_nr
;
/* requested device number + 1
*/
bool
tea5759
;
/* 5759 chip is present
*/
int
tea5759
;
/* 5759 chip is present
*/
bool
mute
;
/* Device is muted?
*/
int
mute
;
/* Device is muted?
*/
bool
stereo
;
/* receiving stereo
*/
unsigned
int
freq_fixup
;
/* crystal onboard
*/
bool
tuned
;
/* tuned to a station
*/
unsigned
int
val
;
/* hw value */
unsigned
int
val
;
/* hw value */
unsigned
long
freq
;
/* frequency */
unsigned
long
freq
;
/* frequency */
unsigned
long
in_use
;
/* set if the device is in use */
unsigned
long
in_use
;
/* set if the device is in use */
struct
snd_tea575x_ops
*
ops
;
struct
snd_tea575x_ops
*
ops
;
void
*
private_data
;
void
*
private_data
;
u8
card
[
32
];
u8
bus_info
[
32
];
};
};
void
snd_tea575x_init
(
struct
snd_tea575x
*
tea
);
int
snd_tea575x_init
(
struct
snd_tea575x
*
tea
);
void
snd_tea575x_exit
(
struct
snd_tea575x
*
tea
);
void
snd_tea575x_exit
(
struct
snd_tea575x
*
tea
);
#endif
/* __SOUND_TEA575X_TUNER_H */
#endif
/* __SOUND_TEA575X_TUNER_H */
sound/core/control.c
浏览文件 @
02e5fbf6
...
@@ -365,6 +365,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
...
@@ -365,6 +365,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
EXPORT_SYMBOL
(
snd_ctl_add
);
EXPORT_SYMBOL
(
snd_ctl_add
);
/**
* snd_ctl_replace - replace the control instance of the card
* @card: the card instance
* @kcontrol: the control instance to replace
* @add_on_replace: add the control if not already added
*
* Replaces the given control. If the given control does not exist
* and the add_on_replace flag is set, the control is added. If the
* control exists, it is destroyed first.
*
* Returns zero if successful, or a negative error code on failure.
*
* It frees automatically the control which cannot be added or replaced.
*/
int
snd_ctl_replace
(
struct
snd_card
*
card
,
struct
snd_kcontrol
*
kcontrol
,
bool
add_on_replace
)
{
struct
snd_ctl_elem_id
id
;
unsigned
int
idx
;
struct
snd_kcontrol
*
old
;
int
ret
;
if
(
!
kcontrol
)
return
-
EINVAL
;
if
(
snd_BUG_ON
(
!
card
||
!
kcontrol
->
info
))
{
ret
=
-
EINVAL
;
goto
error
;
}
id
=
kcontrol
->
id
;
down_write
(
&
card
->
controls_rwsem
);
old
=
snd_ctl_find_id
(
card
,
&
id
);
if
(
!
old
)
{
if
(
add_on_replace
)
goto
add
;
up_write
(
&
card
->
controls_rwsem
);
ret
=
-
EINVAL
;
goto
error
;
}
ret
=
snd_ctl_remove
(
card
,
old
);
if
(
ret
<
0
)
{
up_write
(
&
card
->
controls_rwsem
);
goto
error
;
}
add:
if
(
snd_ctl_find_hole
(
card
,
kcontrol
->
count
)
<
0
)
{
up_write
(
&
card
->
controls_rwsem
);
ret
=
-
ENOMEM
;
goto
error
;
}
list_add_tail
(
&
kcontrol
->
list
,
&
card
->
controls
);
card
->
controls_count
+=
kcontrol
->
count
;
kcontrol
->
id
.
numid
=
card
->
last_numid
+
1
;
card
->
last_numid
+=
kcontrol
->
count
;
up_write
(
&
card
->
controls_rwsem
);
for
(
idx
=
0
;
idx
<
kcontrol
->
count
;
idx
++
,
id
.
index
++
,
id
.
numid
++
)
snd_ctl_notify
(
card
,
SNDRV_CTL_EVENT_MASK_ADD
,
&
id
);
return
0
;
error:
snd_ctl_free_one
(
kcontrol
);
return
ret
;
}
EXPORT_SYMBOL
(
snd_ctl_replace
);
/**
/**
* snd_ctl_remove - remove the control from the card and release it
* snd_ctl_remove - remove the control from the card and release it
* @card: the card instance
* @card: the card instance
...
...
sound/core/init.c
浏览文件 @
02e5fbf6
...
@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
...
@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
id
=
card
->
id
;
id
=
card
->
id
;
if
(
*
id
==
'\0'
)
if
(
*
id
==
'\0'
)
strcpy
(
id
,
"
d
efault"
);
strcpy
(
id
,
"
D
efault"
);
while
(
1
)
{
while
(
1
)
{
if
(
loops
--
==
0
)
{
if
(
loops
--
==
0
)
{
...
...
sound/core/pcm_lib.c
浏览文件 @
02e5fbf6
...
@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream)
...
@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream)
#define XRUN_LOG_CNT 10
#define XRUN_LOG_CNT 10
struct
hwptr_log_entry
{
struct
hwptr_log_entry
{
unsigned
int
in_interrupt
;
unsigned
long
jiffies
;
unsigned
long
jiffies
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
pos
;
snd_pcm_uframes_t
period_size
;
snd_pcm_uframes_t
period_size
;
...
@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log {
...
@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log {
};
};
static
void
xrun_log
(
struct
snd_pcm_substream
*
substream
,
static
void
xrun_log
(
struct
snd_pcm_substream
*
substream
,
snd_pcm_uframes_t
pos
)
snd_pcm_uframes_t
pos
,
int
in_interrupt
)
{
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_pcm_hwptr_log
*
log
=
runtime
->
hwptr_log
;
struct
snd_pcm_hwptr_log
*
log
=
runtime
->
hwptr_log
;
...
@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream,
...
@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream,
return
;
return
;
}
}
entry
=
&
log
->
entries
[
log
->
idx
];
entry
=
&
log
->
entries
[
log
->
idx
];
entry
->
in_interrupt
=
in_interrupt
;
entry
->
jiffies
=
jiffies
;
entry
->
jiffies
=
jiffies
;
entry
->
pos
=
pos
;
entry
->
pos
=
pos
;
entry
->
period_size
=
runtime
->
period_size
;
entry
->
period_size
=
runtime
->
period_size
;
...
@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
...
@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
entry
=
&
log
->
entries
[
idx
];
entry
=
&
log
->
entries
[
idx
];
if
(
entry
->
period_size
==
0
)
if
(
entry
->
period_size
==
0
)
break
;
break
;
snd_printd
(
"hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
snd_printd
(
"hwptr log: %s:
%s
j=%lu, pos=%ld/%ld/%ld, "
"hwptr=%ld/%ld
\n
"
,
"hwptr=%ld/%ld
\n
"
,
name
,
entry
->
jiffies
,
(
unsigned
long
)
entry
->
pos
,
name
,
entry
->
in_interrupt
?
"[Q] "
:
""
,
entry
->
jiffies
,
(
unsigned
long
)
entry
->
pos
,
(
unsigned
long
)
entry
->
period_size
,
(
unsigned
long
)
entry
->
period_size
,
(
unsigned
long
)
entry
->
buffer_size
,
(
unsigned
long
)
entry
->
buffer_size
,
(
unsigned
long
)
entry
->
old_hw_ptr
,
(
unsigned
long
)
entry
->
old_hw_ptr
,
...
@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
...
@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream)
#else
/* ! CONFIG_SND_PCM_XRUN_DEBUG */
#else
/* ! CONFIG_SND_PCM_XRUN_DEBUG */
#define hw_ptr_error(substream, fmt, args...) do { } while (0)
#define hw_ptr_error(substream, fmt, args...) do { } while (0)
#define xrun_log(substream, pos) do { } while (0)
#define xrun_log(substream, pos
, in_interrupt
) do { } while (0)
#define xrun_log_show(substream) do { } while (0)
#define xrun_log_show(substream) do { } while (0)
#endif
#endif
...
@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
...
@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
}
pos
-=
pos
%
runtime
->
min_align
;
pos
-=
pos
%
runtime
->
min_align
;
if
(
xrun_debug
(
substream
,
XRUN_DEBUG_LOG
))
if
(
xrun_debug
(
substream
,
XRUN_DEBUG_LOG
))
xrun_log
(
substream
,
pos
);
xrun_log
(
substream
,
pos
,
in_interrupt
);
hw_base
=
runtime
->
hw_ptr_base
;
hw_base
=
runtime
->
hw_ptr_base
;
new_hw_ptr
=
hw_base
+
pos
;
new_hw_ptr
=
hw_base
+
pos
;
if
(
in_interrupt
)
{
if
(
in_interrupt
)
{
...
...
sound/firewire/Kconfig
浏览文件 @
02e5fbf6
...
@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS
...
@@ -22,4 +22,15 @@ config SND_FIREWIRE_SPEAKERS
To compile this driver as a module, choose M here: the module
To compile this driver as a module, choose M here: the module
will be called snd-firewire-speakers.
will be called snd-firewire-speakers.
config SND_ISIGHT
tristate "Apple iSight microphone"
select SND_PCM
select SND_FIREWIRE_LIB
help
Say Y here to include support for the front and rear microphones
of the Apple iSight web camera.
To compile this driver as a module, choose M here: the module
will be called snd-isight.
endif # SND_FIREWIRE
endif # SND_FIREWIRE
sound/firewire/Makefile
浏览文件 @
02e5fbf6
snd-firewire-lib-objs
:=
lib.o iso-resources.o packets-buffer.o
\
snd-firewire-lib-objs
:=
lib.o iso-resources.o packets-buffer.o
\
fcp.o cmp.o amdtp.o
fcp.o cmp.o amdtp.o
snd-firewire-speakers-objs
:=
speakers.o
snd-firewire-speakers-objs
:=
speakers.o
snd-isight-objs
:=
isight.o
obj-$(CONFIG_SND_FIREWIRE_LIB)
+=
snd-firewire-lib.o
obj-$(CONFIG_SND_FIREWIRE_LIB)
+=
snd-firewire-lib.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS)
+=
snd-firewire-speakers.o
obj-$(CONFIG_SND_FIREWIRE_SPEAKERS)
+=
snd-firewire-speakers.o
obj-$(CONFIG_SND_ISIGHT)
+=
snd-isight.o
sound/firewire/isight.c
0 → 100644
浏览文件 @
02e5fbf6
/*
* Apple iSight audio driver
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
* Licensed under the terms of the GNU General Public License, version 2.
*/
#include <asm/byteorder.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/string.h>
#include <sound/control.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/tlv.h>
#include "lib.h"
#include "iso-resources.h"
#include "packets-buffer.h"
#define OUI_APPLE 0x000a27
#define MODEL_APPLE_ISIGHT 0x000008
#define SW_ISIGHT_AUDIO 0x000010
#define REG_AUDIO_ENABLE 0x000
#define AUDIO_ENABLE 0x80000000
#define REG_DEF_AUDIO_GAIN 0x204
#define REG_GAIN_RAW_START 0x210
#define REG_GAIN_RAW_END 0x214
#define REG_GAIN_DB_START 0x218
#define REG_GAIN_DB_END 0x21c
#define REG_SAMPLE_RATE_INQUIRY 0x280
#define REG_ISO_TX_CONFIG 0x300
#define SPEED_SHIFT 16
#define REG_SAMPLE_RATE 0x400
#define RATE_48000 0x80000000
#define REG_GAIN 0x500
#define REG_MUTE 0x504
#define MAX_FRAMES_PER_PACKET 475
#define QUEUE_LENGTH 20
struct
isight
{
struct
snd_card
*
card
;
struct
fw_unit
*
unit
;
struct
fw_device
*
device
;
u64
audio_base
;
struct
fw_address_handler
iris_handler
;
struct
snd_pcm_substream
*
pcm
;
struct
mutex
mutex
;
struct
iso_packets_buffer
buffer
;
struct
fw_iso_resources
resources
;
struct
fw_iso_context
*
context
;
bool
pcm_active
;
bool
pcm_running
;
bool
first_packet
;
int
packet_index
;
u32
total_samples
;
unsigned
int
buffer_pointer
;
unsigned
int
period_counter
;
s32
gain_min
,
gain_max
;
unsigned
int
gain_tlv
[
4
];
};
struct
audio_payload
{
__be32
sample_count
;
__be32
signature
;
__be32
sample_total
;
__be32
reserved
;
__be16
samples
[
2
*
MAX_FRAMES_PER_PACKET
];
};
MODULE_DESCRIPTION
(
"iSight audio driver"
);
MODULE_AUTHOR
(
"Clemens Ladisch <clemens@ladisch.de>"
);
MODULE_LICENSE
(
"GPL v2"
);
static
struct
fw_iso_packet
audio_packet
=
{
.
payload_length
=
sizeof
(
struct
audio_payload
),
.
interrupt
=
1
,
.
header_length
=
4
,
};
static
void
isight_update_pointers
(
struct
isight
*
isight
,
unsigned
int
count
)
{
struct
snd_pcm_runtime
*
runtime
=
isight
->
pcm
->
runtime
;
unsigned
int
ptr
;
smp_wmb
();
/* update buffer data before buffer pointer */
ptr
=
isight
->
buffer_pointer
;
ptr
+=
count
;
if
(
ptr
>=
runtime
->
buffer_size
)
ptr
-=
runtime
->
buffer_size
;
ACCESS_ONCE
(
isight
->
buffer_pointer
)
=
ptr
;
isight
->
period_counter
+=
count
;
if
(
isight
->
period_counter
>=
runtime
->
period_size
)
{
isight
->
period_counter
-=
runtime
->
period_size
;
snd_pcm_period_elapsed
(
isight
->
pcm
);
}
}
static
void
isight_samples
(
struct
isight
*
isight
,
const
__be16
*
samples
,
unsigned
int
count
)
{
struct
snd_pcm_runtime
*
runtime
;
unsigned
int
count1
;
if
(
!
ACCESS_ONCE
(
isight
->
pcm_running
))
return
;
runtime
=
isight
->
pcm
->
runtime
;
if
(
isight
->
buffer_pointer
+
count
<=
runtime
->
buffer_size
)
{
memcpy
(
runtime
->
dma_area
+
isight
->
buffer_pointer
*
4
,
samples
,
count
*
4
);
}
else
{
count1
=
runtime
->
buffer_size
-
isight
->
buffer_pointer
;
memcpy
(
runtime
->
dma_area
+
isight
->
buffer_pointer
*
4
,
samples
,
count1
*
4
);
samples
+=
count1
*
2
;
memcpy
(
runtime
->
dma_area
,
samples
,
(
count
-
count1
)
*
4
);
}
isight_update_pointers
(
isight
,
count
);
}
static
void
isight_pcm_abort
(
struct
isight
*
isight
)
{
unsigned
long
flags
;
if
(
ACCESS_ONCE
(
isight
->
pcm_active
))
{
snd_pcm_stream_lock_irqsave
(
isight
->
pcm
,
flags
);
if
(
snd_pcm_running
(
isight
->
pcm
))
snd_pcm_stop
(
isight
->
pcm
,
SNDRV_PCM_STATE_XRUN
);
snd_pcm_stream_unlock_irqrestore
(
isight
->
pcm
,
flags
);
}
}
static
void
isight_dropped_samples
(
struct
isight
*
isight
,
unsigned
int
total
)
{
struct
snd_pcm_runtime
*
runtime
;
u32
dropped
;
unsigned
int
count1
;
if
(
!
ACCESS_ONCE
(
isight
->
pcm_running
))
return
;
runtime
=
isight
->
pcm
->
runtime
;
dropped
=
total
-
isight
->
total_samples
;
if
(
dropped
<
runtime
->
buffer_size
)
{
if
(
isight
->
buffer_pointer
+
dropped
<=
runtime
->
buffer_size
)
{
memset
(
runtime
->
dma_area
+
isight
->
buffer_pointer
*
4
,
0
,
dropped
*
4
);
}
else
{
count1
=
runtime
->
buffer_size
-
isight
->
buffer_pointer
;
memset
(
runtime
->
dma_area
+
isight
->
buffer_pointer
*
4
,
0
,
count1
*
4
);
memset
(
runtime
->
dma_area
,
0
,
(
dropped
-
count1
)
*
4
);
}
isight_update_pointers
(
isight
,
dropped
);
}
else
{
isight_pcm_abort
(
isight
);
}
}
static
void
isight_packet
(
struct
fw_iso_context
*
context
,
u32
cycle
,
size_t
header_length
,
void
*
header
,
void
*
data
)
{
struct
isight
*
isight
=
data
;
const
struct
audio_payload
*
payload
;
unsigned
int
index
,
length
,
count
,
total
;
int
err
;
if
(
isight
->
packet_index
<
0
)
return
;
index
=
isight
->
packet_index
;
payload
=
isight
->
buffer
.
packets
[
index
].
buffer
;
length
=
be32_to_cpup
(
header
)
>>
16
;
if
(
likely
(
length
>=
16
&&
payload
->
signature
==
cpu_to_be32
(
0x73676874
/*"sght"*/
)))
{
count
=
be32_to_cpu
(
payload
->
sample_count
);
if
(
likely
(
count
<=
(
length
-
16
)
/
4
))
{
total
=
be32_to_cpu
(
payload
->
sample_total
);
if
(
unlikely
(
total
!=
isight
->
total_samples
))
{
if
(
!
isight
->
first_packet
)
isight_dropped_samples
(
isight
,
total
);
isight
->
first_packet
=
false
;
isight
->
total_samples
=
total
;
}
isight_samples
(
isight
,
payload
->
samples
,
count
);
isight
->
total_samples
+=
count
;
}
}
err
=
fw_iso_context_queue
(
isight
->
context
,
&
audio_packet
,
&
isight
->
buffer
.
iso_buffer
,
isight
->
buffer
.
packets
[
index
].
offset
);
if
(
err
<
0
)
{
dev_err
(
&
isight
->
unit
->
device
,
"queueing error: %d
\n
"
,
err
);
isight_pcm_abort
(
isight
);
isight
->
packet_index
=
-
1
;
return
;
}
if
(
++
index
>=
QUEUE_LENGTH
)
index
=
0
;
isight
->
packet_index
=
index
;
}
static
int
isight_connect
(
struct
isight
*
isight
)
{
int
ch
,
err
,
rcode
,
errors
=
0
;
__be32
value
;
retry_after_bus_reset:
ch
=
fw_iso_resources_allocate
(
&
isight
->
resources
,
sizeof
(
struct
audio_payload
),
isight
->
device
->
max_speed
);
if
(
ch
<
0
)
{
err
=
ch
;
goto
error
;
}
value
=
cpu_to_be32
(
ch
|
(
isight
->
device
->
max_speed
<<
SPEED_SHIFT
));
for
(;;)
{
rcode
=
fw_run_transaction
(
isight
->
device
->
card
,
TCODE_WRITE_QUADLET_REQUEST
,
isight
->
device
->
node_id
,
isight
->
resources
.
generation
,
isight
->
device
->
max_speed
,
isight
->
audio_base
+
REG_ISO_TX_CONFIG
,
&
value
,
4
);
if
(
rcode
==
RCODE_COMPLETE
)
{
return
0
;
}
else
if
(
rcode
==
RCODE_GENERATION
)
{
fw_iso_resources_free
(
&
isight
->
resources
);
goto
retry_after_bus_reset
;
}
else
if
(
rcode_is_permanent_error
(
rcode
)
||
++
errors
>=
3
)
{
err
=
-
EIO
;
goto
err_resources
;
}
msleep
(
5
);
}
err_resources:
fw_iso_resources_free
(
&
isight
->
resources
);
error:
return
err
;
}
static
int
isight_open
(
struct
snd_pcm_substream
*
substream
)
{
static
const
struct
snd_pcm_hardware
hardware
=
{
.
info
=
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_BATCH
|
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_BE
,
.
rates
=
SNDRV_PCM_RATE_48000
,
.
rate_min
=
48000
,
.
rate_max
=
48000
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
buffer_bytes_max
=
4
*
1024
*
1024
,
.
period_bytes_min
=
MAX_FRAMES_PER_PACKET
*
4
,
.
period_bytes_max
=
1024
*
1024
,
.
periods_min
=
2
,
.
periods_max
=
UINT_MAX
,
};
struct
isight
*
isight
=
substream
->
private_data
;
substream
->
runtime
->
hw
=
hardware
;
return
iso_packets_buffer_init
(
&
isight
->
buffer
,
isight
->
unit
,
QUEUE_LENGTH
,
sizeof
(
struct
audio_payload
),
DMA_FROM_DEVICE
);
}
static
int
isight_close
(
struct
snd_pcm_substream
*
substream
)
{
struct
isight
*
isight
=
substream
->
private_data
;
iso_packets_buffer_destroy
(
&
isight
->
buffer
,
isight
->
unit
);
return
0
;
}
static
int
isight_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hw_params
)
{
struct
isight
*
isight
=
substream
->
private_data
;
int
err
;
err
=
snd_pcm_lib_alloc_vmalloc_buffer
(
substream
,
params_buffer_bytes
(
hw_params
));
if
(
err
<
0
)
return
err
;
ACCESS_ONCE
(
isight
->
pcm_active
)
=
true
;
return
0
;
}
static
int
reg_read
(
struct
isight
*
isight
,
int
offset
,
__be32
*
value
)
{
return
snd_fw_transaction
(
isight
->
unit
,
TCODE_READ_QUADLET_REQUEST
,
isight
->
audio_base
+
offset
,
value
,
4
);
}
static
int
reg_write
(
struct
isight
*
isight
,
int
offset
,
__be32
value
)
{
return
snd_fw_transaction
(
isight
->
unit
,
TCODE_WRITE_QUADLET_REQUEST
,
isight
->
audio_base
+
offset
,
&
value
,
4
);
}
static
void
isight_stop_streaming
(
struct
isight
*
isight
)
{
if
(
!
isight
->
context
)
return
;
fw_iso_context_stop
(
isight
->
context
);
fw_iso_context_destroy
(
isight
->
context
);
isight
->
context
=
NULL
;
fw_iso_resources_free
(
&
isight
->
resources
);
reg_write
(
isight
,
REG_AUDIO_ENABLE
,
0
);
}
static
int
isight_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
isight
*
isight
=
substream
->
private_data
;
ACCESS_ONCE
(
isight
->
pcm_active
)
=
false
;
mutex_lock
(
&
isight
->
mutex
);
isight_stop_streaming
(
isight
);
mutex_unlock
(
&
isight
->
mutex
);
return
snd_pcm_lib_free_vmalloc_buffer
(
substream
);
}
static
int
isight_start_streaming
(
struct
isight
*
isight
)
{
unsigned
int
i
;
int
err
;
if
(
isight
->
context
)
{
if
(
isight
->
packet_index
<
0
)
isight_stop_streaming
(
isight
);
else
return
0
;
}
err
=
reg_write
(
isight
,
REG_SAMPLE_RATE
,
cpu_to_be32
(
RATE_48000
));
if
(
err
<
0
)
goto
error
;
err
=
isight_connect
(
isight
);
if
(
err
<
0
)
goto
error
;
err
=
reg_write
(
isight
,
REG_AUDIO_ENABLE
,
cpu_to_be32
(
AUDIO_ENABLE
));
if
(
err
<
0
)
goto
err_resources
;
isight
->
context
=
fw_iso_context_create
(
isight
->
device
->
card
,
FW_ISO_CONTEXT_RECEIVE
,
isight
->
resources
.
channel
,
isight
->
device
->
max_speed
,
4
,
isight_packet
,
isight
);
if
(
IS_ERR
(
isight
->
context
))
{
err
=
PTR_ERR
(
isight
->
context
);
isight
->
context
=
NULL
;
goto
err_resources
;
}
for
(
i
=
0
;
i
<
QUEUE_LENGTH
;
++
i
)
{
err
=
fw_iso_context_queue
(
isight
->
context
,
&
audio_packet
,
&
isight
->
buffer
.
iso_buffer
,
isight
->
buffer
.
packets
[
i
].
offset
);
if
(
err
<
0
)
goto
err_context
;
}
isight
->
first_packet
=
true
;
isight
->
packet_index
=
0
;
err
=
fw_iso_context_start
(
isight
->
context
,
-
1
,
0
,
FW_ISO_CONTEXT_MATCH_ALL_TAGS
/*?*/
);
if
(
err
<
0
)
goto
err_context
;
return
0
;
err_context:
fw_iso_context_destroy
(
isight
->
context
);
isight
->
context
=
NULL
;
err_resources:
fw_iso_resources_free
(
&
isight
->
resources
);
reg_write
(
isight
,
REG_AUDIO_ENABLE
,
0
);
error:
return
err
;
}
static
int
isight_prepare
(
struct
snd_pcm_substream
*
substream
)
{
struct
isight
*
isight
=
substream
->
private_data
;
int
err
;
isight
->
buffer_pointer
=
0
;
isight
->
period_counter
=
0
;
mutex_lock
(
&
isight
->
mutex
);
err
=
isight_start_streaming
(
isight
);
mutex_unlock
(
&
isight
->
mutex
);
return
err
;
}
static
int
isight_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
{
struct
isight
*
isight
=
substream
->
private_data
;
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
ACCESS_ONCE
(
isight
->
pcm_running
)
=
true
;
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
ACCESS_ONCE
(
isight
->
pcm_running
)
=
false
;
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
snd_pcm_uframes_t
isight_pointer
(
struct
snd_pcm_substream
*
substream
)
{
struct
isight
*
isight
=
substream
->
private_data
;
return
ACCESS_ONCE
(
isight
->
buffer_pointer
);
}
static
int
isight_create_pcm
(
struct
isight
*
isight
)
{
static
struct
snd_pcm_ops
ops
=
{
.
open
=
isight_open
,
.
close
=
isight_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
isight_hw_params
,
.
hw_free
=
isight_hw_free
,
.
prepare
=
isight_prepare
,
.
trigger
=
isight_trigger
,
.
pointer
=
isight_pointer
,
.
page
=
snd_pcm_lib_get_vmalloc_page
,
.
mmap
=
snd_pcm_lib_mmap_vmalloc
,
};
struct
snd_pcm
*
pcm
;
int
err
;
err
=
snd_pcm_new
(
isight
->
card
,
"iSight"
,
0
,
0
,
1
,
&
pcm
);
if
(
err
<
0
)
return
err
;
pcm
->
private_data
=
isight
;
strcpy
(
pcm
->
name
,
"iSight"
);
isight
->
pcm
=
pcm
->
streams
[
SNDRV_PCM_STREAM_CAPTURE
].
substream
;
isight
->
pcm
->
ops
=
&
ops
;
return
0
;
}
static
int
isight_gain_info
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_info
*
info
)
{
struct
isight
*
isight
=
ctl
->
private_data
;
info
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
info
->
count
=
1
;
info
->
value
.
integer
.
min
=
isight
->
gain_min
;
info
->
value
.
integer
.
max
=
isight
->
gain_max
;
return
0
;
}
static
int
isight_gain_get
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
isight
*
isight
=
ctl
->
private_data
;
__be32
gain
;
int
err
;
err
=
reg_read
(
isight
,
REG_GAIN
,
&
gain
);
if
(
err
<
0
)
return
err
;
value
->
value
.
integer
.
value
[
0
]
=
(
s32
)
be32_to_cpu
(
gain
);
return
0
;
}
static
int
isight_gain_put
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
isight
*
isight
=
ctl
->
private_data
;
if
(
value
->
value
.
integer
.
value
[
0
]
<
isight
->
gain_min
||
value
->
value
.
integer
.
value
[
0
]
>
isight
->
gain_max
)
return
-
EINVAL
;
return
reg_write
(
isight
,
REG_GAIN
,
cpu_to_be32
(
value
->
value
.
integer
.
value
[
0
]));
}
static
int
isight_mute_get
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
isight
*
isight
=
ctl
->
private_data
;
__be32
mute
;
int
err
;
err
=
reg_read
(
isight
,
REG_MUTE
,
&
mute
);
if
(
err
<
0
)
return
err
;
value
->
value
.
integer
.
value
[
0
]
=
!
mute
;
return
0
;
}
static
int
isight_mute_put
(
struct
snd_kcontrol
*
ctl
,
struct
snd_ctl_elem_value
*
value
)
{
struct
isight
*
isight
=
ctl
->
private_data
;
return
reg_write
(
isight
,
REG_MUTE
,
(
__force
__be32
)
!
value
->
value
.
integer
.
value
[
0
]);
}
static
int
isight_create_mixer
(
struct
isight
*
isight
)
{
static
const
struct
snd_kcontrol_new
gain_control
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Mic Capture Volume"
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READWRITE
|
SNDRV_CTL_ELEM_ACCESS_TLV_READ
,
.
info
=
isight_gain_info
,
.
get
=
isight_gain_get
,
.
put
=
isight_gain_put
,
};
static
const
struct
snd_kcontrol_new
mute_control
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Mic Capture Switch"
,
.
info
=
snd_ctl_boolean_mono_info
,
.
get
=
isight_mute_get
,
.
put
=
isight_mute_put
,
};
__be32
value
;
struct
snd_kcontrol
*
ctl
;
int
err
;
err
=
reg_read
(
isight
,
REG_GAIN_RAW_START
,
&
value
);
if
(
err
<
0
)
return
err
;
isight
->
gain_min
=
be32_to_cpu
(
value
);
err
=
reg_read
(
isight
,
REG_GAIN_RAW_END
,
&
value
);
if
(
err
<
0
)
return
err
;
isight
->
gain_max
=
be32_to_cpu
(
value
);
isight
->
gain_tlv
[
0
]
=
SNDRV_CTL_TLVT_DB_MINMAX
;
isight
->
gain_tlv
[
1
]
=
2
*
sizeof
(
unsigned
int
);
err
=
reg_read
(
isight
,
REG_GAIN_DB_START
,
&
value
);
if
(
err
<
0
)
return
err
;
isight
->
gain_tlv
[
2
]
=
(
s32
)
be32_to_cpu
(
value
)
*
100
;
err
=
reg_read
(
isight
,
REG_GAIN_DB_END
,
&
value
);
if
(
err
<
0
)
return
err
;
isight
->
gain_tlv
[
3
]
=
(
s32
)
be32_to_cpu
(
value
)
*
100
;
ctl
=
snd_ctl_new1
(
&
gain_control
,
isight
);
if
(
ctl
)
ctl
->
tlv
.
p
=
isight
->
gain_tlv
;
err
=
snd_ctl_add
(
isight
->
card
,
ctl
);
if
(
err
<
0
)
return
err
;
err
=
snd_ctl_add
(
isight
->
card
,
snd_ctl_new1
(
&
mute_control
,
isight
));
if
(
err
<
0
)
return
err
;
return
0
;
}
static
void
isight_card_free
(
struct
snd_card
*
card
)
{
struct
isight
*
isight
=
card
->
private_data
;
fw_iso_resources_destroy
(
&
isight
->
resources
);
fw_unit_put
(
isight
->
unit
);
fw_device_put
(
isight
->
device
);
mutex_destroy
(
&
isight
->
mutex
);
}
static
u64
get_unit_base
(
struct
fw_unit
*
unit
)
{
struct
fw_csr_iterator
i
;
int
key
,
value
;
fw_csr_iterator_init
(
&
i
,
unit
->
directory
);
while
(
fw_csr_iterator_next
(
&
i
,
&
key
,
&
value
))
if
(
key
==
CSR_OFFSET
)
return
CSR_REGISTER_BASE
+
value
*
4
;
return
0
;
}
static
int
isight_probe
(
struct
device
*
unit_dev
)
{
struct
fw_unit
*
unit
=
fw_unit
(
unit_dev
);
struct
fw_device
*
fw_dev
=
fw_parent_device
(
unit
);
struct
snd_card
*
card
;
struct
isight
*
isight
;
int
err
;
err
=
snd_card_create
(
-
1
,
NULL
,
THIS_MODULE
,
sizeof
(
*
isight
),
&
card
);
if
(
err
<
0
)
return
err
;
snd_card_set_dev
(
card
,
unit_dev
);
isight
=
card
->
private_data
;
isight
->
card
=
card
;
mutex_init
(
&
isight
->
mutex
);
isight
->
unit
=
fw_unit_get
(
unit
);
isight
->
device
=
fw_device_get
(
fw_dev
);
isight
->
audio_base
=
get_unit_base
(
unit
);
if
(
!
isight
->
audio_base
)
{
dev_err
(
&
unit
->
device
,
"audio unit base not found
\n
"
);
err
=
-
ENXIO
;
goto
err_unit
;
}
fw_iso_resources_init
(
&
isight
->
resources
,
unit
);
card
->
private_free
=
isight_card_free
;
strcpy
(
card
->
driver
,
"iSight"
);
strcpy
(
card
->
shortname
,
"Apple iSight"
);
snprintf
(
card
->
longname
,
sizeof
(
card
->
longname
),
"Apple iSight (GUID %08x%08x) at %s, S%d"
,
fw_dev
->
config_rom
[
3
],
fw_dev
->
config_rom
[
4
],
dev_name
(
&
unit
->
device
),
100
<<
fw_dev
->
max_speed
);
strcpy
(
card
->
mixername
,
"iSight"
);
err
=
isight_create_pcm
(
isight
);
if
(
err
<
0
)
goto
error
;
err
=
isight_create_mixer
(
isight
);
if
(
err
<
0
)
goto
error
;
err
=
snd_card_register
(
card
);
if
(
err
<
0
)
goto
error
;
dev_set_drvdata
(
unit_dev
,
isight
);
return
0
;
err_unit:
fw_unit_put
(
isight
->
unit
);
fw_device_put
(
isight
->
device
);
mutex_destroy
(
&
isight
->
mutex
);
error:
snd_card_free
(
card
);
return
err
;
}
static
int
isight_remove
(
struct
device
*
dev
)
{
struct
isight
*
isight
=
dev_get_drvdata
(
dev
);
isight_pcm_abort
(
isight
);
snd_card_disconnect
(
isight
->
card
);
mutex_lock
(
&
isight
->
mutex
);
isight_stop_streaming
(
isight
);
mutex_unlock
(
&
isight
->
mutex
);
snd_card_free_when_closed
(
isight
->
card
);
return
0
;
}
static
void
isight_bus_reset
(
struct
fw_unit
*
unit
)
{
struct
isight
*
isight
=
dev_get_drvdata
(
&
unit
->
device
);
if
(
fw_iso_resources_update
(
&
isight
->
resources
)
<
0
)
{
isight_pcm_abort
(
isight
);
mutex_lock
(
&
isight
->
mutex
);
isight_stop_streaming
(
isight
);
mutex_unlock
(
&
isight
->
mutex
);
}
}
static
const
struct
ieee1394_device_id
isight_id_table
[]
=
{
{
.
match_flags
=
IEEE1394_MATCH_SPECIFIER_ID
|
IEEE1394_MATCH_VERSION
,
.
specifier_id
=
OUI_APPLE
,
.
version
=
SW_ISIGHT_AUDIO
,
},
{
}
};
MODULE_DEVICE_TABLE
(
ieee1394
,
isight_id_table
);
static
struct
fw_driver
isight_driver
=
{
.
driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
KBUILD_MODNAME
,
.
bus
=
&
fw_bus_type
,
.
probe
=
isight_probe
,
.
remove
=
isight_remove
,
},
.
update
=
isight_bus_reset
,
.
id_table
=
isight_id_table
,
};
static
int
__init
alsa_isight_init
(
void
)
{
return
driver_register
(
&
isight_driver
.
driver
);
}
static
void
__exit
alsa_isight_exit
(
void
)
{
driver_unregister
(
&
isight_driver
.
driver
);
}
module_init
(
alsa_isight_init
);
module_exit
(
alsa_isight_exit
);
sound/firewire/iso-resources.c
浏览文件 @
02e5fbf6
...
@@ -36,6 +36,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
...
@@ -36,6 +36,7 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
return
0
;
return
0
;
}
}
EXPORT_SYMBOL
(
fw_iso_resources_init
);
/**
/**
* fw_iso_resources_destroy - destroy a resource manager
* fw_iso_resources_destroy - destroy a resource manager
...
@@ -48,6 +49,7 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r)
...
@@ -48,6 +49,7 @@ void fw_iso_resources_destroy(struct fw_iso_resources *r)
mutex_destroy
(
&
r
->
mutex
);
mutex_destroy
(
&
r
->
mutex
);
fw_unit_put
(
r
->
unit
);
fw_unit_put
(
r
->
unit
);
}
}
EXPORT_SYMBOL
(
fw_iso_resources_destroy
);
static
unsigned
int
packet_bandwidth
(
unsigned
int
max_payload_bytes
,
int
speed
)
static
unsigned
int
packet_bandwidth
(
unsigned
int
max_payload_bytes
,
int
speed
)
{
{
...
@@ -152,6 +154,7 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r,
...
@@ -152,6 +154,7 @@ int fw_iso_resources_allocate(struct fw_iso_resources *r,
return
channel
;
return
channel
;
}
}
EXPORT_SYMBOL
(
fw_iso_resources_allocate
);
/**
/**
* fw_iso_resources_update - update resource allocations after a bus reset
* fw_iso_resources_update - update resource allocations after a bus reset
...
@@ -203,6 +206,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
...
@@ -203,6 +206,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r)
return
channel
;
return
channel
;
}
}
EXPORT_SYMBOL
(
fw_iso_resources_update
);
/**
/**
* fw_iso_resources_free - frees allocated resources
* fw_iso_resources_free - frees allocated resources
...
@@ -230,3 +234,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
...
@@ -230,3 +234,4 @@ void fw_iso_resources_free(struct fw_iso_resources *r)
mutex_unlock
(
&
r
->
mutex
);
mutex_unlock
(
&
r
->
mutex
);
}
}
EXPORT_SYMBOL
(
fw_iso_resources_free
);
sound/firewire/packets-buffer.c
浏览文件 @
02e5fbf6
...
@@ -60,6 +60,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
...
@@ -60,6 +60,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
error:
error:
return
err
;
return
err
;
}
}
EXPORT_SYMBOL
(
iso_packets_buffer_init
);
/**
/**
* iso_packets_buffer_destroy - frees packet buffer resources
* iso_packets_buffer_destroy - frees packet buffer resources
...
@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
...
@@ -72,3 +73,4 @@ void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
fw_iso_buffer_destroy
(
&
b
->
iso_buffer
,
fw_parent_device
(
unit
)
->
card
);
fw_iso_buffer_destroy
(
&
b
->
iso_buffer
,
fw_parent_device
(
unit
)
->
card
);
kfree
(
b
->
packets
);
kfree
(
b
->
packets
);
}
}
EXPORT_SYMBOL
(
iso_packets_buffer_destroy
);
sound/i2c/other/Makefile
浏览文件 @
02e5fbf6
...
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
...
@@ -14,4 +14,4 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
obj-$(CONFIG_SND_PDAUDIOCF)
+=
snd-ak4117.o
obj-$(CONFIG_SND_PDAUDIOCF)
+=
snd-ak4117.o
obj-$(CONFIG_SND_ICE1712)
+=
snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1712)
+=
snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724)
+=
snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_ICE1724)
+=
snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_
FM801_
TEA575X)
+=
snd-tea575x-tuner.o
obj-$(CONFIG_SND_TEA575X)
+=
snd-tea575x-tuner.o
sound/i2c/other/tea575x-tuner.c
浏览文件 @
02e5fbf6
...
@@ -37,8 +37,8 @@ static int radio_nr = -1;
...
@@ -37,8 +37,8 @@ static int radio_nr = -1;
module_param
(
radio_nr
,
int
,
0
);
module_param
(
radio_nr
,
int
,
0
);
#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
#define FREQ_LO (
87
* 16000)
#define FREQ_LO (
50UL
* 16000)
#define FREQ_HI (1
08
* 16000)
#define FREQ_HI (1
50UL
* 16000)
/*
/*
* definitions
* definitions
...
@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = {
...
@@ -77,27 +77,95 @@ static struct v4l2_queryctrl radio_qctrl[] = {
* lowlevel part
* lowlevel part
*/
*/
static
void
snd_tea575x_write
(
struct
snd_tea575x
*
tea
,
unsigned
int
val
)
{
u16
l
;
u8
data
;
tea
->
ops
->
set_direction
(
tea
,
1
);
udelay
(
16
);
for
(
l
=
25
;
l
>
0
;
l
--
)
{
data
=
(
val
>>
24
)
&
TEA575X_DATA
;
val
<<=
1
;
/* shift data */
tea
->
ops
->
set_pins
(
tea
,
data
|
TEA575X_WREN
);
udelay
(
2
);
tea
->
ops
->
set_pins
(
tea
,
data
|
TEA575X_WREN
|
TEA575X_CLK
);
udelay
(
2
);
tea
->
ops
->
set_pins
(
tea
,
data
|
TEA575X_WREN
);
udelay
(
2
);
}
if
(
!
tea
->
mute
)
tea
->
ops
->
set_pins
(
tea
,
0
);
}
static
unsigned
int
snd_tea575x_read
(
struct
snd_tea575x
*
tea
)
{
u16
l
,
rdata
;
u32
data
=
0
;
tea
->
ops
->
set_direction
(
tea
,
0
);
tea
->
ops
->
set_pins
(
tea
,
0
);
udelay
(
16
);
for
(
l
=
24
;
l
--
;)
{
tea
->
ops
->
set_pins
(
tea
,
TEA575X_CLK
);
udelay
(
2
);
if
(
!
l
)
tea
->
tuned
=
tea
->
ops
->
get_pins
(
tea
)
&
TEA575X_MOST
?
0
:
1
;
tea
->
ops
->
set_pins
(
tea
,
0
);
udelay
(
2
);
data
<<=
1
;
/* shift data */
rdata
=
tea
->
ops
->
get_pins
(
tea
);
if
(
!
l
)
tea
->
stereo
=
(
rdata
&
TEA575X_MOST
)
?
0
:
1
;
if
(
rdata
&
TEA575X_DATA
)
data
++
;
udelay
(
2
);
}
if
(
tea
->
mute
)
tea
->
ops
->
set_pins
(
tea
,
TEA575X_WREN
);
return
data
;
}
static
void
snd_tea575x_get_freq
(
struct
snd_tea575x
*
tea
)
{
unsigned
long
freq
;
freq
=
snd_tea575x_read
(
tea
)
&
TEA575X_BIT_FREQ_MASK
;
/* freq *= 12.5 */
freq
*=
125
;
freq
/=
10
;
/* crystal fixup */
if
(
tea
->
tea5759
)
freq
+=
TEA575X_FMIF
;
else
freq
-=
TEA575X_FMIF
;
tea
->
freq
=
freq
*
16
;
/* from kHz */
}
static
void
snd_tea575x_set_freq
(
struct
snd_tea575x
*
tea
)
static
void
snd_tea575x_set_freq
(
struct
snd_tea575x
*
tea
)
{
{
unsigned
long
freq
;
unsigned
long
freq
;
freq
=
tea
->
freq
/
16
;
/* to kHz */
freq
=
clamp
(
tea
->
freq
,
FREQ_LO
,
FREQ_HI
);
if
(
freq
>
108000
)
freq
/=
16
;
/* to kHz */
freq
=
108000
;
if
(
freq
<
87000
)
freq
=
87000
;
/* crystal fixup */
/* crystal fixup */
if
(
tea
->
tea5759
)
if
(
tea
->
tea5759
)
freq
-=
tea
->
freq_fixup
;
freq
-=
TEA575X_FMIF
;
else
else
freq
+=
tea
->
freq_fixup
;
freq
+=
TEA575X_FMIF
;
/* freq /= 12.5 */
/* freq /= 12.5 */
freq
*=
10
;
freq
*=
10
;
freq
/=
125
;
freq
/=
125
;
tea
->
val
&=
~
TEA575X_BIT_FREQ_MASK
;
tea
->
val
&=
~
TEA575X_BIT_FREQ_MASK
;
tea
->
val
|=
freq
&
TEA575X_BIT_FREQ_MASK
;
tea
->
val
|=
freq
&
TEA575X_BIT_FREQ_MASK
;
tea
->
ops
->
write
(
tea
,
tea
->
val
);
snd_tea575x_
write
(
tea
,
tea
->
val
);
}
}
/*
/*
...
@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv,
...
@@ -109,29 +177,34 @@ static int vidioc_querycap(struct file *file, void *priv,
{
{
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
strcpy
(
v
->
card
,
tea
->
tea5759
?
"TEA5759"
:
"TEA5757"
);
strlcpy
(
v
->
driver
,
"tea575x-tuner"
,
sizeof
(
v
->
driver
));
strlcpy
(
v
->
driver
,
"tea575x-tuner"
,
sizeof
(
v
->
driver
));
strlcpy
(
v
->
card
,
"Maestro Radio"
,
sizeof
(
v
->
card
));
strlcpy
(
v
->
card
,
tea
->
card
,
sizeof
(
v
->
card
));
sprintf
(
v
->
bus_info
,
"PCI"
);
strlcat
(
v
->
card
,
tea
->
tea5759
?
" TEA5759"
:
" TEA5757"
,
sizeof
(
v
->
card
));
strlcpy
(
v
->
bus_info
,
tea
->
bus_info
,
sizeof
(
v
->
bus_info
));
v
->
version
=
RADIO_VERSION
;
v
->
version
=
RADIO_VERSION
;
v
->
capabilities
=
V4L2_CAP_TUNER
;
v
->
capabilities
=
V4L2_CAP_TUNER
|
V4L2_CAP_RADIO
;
return
0
;
return
0
;
}
}
static
int
vidioc_g_tuner
(
struct
file
*
file
,
void
*
priv
,
static
int
vidioc_g_tuner
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_tuner
*
v
)
struct
v4l2_tuner
*
v
)
{
{
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
if
(
v
->
index
>
0
)
if
(
v
->
index
>
0
)
return
-
EINVAL
;
return
-
EINVAL
;
snd_tea575x_read
(
tea
);
strcpy
(
v
->
name
,
"FM"
);
strcpy
(
v
->
name
,
"FM"
);
v
->
type
=
V4L2_TUNER_RADIO
;
v
->
type
=
V4L2_TUNER_RADIO
;
v
->
capability
=
V4L2_TUNER_CAP_LOW
|
V4L2_TUNER_CAP_STEREO
;
v
->
rangelow
=
FREQ_LO
;
v
->
rangelow
=
FREQ_LO
;
v
->
rangehigh
=
FREQ_HI
;
v
->
rangehigh
=
FREQ_HI
;
v
->
rxsubchans
=
V4L2_TUNER_SUB_MONO
|
V4L2_TUNER_SUB_STEREO
;
v
->
rxsubchans
=
V4L2_TUNER_SUB_MONO
|
V4L2_TUNER_SUB_STEREO
;
v
->
capability
=
V4L2_TUNER_CAP_LOW
;
v
->
audmode
=
tea
->
stereo
?
V4L2_TUNER_MODE_STEREO
:
V4L2_TUNER_MODE_MONO
;
v
->
audmode
=
V4L2_TUNER_MODE_MONO
;
v
->
signal
=
tea
->
tuned
?
0xffff
:
0
;
v
->
signal
=
0xffff
;
return
0
;
return
0
;
}
}
...
@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
...
@@ -148,7 +221,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
{
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
)
return
-
EINVAL
;
f
->
type
=
V4L2_TUNER_RADIO
;
f
->
type
=
V4L2_TUNER_RADIO
;
snd_tea575x_get_freq
(
tea
);
f
->
frequency
=
tea
->
freq
;
f
->
frequency
=
tea
->
freq
;
return
0
;
return
0
;
}
}
...
@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
...
@@ -158,6 +234,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
{
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
struct
snd_tea575x
*
tea
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
||
f
->
type
!=
V4L2_TUNER_RADIO
)
return
-
EINVAL
;
if
(
f
->
frequency
<
FREQ_LO
||
f
->
frequency
>
FREQ_HI
)
if
(
f
->
frequency
<
FREQ_LO
||
f
->
frequency
>
FREQ_HI
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
...
@@ -209,10 +288,8 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
switch
(
ctrl
->
id
)
{
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
case
V4L2_CID_AUDIO_MUTE
:
if
(
tea
->
ops
->
mute
)
{
ctrl
->
value
=
tea
->
mute
;
ctrl
->
value
=
tea
->
mute
;
return
0
;
return
0
;
}
}
}
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
...
@@ -224,11 +301,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
switch
(
ctrl
->
id
)
{
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
case
V4L2_CID_AUDIO_MUTE
:
if
(
tea
->
ops
->
mute
)
{
if
(
tea
->
mute
!=
ctrl
->
value
)
{
tea
->
ops
->
mute
(
tea
,
ctrl
->
value
);
tea
->
mute
=
ctrl
->
value
;
tea
->
mute
=
ctrl
->
value
;
return
0
;
snd_tea575x_set_freq
(
tea
)
;
}
}
return
0
;
}
}
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = {
...
@@ -293,18 +370,16 @@ static struct video_device tea575x_radio = {
/*
/*
* initialize all the tea575x chips
* initialize all the tea575x chips
*/
*/
void
snd_tea575x_init
(
struct
snd_tea575x
*
tea
)
int
snd_tea575x_init
(
struct
snd_tea575x
*
tea
)
{
{
int
retval
;
int
retval
;
unsigned
int
val
;
struct
video_device
*
tea575x_radio_inst
;
struct
video_device
*
tea575x_radio_inst
;
val
=
tea
->
ops
->
read
(
tea
);
tea
->
mute
=
1
;
if
(
val
==
0x1ffffff
||
val
==
0
)
{
snd_printk
(
KERN_ERR
snd_tea575x_write
(
tea
,
0x55AA
);
"tea575x-tuner: Cannot find TEA575x chip
\n
"
);
if
(
snd_tea575x_read
(
tea
)
!=
0x55AA
)
return
;
return
-
ENODEV
;
}
tea
->
in_use
=
0
;
tea
->
in_use
=
0
;
tea
->
val
=
TEA575X_BIT_BAND_FM
|
TEA575X_BIT_SEARCH_10_40
;
tea
->
val
=
TEA575X_BIT_BAND_FM
|
TEA575X_BIT_SEARCH_10_40
;
...
@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
...
@@ -313,7 +388,7 @@ void snd_tea575x_init(struct snd_tea575x *tea)
tea575x_radio_inst
=
video_device_alloc
();
tea575x_radio_inst
=
video_device_alloc
();
if
(
tea575x_radio_inst
==
NULL
)
{
if
(
tea575x_radio_inst
==
NULL
)
{
printk
(
KERN_ERR
"tea575x-tuner: not enough memory
\n
"
);
printk
(
KERN_ERR
"tea575x-tuner: not enough memory
\n
"
);
return
;
return
-
ENOMEM
;
}
}
memcpy
(
tea575x_radio_inst
,
&
tea575x_radio
,
sizeof
(
tea575x_radio
));
memcpy
(
tea575x_radio_inst
,
&
tea575x_radio
,
sizeof
(
tea575x_radio
));
...
@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
...
@@ -328,17 +403,13 @@ void snd_tea575x_init(struct snd_tea575x *tea)
if
(
retval
)
{
if
(
retval
)
{
printk
(
KERN_ERR
"tea575x-tuner: can't register video device!
\n
"
);
printk
(
KERN_ERR
"tea575x-tuner: can't register video device!
\n
"
);
kfree
(
tea575x_radio_inst
);
kfree
(
tea575x_radio_inst
);
return
;
return
retval
;
}
}
snd_tea575x_set_freq
(
tea
);
snd_tea575x_set_freq
(
tea
);
/* mute on init */
if
(
tea
->
ops
->
mute
)
{
tea
->
ops
->
mute
(
tea
,
1
);
tea
->
mute
=
1
;
}
tea
->
vd
=
tea575x_radio_inst
;
tea
->
vd
=
tea575x_radio_inst
;
return
0
;
}
}
void
snd_tea575x_exit
(
struct
snd_tea575x
*
tea
)
void
snd_tea575x_exit
(
struct
snd_tea575x
*
tea
)
...
...
sound/pci/Kconfig
浏览文件 @
02e5fbf6
...
@@ -534,6 +534,14 @@ config SND_ES1968_INPUT
...
@@ -534,6 +534,14 @@ config SND_ES1968_INPUT
If you say N the buttons will directly control the master volume.
If you say N the buttons will directly control the master volume.
It is recommended to say Y.
It is recommended to say Y.
config SND_ES1968_RADIO
bool "Enable TEA5757 radio tuner support for es1968"
depends on SND_ES1968
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968
help
Say Y here to include support for TEA5757 radio tuner integrated on
some MediaForte cards (e.g. SF64-PCE2).
config SND_FM801
config SND_FM801
tristate "ForteMedia FM801"
tristate "ForteMedia FM801"
select SND_OPL3_LIB
select SND_OPL3_LIB
...
@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL
...
@@ -552,13 +560,13 @@ config SND_FM801_TEA575X_BOOL
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
help
help
Say Y here to include support for soundcards based on the ForteMedia
Say Y here to include support for soundcards based on the ForteMedia
FM801 chip with a TEA5757 tuner
connected to GPIO1-3 pins (Media
FM801 chip with a TEA5757 tuner
(MediaForte SF256-PCS, SF256-PCP and
Forte SF256-PCS-02
) into the snd-fm801 driver.
SF64-PCR
) into the snd-fm801 driver.
config SND_
FM801_
TEA575X
config SND_TEA575X
tristate
tristate
depends on SND_FM801_TEA575X_BOOL
depends on SND_FM801_TEA575X_BOOL
|| SND_ES1968_RADIO
default SND_FM801
default SND_FM801
|| SND_ES1968
source "sound/pci/hda/Kconfig"
source "sound/pci/hda/Kconfig"
...
...
sound/pci/asihpi/asihpi.c
浏览文件 @
02e5fbf6
此差异已折叠。
点击以展开。
sound/pci/asihpi/hpi6000.c
浏览文件 @
02e5fbf6
...
@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
...
@@ -200,8 +200,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
static
void
subsys_create_adapter
(
struct
hpi_message
*
phm
,
static
void
subsys_create_adapter
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
struct
hpi_response
*
phr
);
static
void
subsys_delete_adapter
(
struct
hpi_message
*
phm
,
static
void
adapter_delete
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_response
*
phr
);
struct
hpi_
message
*
phm
,
struct
hpi_
response
*
phr
);
static
void
adapter_get_asserts
(
struct
hpi_adapter_obj
*
pao
,
static
void
adapter_get_asserts
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
...
@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
...
@@ -222,9 +222,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_SUBSYS_CREATE_ADAPTER
:
subsys_create_adapter
(
phm
,
phr
);
subsys_create_adapter
(
phm
,
phr
);
break
;
break
;
case
HPI_SUBSYS_DELETE_ADAPTER
:
subsys_delete_adapter
(
phm
,
phr
);
break
;
default:
default:
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
break
;
break
;
...
@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
...
@@ -279,6 +276,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
adapter_get_asserts
(
pao
,
phm
,
phr
);
adapter_get_asserts
(
pao
,
phm
,
phr
);
break
;
break
;
case
HPI_ADAPTER_DELETE
:
adapter_delete
(
pao
,
phm
,
phr
);
break
;
default:
default:
hw_message
(
pao
,
phm
,
phr
);
hw_message
(
pao
,
phm
,
phr
);
break
;
break
;
...
@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
...
@@ -333,26 +334,22 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
{
{
struct
hpi_adapter_obj
*
pao
=
NULL
;
struct
hpi_adapter_obj
*
pao
=
NULL
;
/* subsytem messages get executed by every HPI. */
/* All other messages are ignored unless the adapter index matches */
/* an adapter in the HPI */
/*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */
/* if Dsp has crashed then do not communicate with it any more */
if
(
phm
->
object
!=
HPI_OBJ_SUBSYSTEM
)
{
if
(
phm
->
object
!=
HPI_OBJ_SUBSYSTEM
)
{
pao
=
hpi_find_adapter
(
phm
->
adapter_index
);
pao
=
hpi_find_adapter
(
phm
->
adapter_index
);
if
(
!
pao
)
{
if
(
!
pao
)
{
HPI_DEBUG_LOG
(
DEBUG
,
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
" %d,%d refused, for another HPI?
\n
"
,
HPI_ERROR_BAD_ADAPTER_NUMBER
);
phm
->
object
,
phm
->
function
);
HPI_DEBUG_LOG
(
DEBUG
,
"invalid adapter index: %d
\n
"
,
phm
->
adapter_index
);
return
;
return
;
}
}
/* Don't even try to communicate with crashed DSP */
if
(
pao
->
dsp_crashed
>=
10
)
{
if
(
pao
->
dsp_crashed
>=
10
)
{
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
HPI_ERROR_DSP_HARDWARE
);
HPI_ERROR_DSP_HARDWARE
);
HPI_DEBUG_LOG
(
DEBUG
,
"
%d,%d dsp crashed.
\n
"
,
HPI_DEBUG_LOG
(
DEBUG
,
"
adapter %d dsp crashed
\n
"
,
phm
->
object
,
phm
->
function
);
phm
->
adapter_index
);
return
;
return
;
}
}
}
}
...
@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm,
...
@@ -463,15 +460,9 @@ static void subsys_create_adapter(struct hpi_message *phm,
phr
->
error
=
0
;
phr
->
error
=
0
;
}
}
static
void
subsys_delete_adapter
(
struct
hpi_message
*
phm
,
static
void
adapter_delete
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_response
*
phr
)
struct
hpi_
message
*
phm
,
struct
hpi_
response
*
phr
)
{
{
struct
hpi_adapter_obj
*
pao
=
NULL
;
pao
=
hpi_find_adapter
(
phm
->
obj_index
);
if
(
!
pao
)
return
;
delete_adapter_obj
(
pao
);
delete_adapter_obj
(
pao
);
hpi_delete_adapter
(
pao
);
hpi_delete_adapter
(
pao
);
phr
->
error
=
0
;
phr
->
error
=
0
;
...
...
sound/pci/asihpi/hpi6205.c
浏览文件 @
02e5fbf6
...
@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
...
@@ -152,8 +152,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
static
void
subsys_create_adapter
(
struct
hpi_message
*
phm
,
static
void
subsys_create_adapter
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
struct
hpi_response
*
phr
);
static
void
subsys_delete_adapter
(
struct
hpi_message
*
phm
,
static
void
adapter_delete
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_response
*
phr
);
struct
hpi_
message
*
phm
,
struct
hpi_
response
*
phr
);
static
u16
create_adapter_obj
(
struct
hpi_adapter_obj
*
pao
,
static
u16
create_adapter_obj
(
struct
hpi_adapter_obj
*
pao
,
u32
*
pos_error_code
);
u32
*
pos_error_code
);
...
@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
...
@@ -223,15 +223,13 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
/*****************************************************************************/
/*****************************************************************************/
static
void
subsys_message
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
static
void
subsys_message
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
{
{
switch
(
phm
->
function
)
{
switch
(
phm
->
function
)
{
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_SUBSYS_CREATE_ADAPTER
:
subsys_create_adapter
(
phm
,
phr
);
subsys_create_adapter
(
phm
,
phr
);
break
;
break
;
case
HPI_SUBSYS_DELETE_ADAPTER
:
subsys_delete_adapter
(
phm
,
phr
);
break
;
default:
default:
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
break
;
break
;
...
@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
...
@@ -279,6 +277,10 @@ static void adapter_message(struct hpi_adapter_obj *pao,
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
{
{
switch
(
phm
->
function
)
{
switch
(
phm
->
function
)
{
case
HPI_ADAPTER_DELETE
:
adapter_delete
(
pao
,
phm
,
phr
);
break
;
default:
default:
hw_message
(
pao
,
phm
,
phr
);
hw_message
(
pao
,
phm
,
phr
);
break
;
break
;
...
@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao,
...
@@ -371,36 +373,17 @@ static void instream_message(struct hpi_adapter_obj *pao,
/** Entry point to this HPI backend
/** Entry point to this HPI backend
* All calls to the HPI start here
* All calls to the HPI start here
*/
*/
void
HPI_6205
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
void
_HPI_6205
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
{
{
struct
hpi_adapter_obj
*
pao
=
NULL
;
if
(
pao
&&
(
pao
->
dsp_crashed
>=
10
)
&&
(
phm
->
function
!=
HPI_ADAPTER_DEBUG_READ
))
{
/* subsytem messages are processed by every HPI.
/* allow last resort debug read even after crash */
* All other messages are ignored unless the adapter index matches
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
* an adapter in the HPI
HPI_ERROR_DSP_HARDWARE
);
*/
HPI_DEBUG_LOG
(
WARNING
,
" %d,%d dsp crashed.
\n
"
,
phm
->
object
,
/* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject,
phm
->
function
);
phm->wFunction); */
return
;
/* if Dsp has crashed then do not communicate with it any more */
if
(
phm
->
object
!=
HPI_OBJ_SUBSYSTEM
)
{
pao
=
hpi_find_adapter
(
phm
->
adapter_index
);
if
(
!
pao
)
{
HPI_DEBUG_LOG
(
DEBUG
,
" %d,%d refused, for another HPI?
\n
"
,
phm
->
object
,
phm
->
function
);
return
;
}
if
((
pao
->
dsp_crashed
>=
10
)
&&
(
phm
->
function
!=
HPI_ADAPTER_DEBUG_READ
))
{
/* allow last resort debug read even after crash */
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
HPI_ERROR_DSP_HARDWARE
);
HPI_DEBUG_LOG
(
WARNING
,
" %d,%d dsp crashed.
\n
"
,
phm
->
object
,
phm
->
function
);
return
;
}
}
}
/* Init default response */
/* Init default response */
...
@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
...
@@ -412,7 +395,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
case
HPI_TYPE_MESSAGE
:
case
HPI_TYPE_MESSAGE
:
switch
(
phm
->
object
)
{
switch
(
phm
->
object
)
{
case
HPI_OBJ_SUBSYSTEM
:
case
HPI_OBJ_SUBSYSTEM
:
subsys_message
(
phm
,
phr
);
subsys_message
(
p
ao
,
p
hm
,
phr
);
break
;
break
;
case
HPI_OBJ_ADAPTER
:
case
HPI_OBJ_ADAPTER
:
...
@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
...
@@ -444,6 +427,26 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
}
}
}
}
void
HPI_6205
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
)
{
struct
hpi_adapter_obj
*
pao
=
NULL
;
if
(
phm
->
object
!=
HPI_OBJ_SUBSYSTEM
)
{
/* normal messages must have valid adapter index */
pao
=
hpi_find_adapter
(
phm
->
adapter_index
);
}
else
{
/* subsys messages don't address an adapter */
_HPI_6205
(
NULL
,
phm
,
phr
);
return
;
}
if
(
pao
)
_HPI_6205
(
pao
,
phm
,
phr
);
else
hpi_init_response
(
phr
,
phm
->
object
,
phm
->
function
,
HPI_ERROR_BAD_ADAPTER_NUMBER
);
}
/*****************************************************************************/
/*****************************************************************************/
/* SUBSYSTEM */
/* SUBSYSTEM */
...
@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm,
...
@@ -491,13 +494,11 @@ static void subsys_create_adapter(struct hpi_message *phm,
}
}
/** delete an adapter - required by WDM driver */
/** delete an adapter - required by WDM driver */
static
void
subsys_delete_adapter
(
struct
hpi_message
*
phm
,
static
void
adapter_delete
(
struct
hpi_adapter_obj
*
pao
,
struct
hpi_response
*
phr
)
struct
hpi_
message
*
phm
,
struct
hpi_
response
*
phr
)
{
{
struct
hpi_adapter_obj
*
pao
;
struct
hpi_hw_obj
*
phw
;
struct
hpi_hw_obj
*
phw
;
pao
=
hpi_find_adapter
(
phm
->
obj_index
);
if
(
!
pao
)
{
if
(
!
pao
)
{
phr
->
error
=
HPI_ERROR_INVALID_OBJ_INDEX
;
phr
->
error
=
HPI_ERROR_INVALID_OBJ_INDEX
;
return
;
return
;
...
@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
...
@@ -563,11 +564,12 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
}
}
err
=
adapter_boot_load_dsp
(
pao
,
pos_error_code
);
err
=
adapter_boot_load_dsp
(
pao
,
pos_error_code
);
if
(
err
)
if
(
err
)
{
HPI_DEBUG_LOG
(
ERROR
,
"DSP code load failed
\n
"
);
/* no need to clean up as SubSysCreateAdapter */
/* no need to clean up as SubSysCreateAdapter */
/* calls DeleteAdapter on error. */
/* calls DeleteAdapter on error. */
return
err
;
return
err
;
}
HPI_DEBUG_LOG
(
INFO
,
"load DSP code OK
\n
"
);
HPI_DEBUG_LOG
(
INFO
,
"load DSP code OK
\n
"
);
/* allow boot load even if mem alloc wont work */
/* allow boot load even if mem alloc wont work */
...
@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
...
@@ -604,6 +606,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
control_cache
.
number_of_controls
,
control_cache
.
number_of_controls
,
interface
->
control_cache
.
size_in_bytes
,
interface
->
control_cache
.
size_in_bytes
,
p_control_cache_virtual
);
p_control_cache_virtual
);
if
(
!
phw
->
p_cache
)
if
(
!
phw
->
p_cache
)
err
=
HPI_ERROR_MEMORY_ALLOC
;
err
=
HPI_ERROR_MEMORY_ALLOC
;
}
}
...
@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
...
@@ -675,16 +678,14 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
}
}
/** Free memory areas allocated by adapter
/** Free memory areas allocated by adapter
* this routine is called from
SubSysDeleteAdapter
,
* this routine is called from
AdapterDelete
,
* and SubSysCreateAdapter if duplicate index
* and SubSysCreateAdapter if duplicate index
*/
*/
static
void
delete_adapter_obj
(
struct
hpi_adapter_obj
*
pao
)
static
void
delete_adapter_obj
(
struct
hpi_adapter_obj
*
pao
)
{
{
struct
hpi_hw_obj
*
phw
;
struct
hpi_hw_obj
*
phw
=
pao
->
priv
;
int
i
;
int
i
;
phw
=
pao
->
priv
;
if
(
hpios_locked_mem_valid
(
&
phw
->
h_control_cache
))
{
if
(
hpios_locked_mem_valid
(
&
phw
->
h_control_cache
))
{
hpios_locked_mem_free
(
&
phw
->
h_control_cache
);
hpios_locked_mem_free
(
&
phw
->
h_control_cache
);
hpi_free_control_cache
(
phw
->
p_cache
);
hpi_free_control_cache
(
phw
->
p_cache
);
...
@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
...
@@ -1275,6 +1276,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
case
HPI_ADAPTER_FAMILY_ASI
(
0x6300
):
case
HPI_ADAPTER_FAMILY_ASI
(
0x6300
):
boot_code_id
[
1
]
=
HPI_ADAPTER_FAMILY_ASI
(
0x6400
);
boot_code_id
[
1
]
=
HPI_ADAPTER_FAMILY_ASI
(
0x6400
);
break
;
break
;
case
HPI_ADAPTER_FAMILY_ASI
(
0x5500
):
case
HPI_ADAPTER_FAMILY_ASI
(
0x5600
):
case
HPI_ADAPTER_FAMILY_ASI
(
0x5600
):
case
HPI_ADAPTER_FAMILY_ASI
(
0x6500
):
case
HPI_ADAPTER_FAMILY_ASI
(
0x6500
):
boot_code_id
[
1
]
=
HPI_ADAPTER_FAMILY_ASI
(
0x6600
);
boot_code_id
[
1
]
=
HPI_ADAPTER_FAMILY_ASI
(
0x6600
);
...
@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
...
@@ -2059,7 +2061,6 @@ static int wait_dsp_ack(struct hpi_hw_obj *phw, int state, int timeout_us)
static
void
send_dsp_command
(
struct
hpi_hw_obj
*
phw
,
int
cmd
)
static
void
send_dsp_command
(
struct
hpi_hw_obj
*
phw
,
int
cmd
)
{
{
struct
bus_master_interface
*
interface
=
phw
->
p_interface_buffer
;
struct
bus_master_interface
*
interface
=
phw
->
p_interface_buffer
;
u32
r
;
u32
r
;
interface
->
host_cmd
=
cmd
;
interface
->
host_cmd
=
cmd
;
...
...
sound/pci/asihpi/hpi_internal.h
浏览文件 @
02e5fbf6
...
@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES {
...
@@ -294,7 +294,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/* These defines are used to fill in protocol information for an Ethernet packet
/* These defines are used to fill in protocol information for an Ethernet packet
sent using HMI on CS18102 */
sent using HMI on CS18102 */
/** ID supplied by Cirr
i
us for ASI packets. */
/** ID supplied by Cirrus for ASI packets. */
#define HPI_ETHERNET_PACKET_ID 0x85
#define HPI_ETHERNET_PACKET_ID 0x85
/** Simple packet - no special routing required */
/** Simple packet - no special routing required */
#define HPI_ETHERNET_PACKET_V1 0x01
#define HPI_ETHERNET_PACKET_V1 0x01
...
@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES {
...
@@ -307,7 +307,7 @@ enum HPI_CONTROL_ATTRIBUTES {
/** This packet must make its way to the host across the HPI interface */
/** This packet must make its way to the host across the HPI interface */
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41
#define HPI_ETHERNET_PACKET_HOSTED_VIA_HPI_V1 0x41
#define HPI_ETHERNET_UDP_PORT
(44600)
/*!< UDP messaging port
*/
#define HPI_ETHERNET_UDP_PORT
44600
/**< HPI UDP service
*/
/** Default network timeout in milli-seconds. */
/** Default network timeout in milli-seconds. */
#define HPI_ETHERNET_TIMEOUT_MS 500
#define HPI_ETHERNET_TIMEOUT_MS 500
...
@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS {
...
@@ -397,14 +397,14 @@ enum HPI_FUNCTION_IDS {
HPI_SUBSYS_OPEN
=
HPI_FUNC_ID
(
SUBSYSTEM
,
1
),
HPI_SUBSYS_OPEN
=
HPI_FUNC_ID
(
SUBSYSTEM
,
1
),
HPI_SUBSYS_GET_VERSION
=
HPI_FUNC_ID
(
SUBSYSTEM
,
2
),
HPI_SUBSYS_GET_VERSION
=
HPI_FUNC_ID
(
SUBSYSTEM
,
2
),
HPI_SUBSYS_GET_INFO
=
HPI_FUNC_ID
(
SUBSYSTEM
,
3
),
HPI_SUBSYS_GET_INFO
=
HPI_FUNC_ID
(
SUBSYSTEM
,
3
),
HPI_SUBSYS_FIND_ADAPTERS
=
HPI_FUNC_ID
(
SUBSYSTEM
,
4
),
/* HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), */
HPI_SUBSYS_CREATE_ADAPTER
=
HPI_FUNC_ID
(
SUBSYSTEM
,
5
),
HPI_SUBSYS_CREATE_ADAPTER
=
HPI_FUNC_ID
(
SUBSYSTEM
,
5
),
HPI_SUBSYS_CLOSE
=
HPI_FUNC_ID
(
SUBSYSTEM
,
6
),
HPI_SUBSYS_CLOSE
=
HPI_FUNC_ID
(
SUBSYSTEM
,
6
),
HPI_SUBSYS_DELETE_ADAPTER
=
HPI_FUNC_ID
(
SUBSYSTEM
,
7
),
/* HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), */
HPI_SUBSYS_DRIVER_LOAD
=
HPI_FUNC_ID
(
SUBSYSTEM
,
8
),
HPI_SUBSYS_DRIVER_LOAD
=
HPI_FUNC_ID
(
SUBSYSTEM
,
8
),
HPI_SUBSYS_DRIVER_UNLOAD
=
HPI_FUNC_ID
(
SUBSYSTEM
,
9
),
HPI_SUBSYS_DRIVER_UNLOAD
=
HPI_FUNC_ID
(
SUBSYSTEM
,
9
),
HPI_SUBSYS_READ_PORT_8
=
HPI_FUNC_ID
(
SUBSYSTEM
,
10
),
/* HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), */
HPI_SUBSYS_WRITE_PORT_8
=
HPI_FUNC_ID
(
SUBSYSTEM
,
11
),
/* HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), */
HPI_SUBSYS_GET_NUM_ADAPTERS
=
HPI_FUNC_ID
(
SUBSYSTEM
,
12
),
HPI_SUBSYS_GET_NUM_ADAPTERS
=
HPI_FUNC_ID
(
SUBSYSTEM
,
12
),
HPI_SUBSYS_GET_ADAPTER
=
HPI_FUNC_ID
(
SUBSYSTEM
,
13
),
HPI_SUBSYS_GET_ADAPTER
=
HPI_FUNC_ID
(
SUBSYSTEM
,
13
),
HPI_SUBSYS_SET_NETWORK_INTERFACE
=
HPI_FUNC_ID
(
SUBSYSTEM
,
14
),
HPI_SUBSYS_SET_NETWORK_INTERFACE
=
HPI_FUNC_ID
(
SUBSYSTEM
,
14
),
...
@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS {
...
@@ -433,7 +433,8 @@ enum HPI_FUNCTION_IDS {
HPI_ADAPTER_DEBUG_READ
=
HPI_FUNC_ID
(
ADAPTER
,
18
),
HPI_ADAPTER_DEBUG_READ
=
HPI_FUNC_ID
(
ADAPTER
,
18
),
HPI_ADAPTER_IRQ_QUERY_AND_CLEAR
=
HPI_FUNC_ID
(
ADAPTER
,
19
),
HPI_ADAPTER_IRQ_QUERY_AND_CLEAR
=
HPI_FUNC_ID
(
ADAPTER
,
19
),
HPI_ADAPTER_IRQ_CALLBACK
=
HPI_FUNC_ID
(
ADAPTER
,
20
),
HPI_ADAPTER_IRQ_CALLBACK
=
HPI_FUNC_ID
(
ADAPTER
,
20
),
#define HPI_ADAPTER_FUNCTION_COUNT 20
HPI_ADAPTER_DELETE
=
HPI_FUNC_ID
(
ADAPTER
,
21
),
#define HPI_ADAPTER_FUNCTION_COUNT 21
HPI_OSTREAM_OPEN
=
HPI_FUNC_ID
(
OSTREAM
,
1
),
HPI_OSTREAM_OPEN
=
HPI_FUNC_ID
(
OSTREAM
,
1
),
HPI_OSTREAM_CLOSE
=
HPI_FUNC_ID
(
OSTREAM
,
2
),
HPI_OSTREAM_CLOSE
=
HPI_FUNC_ID
(
OSTREAM
,
2
),
...
@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
...
@@ -1561,8 +1562,6 @@ void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
u16
hpi_subsys_create_adapter
(
const
struct
hpi_resource
*
p_resource
,
u16
hpi_subsys_create_adapter
(
const
struct
hpi_resource
*
p_resource
,
u16
*
pw_adapter_index
);
u16
*
pw_adapter_index
);
u16
hpi_subsys_delete_adapter
(
u16
adapter_index
);
u16
hpi_outstream_host_buffer_get_info
(
u32
h_outstream
,
u8
**
pp_buffer
,
u16
hpi_outstream_host_buffer_get_info
(
u32
h_outstream
,
u8
**
pp_buffer
,
struct
hpi_hostbuffer_status
**
pp_status
);
struct
hpi_hostbuffer_status
**
pp_status
);
...
@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR);
...
@@ -1584,9 +1583,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR);
/*////////////////////////////////////////////////////////////////////////// */
/*////////////////////////////////////////////////////////////////////////// */
/* declarations for individual HPI entry points */
/* declarations for individual HPI entry points */
hpi_handler_func
HPI_1000
;
hpi_handler_func
HPI_6000
;
hpi_handler_func
HPI_6000
;
hpi_handler_func
HPI_6205
;
hpi_handler_func
HPI_6205
;
hpi_handler_func
HPI_COMMON
;
#endif
/* _HPI_INTERNAL_H_ */
#endif
/* _HPI_INTERNAL_H_ */
sound/pci/asihpi/hpicmn.c
浏览文件 @
02e5fbf6
...
@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
...
@@ -227,8 +227,9 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
if
(
info
->
control_type
)
{
if
(
info
->
control_type
)
{
pC
->
p_info
[
info
->
control_index
]
=
info
;
pC
->
p_info
[
info
->
control_index
]
=
info
;
cached
++
;
cached
++
;
}
else
/* dummy cache entry */
}
else
{
/* dummy cache entry */
pC
->
p_info
[
info
->
control_index
]
=
NULL
;
pC
->
p_info
[
info
->
control_index
]
=
NULL
;
}
byte_count
+=
info
->
size_in32bit_words
*
4
;
byte_count
+=
info
->
size_in32bit_words
*
4
;
...
@@ -298,7 +299,7 @@ struct pad_ofs_size {
...
@@ -298,7 +299,7 @@ struct pad_ofs_size {
unsigned
int
field_size
;
unsigned
int
field_size
;
};
};
static
struct
pad_ofs_size
pad_desc
[]
=
{
static
const
struct
pad_ofs_size
pad_desc
[]
=
{
HPICMN_PAD_OFS_AND_SIZE
(
c_channel
),
/* HPI_PAD_CHANNEL_NAME */
HPICMN_PAD_OFS_AND_SIZE
(
c_channel
),
/* HPI_PAD_CHANNEL_NAME */
HPICMN_PAD_OFS_AND_SIZE
(
c_artist
),
/* HPI_PAD_ARTIST */
HPICMN_PAD_OFS_AND_SIZE
(
c_artist
),
/* HPI_PAD_ARTIST */
HPICMN_PAD_OFS_AND_SIZE
(
c_title
),
/* HPI_PAD_TITLE */
HPICMN_PAD_OFS_AND_SIZE
(
c_title
),
/* HPI_PAD_TITLE */
...
@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
...
@@ -617,6 +618,10 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
}
}
}
}
/** Allocate control cache.
\return Cache pointer, or NULL if allocation fails.
*/
struct
hpi_control_cache
*
hpi_alloc_control_cache
(
const
u32
control_count
,
struct
hpi_control_cache
*
hpi_alloc_control_cache
(
const
u32
control_count
,
const
u32
size_in_bytes
,
u8
*
p_dsp_control_buffer
)
const
u32
size_in_bytes
,
u8
*
p_dsp_control_buffer
)
{
{
...
@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
...
@@ -667,7 +672,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
phr
->
u
.
s
.
num_adapters
=
adapters
.
gw_num_adapters
;
phr
->
u
.
s
.
num_adapters
=
adapters
.
gw_num_adapters
;
break
;
break
;
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_SUBSYS_DELETE_ADAPTER
:
break
;
break
;
default:
default:
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
phr
->
error
=
HPI_ERROR_INVALID_FUNC
;
...
...
sound/pci/asihpi/hpicmn.h
浏览文件 @
02e5fbf6
...
@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
...
@@ -60,3 +60,5 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
u16
hpi_validate_response
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
u16
hpi_validate_response
(
struct
hpi_message
*
phm
,
struct
hpi_response
*
phr
);
hpi_handler_func
HPI_COMMON
;
sound/pci/asihpi/hpifunc.c
浏览文件 @
02e5fbf6
...
@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex)
...
@@ -105,33 +105,6 @@ u16 hpi_subsys_get_version_ex(u32 *pversion_ex)
return
hr
.
error
;
return
hr
.
error
;
}
}
u16
hpi_subsys_create_adapter
(
const
struct
hpi_resource
*
p_resource
,
u16
*
pw_adapter_index
)
{
struct
hpi_message
hm
;
struct
hpi_response
hr
;
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_SUBSYSTEM
,
HPI_SUBSYS_CREATE_ADAPTER
);
hm
.
u
.
s
.
resource
=
*
p_resource
;
hpi_send_recv
(
&
hm
,
&
hr
);
*
pw_adapter_index
=
hr
.
u
.
s
.
adapter_index
;
return
hr
.
error
;
}
u16
hpi_subsys_delete_adapter
(
u16
adapter_index
)
{
struct
hpi_message
hm
;
struct
hpi_response
hr
;
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_SUBSYSTEM
,
HPI_SUBSYS_DELETE_ADAPTER
);
hm
.
obj_index
=
adapter_index
;
hpi_send_recv
(
&
hm
,
&
hr
);
return
hr
.
error
;
}
u16
hpi_subsys_get_num_adapters
(
int
*
pn_num_adapters
)
u16
hpi_subsys_get_num_adapters
(
int
*
pn_num_adapters
)
{
{
struct
hpi_message
hm
;
struct
hpi_message
hm
;
...
...
sound/pci/asihpi/hpimsgx.c
浏览文件 @
02e5fbf6
...
@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
...
@@ -211,24 +211,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
HPIMSGX__init
(
phm
,
phr
);
HPIMSGX__init
(
phm
,
phr
);
break
;
break
;
case
HPI_SUBSYS_DELETE_ADAPTER
:
HPIMSGX__cleanup
(
phm
->
obj_index
,
h_owner
);
{
struct
hpi_message
hm
;
struct
hpi_response
hr
;
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_ADAPTER
,
HPI_ADAPTER_CLOSE
);
hm
.
adapter_index
=
phm
->
obj_index
;
hw_entry_point
(
&
hm
,
&
hr
);
}
if
((
phm
->
obj_index
<
HPI_MAX_ADAPTERS
)
&&
hpi_entry_points
[
phm
->
obj_index
])
{
hpi_entry_points
[
phm
->
obj_index
]
(
phm
,
phr
);
hpi_entry_points
[
phm
->
obj_index
]
=
NULL
;
}
else
phr
->
error
=
HPI_ERROR_INVALID_OBJ_INDEX
;
break
;
default:
default:
/* Must explicitly handle every subsys message in this switch */
/* Must explicitly handle every subsys message in this switch */
hpi_init_response
(
phr
,
HPI_OBJ_SUBSYSTEM
,
phm
->
function
,
hpi_init_response
(
phr
,
HPI_OBJ_SUBSYSTEM
,
phm
->
function
,
...
@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
...
@@ -247,6 +229,19 @@ static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
case
HPI_ADAPTER_CLOSE
:
case
HPI_ADAPTER_CLOSE
:
adapter_close
(
phm
,
phr
);
adapter_close
(
phm
,
phr
);
break
;
break
;
case
HPI_ADAPTER_DELETE
:
HPIMSGX__cleanup
(
phm
->
adapter_index
,
h_owner
);
{
struct
hpi_message
hm
;
struct
hpi_response
hr
;
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_ADAPTER
,
HPI_ADAPTER_CLOSE
);
hm
.
adapter_index
=
phm
->
adapter_index
;
hw_entry_point
(
&
hm
,
&
hr
);
}
hw_entry_point
(
phm
,
phr
);
break
;
default:
default:
hw_entry_point
(
phm
,
phr
);
hw_entry_point
(
phm
,
phr
);
break
;
break
;
...
...
sound/pci/asihpi/hpioctl.c
浏览文件 @
02e5fbf6
...
@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions
...
@@ -25,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions
#include "hpidebug.h"
#include "hpidebug.h"
#include "hpimsgx.h"
#include "hpimsgx.h"
#include "hpioctl.h"
#include "hpioctl.h"
#include "hpicmn.h"
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/slab.h>
...
@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
...
@@ -161,26 +162,24 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto
out
;
goto
out
;
}
}
pa
=
&
adapters
[
hm
->
h
.
adapter_index
];
switch
(
hm
->
h
.
function
)
{
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_ADAPTER_DELETE
:
/* Application must not use these functions! */
hr
->
h
.
size
=
sizeof
(
hr
->
h
);
hr
->
h
.
error
=
HPI_ERROR_INVALID_OPERATION
;
hr
->
h
.
function
=
hm
->
h
.
function
;
uncopied_bytes
=
copy_to_user
(
puhr
,
hr
,
hr
->
h
.
size
);
if
(
uncopied_bytes
)
err
=
-
EFAULT
;
else
err
=
0
;
goto
out
;
}
hr
->
h
.
size
=
res_max_size
;
hr
->
h
.
size
=
res_max_size
;
if
(
hm
->
h
.
object
==
HPI_OBJ_SUBSYSTEM
)
{
if
(
hm
->
h
.
object
==
HPI_OBJ_SUBSYSTEM
)
{
switch
(
hm
->
h
.
function
)
{
hpi_send_recv_f
(
&
hm
->
m0
,
&
hr
->
r0
,
file
);
case
HPI_SUBSYS_CREATE_ADAPTER
:
case
HPI_SUBSYS_DELETE_ADAPTER
:
/* Application must not use these functions! */
hr
->
h
.
size
=
sizeof
(
hr
->
h
);
hr
->
h
.
error
=
HPI_ERROR_INVALID_OPERATION
;
hr
->
h
.
function
=
hm
->
h
.
function
;
uncopied_bytes
=
copy_to_user
(
puhr
,
hr
,
hr
->
h
.
size
);
if
(
uncopied_bytes
)
err
=
-
EFAULT
;
else
err
=
0
;
goto
out
;
default:
hpi_send_recv_f
(
&
hm
->
m0
,
&
hr
->
r0
,
file
);
}
}
else
{
}
else
{
u16
__user
*
ptr
=
NULL
;
u16
__user
*
ptr
=
NULL
;
u32
size
=
0
;
u32
size
=
0
;
...
@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
...
@@ -188,8 +187,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* -1=no data 0=read from user mem, 1=write to user mem */
/* -1=no data 0=read from user mem, 1=write to user mem */
int
wrflag
=
-
1
;
int
wrflag
=
-
1
;
u32
adapter
=
hm
->
h
.
adapter_index
;
u32
adapter
=
hm
->
h
.
adapter_index
;
pa
=
&
adapters
[
adapter
];
if
((
hm
->
h
.
adapter_index
>
HPI_MAX_ADAPTERS
)
||
(
!
pa
->
type
))
{
if
((
adapter
>
HPI_MAX_ADAPTERS
)
||
(
!
pa
->
type
))
{
hpi_init_response
(
&
hr
->
r0
,
HPI_OBJ_ADAPTER
,
hpi_init_response
(
&
hr
->
r0
,
HPI_OBJ_ADAPTER
,
HPI_ADAPTER_OPEN
,
HPI_ADAPTER_OPEN
,
HPI_ERROR_BAD_ADAPTER_NUMBER
);
HPI_ERROR_BAD_ADAPTER_NUMBER
);
...
@@ -317,7 +317,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
...
@@ -317,7 +317,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int
__devinit
asihpi_adapter_probe
(
struct
pci_dev
*
pci_dev
,
int
__devinit
asihpi_adapter_probe
(
struct
pci_dev
*
pci_dev
,
const
struct
pci_device_id
*
pci_id
)
const
struct
pci_device_id
*
pci_id
)
{
{
int
err
,
idx
,
nm
;
int
idx
,
nm
;
unsigned
int
memlen
;
unsigned
int
memlen
;
struct
hpi_message
hm
;
struct
hpi_message
hm
;
struct
hpi_response
hr
;
struct
hpi_response
hr
;
...
@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
...
@@ -351,11 +351,8 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
nm
=
HPI_MAX_ADAPTER_MEM_SPACES
;
nm
=
HPI_MAX_ADAPTER_MEM_SPACES
;
for
(
idx
=
0
;
idx
<
nm
;
idx
++
)
{
for
(
idx
=
0
;
idx
<
nm
;
idx
++
)
{
HPI_DEBUG_LOG
(
INFO
,
"resource %d %s %08llx-%08llx %04llx
\n
"
,
HPI_DEBUG_LOG
(
INFO
,
"resource %d %pR
\n
"
,
idx
,
idx
,
pci_dev
->
resource
[
idx
].
name
,
&
pci_dev
->
resource
[
idx
]);
(
unsigned
long
long
)
pci_resource_start
(
pci_dev
,
idx
),
(
unsigned
long
long
)
pci_resource_end
(
pci_dev
,
idx
),
(
unsigned
long
long
)
pci_resource_flags
(
pci_dev
,
idx
));
if
(
pci_resource_flags
(
pci_dev
,
idx
)
&
IORESOURCE_MEM
)
{
if
(
pci_resource_flags
(
pci_dev
,
idx
)
&
IORESOURCE_MEM
)
{
memlen
=
pci_resource_len
(
pci_dev
,
idx
);
memlen
=
pci_resource_len
(
pci_dev
,
idx
);
...
@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
...
@@ -395,17 +392,20 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
adapter
.
index
=
hr
.
u
.
s
.
adapter_index
;
adapter
.
index
=
hr
.
u
.
s
.
adapter_index
;
adapter
.
type
=
hr
.
u
.
s
.
adapter_type
;
adapter
.
type
=
hr
.
u
.
s
.
adapter_type
;
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_ADAPTER
,
HPI_ADAPTER_OPEN
);
hm
.
adapter_index
=
adapter
.
index
;
hm
.
adapter_index
=
adapter
.
index
;
hpi_send_recv_ex
(
&
hm
,
&
hr
,
HOWNER_KERNEL
);
err
=
hpi_adapter_open
(
adapter
.
index
);
if
(
hr
.
error
)
if
(
err
)
goto
err
;
goto
err
;
adapter
.
snd_card_asihpi
=
NULL
;
adapter
.
snd_card_asihpi
=
NULL
;
/* WARNING can't init mutex in 'adapter'
/* WARNING can't init mutex in 'adapter'
* and then copy it to adapters[] ?!?!
* and then copy it to adapters[] ?!?!
*/
*/
adapters
[
hr
.
u
.
s
.
adapter_
index
]
=
adapter
;
adapters
[
adapter
.
index
]
=
adapter
;
mutex_init
(
&
adapters
[
adapter
.
index
].
mutex
);
mutex_init
(
&
adapters
[
adapter
.
index
].
mutex
);
pci_set_drvdata
(
pci_dev
,
&
adapters
[
adapter
.
index
]);
pci_set_drvdata
(
pci_dev
,
&
adapters
[
adapter
.
index
]);
...
@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
...
@@ -440,10 +440,9 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
struct
hpi_adapter
*
pa
;
struct
hpi_adapter
*
pa
;
pa
=
pci_get_drvdata
(
pci_dev
);
pa
=
pci_get_drvdata
(
pci_dev
);
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_SUBSYSTEM
,
hpi_init_message_response
(
&
hm
,
&
hr
,
HPI_OBJ_ADAPTER
,
HPI_SUBSYS_DELETE_ADAPTER
);
HPI_ADAPTER_DELETE
);
hm
.
obj_index
=
pa
->
index
;
hm
.
adapter_index
=
pa
->
index
;
hm
.
adapter_index
=
HPI_ADAPTER_INDEX_INVALID
;
hpi_send_recv_ex
(
&
hm
,
&
hr
,
HOWNER_KERNEL
);
hpi_send_recv_ex
(
&
hm
,
&
hr
,
HOWNER_KERNEL
);
/* unmap PCI memory space, mapped during device init. */
/* unmap PCI memory space, mapped during device init. */
...
...
sound/pci/au88x0/au8810.h
浏览文件 @
02e5fbf6
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
#define CHIP_AU8810
#define CHIP_AU8810
#define CARD_NAME "Aureal Advantage
3D Sound Processor
"
#define CARD_NAME "Aureal Advantage"
#define CARD_NAME_SHORT "au8810"
#define CARD_NAME_SHORT "au8810"
#define NR_ADB 0x10
#define NR_ADB 0x10
...
...
sound/pci/au88x0/au8820.h
浏览文件 @
02e5fbf6
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#define CHIP_AU8820
#define CHIP_AU8820
#define CARD_NAME "Aureal Vortex
3D Sound Processor
"
#define CARD_NAME "Aureal Vortex"
#define CARD_NAME_SHORT "au8820"
#define CARD_NAME_SHORT "au8820"
/* Number of ADB and WT channels */
/* Number of ADB and WT channels */
...
...
sound/pci/au88x0/au8830.h
浏览文件 @
02e5fbf6
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#define CHIP_AU8830
#define CHIP_AU8830
#define CARD_NAME "Aureal Vortex 2
3D Sound Processor
"
#define CARD_NAME "Aureal Vortex 2"
#define CARD_NAME_SHORT "au8830"
#define CARD_NAME_SHORT "au8830"
#define NR_ADB 0x20
#define NR_ADB 0x20
...
...
sound/pci/au88x0/au88x0_pcm.c
浏览文件 @
02e5fbf6
...
@@ -426,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = {
...
@@ -426,11 +426,11 @@ static struct snd_pcm_ops snd_vortex_playback_ops = {
*/
*/
static
char
*
vortex_pcm_prettyname
[
VORTEX_PCM_LAST
]
=
{
static
char
*
vortex_pcm_prettyname
[
VORTEX_PCM_LAST
]
=
{
"AU88x0
ADB"
,
CARD_NAME
"
ADB"
,
"AU88x0
SPDIF"
,
CARD_NAME
"
SPDIF"
,
"AU88x0
A3D"
,
CARD_NAME
"
A3D"
,
"AU88x0
WT"
,
CARD_NAME
"
WT"
,
"AU88x0
I2S"
,
CARD_NAME
"
I2S"
,
};
};
static
char
*
vortex_pcm_name
[
VORTEX_PCM_LAST
]
=
{
static
char
*
vortex_pcm_name
[
VORTEX_PCM_LAST
]
=
{
"adb"
,
"adb"
,
...
@@ -527,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
...
@@ -527,7 +527,8 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
nr_capt
,
&
pcm
);
nr_capt
,
&
pcm
);
if
(
err
<
0
)
if
(
err
<
0
)
return
err
;
return
err
;
strcpy
(
pcm
->
name
,
vortex_pcm_name
[
idx
]);
snprintf
(
pcm
->
name
,
sizeof
(
pcm
->
name
),
"%s %s"
,
CARD_NAME_SHORT
,
vortex_pcm_name
[
idx
]);
chip
->
pcm
[
idx
]
=
pcm
;
chip
->
pcm
[
idx
]
=
pcm
;
// This is an evil hack, but it saves a lot of duplicated code.
// This is an evil hack, but it saves a lot of duplicated code.
VORTEX_PCM_TYPE
(
pcm
)
=
idx
;
VORTEX_PCM_TYPE
(
pcm
)
=
idx
;
...
...
sound/pci/emu10k1/emufx.c
浏览文件 @
02e5fbf6
...
@@ -303,6 +303,9 @@ static const u32 db_table[101] = {
...
@@ -303,6 +303,9 @@ static const u32 db_table[101] = {
static
const
DECLARE_TLV_DB_SCALE
(
snd_emu10k1_db_scale1
,
-
4000
,
40
,
1
);
static
const
DECLARE_TLV_DB_SCALE
(
snd_emu10k1_db_scale1
,
-
4000
,
40
,
1
);
static
const
DECLARE_TLV_DB_LINEAR
(
snd_emu10k1_db_linear
,
TLV_DB_GAIN_MUTE
,
0
);
static
const
DECLARE_TLV_DB_LINEAR
(
snd_emu10k1_db_linear
,
TLV_DB_GAIN_MUTE
,
0
);
/* EMU10K1 bass/treble db gain */
static
const
DECLARE_TLV_DB_SCALE
(
snd_emu10k1_bass_treble_db_scale
,
-
1200
,
60
,
0
);
static
const
u32
onoff_table
[
2
]
=
{
static
const
u32
onoff_table
[
2
]
=
{
0x00000000
,
0x00000001
0x00000000
,
0x00000001
};
};
...
@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
...
@@ -2163,6 +2166,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl
->
min
=
0
;
ctl
->
min
=
0
;
ctl
->
max
=
40
;
ctl
->
max
=
40
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
tlv
=
snd_emu10k1_bass_treble_db_scale
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_BASS
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_BASS
;
ctl
=
&
controls
[
i
+
1
];
ctl
=
&
controls
[
i
+
1
];
ctl
->
id
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
ctl
->
id
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
...
@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
...
@@ -2172,6 +2176,7 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
ctl
->
min
=
0
;
ctl
->
min
=
0
;
ctl
->
max
=
40
;
ctl
->
max
=
40
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
value
[
0
]
=
ctl
->
value
[
1
]
=
20
;
ctl
->
tlv
=
snd_emu10k1_bass_treble_db_scale
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_TREBLE
;
ctl
->
translation
=
EMU10K1_GPR_TRANSLATION_TREBLE
;
#define BASS_GPR 0x8c
#define BASS_GPR 0x8c
...
...
sound/pci/emu10k1/emumixer.c
浏览文件 @
02e5fbf6
...
@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
...
@@ -1729,8 +1729,6 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
"Master Mono Playback Volume"
,
"Master Mono Playback Volume"
,
"PCM Out Path & Mute"
,
"PCM Out Path & Mute"
,
"Mono Output Select"
,
"Mono Output Select"
,
"Front Playback Switch"
,
"Front Playback Volume"
,
"Surround Playback Switch"
,
"Surround Playback Switch"
,
"Surround Playback Volume"
,
"Surround Playback Volume"
,
"Center Playback Switch"
,
"Center Playback Switch"
,
...
@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
...
@@ -1879,6 +1877,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
emu
->
rear_ac97
=
1
;
emu
->
rear_ac97
=
1
;
snd_emu10k1_ptr_write
(
emu
,
AC97SLOT
,
0
,
AC97SLOT_CNTR
|
AC97SLOT_LFE
|
AC97SLOT_REAR_LEFT
|
AC97SLOT_REAR_RIGHT
);
snd_emu10k1_ptr_write
(
emu
,
AC97SLOT
,
0
,
AC97SLOT_CNTR
|
AC97SLOT_LFE
|
AC97SLOT_REAR_LEFT
|
AC97SLOT_REAR_RIGHT
);
snd_ac97_write_cache
(
emu
->
ac97
,
AC97_HEADPHONE
,
0x0202
);
snd_ac97_write_cache
(
emu
->
ac97
,
AC97_HEADPHONE
,
0x0202
);
remove_ctl
(
card
,
"Front Playback Volume"
);
remove_ctl
(
card
,
"Front Playback Switch"
);
}
}
/* remove unused AC97 controls */
/* remove unused AC97 controls */
snd_ac97_write_cache
(
emu
->
ac97
,
AC97_SURROUND_MASTER
,
0x0202
);
snd_ac97_write_cache
(
emu
->
ac97
,
AC97_SURROUND_MASTER
,
0x0202
);
...
@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
...
@@ -1913,6 +1913,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
for
(;
*
c
;
c
+=
2
)
for
(;
*
c
;
c
+=
2
)
rename_ctl
(
card
,
c
[
0
],
c
[
1
]);
rename_ctl
(
card
,
c
[
0
],
c
[
1
]);
if
(
emu
->
card_capabilities
->
subsystem
==
0x80401102
)
{
/* SB Live! Platinum CT4760P */
remove_ctl
(
card
,
"Center Playback Volume"
);
remove_ctl
(
card
,
"LFE Playback Volume"
);
remove_ctl
(
card
,
"Wave Center Playback Volume"
);
remove_ctl
(
card
,
"Wave LFE Playback Volume"
);
}
if
(
emu
->
card_capabilities
->
subsystem
==
0x20071102
)
{
/* Audigy 4 Pro */
if
(
emu
->
card_capabilities
->
subsystem
==
0x20071102
)
{
/* Audigy 4 Pro */
rename_ctl
(
card
,
"Line2 Capture Volume"
,
"Line1/Mic Capture Volume"
);
rename_ctl
(
card
,
"Line2 Capture Volume"
,
"Line1/Mic Capture Volume"
);
rename_ctl
(
card
,
"Analog Mix Capture Volume"
,
"Line2 Capture Volume"
);
rename_ctl
(
card
,
"Analog Mix Capture Volume"
,
"Line2 Capture Volume"
);
...
...
sound/pci/es1968.c
浏览文件 @
02e5fbf6
...
@@ -112,6 +112,10 @@
...
@@ -112,6 +112,10 @@
#include <sound/ac97_codec.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/initval.h>
#ifdef CONFIG_SND_ES1968_RADIO
#include <sound/tea575x-tuner.h>
#endif
#define CARD_NAME "ESS Maestro1/2"
#define CARD_NAME "ESS Maestro1/2"
#define DRIVER_NAME "ES1968"
#define DRIVER_NAME "ES1968"
...
@@ -553,6 +557,10 @@ struct es1968 {
...
@@ -553,6 +557,10 @@ struct es1968 {
spinlock_t
ac97_lock
;
spinlock_t
ac97_lock
;
struct
tasklet_struct
hwvol_tq
;
struct
tasklet_struct
hwvol_tq
;
#endif
#endif
#ifdef CONFIG_SND_ES1968_RADIO
struct
snd_tea575x
tea
;
#endif
};
};
static
irqreturn_t
snd_es1968_interrupt
(
int
irq
,
void
*
dev_id
);
static
irqreturn_t
snd_es1968_interrupt
(
int
irq
,
void
*
dev_id
);
...
@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip)
...
@@ -2571,6 +2579,63 @@ static int __devinit snd_es1968_input_register(struct es1968 *chip)
}
}
#endif
/* CONFIG_SND_ES1968_INPUT */
#endif
/* CONFIG_SND_ES1968_INPUT */
#ifdef CONFIG_SND_ES1968_RADIO
#define GPIO_DATA 0x60
#define IO_MASK 4
/* mask register offset from GPIO_DATA
bits 1=unmask write to given bit */
#define IO_DIR 8
/* direction register offset from GPIO_DATA
bits 0/1=read/write direction */
/* mask bits for GPIO lines */
#define STR_DATA 0x0040
/* GPIO6 */
#define STR_CLK 0x0080
/* GPIO7 */
#define STR_WREN 0x0100
/* GPIO8 */
#define STR_MOST 0x0200
/* GPIO9 */
static
void
snd_es1968_tea575x_set_pins
(
struct
snd_tea575x
*
tea
,
u8
pins
)
{
struct
es1968
*
chip
=
tea
->
private_data
;
unsigned
long
io
=
chip
->
io_port
+
GPIO_DATA
;
u16
val
=
0
;
val
|=
(
pins
&
TEA575X_DATA
)
?
STR_DATA
:
0
;
val
|=
(
pins
&
TEA575X_CLK
)
?
STR_CLK
:
0
;
val
|=
(
pins
&
TEA575X_WREN
)
?
STR_WREN
:
0
;
outw
(
val
,
io
);
}
static
u8
snd_es1968_tea575x_get_pins
(
struct
snd_tea575x
*
tea
)
{
struct
es1968
*
chip
=
tea
->
private_data
;
unsigned
long
io
=
chip
->
io_port
+
GPIO_DATA
;
u16
val
=
inw
(
io
);
return
(
val
&
STR_DATA
)
?
TEA575X_DATA
:
0
|
(
val
&
STR_MOST
)
?
TEA575X_MOST
:
0
;
}
static
void
snd_es1968_tea575x_set_direction
(
struct
snd_tea575x
*
tea
,
bool
output
)
{
struct
es1968
*
chip
=
tea
->
private_data
;
unsigned
long
io
=
chip
->
io_port
+
GPIO_DATA
;
u16
odir
=
inw
(
io
+
IO_DIR
);
if
(
output
)
{
outw
(
~
(
STR_DATA
|
STR_CLK
|
STR_WREN
),
io
+
IO_MASK
);
outw
(
odir
|
STR_DATA
|
STR_CLK
|
STR_WREN
,
io
+
IO_DIR
);
}
else
{
outw
(
~
(
STR_CLK
|
STR_WREN
|
STR_DATA
|
STR_MOST
),
io
+
IO_MASK
);
outw
((
odir
&
~
(
STR_DATA
|
STR_MOST
))
|
STR_CLK
|
STR_WREN
,
io
+
IO_DIR
);
}
}
static
struct
snd_tea575x_ops
snd_es1968_tea_ops
=
{
.
set_pins
=
snd_es1968_tea575x_set_pins
,
.
get_pins
=
snd_es1968_tea575x_get_pins
,
.
set_direction
=
snd_es1968_tea575x_set_direction
,
};
#endif
static
int
snd_es1968_free
(
struct
es1968
*
chip
)
static
int
snd_es1968_free
(
struct
es1968
*
chip
)
{
{
#ifdef CONFIG_SND_ES1968_INPUT
#ifdef CONFIG_SND_ES1968_INPUT
...
@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip)
...
@@ -2585,6 +2650,10 @@ static int snd_es1968_free(struct es1968 *chip)
outw
(
0
,
chip
->
io_port
+
ESM_PORT_HOST_IRQ
);
/* disable IRQ */
outw
(
0
,
chip
->
io_port
+
ESM_PORT_HOST_IRQ
);
/* disable IRQ */
}
}
#ifdef CONFIG_SND_ES1968_RADIO
snd_tea575x_exit
(
&
chip
->
tea
);
#endif
if
(
chip
->
irq
>=
0
)
if
(
chip
->
irq
>=
0
)
free_irq
(
chip
->
irq
,
chip
);
free_irq
(
chip
->
irq
,
chip
);
snd_es1968_free_gameport
(
chip
);
snd_es1968_free_gameport
(
chip
);
...
@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card,
...
@@ -2723,6 +2792,15 @@ static int __devinit snd_es1968_create(struct snd_card *card,
snd_card_set_dev
(
card
,
&
pci
->
dev
);
snd_card_set_dev
(
card
,
&
pci
->
dev
);
#ifdef CONFIG_SND_ES1968_RADIO
chip
->
tea
.
private_data
=
chip
;
chip
->
tea
.
ops
=
&
snd_es1968_tea_ops
;
strlcpy
(
chip
->
tea
.
card
,
"SF64-PCE2"
,
sizeof
(
chip
->
tea
.
card
));
sprintf
(
chip
->
tea
.
bus_info
,
"PCI:%s"
,
pci_name
(
pci
));
if
(
!
snd_tea575x_init
(
&
chip
->
tea
))
printk
(
KERN_INFO
"es1968: detected TEA575x radio
\n
"
);
#endif
*
chip_ret
=
chip
;
*
chip_ret
=
chip
;
return
0
;
return
0
;
...
...
sound/pci/fm801.c
浏览文件 @
02e5fbf6
...
@@ -38,7 +38,6 @@
...
@@ -38,7 +38,6 @@
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
#include <sound/tea575x-tuner.h>
#include <sound/tea575x-tuner.h>
#define TEA575X_RADIO 1
#endif
#endif
MODULE_AUTHOR
(
"Jaroslav Kysela <perex@perex.cz>"
);
MODULE_AUTHOR
(
"Jaroslav Kysela <perex@perex.cz>"
);
...
@@ -53,7 +52,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
...
@@ -53,7 +52,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
/*
/*
* Enable TEA575x tuner
* Enable TEA575x tuner
* 1 = MediaForte 256-PCS
* 1 = MediaForte 256-PCS
* 2 = MediaForte 256-PCP
R
* 2 = MediaForte 256-PCP
* 3 = MediaForte 64-PCR
* 3 = MediaForte 64-PCR
* 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card
* 16 = setup tuner only (this is additional bit), i.e. SF64-PCR FM card
* High 16-bits are video (radio) device number + 1
* High 16-bits are video (radio) device number + 1
...
@@ -67,7 +66,7 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
...
@@ -67,7 +66,7 @@ MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
module_param_array
(
enable
,
bool
,
NULL
,
0444
);
module_param_array
(
enable
,
bool
,
NULL
,
0444
);
MODULE_PARM_DESC
(
enable
,
"Enable FM801 soundcard."
);
MODULE_PARM_DESC
(
enable
,
"Enable FM801 soundcard."
);
module_param_array
(
tea575x_tuner
,
int
,
NULL
,
0444
);
module_param_array
(
tea575x_tuner
,
int
,
NULL
,
0444
);
MODULE_PARM_DESC
(
tea575x_tuner
,
"TEA575x tuner access method (
1 = SF256-PCS, 2=SF256-PCPR, 3=SF64-PCR
, +16=tuner-only)."
);
MODULE_PARM_DESC
(
tea575x_tuner
,
"TEA575x tuner access method (
0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable
, +16=tuner-only)."
);
#define TUNER_ONLY (1<<4)
#define TUNER_ONLY (1<<4)
#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF)
#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF)
...
@@ -196,7 +195,7 @@ struct fm801 {
...
@@ -196,7 +195,7 @@ struct fm801 {
spinlock_t
reg_lock
;
spinlock_t
reg_lock
;
struct
snd_info_entry
*
proc_entry
;
struct
snd_info_entry
*
proc_entry
;
#ifdef
TEA575X_RADIO
#ifdef
CONFIG_SND_FM801_TEA575X_BOOL
struct
snd_tea575x
tea
;
struct
snd_tea575x
tea
;
#endif
#endif
...
@@ -715,310 +714,89 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc
...
@@ -715,310 +714,89 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc
* TEA5757 radio
* TEA5757 radio
*/
*/
#ifdef TEA575X_RADIO
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
/* 256PCS GPIO numbers */
#define TEA_256PCS_DATA 1
#define TEA_256PCS_WRITE_ENABLE 2
/* inverted */
#define TEA_256PCS_BUS_CLOCK 3
static
void
snd_fm801_tea575x_256pcs_write
(
struct
snd_tea575x
*
tea
,
unsigned
int
val
)
{
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
int
i
=
25
;
spin_lock_irq
(
&
chip
->
reg_lock
);
/* GPIO to TEA575x maps */
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
struct
snd_fm801_tea575x_gpio
{
/* use GPIO lines and set write enable bit */
u8
data
,
clk
,
wren
,
most
;
reg
|=
FM801_GPIO_GS
(
TEA_256PCS_DATA
)
|
char
*
name
;
FM801_GPIO_GS
(
TEA_256PCS_WRITE_ENABLE
)
|
};
FM801_GPIO_GS
(
TEA_256PCS_BUS_CLOCK
);
/* all of lines are in the write direction */
/* clear data and clock lines */
reg
&=
~
(
FM801_GPIO_GD
(
TEA_256PCS_DATA
)
|
FM801_GPIO_GD
(
TEA_256PCS_WRITE_ENABLE
)
|
FM801_GPIO_GD
(
TEA_256PCS_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCS_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCS_WRITE_ENABLE
));
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
while
(
i
--
)
{
if
(
val
&
(
1
<<
i
))
reg
|=
FM801_GPIO_GP
(
TEA_256PCS_DATA
);
else
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCS_DATA
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
reg
|=
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
}
/* and reset the write enable bit */
static
struct
snd_fm801_tea575x_gpio
snd_fm801_tea575x_gpios
[]
=
{
reg
|=
FM801_GPIO_GP
(
TEA_256PCS_WRITE_ENABLE
)
|
{
.
data
=
1
,
.
clk
=
3
,
.
wren
=
2
,
.
most
=
0
,
.
name
=
"SF256-PCS"
},
FM801_GPIO_GP
(
TEA_256PCS_DATA
);
{
.
data
=
1
,
.
clk
=
0
,
.
wren
=
2
,
.
most
=
3
,
.
name
=
"SF256-PCP"
},
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
{
.
data
=
2
,
.
clk
=
0
,
.
wren
=
1
,
.
most
=
3
,
.
name
=
"SF64-PCR"
},
spin_unlock_irq
(
&
chip
->
reg_lock
);
};
}
static
unsigned
int
snd_fm801_tea575x_256pcs_read
(
struct
snd_tea575x
*
tea
)
static
void
snd_fm801_tea575x_set_pins
(
struct
snd_tea575x
*
tea
,
u8
pins
)
{
{
struct
fm801
*
chip
=
tea
->
private_data
;
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
unsigned
short
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
unsigned
int
val
=
0
;
struct
snd_fm801_tea575x_gpio
gpio
=
snd_fm801_tea575x_gpios
[(
chip
->
tea575x_tuner
&
TUNER_TYPE_MASK
)
-
1
];
int
i
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
/* use GPIO lines, set data direction to input */
reg
|=
FM801_GPIO_GS
(
TEA_256PCS_DATA
)
|
FM801_GPIO_GS
(
TEA_256PCS_WRITE_ENABLE
)
|
FM801_GPIO_GS
(
TEA_256PCS_BUS_CLOCK
)
|
FM801_GPIO_GD
(
TEA_256PCS_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCS_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCS_WRITE_ENABLE
);
/* all of lines are in the write direction, except data */
/* clear data, write enable and clock lines */
reg
&=
~
(
FM801_GPIO_GD
(
TEA_256PCS_WRITE_ENABLE
)
|
FM801_GPIO_GD
(
TEA_256PCS_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
));
for
(
i
=
0
;
i
<
24
;
i
++
)
{
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
reg
|=
FM801_GPIO_GP
(
TEA_256PCS_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
val
<<=
1
;
if
(
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
))
&
FM801_GPIO_GP
(
TEA_256PCS_DATA
))
val
|=
1
;
}
spin_unlock_irq
(
&
chip
->
reg_lock
);
reg
&=
~
(
FM801_GPIO_GP
(
gpio
.
data
)
|
FM801_GPIO_GP
(
gpio
.
clk
)
|
FM801_GPIO_GP
(
gpio
.
wren
));
return
val
;
reg
|=
(
pins
&
TEA575X_DATA
)
?
FM801_GPIO_GP
(
gpio
.
data
)
:
0
;
}
reg
|=
(
pins
&
TEA575X_CLK
)
?
FM801_GPIO_GP
(
gpio
.
clk
)
:
0
;
/* WRITE_ENABLE is inverted */
reg
|=
(
pins
&
TEA575X_WREN
)
?
0
:
FM801_GPIO_GP
(
gpio
.
wren
);
/* 256PCPR GPIO numbers */
#define TEA_256PCPR_BUS_CLOCK 0
#define TEA_256PCPR_DATA 1
#define TEA_256PCPR_WRITE_ENABLE 2
/* inverted */
static
void
snd_fm801_tea575x_256pcpr_write
(
struct
snd_tea575x
*
tea
,
unsigned
int
val
)
{
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
int
i
=
25
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
/* use GPIO lines and set write enable bit */
reg
|=
FM801_GPIO_GS
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GS
(
TEA_256PCPR_WRITE_ENABLE
)
|
FM801_GPIO_GS
(
TEA_256PCPR_BUS_CLOCK
);
/* all of lines are in the write direction */
/* clear data and clock lines */
reg
&=
~
(
FM801_GPIO_GD
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GD
(
TEA_256PCPR_WRITE_ENABLE
)
|
FM801_GPIO_GD
(
TEA_256PCPR_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCPR_WRITE_ENABLE
));
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
while
(
i
--
)
{
if
(
val
&
(
1
<<
i
))
reg
|=
FM801_GPIO_GP
(
TEA_256PCPR_DATA
);
else
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCPR_DATA
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
reg
|=
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
}
/* and reset the write enable bit */
reg
|=
FM801_GPIO_GP
(
TEA_256PCPR_WRITE_ENABLE
)
|
FM801_GPIO_GP
(
TEA_256PCPR_DATA
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
spin_unlock_irq
(
&
chip
->
reg_lock
);
}
}
static
u
nsigned
int
snd_fm801_tea575x_256pcpr_read
(
struct
snd_tea575x
*
tea
)
static
u
8
snd_fm801_tea575x_get_pins
(
struct
snd_tea575x
*
tea
)
{
{
struct
fm801
*
chip
=
tea
->
private_data
;
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
unsigned
short
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
unsigned
int
val
=
0
;
struct
snd_fm801_tea575x_gpio
gpio
=
snd_fm801_tea575x_gpios
[(
chip
->
tea575x_tuner
&
TUNER_TYPE_MASK
)
-
1
];
int
i
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
/* use GPIO lines, set data direction to input */
reg
|=
FM801_GPIO_GS
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GS
(
TEA_256PCPR_WRITE_ENABLE
)
|
FM801_GPIO_GS
(
TEA_256PCPR_BUS_CLOCK
)
|
FM801_GPIO_GD
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCPR_DATA
)
|
FM801_GPIO_GP
(
TEA_256PCPR_WRITE_ENABLE
);
/* all of lines are in the write direction, except data */
/* clear data, write enable and clock lines */
reg
&=
~
(
FM801_GPIO_GD
(
TEA_256PCPR_WRITE_ENABLE
)
|
FM801_GPIO_GD
(
TEA_256PCPR_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
));
for
(
i
=
0
;
i
<
24
;
i
++
)
{
reg
&=
~
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
reg
|=
FM801_GPIO_GP
(
TEA_256PCPR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
val
<<=
1
;
if
(
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
))
&
FM801_GPIO_GP
(
TEA_256PCPR_DATA
))
val
|=
1
;
}
spin_unlock_irq
(
&
chip
->
reg_lock
);
return
(
reg
&
FM801_GPIO_GP
(
gpio
.
data
))
?
TEA575X_DATA
:
0
|
(
reg
&
FM801_GPIO_GP
(
gpio
.
most
))
?
TEA575X_MOST
:
0
;
return
val
;
}
}
/* 64PCR GPIO numbers */
static
void
snd_fm801_tea575x_set_direction
(
struct
snd_tea575x
*
tea
,
bool
output
)
#define TEA_64PCR_BUS_CLOCK 0
#define TEA_64PCR_WRITE_ENABLE 1
/* inverted */
#define TEA_64PCR_DATA 2
static
void
snd_fm801_tea575x_64pcr_write
(
struct
snd_tea575x
*
tea
,
unsigned
int
val
)
{
{
struct
fm801
*
chip
=
tea
->
private_data
;
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
unsigned
short
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
))
;
int
i
=
25
;
struct
snd_fm801_tea575x_gpio
gpio
=
snd_fm801_tea575x_gpios
[(
chip
->
tea575x_tuner
&
TUNER_TYPE_MASK
)
-
1
]
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
/* use GPIO lines and set write enable bit */
/* use GPIO lines and set write enable bit */
reg
|=
FM801_GPIO_GS
(
TEA_64PCR_DATA
)
|
reg
|=
FM801_GPIO_GS
(
gpio
.
data
)
|
FM801_GPIO_GS
(
TEA_64PCR_WRITE_ENABLE
)
|
FM801_GPIO_GS
(
gpio
.
wren
)
|
FM801_GPIO_GS
(
TEA_64PCR_BUS_CLOCK
);
FM801_GPIO_GS
(
gpio
.
clk
)
|
/* all of lines are in the write direction */
FM801_GPIO_GS
(
gpio
.
most
);
/* clear data and clock lines */
if
(
output
)
{
reg
&=
~
(
FM801_GPIO_GD
(
TEA_64PCR_DATA
)
|
/* all of lines are in the write direction */
FM801_GPIO_GD
(
TEA_64PCR_WRITE_ENABLE
)
|
/* clear data and clock lines */
FM801_GPIO_GD
(
TEA_64PCR_BUS_CLOCK
)
|
reg
&=
~
(
FM801_GPIO_GD
(
gpio
.
data
)
|
FM801_GPIO_GP
(
TEA_64PCR_DATA
)
|
FM801_GPIO_GD
(
gpio
.
wren
)
|
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
)
|
FM801_GPIO_GD
(
gpio
.
clk
)
|
FM801_GPIO_GP
(
TEA_64PCR_WRITE_ENABLE
));
FM801_GPIO_GP
(
gpio
.
data
)
|
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
FM801_GPIO_GP
(
gpio
.
clk
)
|
udelay
(
1
);
FM801_GPIO_GP
(
gpio
.
wren
));
}
else
{
while
(
i
--
)
{
/* use GPIO lines, set data direction to input */
if
(
val
&
(
1
<<
i
))
reg
|=
FM801_GPIO_GD
(
gpio
.
data
)
|
reg
|=
FM801_GPIO_GP
(
TEA_64PCR_DATA
);
FM801_GPIO_GD
(
gpio
.
most
)
|
else
FM801_GPIO_GP
(
gpio
.
data
)
|
reg
&=
~
FM801_GPIO_GP
(
TEA_64PCR_DATA
);
FM801_GPIO_GP
(
gpio
.
most
)
|
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
FM801_GPIO_GP
(
gpio
.
wren
);
udelay
(
1
);
/* all of lines are in the write direction, except data */
reg
|=
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
);
/* clear data, write enable and clock lines */
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
reg
&=
~
(
FM801_GPIO_GD
(
gpio
.
wren
)
|
reg
&=
~
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
);
FM801_GPIO_GD
(
gpio
.
clk
)
|
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
FM801_GPIO_GP
(
gpio
.
clk
));
udelay
(
1
);
}
}
/* and reset the write enable bit */
reg
|=
FM801_GPIO_GP
(
TEA_64PCR_WRITE_ENABLE
)
|
FM801_GPIO_GP
(
TEA_64PCR_DATA
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
spin_unlock_irq
(
&
chip
->
reg_lock
);
}
static
unsigned
int
snd_fm801_tea575x_64pcr_read
(
struct
snd_tea575x
*
tea
)
{
struct
fm801
*
chip
=
tea
->
private_data
;
unsigned
short
reg
;
unsigned
int
val
=
0
;
int
i
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
/* use GPIO lines, set data direction to input */
reg
|=
FM801_GPIO_GS
(
TEA_64PCR_DATA
)
|
FM801_GPIO_GS
(
TEA_64PCR_WRITE_ENABLE
)
|
FM801_GPIO_GS
(
TEA_64PCR_BUS_CLOCK
)
|
FM801_GPIO_GD
(
TEA_64PCR_DATA
)
|
FM801_GPIO_GP
(
TEA_64PCR_DATA
)
|
FM801_GPIO_GP
(
TEA_64PCR_WRITE_ENABLE
);
/* all of lines are in the write direction, except data */
/* clear data, write enable and clock lines */
reg
&=
~
(
FM801_GPIO_GD
(
TEA_64PCR_WRITE_ENABLE
)
|
FM801_GPIO_GD
(
TEA_64PCR_BUS_CLOCK
)
|
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
));
for
(
i
=
0
;
i
<
24
;
i
++
)
{
reg
&=
~
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
reg
|=
FM801_GPIO_GP
(
TEA_64PCR_BUS_CLOCK
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
val
<<=
1
;
if
(
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
))
&
FM801_GPIO_GP
(
TEA_64PCR_DATA
))
val
|=
1
;
}
spin_unlock_irq
(
&
chip
->
reg_lock
);
return
val
;
}
}
static
void
snd_fm801_tea575x_64pcr_mute
(
struct
snd_tea575x
*
tea
,
static
struct
snd_tea575x_ops
snd_fm801_tea_ops
=
{
unsigned
int
mute
)
.
set_pins
=
snd_fm801_tea575x_set_pins
,
{
.
get_pins
=
snd_fm801_tea575x_get_pins
,
struct
fm801
*
chip
=
tea
->
private_data
;
.
set_direction
=
snd_fm801_tea575x_set_direction
,
unsigned
short
reg
;
spin_lock_irq
(
&
chip
->
reg_lock
);
reg
=
inw
(
FM801_REG
(
chip
,
GPIO_CTRL
));
if
(
mute
)
/* 0xf800 (mute) */
reg
&=
~
FM801_GPIO_GP
(
TEA_64PCR_WRITE_ENABLE
);
else
/* 0xf802 (unmute) */
reg
|=
FM801_GPIO_GP
(
TEA_64PCR_WRITE_ENABLE
);
outw
(
reg
,
FM801_REG
(
chip
,
GPIO_CTRL
));
udelay
(
1
);
spin_unlock_irq
(
&
chip
->
reg_lock
);
}
static
struct
snd_tea575x_ops
snd_fm801_tea_ops
[
3
]
=
{
{
/* 1 = MediaForte 256-PCS */
.
write
=
snd_fm801_tea575x_256pcs_write
,
.
read
=
snd_fm801_tea575x_256pcs_read
,
},
{
/* 2 = MediaForte 256-PCPR */
.
write
=
snd_fm801_tea575x_256pcpr_write
,
.
read
=
snd_fm801_tea575x_256pcpr_read
,
},
{
/* 3 = MediaForte 64-PCR */
.
write
=
snd_fm801_tea575x_64pcr_write
,
.
read
=
snd_fm801_tea575x_64pcr_read
,
.
mute
=
snd_fm801_tea575x_64pcr_mute
,
}
};
};
#endif
#endif
...
@@ -1371,7 +1149,7 @@ static int snd_fm801_free(struct fm801 *chip)
...
@@ -1371,7 +1149,7 @@ static int snd_fm801_free(struct fm801 *chip)
outw
(
cmdw
,
FM801_REG
(
chip
,
IRQ_MASK
));
outw
(
cmdw
,
FM801_REG
(
chip
,
IRQ_MASK
));
__end_hw:
__end_hw:
#ifdef
TEA575X_RADIO
#ifdef
CONFIG_SND_FM801_TEA575X_BOOL
snd_tea575x_exit
(
&
chip
->
tea
);
snd_tea575x_exit
(
&
chip
->
tea
);
#endif
#endif
if
(
chip
->
irq
>=
0
)
if
(
chip
->
irq
>=
0
)
...
@@ -1450,16 +1228,25 @@ static int __devinit snd_fm801_create(struct snd_card *card,
...
@@ -1450,16 +1228,25 @@ static int __devinit snd_fm801_create(struct snd_card *card,
snd_card_set_dev
(
card
,
&
pci
->
dev
);
snd_card_set_dev
(
card
,
&
pci
->
dev
);
#ifdef TEA575X_RADIO
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
chip
->
tea
.
private_data
=
chip
;
chip
->
tea
.
ops
=
&
snd_fm801_tea_ops
;
sprintf
(
chip
->
tea
.
bus_info
,
"PCI:%s"
,
pci_name
(
pci
));
if
((
tea575x_tuner
&
TUNER_TYPE_MASK
)
>
0
&&
if
((
tea575x_tuner
&
TUNER_TYPE_MASK
)
>
0
&&
(
tea575x_tuner
&
TUNER_TYPE_MASK
)
<
4
)
{
(
tea575x_tuner
&
TUNER_TYPE_MASK
)
<
4
)
{
chip
->
tea
.
dev_nr
=
tea575x_tuner
>>
16
;
if
(
snd_tea575x_init
(
&
chip
->
tea
))
chip
->
tea
.
card
=
card
;
snd_printk
(
KERN_ERR
"TEA575x radio not found
\n
"
);
chip
->
tea
.
freq_fixup
=
10700
;
}
else
if
((
tea575x_tuner
&
TUNER_TYPE_MASK
)
==
0
)
chip
->
tea
.
private_data
=
chip
;
/* autodetect tuner connection */
chip
->
tea
.
ops
=
&
snd_fm801_tea_ops
[(
tea575x_tuner
&
TUNER_TYPE_MASK
)
-
1
];
for
(
tea575x_tuner
=
1
;
tea575x_tuner
<=
3
;
tea575x_tuner
++
)
{
snd_tea575x_init
(
&
chip
->
tea
);
chip
->
tea575x_tuner
=
tea575x_tuner
;
}
if
(
!
snd_tea575x_init
(
&
chip
->
tea
))
{
snd_printk
(
KERN_INFO
"detected TEA575x radio type %s
\n
"
,
snd_fm801_tea575x_gpios
[
tea575x_tuner
-
1
].
name
);
break
;
}
}
strlcpy
(
chip
->
tea
.
card
,
snd_fm801_tea575x_gpios
[(
tea575x_tuner
&
TUNER_TYPE_MASK
)
-
1
].
name
,
sizeof
(
chip
->
tea
.
card
));
#endif
#endif
*
rchip
=
chip
;
*
rchip
=
chip
;
...
...
sound/pci/intel8x0m.c
浏览文件 @
02e5fbf6
...
@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = {
...
@@ -235,8 +235,8 @@ static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0m_ids) = {
{
PCI_VDEVICE
(
NVIDIA
,
0x0069
),
DEVICE_NFORCE
},
/* NFORCE2 */
{
PCI_VDEVICE
(
NVIDIA
,
0x0069
),
DEVICE_NFORCE
},
/* NFORCE2 */
{
PCI_VDEVICE
(
NVIDIA
,
0x0089
),
DEVICE_NFORCE
},
/* NFORCE2s */
{
PCI_VDEVICE
(
NVIDIA
,
0x0089
),
DEVICE_NFORCE
},
/* NFORCE2s */
{
PCI_VDEVICE
(
NVIDIA
,
0x00d9
),
DEVICE_NFORCE
},
/* NFORCE3 */
{
PCI_VDEVICE
(
NVIDIA
,
0x00d9
),
DEVICE_NFORCE
},
/* NFORCE3 */
{
PCI_VDEVICE
(
AMD
,
0x746e
),
DEVICE_INTEL
},
/* AMD8111 */
#if 0
#if 0
{ PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */
{ PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
{ PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
#endif
#endif
{
0
,
}
{
0
,
}
...
@@ -1261,9 +1261,9 @@ static struct shortname_table {
...
@@ -1261,9 +1261,9 @@ static struct shortname_table {
{
PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
,
"NVidia nForce2"
},
{
PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
,
"NVidia nForce2"
},
{
PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
,
"NVidia nForce2s"
},
{
PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
,
"NVidia nForce2s"
},
{
PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
,
"NVidia nForce3"
},
{
PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
,
"NVidia nForce3"
},
{
0x746e
,
"AMD AMD8111"
},
#if 0
#if 0
{ 0x5455, "ALi M5455" },
{ 0x5455, "ALi M5455" },
{ 0x746d, "AMD AMD8111" },
#endif
#endif
{
0
},
{
0
},
};
};
...
...
sound/ppc/tumbler.c
浏览文件 @
02e5fbf6
...
@@ -1000,7 +1000,7 @@ static void device_change_handler(struct work_struct *work)
...
@@ -1000,7 +1000,7 @@ static void device_change_handler(struct work_struct *work)
chip
->
lineout_sw_ctl
);
chip
->
lineout_sw_ctl
);
if
(
mix
->
anded_reset
)
if
(
mix
->
anded_reset
)
msleep
(
10
);
msleep
(
10
);
check_mute
(
chip
,
&
mix
->
amp_mute
,
1
,
mix
->
auto_mute_notify
,
check_mute
(
chip
,
&
mix
->
amp_mute
,
!
IS_G4DA
,
mix
->
auto_mute_notify
,
chip
->
speaker_sw_ctl
);
chip
->
speaker_sw_ctl
);
}
else
{
}
else
{
/* unmute speaker, mute others */
/* unmute speaker, mute others */
...
...
sound/usb/6fire/control.c
浏览文件 @
02e5fbf6
...
@@ -65,6 +65,15 @@ init_data[] = {
...
@@ -65,6 +65,15 @@ init_data[] = {
{
0
}
/* TERMINATING ENTRY */
{
0
}
/* TERMINATING ENTRY */
};
};
static
const
int
rates_altsetting
[]
=
{
1
,
1
,
2
,
2
,
3
,
3
};
/* values to write to soundcard register for all samplerates */
static
const
u16
rates_6fire_vl
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
};
static
const
u16
rates_6fire_vh
[]
=
{
0x11
,
0x11
,
0x10
,
0x10
,
0x00
,
0x00
};
enum
{
DIGITAL_THRU_ONLY_SAMPLERATE
=
3
};
static
void
usb6fire_control_master_vol_update
(
struct
control_runtime
*
rt
)
static
void
usb6fire_control_master_vol_update
(
struct
control_runtime
*
rt
)
{
{
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
...
@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
...
@@ -95,6 +104,67 @@ static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
}
}
}
}
static
int
usb6fire_control_set_rate
(
struct
control_runtime
*
rt
,
int
rate
)
{
int
ret
;
struct
usb_device
*
device
=
rt
->
chip
->
dev
;
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
if
(
rate
<
0
||
rate
>=
CONTROL_N_RATES
)
return
-
EINVAL
;
ret
=
usb_set_interface
(
device
,
1
,
rates_altsetting
[
rate
]);
if
(
ret
<
0
)
return
ret
;
/* set soundcard clock */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x01
,
rates_6fire_vl
[
rate
],
rates_6fire_vh
[
rate
]);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
usb6fire_control_set_channels
(
struct
control_runtime
*
rt
,
int
n_analog_out
,
int
n_analog_in
,
bool
spdif_out
,
bool
spdif_in
)
{
int
ret
;
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
/* enable analog inputs and outputs
* (one bit per stereo-channel) */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x02
,
(
1
<<
(
n_analog_out
/
2
))
-
1
,
(
1
<<
(
n_analog_in
/
2
))
-
1
);
if
(
ret
<
0
)
return
ret
;
/* disable digital inputs and outputs */
/* TODO: use spdif_x to enable/disable digital channels */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x03
,
0x00
,
0x00
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
usb6fire_control_streaming_update
(
struct
control_runtime
*
rt
)
{
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
if
(
comm_rt
)
{
if
(
!
rt
->
usb_streaming
&&
rt
->
digital_thru_switch
)
usb6fire_control_set_rate
(
rt
,
DIGITAL_THRU_ONLY_SAMPLERATE
);
return
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x00
,
0x00
,
(
rt
->
usb_streaming
?
0x01
:
0x00
)
|
(
rt
->
digital_thru_switch
?
0x08
:
0x00
));
}
return
-
EINVAL
;
}
static
int
usb6fire_control_master_vol_info
(
struct
snd_kcontrol
*
kcontrol
,
static
int
usb6fire_control_master_vol_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
struct
snd_ctl_elem_info
*
uinfo
)
{
{
...
@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
...
@@ -195,6 +265,28 @@ static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
return
0
;
return
0
;
}
}
static
int
usb6fire_control_digital_thru_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
control_runtime
*
rt
=
snd_kcontrol_chip
(
kcontrol
);
int
changed
=
0
;
if
(
rt
->
digital_thru_switch
!=
ucontrol
->
value
.
integer
.
value
[
0
])
{
rt
->
digital_thru_switch
=
ucontrol
->
value
.
integer
.
value
[
0
];
usb6fire_control_streaming_update
(
rt
);
changed
=
1
;
}
return
changed
;
}
static
int
usb6fire_control_digital_thru_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
control_runtime
*
rt
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
rt
->
digital_thru_switch
;
return
0
;
}
static
struct
__devinitdata
snd_kcontrol_new
elements
[]
=
{
static
struct
__devinitdata
snd_kcontrol_new
elements
[]
=
{
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
...
@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
...
@@ -223,6 +315,15 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
.
get
=
usb6fire_control_opt_coax_get
,
.
get
=
usb6fire_control_opt_coax_get
,
.
put
=
usb6fire_control_opt_coax_put
.
put
=
usb6fire_control_opt_coax_put
},
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Digital Thru Playback Route"
,
.
index
=
0
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READWRITE
,
.
info
=
snd_ctl_boolean_mono_info
,
.
get
=
usb6fire_control_digital_thru_get
,
.
put
=
usb6fire_control_digital_thru_put
},
{}
{}
};
};
...
@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
...
@@ -238,6 +339,9 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
return
-
ENOMEM
;
return
-
ENOMEM
;
rt
->
chip
=
chip
;
rt
->
chip
=
chip
;
rt
->
update_streaming
=
usb6fire_control_streaming_update
;
rt
->
set_rate
=
usb6fire_control_set_rate
;
rt
->
set_channels
=
usb6fire_control_set_channels
;
i
=
0
;
i
=
0
;
while
(
init_data
[
i
].
type
)
{
while
(
init_data
[
i
].
type
)
{
...
@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
...
@@ -249,6 +353,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
usb6fire_control_opt_coax_update
(
rt
);
usb6fire_control_opt_coax_update
(
rt
);
usb6fire_control_line_phono_update
(
rt
);
usb6fire_control_line_phono_update
(
rt
);
usb6fire_control_master_vol_update
(
rt
);
usb6fire_control_master_vol_update
(
rt
);
usb6fire_control_streaming_update
(
rt
);
i
=
0
;
i
=
0
;
while
(
elements
[
i
].
name
)
{
while
(
elements
[
i
].
name
)
{
...
...
sound/usb/6fire/control.h
浏览文件 @
02e5fbf6
...
@@ -21,12 +21,29 @@ enum {
...
@@ -21,12 +21,29 @@ enum {
CONTROL_MAX_ELEMENTS
=
32
CONTROL_MAX_ELEMENTS
=
32
};
};
enum
{
CONTROL_RATE_44KHZ
,
CONTROL_RATE_48KHZ
,
CONTROL_RATE_88KHZ
,
CONTROL_RATE_96KHZ
,
CONTROL_RATE_176KHZ
,
CONTROL_RATE_192KHZ
,
CONTROL_N_RATES
};
struct
control_runtime
{
struct
control_runtime
{
int
(
*
update_streaming
)(
struct
control_runtime
*
rt
);
int
(
*
set_rate
)(
struct
control_runtime
*
rt
,
int
rate
);
int
(
*
set_channels
)(
struct
control_runtime
*
rt
,
int
n_analog_out
,
int
n_analog_in
,
bool
spdif_out
,
bool
spdif_in
);
struct
sfire_chip
*
chip
;
struct
sfire_chip
*
chip
;
struct
snd_kcontrol
*
element
[
CONTROL_MAX_ELEMENTS
];
struct
snd_kcontrol
*
element
[
CONTROL_MAX_ELEMENTS
];
bool
opt_coax_switch
;
bool
opt_coax_switch
;
bool
line_phono_switch
;
bool
line_phono_switch
;
bool
digital_thru_switch
;
bool
usb_streaming
;
u8
master_vol
;
u8
master_vol
;
};
};
...
...
sound/usb/6fire/firmware.c
浏览文件 @
02e5fbf6
...
@@ -3,12 +3,6 @@
...
@@ -3,12 +3,6 @@
*
*
* Firmware loader
* Firmware loader
*
*
* Currently not working for all devices. To be able to use the device
* in linux, it is also possible to let the windows driver upload the firmware.
* For that, start the computer in windows and reboot.
* As long as the device is connected to the power supply, no firmware reload
* needs to be performed.
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
* Created: Jan 01, 2011
* Version: 0.3.0
* Version: 0.3.0
...
@@ -21,6 +15,7 @@
...
@@ -21,6 +15,7 @@
*/
*/
#include <linux/firmware.h>
#include <linux/firmware.h>
#include <linux/bitrev.h>
#include "firmware.h"
#include "firmware.h"
#include "chip.h"
#include "chip.h"
...
@@ -33,32 +28,6 @@ enum {
...
@@ -33,32 +28,6 @@ enum {
FPGA_BUFSIZE
=
512
,
FPGA_EP
=
2
FPGA_BUFSIZE
=
512
,
FPGA_EP
=
2
};
};
static
const
u8
BIT_REVERSE_TABLE
[
256
]
=
{
0x00
,
0x80
,
0x40
,
0xc0
,
0x20
,
0xa0
,
0x60
,
0xe0
,
0x10
,
0x90
,
0x50
,
0xd0
,
0x30
,
0xb0
,
0x70
,
0xf0
,
0x08
,
0x88
,
0x48
,
0xc8
,
0x28
,
0xa8
,
0x68
,
0xe8
,
0x18
,
0x98
,
0x58
,
0xd8
,
0x38
,
0xb8
,
0x78
,
0xf8
,
0x04
,
0x84
,
0x44
,
0xc4
,
0x24
,
0xa4
,
0x64
,
0xe4
,
0x14
,
0x94
,
0x54
,
0xd4
,
0x34
,
0xb4
,
0x74
,
0xf4
,
0x0c
,
0x8c
,
0x4c
,
0xcc
,
0x2c
,
0xac
,
0x6c
,
0xec
,
0x1c
,
0x9c
,
0x5c
,
0xdc
,
0x3c
,
0xbc
,
0x7c
,
0xfc
,
0x02
,
0x82
,
0x42
,
0xc2
,
0x22
,
0xa2
,
0x62
,
0xe2
,
0x12
,
0x92
,
0x52
,
0xd2
,
0x32
,
0xb2
,
0x72
,
0xf2
,
0x0a
,
0x8a
,
0x4a
,
0xca
,
0x2a
,
0xaa
,
0x6a
,
0xea
,
0x1a
,
0x9a
,
0x5a
,
0xda
,
0x3a
,
0xba
,
0x7a
,
0xfa
,
0x06
,
0x86
,
0x46
,
0xc6
,
0x26
,
0xa6
,
0x66
,
0xe6
,
0x16
,
0x96
,
0x56
,
0xd6
,
0x36
,
0xb6
,
0x76
,
0xf6
,
0x0e
,
0x8e
,
0x4e
,
0xce
,
0x2e
,
0xae
,
0x6e
,
0xee
,
0x1e
,
0x9e
,
0x5e
,
0xde
,
0x3e
,
0xbe
,
0x7e
,
0xfe
,
0x01
,
0x81
,
0x41
,
0xc1
,
0x21
,
0xa1
,
0x61
,
0xe1
,
0x11
,
0x91
,
0x51
,
0xd1
,
0x31
,
0xb1
,
0x71
,
0xf1
,
0x09
,
0x89
,
0x49
,
0xc9
,
0x29
,
0xa9
,
0x69
,
0xe9
,
0x19
,
0x99
,
0x59
,
0xd9
,
0x39
,
0xb9
,
0x79
,
0xf9
,
0x05
,
0x85
,
0x45
,
0xc5
,
0x25
,
0xa5
,
0x65
,
0xe5
,
0x15
,
0x95
,
0x55
,
0xd5
,
0x35
,
0xb5
,
0x75
,
0xf5
,
0x0d
,
0x8d
,
0x4d
,
0xcd
,
0x2d
,
0xad
,
0x6d
,
0xed
,
0x1d
,
0x9d
,
0x5d
,
0xdd
,
0x3d
,
0xbd
,
0x7d
,
0xfd
,
0x03
,
0x83
,
0x43
,
0xc3
,
0x23
,
0xa3
,
0x63
,
0xe3
,
0x13
,
0x93
,
0x53
,
0xd3
,
0x33
,
0xb3
,
0x73
,
0xf3
,
0x0b
,
0x8b
,
0x4b
,
0xcb
,
0x2b
,
0xab
,
0x6b
,
0xeb
,
0x1b
,
0x9b
,
0x5b
,
0xdb
,
0x3b
,
0xbb
,
0x7b
,
0xfb
,
0x07
,
0x87
,
0x47
,
0xc7
,
0x27
,
0xa7
,
0x67
,
0xe7
,
0x17
,
0x97
,
0x57
,
0xd7
,
0x37
,
0xb7
,
0x77
,
0xf7
,
0x0f
,
0x8f
,
0x4f
,
0xcf
,
0x2f
,
0xaf
,
0x6f
,
0xef
,
0x1f
,
0x9f
,
0x5f
,
0xdf
,
0x3f
,
0xbf
,
0x7f
,
0xff
};
/*
/*
* wMaxPacketSize of pcm endpoints.
* wMaxPacketSize of pcm endpoints.
* keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
* keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
...
@@ -72,6 +41,10 @@ static const u8 ep_w_max_packet_size[] = {
...
@@ -72,6 +41,10 @@ static const u8 ep_w_max_packet_size[] = {
0x94
,
0x01
,
0x5c
,
0x02
/* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
0x94
,
0x01
,
0x5c
,
0x02
/* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
};
};
static
const
u8
known_fw_versions
[][
4
]
=
{
{
0x03
,
0x01
,
0x0b
,
0x00
}
};
struct
ihex_record
{
struct
ihex_record
{
u16
address
;
u16
address
;
u8
len
;
u8
len
;
...
@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload(
...
@@ -340,7 +313,7 @@ static int usb6fire_fw_fpga_upload(
while
(
c
!=
end
)
{
while
(
c
!=
end
)
{
for
(
i
=
0
;
c
!=
end
&&
i
<
FPGA_BUFSIZE
;
i
++
,
c
++
)
for
(
i
=
0
;
c
!=
end
&&
i
<
FPGA_BUFSIZE
;
i
++
,
c
++
)
buffer
[
i
]
=
BIT_REVERSE_TABLE
[(
u8
)
*
c
];
buffer
[
i
]
=
byte_rev_table
[(
u8
)
*
c
];
ret
=
usb6fire_fw_fpga_write
(
device
,
buffer
,
i
);
ret
=
usb6fire_fw_fpga_write
(
device
,
buffer
,
i
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
...
@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload(
...
@@ -363,6 +336,25 @@ static int usb6fire_fw_fpga_upload(
return
0
;
return
0
;
}
}
/* check, if the firmware version the devices has currently loaded
* is known by this driver. 'version' needs to have 4 bytes version
* info data. */
static
int
usb6fire_fw_check
(
u8
*
version
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
known_fw_versions
);
i
++
)
if
(
!
memcmp
(
version
,
known_fw_versions
+
i
,
4
))
return
0
;
snd_printk
(
KERN_ERR
PREFIX
"invalid fimware version in device: "
"%02x %02x %02x %02x. "
"please reconnect to power. if this failure "
"still happens, check your firmware installation."
,
version
[
0
],
version
[
1
],
version
[
2
],
version
[
3
]);
return
-
EINVAL
;
}
int
usb6fire_fw_init
(
struct
usb_interface
*
intf
)
int
usb6fire_fw_init
(
struct
usb_interface
*
intf
)
{
{
int
i
;
int
i
;
...
@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
...
@@ -378,9 +370,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
"firmware state.
\n
"
);
"firmware state.
\n
"
);
return
ret
;
return
ret
;
}
}
if
(
buffer
[
0
]
!=
0xeb
||
buffer
[
1
]
!=
0xaa
||
buffer
[
2
]
!=
0x55
if
(
buffer
[
0
]
!=
0xeb
||
buffer
[
1
]
!=
0xaa
||
buffer
[
2
]
!=
0x55
)
{
||
buffer
[
4
]
!=
0x03
||
buffer
[
5
]
!=
0x01
||
buffer
[
7
]
!=
0x00
)
{
snd_printk
(
KERN_ERR
PREFIX
"unknown device firmware state "
snd_printk
(
KERN_ERR
PREFIX
"unknown device firmware state "
"received from device: "
);
"received from device: "
);
for
(
i
=
0
;
i
<
8
;
i
++
)
for
(
i
=
0
;
i
<
8
;
i
++
)
...
@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
...
@@ -389,7 +379,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
return
-
EIO
;
return
-
EIO
;
}
}
/* do we need fpga loader ezusb firmware? */
/* do we need fpga loader ezusb firmware? */
if
(
buffer
[
3
]
==
0x01
&&
buffer
[
6
]
==
0x19
)
{
if
(
buffer
[
3
]
==
0x01
)
{
ret
=
usb6fire_fw_ezusb_upload
(
intf
,
ret
=
usb6fire_fw_ezusb_upload
(
intf
,
"6fire/dmx6firel2.ihx"
,
0
,
NULL
,
0
);
"6fire/dmx6firel2.ihx"
,
0
,
NULL
,
0
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf)
...
@@ -397,7 +387,10 @@ int usb6fire_fw_init(struct usb_interface *intf)
return
FW_NOT_READY
;
return
FW_NOT_READY
;
}
}
/* do we need fpga firmware and application ezusb firmware? */
/* do we need fpga firmware and application ezusb firmware? */
else
if
(
buffer
[
3
]
==
0x02
&&
buffer
[
6
]
==
0x0b
)
{
else
if
(
buffer
[
3
]
==
0x02
)
{
ret
=
usb6fire_fw_check
(
buffer
+
4
);
if
(
ret
<
0
)
return
ret
;
ret
=
usb6fire_fw_fpga_upload
(
intf
,
"6fire/dmx6firecf.bin"
);
ret
=
usb6fire_fw_fpga_upload
(
intf
,
"6fire/dmx6firecf.bin"
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf)
...
@@ -410,8 +403,8 @@ int usb6fire_fw_init(struct usb_interface *intf)
return
FW_NOT_READY
;
return
FW_NOT_READY
;
}
}
/* all fw loaded? */
/* all fw loaded? */
else
if
(
buffer
[
3
]
==
0x03
&&
buffer
[
6
]
==
0x0b
)
else
if
(
buffer
[
3
]
==
0x03
)
return
0
;
return
usb6fire_fw_check
(
buffer
+
4
)
;
/* unknown data? */
/* unknown data? */
else
{
else
{
snd_printk
(
KERN_ERR
PREFIX
"unknown device firmware state "
snd_printk
(
KERN_ERR
PREFIX
"unknown device firmware state "
...
...
sound/usb/6fire/pcm.c
浏览文件 @
02e5fbf6
...
@@ -17,26 +17,23 @@
...
@@ -17,26 +17,23 @@
#include "pcm.h"
#include "pcm.h"
#include "chip.h"
#include "chip.h"
#include "comm.h"
#include "comm.h"
#include "control.h"
enum
{
enum
{
OUT_N_CHANNELS
=
6
,
IN_N_CHANNELS
=
4
OUT_N_CHANNELS
=
6
,
IN_N_CHANNELS
=
4
};
};
/* keep next two synced with
/* keep next two synced with
* FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */
* FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE
* and CONTROL_RATE_XXX in control.h */
static
const
int
rates_in_packet_size
[]
=
{
228
,
228
,
420
,
420
,
404
,
404
};
static
const
int
rates_in_packet_size
[]
=
{
228
,
228
,
420
,
420
,
404
,
404
};
static
const
int
rates_out_packet_size
[]
=
{
228
,
228
,
420
,
420
,
604
,
604
};
static
const
int
rates_out_packet_size
[]
=
{
228
,
228
,
420
,
420
,
604
,
604
};
static
const
int
rates
[]
=
{
44100
,
48000
,
88200
,
96000
,
176400
,
192000
};
static
const
int
rates
[]
=
{
44100
,
48000
,
88200
,
96000
,
176400
,
192000
};
static
const
int
rates_altsetting
[]
=
{
1
,
1
,
2
,
2
,
3
,
3
};
static
const
int
rates_alsaid
[]
=
{
static
const
int
rates_alsaid
[]
=
{
SNDRV_PCM_RATE_44100
,
SNDRV_PCM_RATE_48000
,
SNDRV_PCM_RATE_44100
,
SNDRV_PCM_RATE_48000
,
SNDRV_PCM_RATE_88200
,
SNDRV_PCM_RATE_96000
,
SNDRV_PCM_RATE_88200
,
SNDRV_PCM_RATE_96000
,
SNDRV_PCM_RATE_176400
,
SNDRV_PCM_RATE_192000
};
SNDRV_PCM_RATE_176400
,
SNDRV_PCM_RATE_192000
};
/* values to write to soundcard register for all samplerates */
static
const
u16
rates_6fire_vl
[]
=
{
0x00
,
0x01
,
0x00
,
0x01
,
0x00
,
0x01
};
static
const
u16
rates_6fire_vh
[]
=
{
0x11
,
0x11
,
0x10
,
0x10
,
0x00
,
0x00
};
enum
{
/* settings for pcm */
enum
{
/* settings for pcm */
OUT_EP
=
6
,
IN_EP
=
2
,
MAX_BUFSIZE
=
128
*
1024
OUT_EP
=
6
,
IN_EP
=
2
,
MAX_BUFSIZE
=
128
*
1024
};
};
...
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */
...
@@ -48,15 +45,6 @@ enum { /* pcm streaming states */
STREAM_STOPPING
STREAM_STOPPING
};
};
enum
{
/* pcm sample rates (also index into RATES_XXX[]) */
RATE_44KHZ
,
RATE_48KHZ
,
RATE_88KHZ
,
RATE_96KHZ
,
RATE_176KHZ
,
RATE_192KHZ
};
static
const
struct
snd_pcm_hardware
pcm_hw
=
{
static
const
struct
snd_pcm_hardware
pcm_hw
=
{
.
info
=
SNDRV_PCM_INFO_MMAP
|
.
info
=
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_INTERLEAVED
|
...
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = {
...
@@ -64,7 +52,7 @@ static const struct snd_pcm_hardware pcm_hw = {
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_BATCH
,
SNDRV_PCM_INFO_BATCH
,
.
formats
=
SNDRV_PCM_FMTBIT_S24_LE
,
.
formats
=
SNDRV_PCM_FMTBIT_S24_LE
|
SNDRV_PCM_FMTBIT_S32_LE
,
.
rates
=
SNDRV_PCM_RATE_44100
|
.
rates
=
SNDRV_PCM_RATE_44100
|
SNDRV_PCM_RATE_48000
|
SNDRV_PCM_RATE_48000
|
...
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = {
...
@@ -87,57 +75,34 @@ static const struct snd_pcm_hardware pcm_hw = {
static
int
usb6fire_pcm_set_rate
(
struct
pcm_runtime
*
rt
)
static
int
usb6fire_pcm_set_rate
(
struct
pcm_runtime
*
rt
)
{
{
int
ret
;
int
ret
;
struct
usb_device
*
device
=
rt
->
chip
->
dev
;
struct
control_runtime
*
ctrl_rt
=
rt
->
chip
->
control
;
struct
comm_runtime
*
comm_rt
=
rt
->
chip
->
comm
;
if
(
rt
->
rate
>=
ARRAY_SIZE
(
rates
))
ctrl_rt
->
usb_streaming
=
false
;
return
-
EINVAL
;
ret
=
ctrl_rt
->
update_streaming
(
ctrl_rt
);
/* disable streaming */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x00
,
0x00
,
0x00
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error stopping streaming while "
snd_printk
(
KERN_ERR
PREFIX
"error stopping streaming while "
"setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
"setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
return
ret
;
return
ret
;
}
}
ret
=
usb_set_interface
(
device
,
1
,
rates_altsetting
[
rt
->
rate
]);
ret
=
ctrl_rt
->
set_rate
(
ctrl_rt
,
rt
->
rate
);
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error setting interface "
"altsetting %d for samplerate %d.
\n
"
,
rates_altsetting
[
rt
->
rate
],
rates
[
rt
->
rate
]);
return
ret
;
}
/* set soundcard clock */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x01
,
rates_6fire_vl
[
rt
->
rate
],
rates_6fire_vh
[
rt
->
rate
]);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error setting samplerate %d.
\n
"
,
snd_printk
(
KERN_ERR
PREFIX
"error setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
rates
[
rt
->
rate
]);
return
ret
;
return
ret
;
}
}
/* enable analog inputs and outputs
ret
=
ctrl_rt
->
set_channels
(
ctrl_rt
,
OUT_N_CHANNELS
,
IN_N_CHANNELS
,
* (one bit per stereo-channel) */
false
,
false
);
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x02
,
(
1
<<
(
OUT_N_CHANNELS
/
2
))
-
1
,
(
1
<<
(
IN_N_CHANNELS
/
2
))
-
1
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error initializing
analog
channels "
snd_printk
(
KERN_ERR
PREFIX
"error initializing channels "
"while setting samplerate %d.
\n
"
,
"while setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
rates
[
rt
->
rate
]);
return
ret
;
return
ret
;
}
}
/* disable digital inputs and outputs */
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x03
,
0x00
,
0x00
);
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error initializing digital "
"channels while setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
return
ret
;
}
ret
=
comm_rt
->
write16
(
comm_rt
,
0x02
,
0x00
,
0x00
,
0x01
);
ctrl_rt
->
usb_streaming
=
true
;
ret
=
ctrl_rt
->
update_streaming
(
ctrl_rt
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
snd_printk
(
KERN_ERR
PREFIX
"error starting streaming while "
snd_printk
(
KERN_ERR
PREFIX
"error starting streaming while "
"setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
"setting samplerate %d.
\n
"
,
rates
[
rt
->
rate
]);
...
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
...
@@ -168,12 +133,15 @@ static struct pcm_substream *usb6fire_pcm_get_substream(
static
void
usb6fire_pcm_stream_stop
(
struct
pcm_runtime
*
rt
)
static
void
usb6fire_pcm_stream_stop
(
struct
pcm_runtime
*
rt
)
{
{
int
i
;
int
i
;
struct
control_runtime
*
ctrl_rt
=
rt
->
chip
->
control
;
if
(
rt
->
stream_state
!=
STREAM_DISABLED
)
{
if
(
rt
->
stream_state
!=
STREAM_DISABLED
)
{
for
(
i
=
0
;
i
<
PCM_N_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
PCM_N_URBS
;
i
++
)
{
usb_kill_urb
(
&
rt
->
in_urbs
[
i
].
instance
);
usb_kill_urb
(
&
rt
->
in_urbs
[
i
].
instance
);
usb_kill_urb
(
&
rt
->
out_urbs
[
i
].
instance
);
usb_kill_urb
(
&
rt
->
out_urbs
[
i
].
instance
);
}
}
ctrl_rt
->
usb_streaming
=
false
;
ctrl_rt
->
update_streaming
(
ctrl_rt
);
rt
->
stream_state
=
STREAM_DISABLED
;
rt
->
stream_state
=
STREAM_DISABLED
;
}
}
}
}
...
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
...
@@ -228,7 +196,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
unsigned
int
total_length
=
0
;
unsigned
int
total_length
=
0
;
struct
pcm_runtime
*
rt
=
snd_pcm_substream_chip
(
sub
->
instance
);
struct
pcm_runtime
*
rt
=
snd_pcm_substream_chip
(
sub
->
instance
);
struct
snd_pcm_runtime
*
alsa_rt
=
sub
->
instance
->
runtime
;
struct
snd_pcm_runtime
*
alsa_rt
=
sub
->
instance
->
runtime
;
u32
*
src
=
(
u32
*
)
urb
->
buffer
;
u32
*
src
=
NULL
;
u32
*
dest
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
sub
->
dma_off
u32
*
dest
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
sub
->
dma_off
*
(
alsa_rt
->
frame_bits
>>
3
));
*
(
alsa_rt
->
frame_bits
>>
3
));
u32
*
dest_end
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
alsa_rt
->
buffer_size
u32
*
dest_end
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
alsa_rt
->
buffer_size
...
@@ -244,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
...
@@ -244,7 +212,12 @@ static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
else
else
frame_count
=
0
;
frame_count
=
0
;
src
=
(
u32
*
)
(
urb
->
buffer
+
total_length
);
if
(
alsa_rt
->
format
==
SNDRV_PCM_FORMAT_S24_LE
)
src
=
(
u32
*
)
(
urb
->
buffer
+
total_length
);
else
if
(
alsa_rt
->
format
==
SNDRV_PCM_FORMAT_S32_LE
)
src
=
(
u32
*
)
(
urb
->
buffer
-
1
+
total_length
);
else
return
;
src
++
;
/* skip leading 4 bytes of every packet */
src
++
;
/* skip leading 4 bytes of every packet */
total_length
+=
urb
->
packets
[
i
].
length
;
total_length
+=
urb
->
packets
[
i
].
length
;
for
(
frame
=
0
;
frame
<
frame_count
;
frame
++
)
{
for
(
frame
=
0
;
frame
<
frame_count
;
frame
++
)
{
...
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
...
@@ -274,9 +247,18 @@ static void usb6fire_pcm_playback(struct pcm_substream *sub,
*
(
alsa_rt
->
frame_bits
>>
3
));
*
(
alsa_rt
->
frame_bits
>>
3
));
u32
*
src_end
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
alsa_rt
->
buffer_size
u32
*
src_end
=
(
u32
*
)
(
alsa_rt
->
dma_area
+
alsa_rt
->
buffer_size
*
(
alsa_rt
->
frame_bits
>>
3
));
*
(
alsa_rt
->
frame_bits
>>
3
));
u32
*
dest
=
(
u32
*
)
urb
->
buffer
;
u32
*
dest
;
int
bytes_per_frame
=
alsa_rt
->
channels
<<
2
;
int
bytes_per_frame
=
alsa_rt
->
channels
<<
2
;
if
(
alsa_rt
->
format
==
SNDRV_PCM_FORMAT_S32_LE
)
dest
=
(
u32
*
)
(
urb
->
buffer
-
1
);
else
if
(
alsa_rt
->
format
==
SNDRV_PCM_FORMAT_S24_LE
)
dest
=
(
u32
*
)
(
urb
->
buffer
);
else
{
snd_printk
(
KERN_ERR
PREFIX
"Unknown sample format."
);
return
;
}
for
(
i
=
0
;
i
<
PCM_N_PACKETS_PER_URB
;
i
++
)
{
for
(
i
=
0
;
i
<
PCM_N_PACKETS_PER_URB
;
i
++
)
{
/* at least 4 header bytes for valid packet.
/* at least 4 header bytes for valid packet.
* after that: 32 bits per sample for analog channels */
* after that: 32 bits per sample for analog channels */
...
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
...
@@ -456,7 +438,7 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
/* all substreams closed? if so, stop streaming */
/* all substreams closed? if so, stop streaming */
if
(
!
rt
->
playback
.
instance
&&
!
rt
->
capture
.
instance
)
{
if
(
!
rt
->
playback
.
instance
&&
!
rt
->
capture
.
instance
)
{
usb6fire_pcm_stream_stop
(
rt
);
usb6fire_pcm_stream_stop
(
rt
);
rt
->
rate
=
-
1
;
rt
->
rate
=
ARRAY_SIZE
(
rates
)
;
}
}
}
}
mutex_unlock
(
&
rt
->
stream_mutex
);
mutex_unlock
(
&
rt
->
stream_mutex
);
...
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
...
@@ -480,7 +462,6 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
struct
pcm_runtime
*
rt
=
snd_pcm_substream_chip
(
alsa_sub
);
struct
pcm_runtime
*
rt
=
snd_pcm_substream_chip
(
alsa_sub
);
struct
pcm_substream
*
sub
=
usb6fire_pcm_get_substream
(
alsa_sub
);
struct
pcm_substream
*
sub
=
usb6fire_pcm_get_substream
(
alsa_sub
);
struct
snd_pcm_runtime
*
alsa_rt
=
alsa_sub
->
runtime
;
struct
snd_pcm_runtime
*
alsa_rt
=
alsa_sub
->
runtime
;
int
i
;
int
ret
;
int
ret
;
if
(
rt
->
panic
)
if
(
rt
->
panic
)
...
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
...
@@ -493,12 +474,10 @@ static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
sub
->
period_off
=
0
;
sub
->
period_off
=
0
;
if
(
rt
->
stream_state
==
STREAM_DISABLED
)
{
if
(
rt
->
stream_state
==
STREAM_DISABLED
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
rates
);
i
++
)
for
(
rt
->
rate
=
0
;
rt
->
rate
<
ARRAY_SIZE
(
rates
);
rt
->
rate
++
)
if
(
alsa_rt
->
rate
==
rates
[
i
])
{
if
(
alsa_rt
->
rate
==
rates
[
rt
->
rate
])
rt
->
rate
=
i
;
break
;
break
;
}
if
(
rt
->
rate
==
ARRAY_SIZE
(
rates
))
{
if
(
i
==
ARRAY_SIZE
(
rates
))
{
mutex_unlock
(
&
rt
->
stream_mutex
);
mutex_unlock
(
&
rt
->
stream_mutex
);
snd_printk
(
"invalid rate %d in prepare.
\n
"
,
snd_printk
(
"invalid rate %d in prepare.
\n
"
,
alsa_rt
->
rate
);
alsa_rt
->
rate
);
...
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
...
@@ -613,7 +592,7 @@ int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
rt
->
chip
=
chip
;
rt
->
chip
=
chip
;
rt
->
stream_state
=
STREAM_DISABLED
;
rt
->
stream_state
=
STREAM_DISABLED
;
rt
->
rate
=
-
1
;
rt
->
rate
=
ARRAY_SIZE
(
rates
)
;
init_waitqueue_head
(
&
rt
->
stream_wait_queue
);
init_waitqueue_head
(
&
rt
->
stream_wait_queue
);
mutex_init
(
&
rt
->
stream_mutex
);
mutex_init
(
&
rt
->
stream_mutex
);
...
...
sound/usb/Kconfig
浏览文件 @
02e5fbf6
...
@@ -100,19 +100,17 @@ config SND_USB_US122L
...
@@ -100,19 +100,17 @@ config SND_USB_US122L
config SND_USB_6FIRE
config SND_USB_6FIRE
tristate "TerraTec DMX 6Fire USB"
tristate "TerraTec DMX 6Fire USB"
depends on EXPERIMENTAL
select FW_LOADER
select FW_LOADER
select BITREVERSE
select SND_RAWMIDI
select SND_RAWMIDI
select SND_PCM
select SND_PCM
help
help
Say Y here to include support for TerraTec 6fire DMX USB interface.
Say Y here to include support for TerraTec 6fire DMX USB interface.
You will need firmware files in order to be able to use the device
You will need firmware files in order to be able to use the device
after it has been coldstarted. This driver currently does not support
after it has been coldstarted. An install script for the firmware
firmware loading for all devices. If you own such a device,
and further help can be found at
you could start windows and let the windows driver upload
http://sixfireusb.sourceforge.net
the firmware. As long as you do not unplug your device from power,
it should be usable.
endif # SND_USB
endif # SND_USB
sound/usb/clock.c
浏览文件 @
02e5fbf6
...
@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
...
@@ -104,6 +104,15 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
int
err
;
int
err
;
unsigned
char
data
;
unsigned
char
data
;
struct
usb_device
*
dev
=
chip
->
dev
;
struct
usb_device
*
dev
=
chip
->
dev
;
struct
uac_clock_source_descriptor
*
cs_desc
=
snd_usb_find_clock_source
(
chip
->
ctrl_intf
,
source_id
);
if
(
!
cs_desc
)
return
0
;
/* If a clock source can't tell us whether it's valid, we assume it is */
if
(
!
uac2_control_is_readable
(
cs_desc
->
bmControls
,
UAC2_CS_CONTROL_CLOCK_VALID
))
return
1
;
err
=
snd_usb_ctl_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
UAC2_CS_CUR
,
err
=
snd_usb_ctl_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
UAC2_CS_CUR
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
USB_DIR_IN
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
USB_DIR_IN
,
...
@@ -114,7 +123,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
...
@@ -114,7 +123,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
if
(
err
<
0
)
{
if
(
err
<
0
)
{
snd_printk
(
KERN_WARNING
"%s(): cannot get clock validity for id %d
\n
"
,
snd_printk
(
KERN_WARNING
"%s(): cannot get clock validity for id %d
\n
"
,
__func__
,
source_id
);
__func__
,
source_id
);
return
err
;
return
0
;
}
}
return
!!
data
;
return
!!
data
;
...
...
sound/usb/debug.h
浏览文件 @
02e5fbf6
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
#ifdef HW_CONST_DEBUG
#ifdef HW_CONST_DEBUG
#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args)
#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args)
#else
#else
#define hwc_debug(fmt, args...)
/**/
#define hwc_debug(fmt, args...)
do { } while(0)
#endif
#endif
#endif
/* __USBAUDIO_DEBUG_H */
#endif
/* __USBAUDIO_DEBUG_H */
...
...
sound/usb/format.c
浏览文件 @
02e5fbf6
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#include "helper.h"
#include "helper.h"
#include "debug.h"
#include "debug.h"
#include "clock.h"
#include "clock.h"
#include "format.h"
/*
/*
* parse the audio format type I descriptor
* parse the audio format type I descriptor
...
...
sound/usb/mixer.c
浏览文件 @
02e5fbf6
...
@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
...
@@ -1097,11 +1097,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
append_ctl_name
(
kctl
,
control
==
UAC_FU_MUTE
?
append_ctl_name
(
kctl
,
control
==
UAC_FU_MUTE
?
" Switch"
:
" Volume"
);
" Switch"
:
" Volume"
);
if
(
control
==
UAC_FU_VOLUME
)
{
if
(
control
==
UAC_FU_VOLUME
)
{
kctl
->
tlv
.
c
=
mixer_vol_tlv
;
kctl
->
vd
[
0
].
access
|=
SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
;
check_mapped_dB
(
map
,
cval
);
check_mapped_dB
(
map
,
cval
);
if
(
cval
->
dBmin
<
cval
->
dBmax
)
{
kctl
->
tlv
.
c
=
mixer_vol_tlv
;
kctl
->
vd
[
0
].
access
|=
SNDRV_CTL_ELEM_ACCESS_TLV_READ
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
;
}
}
}
break
;
break
;
...
...
sound/usb/mixer_quirks.c
浏览文件 @
02e5fbf6
...
@@ -61,6 +61,7 @@ static const struct rc_config {
...
@@ -61,6 +61,7 @@ static const struct rc_config {
{
USB_ID
(
0x041e
,
0x3020
),
2
,
1
,
6
,
6
,
18
,
0x0013
},
/* Audigy 2 NX */
{
USB_ID
(
0x041e
,
0x3020
),
2
,
1
,
6
,
6
,
18
,
0x0013
},
/* Audigy 2 NX */
{
USB_ID
(
0x041e
,
0x3040
),
2
,
2
,
6
,
6
,
2
,
0x6e91
},
/* Live! 24-bit */
{
USB_ID
(
0x041e
,
0x3040
),
2
,
2
,
6
,
6
,
2
,
0x6e91
},
/* Live! 24-bit */
{
USB_ID
(
0x041e
,
0x3042
),
0
,
1
,
1
,
1
,
1
,
0x000d
},
/* Usb X-Fi S51 */
{
USB_ID
(
0x041e
,
0x3042
),
0
,
1
,
1
,
1
,
1
,
0x000d
},
/* Usb X-Fi S51 */
{
USB_ID
(
0x041e
,
0x30df
),
0
,
1
,
1
,
1
,
1
,
0x000d
},
/* Usb X-Fi S51 Pro */
{
USB_ID
(
0x041e
,
0x3048
),
2
,
2
,
6
,
6
,
2
,
0x6e91
},
/* Toshiba SB0500 */
{
USB_ID
(
0x041e
,
0x3048
),
2
,
2
,
6
,
6
,
2
,
0x6e91
},
/* Toshiba SB0500 */
};
};
...
@@ -188,6 +189,12 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
...
@@ -188,6 +189,12 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
usb_sndctrlpipe
(
mixer
->
chip
->
dev
,
0
),
0x24
,
usb_sndctrlpipe
(
mixer
->
chip
->
dev
,
0
),
0x24
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_OTHER
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_OTHER
,
!
value
,
0
,
NULL
,
0
,
100
);
!
value
,
0
,
NULL
,
0
,
100
);
/* USB X-Fi S51 Pro */
if
(
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x30df
))
err
=
snd_usb_ctl_msg
(
mixer
->
chip
->
dev
,
usb_sndctrlpipe
(
mixer
->
chip
->
dev
,
0
),
0x24
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_OTHER
,
!
value
,
0
,
NULL
,
0
,
100
);
else
else
err
=
snd_usb_ctl_msg
(
mixer
->
chip
->
dev
,
err
=
snd_usb_ctl_msg
(
mixer
->
chip
->
dev
,
usb_sndctrlpipe
(
mixer
->
chip
->
dev
,
0
),
0x24
,
usb_sndctrlpipe
(
mixer
->
chip
->
dev
,
0
),
0x24
,
...
@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
...
@@ -234,9 +241,13 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
/* USB X-Fi S51 doesn't have a CMSS LED */
/* USB X-Fi S51 doesn't have a CMSS LED */
if
((
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3042
))
&&
i
==
0
)
if
((
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3042
))
&&
i
==
0
)
continue
;
continue
;
/* USB X-Fi S51 Pro doesn't have one either */
if
((
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x30df
))
&&
i
==
0
)
continue
;
if
(
i
>
1
&&
/* Live24ext has 2 LEDs only */
if
(
i
>
1
&&
/* Live24ext has 2 LEDs only */
(
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3040
)
||
(
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3040
)
||
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3042
)
||
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3042
)
||
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x30df
)
||
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3048
)))
mixer
->
chip
->
usb_id
==
USB_ID
(
0x041e
,
0x3048
)))
break
;
break
;
err
=
snd_ctl_add
(
mixer
->
chip
->
card
,
err
=
snd_ctl_add
(
mixer
->
chip
->
card
,
...
@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
...
@@ -512,6 +523,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case
USB_ID
(
0x041e
,
0x3020
):
case
USB_ID
(
0x041e
,
0x3020
):
case
USB_ID
(
0x041e
,
0x3040
):
case
USB_ID
(
0x041e
,
0x3040
):
case
USB_ID
(
0x041e
,
0x3042
):
case
USB_ID
(
0x041e
,
0x3042
):
case
USB_ID
(
0x041e
,
0x30df
):
case
USB_ID
(
0x041e
,
0x3048
):
case
USB_ID
(
0x041e
,
0x3048
):
err
=
snd_audigy2nx_controls_create
(
mixer
);
err
=
snd_audigy2nx_controls_create
(
mixer
);
if
(
err
<
0
)
if
(
err
<
0
)
...
...
sound/usb/quirks-table.h
浏览文件 @
02e5fbf6
...
@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"),
...
@@ -1651,6 +1651,32 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
}
}
},
},
{
USB_DEVICE
(
0x0582
,
0x0127
),
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
/* .vendor_name = "Roland", */
/* .product_name = "GR-55", */
.
ifnum
=
QUIRK_ANY_INTERFACE
,
.
type
=
QUIRK_COMPOSITE
,
.
data
=
(
const
struct
snd_usb_audio_quirk
[])
{
{
.
ifnum
=
0
,
.
type
=
QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.
ifnum
=
1
,
.
type
=
QUIRK_AUDIO_STANDARD_INTERFACE
},
{
.
ifnum
=
2
,
.
type
=
QUIRK_MIDI_STANDARD_INTERFACE
},
{
.
ifnum
=
-
1
}
}
}
},
/* Guillemot devices */
/* Guillemot devices */
{
{
...
@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
...
@@ -1953,7 +1979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
},
{
{
USB_DEVICE
(
0x0763
,
0x2080
),
USB_DEVICE
_VENDOR_SPEC
(
0x0763
,
0x2080
),
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
/* .vendor_name = "M-Audio", */
/* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra", */
/* .product_name = "Fast Track Ultra", */
...
@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
...
@@ -2020,7 +2046,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
},
{
{
USB_DEVICE
(
0x0763
,
0x2081
),
USB_DEVICE
_VENDOR_SPEC
(
0x0763
,
0x2081
),
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
/* .vendor_name = "M-Audio", */
/* .vendor_name = "M-Audio", */
/* .product_name = "Fast Track Ultra 8R", */
/* .product_name = "Fast Track Ultra 8R", */
...
@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
...
@@ -2179,6 +2205,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
},
/* KORG devices */
{
USB_DEVICE_VENDOR_SPEC
(
0x0944
,
0x0200
),
.
driver_info
=
(
unsigned
long
)
&
(
const
struct
snd_usb_audio_quirk
)
{
.
vendor_name
=
"KORG, Inc."
,
/* .product_name = "PANDORA PX5D", */
.
ifnum
=
3
,
.
type
=
QUIRK_MIDI_STANDARD_INTERFACE
,
}
},
/* AKAI devices */
/* AKAI devices */
{
{
USB_DEVICE
(
0x09e8
,
0x0062
),
USB_DEVICE
(
0x09e8
,
0x0062
),
...
@@ -2331,6 +2368,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
...
@@ -2331,6 +2368,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
},
/* Native Instruments MK2 series */
/* Native Instruments MK2 series */
{
/* Komplete Audio 6 */
.
match_flags
=
USB_DEVICE_ID_MATCH_DEVICE
,
.
idVendor
=
0x17cc
,
.
idProduct
=
0x1000
,
},
{
{
/* Traktor Audio 6 */
/* Traktor Audio 6 */
.
match_flags
=
USB_DEVICE_ID_MATCH_DEVICE
,
.
match_flags
=
USB_DEVICE_ID_MATCH_DEVICE
,
...
...
sound/usb/quirks.c
浏览文件 @
02e5fbf6
...
@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
...
@@ -540,6 +540,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
/* Access Music VirusTI Desktop */
/* Access Music VirusTI Desktop */
return
snd_usb_accessmusic_boot_quirk
(
dev
);
return
snd_usb_accessmusic_boot_quirk
(
dev
);
case
USB_ID
(
0x17cc
,
0x1000
):
/* Komplete Audio 6 */
case
USB_ID
(
0x17cc
,
0x1010
):
/* Traktor Audio 6 */
case
USB_ID
(
0x17cc
,
0x1010
):
/* Traktor Audio 6 */
case
USB_ID
(
0x17cc
,
0x1020
):
/* Traktor Audio 10 */
case
USB_ID
(
0x17cc
,
0x1020
):
/* Traktor Audio 10 */
return
snd_usb_nativeinstruments_boot_quirk
(
dev
);
return
snd_usb_nativeinstruments_boot_quirk
(
dev
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录