Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
abe6becb
Commit
abe6becb
authored
Nov 27, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next/isa' into topic/misc
parents
bbb3c644
8366fc39
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
456 additions
and
109 deletions
+456
-109
drivers/media/radio/Kconfig
drivers/media/radio/Kconfig
+18
-0
drivers/media/radio/Makefile
drivers/media/radio/Makefile
+1
-0
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-miropcm20.c
+270
-0
include/sound/aci.h
include/sound/aci.h
+20
-3
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/miro.c
+147
-106
No files found.
drivers/media/radio/Kconfig
View file @
abe6becb
...
...
@@ -195,6 +195,24 @@ config RADIO_MAESTRO
To compile this driver as a module, choose M here: the
module will be called radio-maestro.
config RADIO_MIROPCM20
tristate "miroSOUND PCM20 radio"
depends on ISA && VIDEO_V4L2
select SND_MIRO
---help---
Choose Y here if you have this FM radio card. You also need to enable
the ALSA sound system. This choice automatically selects the ALSA
sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this
is required for the radio-miropcm20.
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-miropcm20.
config RADIO_SF16FMI
tristate "SF16FMI Radio"
depends on ISA && VIDEO_V4L2
...
...
drivers/media/radio/Makefile
View file @
abe6becb
...
...
@@ -18,6 +18,7 @@ obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_I2C_SI4713)
+=
si4713-i2c.o
obj-$(CONFIG_RADIO_SI4713)
+=
radio-si4713.o
obj-$(CONFIG_RADIO_MAESTRO)
+=
radio-maestro.o
obj-$(CONFIG_RADIO_MIROPCM20)
+=
radio-miropcm20.o
obj-$(CONFIG_USB_DSBR)
+=
dsbr100.o
obj-$(CONFIG_RADIO_SI470X)
+=
si470x/
obj-$(CONFIG_USB_MR800)
+=
radio-mr800.o
...
...
drivers/media/radio/radio-miropcm20.c
0 → 100644
View file @
abe6becb
/* Miro PCM20 radio driver for Linux radio support
* (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
* Thanks to Norberto Pellici for the ACI device interface specification
* The API part is based on the radiotrack driver by M. Kirkwood
* This driver relies on the aci mixer provided by the snd-miro
* ALSA driver.
* Look there for further info...
*/
/* What ever you think about the ACI, version 0x07 is not very well!
* I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
* conditions... Robert
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <sound/aci.h>
static
int
radio_nr
=
-
1
;
module_param
(
radio_nr
,
int
,
0
);
MODULE_PARM_DESC
(
radio_nr
,
"Set radio device number (/dev/radioX). Default: -1 (autodetect)"
);
static
int
mono
;
module_param
(
mono
,
bool
,
0
);
MODULE_PARM_DESC
(
mono
,
"Force tuner into mono mode."
);
struct
pcm20
{
struct
v4l2_device
v4l2_dev
;
struct
video_device
vdev
;
unsigned
long
freq
;
int
muted
;
struct
snd_miro_aci
*
aci
;
};
static
struct
pcm20
pcm20_card
=
{
.
freq
=
87
*
16000
,
.
muted
=
1
,
};
static
int
pcm20_mute
(
struct
pcm20
*
dev
,
unsigned
char
mute
)
{
dev
->
muted
=
mute
;
return
snd_aci_cmd
(
dev
->
aci
,
ACI_SET_TUNERMUTE
,
mute
,
-
1
);
}
static
int
pcm20_stereo
(
struct
pcm20
*
dev
,
unsigned
char
stereo
)
{
return
snd_aci_cmd
(
dev
->
aci
,
ACI_SET_TUNERMONO
,
!
stereo
,
-
1
);
}
static
int
pcm20_setfreq
(
struct
pcm20
*
dev
,
unsigned
long
freq
)
{
unsigned
char
freql
;
unsigned
char
freqh
;
struct
snd_miro_aci
*
aci
=
dev
->
aci
;
dev
->
freq
=
freq
;
freq
/=
160
;
if
(
!
(
aci
->
aci_version
==
0x07
||
aci
->
aci_version
>=
0xb0
))
freq
/=
10
;
/* I don't know exactly which version
* needs this hack */
freql
=
freq
&
0xff
;
freqh
=
freq
>>
8
;
pcm20_stereo
(
dev
,
!
mono
);
return
snd_aci_cmd
(
aci
,
ACI_WRITE_TUNE
,
freql
,
freqh
);
}
static
const
struct
v4l2_file_operations
pcm20_fops
=
{
.
owner
=
THIS_MODULE
,
.
ioctl
=
video_ioctl2
,
};
static
int
vidioc_querycap
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_capability
*
v
)
{
strlcpy
(
v
->
driver
,
"Miro PCM20"
,
sizeof
(
v
->
driver
));
strlcpy
(
v
->
card
,
"Miro PCM20"
,
sizeof
(
v
->
card
));
strlcpy
(
v
->
bus_info
,
"ISA"
,
sizeof
(
v
->
bus_info
));
v
->
version
=
0x1
;
v
->
capabilities
=
V4L2_CAP_TUNER
|
V4L2_CAP_RADIO
;
return
0
;
}
static
int
vidioc_g_tuner
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_tuner
*
v
)
{
if
(
v
->
index
)
/* Only 1 tuner */
return
-
EINVAL
;
strlcpy
(
v
->
name
,
"FM"
,
sizeof
(
v
->
name
));
v
->
type
=
V4L2_TUNER_RADIO
;
v
->
rangelow
=
87
*
16000
;
v
->
rangehigh
=
108
*
16000
;
v
->
signal
=
0xffff
;
v
->
rxsubchans
=
V4L2_TUNER_SUB_MONO
|
V4L2_TUNER_SUB_STEREO
;
v
->
capability
=
V4L2_TUNER_CAP_LOW
;
v
->
audmode
=
V4L2_TUNER_MODE_MONO
;
return
0
;
}
static
int
vidioc_s_tuner
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_tuner
*
v
)
{
return
v
->
index
?
-
EINVAL
:
0
;
}
static
int
vidioc_g_frequency
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_frequency
*
f
)
{
struct
pcm20
*
dev
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
)
return
-
EINVAL
;
f
->
type
=
V4L2_TUNER_RADIO
;
f
->
frequency
=
dev
->
freq
;
return
0
;
}
static
int
vidioc_s_frequency
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_frequency
*
f
)
{
struct
pcm20
*
dev
=
video_drvdata
(
file
);
if
(
f
->
tuner
!=
0
||
f
->
type
!=
V4L2_TUNER_RADIO
)
return
-
EINVAL
;
dev
->
freq
=
f
->
frequency
;
pcm20_setfreq
(
dev
,
f
->
frequency
);
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
pcm20
*
dev
=
video_drvdata
(
file
);
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
ctrl
->
value
=
dev
->
muted
;
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
int
vidioc_s_ctrl
(
struct
file
*
file
,
void
*
priv
,
struct
v4l2_control
*
ctrl
)
{
struct
pcm20
*
dev
=
video_drvdata
(
file
);
switch
(
ctrl
->
id
)
{
case
V4L2_CID_AUDIO_MUTE
:
pcm20_mute
(
dev
,
ctrl
->
value
);
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
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_ioctl_ops
pcm20_ioctl_ops
=
{
.
vidioc_querycap
=
vidioc_querycap
,
.
vidioc_g_tuner
=
vidioc_g_tuner
,
.
vidioc_s_tuner
=
vidioc_s_tuner
,
.
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
,
.
vidioc_g_audio
=
vidioc_g_audio
,
.
vidioc_s_audio
=
vidioc_s_audio
,
.
vidioc_g_input
=
vidioc_g_input
,
.
vidioc_s_input
=
vidioc_s_input
,
};
static
int
__init
pcm20_init
(
void
)
{
struct
pcm20
*
dev
=
&
pcm20_card
;
struct
v4l2_device
*
v4l2_dev
=
&
dev
->
v4l2_dev
;
int
res
;
dev
->
aci
=
snd_aci_get_aci
();
if
(
dev
->
aci
==
NULL
)
{
v4l2_err
(
v4l2_dev
,
"you must load the snd-miro driver first!
\n
"
);
return
-
ENODEV
;
}
strlcpy
(
v4l2_dev
->
name
,
"miropcm20"
,
sizeof
(
v4l2_dev
->
name
));
res
=
v4l2_device_register
(
NULL
,
v4l2_dev
);
if
(
res
<
0
)
{
v4l2_err
(
v4l2_dev
,
"could not register v4l2_device
\n
"
);
return
-
EINVAL
;
}
strlcpy
(
dev
->
vdev
.
name
,
v4l2_dev
->
name
,
sizeof
(
dev
->
vdev
.
name
));
dev
->
vdev
.
v4l2_dev
=
v4l2_dev
;
dev
->
vdev
.
fops
=
&
pcm20_fops
;
dev
->
vdev
.
ioctl_ops
=
&
pcm20_ioctl_ops
;
dev
->
vdev
.
release
=
video_device_release_empty
;
video_set_drvdata
(
&
dev
->
vdev
,
dev
);
if
(
video_register_device
(
&
dev
->
vdev
,
VFL_TYPE_RADIO
,
radio_nr
)
<
0
)
goto
fail
;
v4l2_info
(
v4l2_dev
,
"Mirosound PCM20 Radio tuner
\n
"
);
return
0
;
fail:
v4l2_device_unregister
(
v4l2_dev
);
return
-
EINVAL
;
}
MODULE_AUTHOR
(
"Ruurd Reitsma, Krzysztof Helt"
);
MODULE_DESCRIPTION
(
"A driver for the Miro PCM20 radio card."
);
MODULE_LICENSE
(
"GPL"
);
static
void
__exit
pcm20_cleanup
(
void
)
{
struct
pcm20
*
dev
=
&
pcm20_card
;
video_unregister_device
(
&
dev
->
vdev
);
v4l2_device_unregister
(
&
dev
->
v4l2_dev
);
}
module_init
(
pcm20_init
);
module_exit
(
pcm20_cleanup
);
sound/isa/opti9xx/miro
.h
→
include/sound/aci
.h
View file @
abe6becb
#ifndef _
MIRO
_H_
#define _
MIRO
_H_
#ifndef _
ACI
_H_
#define _
ACI
_H_
#define ACI_REG_COMMAND 0
/* write register offset */
#define ACI_REG_STATUS 1
/* read register offset */
...
...
@@ -70,4 +70,21 @@
#define ACI_SET_EQ6 0x45
#define ACI_SET_EQ7 0x46
/* ... to Treble */
#endif
/* _MIRO_H_ */
struct
snd_miro_aci
{
unsigned
long
aci_port
;
int
aci_vendor
;
int
aci_product
;
int
aci_version
;
int
aci_amp
;
int
aci_preamp
;
int
aci_solomode
;
struct
mutex
aci_mutex
;
};
int
snd_aci_cmd
(
struct
snd_miro_aci
*
aci
,
int
write1
,
int
write2
,
int
write3
);
struct
snd_miro_aci
*
snd_aci_get_aci
(
void
);
#endif
/* _ACI_H_ */
sound/isa/opti9xx/miro.c
View file @
abe6becb
...
...
@@ -40,7 +40,7 @@
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
#include
"miro.h"
#include
<sound/aci.h>
MODULE_AUTHOR
(
"Martin Langer <martin-langer@gmx.de>"
);
MODULE_LICENSE
(
"GPL"
);
...
...
@@ -96,7 +96,6 @@ MODULE_PARM_DESC(ide, "enable ide port");
#define OPTi9XX_MC_REG(n) n
struct
snd_miro
{
unsigned
short
hardware
;
unsigned
char
password
;
...
...
@@ -120,17 +119,11 @@ struct snd_miro {
long
mpu_port
;
int
mpu_irq
;
unsigned
long
aci_port
;
int
aci_vendor
;
int
aci_product
;
int
aci_version
;
int
aci_amp
;
int
aci_preamp
;
int
aci_solomode
;
struct
mutex
aci_mutex
;
struct
snd_miro_aci
*
aci
;
};
static
struct
snd_miro_aci
aci_device
;
static
char
*
snd_opti9xx_names
[]
=
{
"unkown"
,
"82C928"
,
"82C929"
,
...
...
@@ -142,13 +135,14 @@ static char * snd_opti9xx_names[] = {
* ACI control
*/
static
int
aci_busy_wait
(
struct
snd_miro
*
miro
)
static
int
aci_busy_wait
(
struct
snd_miro
_aci
*
aci
)
{
long
timeout
;
unsigned
char
byte
;
for
(
timeout
=
1
;
timeout
<=
ACI_MINTIME
+
30
;
timeout
++
)
{
if
(((
byte
=
inb
(
miro
->
aci_port
+
ACI_REG_BUSY
))
&
1
)
==
0
)
{
for
(
timeout
=
1
;
timeout
<=
ACI_MINTIME
+
30
;
timeout
++
)
{
byte
=
inb
(
aci
->
aci_port
+
ACI_REG_BUSY
);
if
((
byte
&
1
)
==
0
)
{
if
(
timeout
>=
ACI_MINTIME
)
snd_printd
(
"aci ready in round %ld.
\n
"
,
timeout
-
ACI_MINTIME
);
...
...
@@ -174,10 +168,10 @@ static int aci_busy_wait(struct snd_miro * miro)
return
-
EBUSY
;
}
static
inline
int
aci_write
(
struct
snd_miro
*
miro
,
unsigned
char
byte
)
static
inline
int
aci_write
(
struct
snd_miro
_aci
*
aci
,
unsigned
char
byte
)
{
if
(
aci_busy_wait
(
miro
)
>=
0
)
{
outb
(
byte
,
miro
->
aci_port
+
ACI_REG_COMMAND
);
if
(
aci_busy_wait
(
aci
)
>=
0
)
{
outb
(
byte
,
aci
->
aci_port
+
ACI_REG_COMMAND
);
return
0
;
}
else
{
snd_printk
(
KERN_ERR
"aci busy, aci_write(0x%x) stopped.
\n
"
,
byte
);
...
...
@@ -185,12 +179,12 @@ static inline int aci_write(struct snd_miro * miro, unsigned char byte)
}
}
static
inline
int
aci_read
(
struct
snd_miro
*
miro
)
static
inline
int
aci_read
(
struct
snd_miro
_aci
*
aci
)
{
unsigned
char
byte
;
if
(
aci_busy_wait
(
miro
)
>=
0
)
{
byte
=
inb
(
miro
->
aci_port
+
ACI_REG_STATUS
);
if
(
aci_busy_wait
(
aci
)
>=
0
)
{
byte
=
inb
(
aci
->
aci_port
+
ACI_REG_STATUS
);
return
byte
;
}
else
{
snd_printk
(
KERN_ERR
"aci busy, aci_read() stopped.
\n
"
);
...
...
@@ -198,39 +192,49 @@ static inline int aci_read(struct snd_miro * miro)
}
}
static
int
aci_cmd
(
struct
snd_miro
*
miro
,
int
write1
,
int
write2
,
int
write3
)
int
snd_aci_cmd
(
struct
snd_miro_aci
*
aci
,
int
write1
,
int
write2
,
int
write3
)
{
int
write
[]
=
{
write1
,
write2
,
write3
};
int
value
,
i
;
if
(
mutex_lock_interruptible
(
&
miro
->
aci_mutex
))
if
(
mutex_lock_interruptible
(
&
aci
->
aci_mutex
))
return
-
EINTR
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
(
write
[
i
]
<
0
||
write
[
i
]
>
255
)
break
;
else
{
value
=
aci_write
(
miro
,
write
[
i
]);
value
=
aci_write
(
aci
,
write
[
i
]);
if
(
value
<
0
)
goto
out
;
}
}
value
=
aci_read
(
miro
);
value
=
aci_read
(
aci
);
out:
mutex_unlock
(
&
miro
->
aci_mutex
);
out:
mutex_unlock
(
&
aci
->
aci_mutex
);
return
value
;
}
EXPORT_SYMBOL
(
snd_aci_cmd
);
static
int
aci_getvalue
(
struct
snd_miro_aci
*
aci
,
unsigned
char
index
)
{
return
snd_aci_cmd
(
aci
,
ACI_STATUS
,
index
,
-
1
);
}
static
int
aci_getvalue
(
struct
snd_miro
*
miro
,
unsigned
char
index
)
static
int
aci_setvalue
(
struct
snd_miro_aci
*
aci
,
unsigned
char
index
,
int
value
)
{
return
aci_cmd
(
miro
,
ACI_STATUS
,
index
,
-
1
);
return
snd_aci_cmd
(
aci
,
index
,
value
,
-
1
);
}
st
atic
int
aci_setvalue
(
struct
snd_miro
*
miro
,
unsigned
char
index
,
int
value
)
st
ruct
snd_miro_aci
*
snd_aci_get_aci
(
void
)
{
return
aci_cmd
(
miro
,
index
,
value
,
-
1
);
if
(
aci_device
.
aci_port
==
0
)
return
NULL
;
return
&
aci_device
;
}
EXPORT_SYMBOL
(
snd_aci_get_aci
);
/*
* MIXER part
...
...
@@ -244,8 +248,10 @@ static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
struct
snd_miro
*
miro
=
snd_kcontrol_chip
(
kcontrol
);
int
value
;
if
((
value
=
aci_getvalue
(
miro
,
ACI_S_GENERAL
))
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_get_capture() failed: %d
\n
"
,
value
);
value
=
aci_getvalue
(
miro
->
aci
,
ACI_S_GENERAL
);
if
(
value
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_get_capture() failed: %d
\n
"
,
value
);
return
value
;
}
...
...
@@ -262,13 +268,15 @@ static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
value
=
!
(
ucontrol
->
value
.
integer
.
value
[
0
]);
if
((
error
=
aci_setvalue
(
miro
,
ACI_SET_SOLOMODE
,
value
))
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_put_capture() failed: %d
\n
"
,
error
);
error
=
aci_setvalue
(
miro
->
aci
,
ACI_SET_SOLOMODE
,
value
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_put_capture() failed: %d
\n
"
,
error
);
return
error
;
}
change
=
(
value
!=
miro
->
aci_solomode
);
miro
->
aci_solomode
=
value
;
change
=
(
value
!=
miro
->
aci
->
aci
_solomode
);
miro
->
aci
->
aci
_solomode
=
value
;
return
change
;
}
...
...
@@ -290,7 +298,7 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
struct
snd_miro
*
miro
=
snd_kcontrol_chip
(
kcontrol
);
int
value
;
if
(
miro
->
aci_version
<=
176
)
{
if
(
miro
->
aci
->
aci
_version
<=
176
)
{
/*
OSS says it's not readable with versions < 176.
...
...
@@ -298,12 +306,14 @@ static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
which is a PCM12 with aci_version = 176.
*/
ucontrol
->
value
.
integer
.
value
[
0
]
=
miro
->
aci_preamp
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
miro
->
aci
->
aci
_preamp
;
return
0
;
}
if
((
value
=
aci_getvalue
(
miro
,
ACI_GET_PREAMP
))
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_get_preamp() failed: %d
\n
"
,
value
);
value
=
aci_getvalue
(
miro
->
aci
,
ACI_GET_PREAMP
);
if
(
value
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_get_preamp() failed: %d
\n
"
,
value
);
return
value
;
}
...
...
@@ -320,13 +330,15 @@ static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
value
=
ucontrol
->
value
.
integer
.
value
[
0
];
if
((
error
=
aci_setvalue
(
miro
,
ACI_SET_PREAMP
,
value
))
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_put_preamp() failed: %d
\n
"
,
error
);
error
=
aci_setvalue
(
miro
->
aci
,
ACI_SET_PREAMP
,
value
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_put_preamp() failed: %d
\n
"
,
error
);
return
error
;
}
change
=
(
value
!=
miro
->
aci_preamp
);
miro
->
aci_preamp
=
value
;
change
=
(
value
!=
miro
->
aci
->
aci
_preamp
);
miro
->
aci
->
aci
_preamp
=
value
;
return
change
;
}
...
...
@@ -337,7 +349,7 @@ static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_miro
*
miro
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
miro
->
aci_amp
;
ucontrol
->
value
.
integer
.
value
[
0
]
=
miro
->
aci
->
aci
_amp
;
return
0
;
}
...
...
@@ -350,13 +362,14 @@ static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
value
=
ucontrol
->
value
.
integer
.
value
[
0
];
if
((
error
=
aci_setvalue
(
miro
,
ACI_SET_POWERAMP
,
value
))
<
0
)
{
error
=
aci_setvalue
(
miro
->
aci
,
ACI_SET_POWERAMP
,
value
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"snd_miro_put_amp() to %d failed: %d
\n
"
,
value
,
error
);
return
error
;
}
change
=
(
value
!=
miro
->
aci_amp
);
miro
->
aci_amp
=
value
;
change
=
(
value
!=
miro
->
aci
->
aci
_amp
);
miro
->
aci
->
aci
_amp
=
value
;
return
change
;
}
...
...
@@ -405,12 +418,14 @@ static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
int
right_reg
=
kcontrol
->
private_value
&
0xff
;
int
left_reg
=
right_reg
+
1
;
if
((
right_val
=
aci_getvalue
(
miro
,
right_reg
))
<
0
)
{
right_val
=
aci_getvalue
(
miro
->
aci
,
right_reg
);
if
(
right_val
<
0
)
{
snd_printk
(
KERN_ERR
"aci_getvalue(%d) failed: %d
\n
"
,
right_reg
,
right_val
);
return
right_val
;
}
if
((
left_val
=
aci_getvalue
(
miro
,
left_reg
))
<
0
)
{
left_val
=
aci_getvalue
(
miro
->
aci
,
left_reg
);
if
(
left_val
<
0
)
{
snd_printk
(
KERN_ERR
"aci_getvalue(%d) failed: %d
\n
"
,
left_reg
,
left_val
);
return
left_val
;
}
...
...
@@ -446,6 +461,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_miro
*
miro
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_miro_aci
*
aci
=
miro
->
aci
;
int
left
,
right
,
left_old
,
right_old
;
int
setreg_left
,
setreg_right
,
getreg_left
,
getreg_right
;
int
change
,
error
;
...
...
@@ -461,12 +477,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
getreg_right
=
kcontrol
->
private_value
&
0xff
;
getreg_left
=
getreg_right
+
1
;
if
((
left_old
=
aci_getvalue
(
miro
,
getreg_left
))
<
0
)
{
left_old
=
aci_getvalue
(
aci
,
getreg_left
);
if
(
left_old
<
0
)
{
snd_printk
(
KERN_ERR
"aci_getvalue(%d) failed: %d
\n
"
,
getreg_left
,
left_old
);
return
left_old
;
}
if
((
right_old
=
aci_getvalue
(
miro
,
getreg_right
))
<
0
)
{
right_old
=
aci_getvalue
(
aci
,
getreg_right
);
if
(
right_old
<
0
)
{
snd_printk
(
KERN_ERR
"aci_getvalue(%d) failed: %d
\n
"
,
getreg_right
,
right_old
);
return
right_old
;
}
...
...
@@ -485,13 +503,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
right_old
=
0x80
-
right_old
;
if
(
left
>=
0
)
{
if
((
error
=
aci_setvalue
(
miro
,
setreg_left
,
left
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_left
,
left
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
left
,
error
);
return
error
;
}
}
else
{
if
((
error
=
aci_setvalue
(
miro
,
setreg_left
,
0x80
-
left
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_left
,
0x80
-
left
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
0x80
-
left
,
error
);
return
error
;
...
...
@@ -499,13 +519,15 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
}
if
(
right
>=
0
)
{
if
((
error
=
aci_setvalue
(
miro
,
setreg_right
,
right
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_right
,
right
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
right
,
error
);
return
error
;
}
}
else
{
if
((
error
=
aci_setvalue
(
miro
,
setreg_right
,
0x80
-
right
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_right
,
0x80
-
right
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
0x80
-
right
,
error
);
return
error
;
...
...
@@ -523,12 +545,14 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
left_old
=
0x20
-
left_old
;
right_old
=
0x20
-
right_old
;
if
((
error
=
aci_setvalue
(
miro
,
setreg_left
,
0x20
-
left
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_left
,
0x20
-
left
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
0x20
-
left
,
error
);
return
error
;
}
if
((
error
=
aci_setvalue
(
miro
,
setreg_right
,
0x20
-
right
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
setreg_right
,
0x20
-
right
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
0x20
-
right
,
error
);
return
error
;
...
...
@@ -626,11 +650,13 @@ static unsigned char aci_init_values[][2] __devinitdata = {
static
int
__devinit
snd_set_aci_init_values
(
struct
snd_miro
*
miro
)
{
int
idx
,
error
;
struct
snd_miro_aci
*
aci
=
miro
->
aci
;
/* enable WSS on PCM1 */
if
((
miro
->
aci_product
==
'A'
)
&&
wss
)
{
if
((
error
=
aci_setvalue
(
miro
,
ACI_SET_WSS
,
wss
))
<
0
)
{
if
((
aci
->
aci_product
==
'A'
)
&&
wss
)
{
error
=
aci_setvalue
(
aci
,
ACI_SET_WSS
,
wss
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"enabling WSS mode failed
\n
"
);
return
error
;
}
...
...
@@ -639,7 +665,8 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
/* enable IDE port */
if
(
ide
)
{
if
((
error
=
aci_setvalue
(
miro
,
ACI_SET_IDE
,
ide
))
<
0
)
{
error
=
aci_setvalue
(
aci
,
ACI_SET_IDE
,
ide
);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"enabling IDE port failed
\n
"
);
return
error
;
}
...
...
@@ -647,17 +674,18 @@ static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
/* set common aci values */
for
(
idx
=
0
;
idx
<
ARRAY_SIZE
(
aci_init_values
);
idx
++
)
if
((
error
=
aci_setvalue
(
miro
,
aci_init_values
[
idx
][
0
],
aci_init_values
[
idx
][
1
]))
<
0
)
{
for
(
idx
=
0
;
idx
<
ARRAY_SIZE
(
aci_init_values
);
idx
++
)
{
error
=
aci_setvalue
(
aci
,
aci_init_values
[
idx
][
0
],
aci_init_values
[
idx
][
1
]);
if
(
error
<
0
)
{
snd_printk
(
KERN_ERR
"aci_setvalue(%d) failed: %d
\n
"
,
aci_init_values
[
idx
][
0
],
error
);
return
error
;
}
miro
->
aci_amp
=
0
;
miro
->
aci_preamp
=
0
;
miro
->
aci_solomode
=
1
;
}
aci
->
aci_amp
=
0
;
aci
->
aci_preamp
=
0
;
aci
->
aci_solomode
=
1
;
return
0
;
}
...
...
@@ -688,7 +716,8 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
return
err
;
}
if
((
miro
->
aci_product
==
'A'
)
||
(
miro
->
aci_product
==
'B'
))
{
if
((
miro
->
aci
->
aci_product
==
'A'
)
||
(
miro
->
aci
->
aci_product
==
'B'
))
{
/* PCM1/PCM12 with power-amp and Line 2 */
if
((
err
=
snd_ctl_add
(
card
,
snd_ctl_new1
(
&
snd_miro_line_control
[
0
],
miro
)))
<
0
)
return
err
;
...
...
@@ -696,16 +725,17 @@ static int __devinit snd_miro_mixer(struct snd_card *card,
return
err
;
}
if
((
miro
->
aci_product
==
'B'
)
||
(
miro
->
aci_product
==
'C'
))
{
if
((
miro
->
aci
->
aci_product
==
'B'
)
||
(
miro
->
aci
->
aci_product
==
'C'
))
{
/* PCM12/PCM20 with mic-preamp */
if
((
err
=
snd_ctl_add
(
card
,
snd_ctl_new1
(
&
snd_miro_preamp_control
[
0
],
miro
)))
<
0
)
return
err
;
if
(
miro
->
aci_version
>=
176
)
if
(
miro
->
aci
->
aci
_version
>=
176
)
if
((
err
=
snd_ctl_add
(
card
,
snd_ctl_new1
(
&
snd_miro_capture_control
[
0
],
miro
)))
<
0
)
return
err
;
}
if
(
miro
->
aci_product
==
'C'
)
{
if
(
miro
->
aci
->
aci
_product
==
'C'
)
{
/* PCM20 with radio and 7 band equalizer */
if
((
err
=
snd_ctl_add
(
card
,
snd_ctl_new1
(
&
snd_miro_radio_control
[
0
],
miro
)))
<
0
)
return
err
;
...
...
@@ -843,14 +873,15 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
struct
snd_info_buffer
*
buffer
)
{
struct
snd_miro
*
miro
=
(
struct
snd_miro
*
)
entry
->
private_data
;
struct
snd_miro_aci
*
aci
=
miro
->
aci
;
char
*
model
=
"unknown"
;
/* miroSOUND PCM1 pro, early PCM12 */
if
((
miro
->
hardware
==
OPTi9XX_HW_82C929
)
&&
(
miro
->
aci_vendor
==
'm'
)
&&
(
miro
->
aci_product
==
'A'
))
{
switch
(
miro
->
aci_version
)
{
(
aci
->
aci_vendor
==
'm'
)
&&
(
aci
->
aci_product
==
'A'
))
{
switch
(
aci
->
aci_version
)
{
case
3
:
model
=
"miroSOUND PCM1 pro"
;
break
;
...
...
@@ -863,9 +894,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
/* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
if
((
miro
->
hardware
==
OPTi9XX_HW_82C924
)
&&
(
miro
->
aci_vendor
==
'm'
)
&&
(
miro
->
aci_product
==
'B'
))
{
switch
(
miro
->
aci_version
)
{
(
aci
->
aci_vendor
==
'm'
)
&&
(
aci
->
aci_product
==
'B'
))
{
switch
(
aci
->
aci_version
)
{
case
4
:
model
=
"miroSOUND PCM12"
;
break
;
...
...
@@ -881,9 +912,9 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
/* miroSOUND PCM20 radio */
if
((
miro
->
hardware
==
OPTi9XX_HW_82C924
)
&&
(
miro
->
aci_vendor
==
'm'
)
&&
(
miro
->
aci_product
==
'C'
))
{
switch
(
miro
->
aci_version
)
{
(
aci
->
aci_vendor
==
'm'
)
&&
(
aci
->
aci_product
==
'C'
))
{
switch
(
aci
->
aci_version
)
{
case
7
:
model
=
"miroSOUND PCM20 radio (Rev. E)"
;
break
;
...
...
@@ -907,17 +938,17 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf
(
buffer
,
"ACI information:
\n
"
);
snd_iprintf
(
buffer
,
" vendor : "
);
switch
(
miro
->
aci_vendor
)
{
switch
(
aci
->
aci_vendor
)
{
case
'm'
:
snd_iprintf
(
buffer
,
"Miro
\n
"
);
break
;
default:
snd_iprintf
(
buffer
,
"unknown (0x%x)
\n
"
,
miro
->
aci_vendor
);
snd_iprintf
(
buffer
,
"unknown (0x%x)
\n
"
,
aci
->
aci_vendor
);
break
;
}
snd_iprintf
(
buffer
,
" product : "
);
switch
(
miro
->
aci_product
)
{
switch
(
aci
->
aci_product
)
{
case
'A'
:
snd_iprintf
(
buffer
,
"miroSOUND PCM1 pro / (early) PCM12
\n
"
);
break
;
...
...
@@ -928,19 +959,19 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
snd_iprintf
(
buffer
,
"miroSOUND PCM20 radio
\n
"
);
break
;
default:
snd_iprintf
(
buffer
,
"unknown (0x%x)
\n
"
,
miro
->
aci_product
);
snd_iprintf
(
buffer
,
"unknown (0x%x)
\n
"
,
aci
->
aci_product
);
break
;
}
snd_iprintf
(
buffer
,
" firmware: %d (0x%x)
\n
"
,
miro
->
aci_version
,
miro
->
aci_version
);
aci
->
aci_version
,
aci
->
aci_version
);
snd_iprintf
(
buffer
,
" port : 0x%lx-0x%lx
\n
"
,
miro
->
aci_port
,
miro
->
aci_port
+
2
);
aci
->
aci_port
,
aci
->
aci_port
+
2
);
snd_iprintf
(
buffer
,
" wss : 0x%x
\n
"
,
wss
);
snd_iprintf
(
buffer
,
" ide : 0x%x
\n
"
,
ide
);
snd_iprintf
(
buffer
,
" solomode: 0x%x
\n
"
,
miro
->
aci_solomode
);
snd_iprintf
(
buffer
,
" amp : 0x%x
\n
"
,
miro
->
aci_amp
);
snd_iprintf
(
buffer
,
" preamp : 0x%x
\n
"
,
miro
->
aci_preamp
);
snd_iprintf
(
buffer
,
" solomode: 0x%x
\n
"
,
aci
->
aci_solomode
);
snd_iprintf
(
buffer
,
" amp : 0x%x
\n
"
,
aci
->
aci_amp
);
snd_iprintf
(
buffer
,
" preamp : 0x%x
\n
"
,
aci
->
aci_preamp
);
}
static
void
__devinit
snd_miro_proc_init
(
struct
snd_card
*
card
,
...
...
@@ -1139,46 +1170,53 @@ static int __devinit snd_card_miro_detect(struct snd_card *card,
}
static
int
__devinit
snd_card_miro_aci_detect
(
struct
snd_card
*
card
,
struct
snd_miro
*
miro
)
struct
snd_miro
*
miro
)
{
unsigned
char
regval
;
int
i
;
struct
snd_miro_aci
*
aci
=
&
aci_device
;
miro
->
aci
=
aci
;
mutex_init
(
&
miro
->
aci_mutex
);
mutex_init
(
&
aci
->
aci_mutex
);
/* get ACI port from OPTi9xx MC 4 */
regval
=
inb
(
miro
->
mc_base
+
4
);
miro
->
aci_port
=
(
regval
&
0x10
)
?
0x344
:
0x354
;
aci
->
aci_port
=
(
regval
&
0x10
)
?
0x344
:
0x354
;
if
((
miro
->
res_aci_port
=
request_region
(
miro
->
aci_port
,
3
,
"miro aci"
))
==
NULL
)
{
miro
->
res_aci_port
=
request_region
(
aci
->
aci_port
,
3
,
"miro aci"
);
if
(
miro
->
res_aci_port
==
NULL
)
{
snd_printk
(
KERN_ERR
"aci i/o area 0x%lx-0x%lx already used.
\n
"
,
miro
->
aci_port
,
miro
->
aci_port
+
2
);
aci
->
aci_port
,
aci
->
aci_port
+
2
);
return
-
ENOMEM
;
}
/* force ACI into a known state */
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
aci_cmd
(
miro
,
ACI_ERROR_OP
,
-
1
,
-
1
)
<
0
)
{
if
(
snd_aci_cmd
(
aci
,
ACI_ERROR_OP
,
-
1
,
-
1
)
<
0
)
{
snd_printk
(
KERN_ERR
"can't force aci into known state.
\n
"
);
return
-
ENXIO
;
}
if
((
miro
->
aci_vendor
=
aci_cmd
(
miro
,
ACI_READ_IDCODE
,
-
1
,
-
1
))
<
0
||
(
miro
->
aci_product
=
aci_cmd
(
miro
,
ACI_READ_IDCODE
,
-
1
,
-
1
))
<
0
)
{
snd_printk
(
KERN_ERR
"can't read aci id on 0x%lx.
\n
"
,
miro
->
aci_port
);
aci
->
aci_vendor
=
snd_aci_cmd
(
aci
,
ACI_READ_IDCODE
,
-
1
,
-
1
);
aci
->
aci_product
=
snd_aci_cmd
(
aci
,
ACI_READ_IDCODE
,
-
1
,
-
1
);
if
(
aci
->
aci_vendor
<
0
||
aci
->
aci_product
<
0
)
{
snd_printk
(
KERN_ERR
"can't read aci id on 0x%lx.
\n
"
,
aci
->
aci_port
);
return
-
ENXIO
;
}
if
((
miro
->
aci_version
=
aci_cmd
(
miro
,
ACI_READ_VERSION
,
-
1
,
-
1
))
<
0
)
{
aci
->
aci_version
=
snd_aci_cmd
(
aci
,
ACI_READ_VERSION
,
-
1
,
-
1
);
if
(
aci
->
aci_version
<
0
)
{
snd_printk
(
KERN_ERR
"can't read aci version on 0x%lx.
\n
"
,
miro
->
aci_port
);
aci
->
aci_port
);
return
-
ENXIO
;
}
if
(
aci_cmd
(
miro
,
ACI_INIT
,
-
1
,
-
1
)
<
0
||
aci_cmd
(
miro
,
ACI_ERROR_OP
,
ACI_ERROR_OP
,
ACI_ERROR_OP
)
<
0
||
aci_cmd
(
miro
,
ACI_ERROR_OP
,
ACI_ERROR_OP
,
ACI_ERROR_OP
)
<
0
)
{
if
(
snd_aci_cmd
(
aci
,
ACI_INIT
,
-
1
,
-
1
)
<
0
||
snd_aci_cmd
(
aci
,
ACI_ERROR_OP
,
ACI_ERROR_OP
,
ACI_ERROR_OP
)
<
0
||
snd_aci_cmd
(
aci
,
ACI_ERROR_OP
,
ACI_ERROR_OP
,
ACI_ERROR_OP
)
<
0
)
{
snd_printk
(
KERN_ERR
"can't initialize aci.
\n
"
);
return
-
ENXIO
;
}
...
...
@@ -1191,6 +1229,8 @@ static void snd_card_miro_free(struct snd_card *card)
struct
snd_miro
*
miro
=
card
->
private_data
;
release_and_free_resource
(
miro
->
res_aci_port
);
if
(
miro
->
aci
)
miro
->
aci
->
aci_port
=
0
;
release_and_free_resource
(
miro
->
res_mc_base
);
}
...
...
@@ -1250,7 +1290,6 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
}
miro
->
wss_base
=
port
;
miro
->
mpu_port
=
mpu_port
;
miro
->
irq
=
irq
;
miro
->
mpu_irq
=
mpu_irq
;
miro
->
dma1
=
dma1
;
...
...
@@ -1272,6 +1311,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
return
-
EBUSY
;
}
}
miro
->
mpu_port
=
mpu_port
;
if
(
miro
->
irq
==
SNDRV_AUTO_IRQ
)
{
if
((
miro
->
irq
=
snd_legacy_find_free_irq
(
possible_irqs
))
<
0
)
{
snd_card_free
(
card
);
...
...
@@ -1339,9 +1380,9 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
return
error
;
}
if
(
miro
->
aci_vendor
==
'm'
)
{
if
(
miro
->
aci
->
aci
_vendor
==
'm'
)
{
/* It looks like a miro sound card. */
switch
(
miro
->
aci_product
)
{
switch
(
miro
->
aci
->
aci
_product
)
{
case
'A'
:
sprintf
(
card
->
shortname
,
"miroSOUND PCM1 pro / PCM12"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment