Merge branch 'topic/misc' into for-linus

This commit is contained in:
Takashi Iwai
2009-12-04 16:22:37 +01:00
36 changed files with 1467 additions and 706 deletions
+18
View File
@@ -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
+1
View File
@@ -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
+270
View File
@@ -0,0 +1,270 @@
/* 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);
@@ -1,5 +1,5 @@
#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_ */
-1
View File
@@ -70,7 +70,6 @@
#define AD1845_PWR_DOWN 0x1b /* power down control */
#define CS4235_LEFT_MASTER 0x1b /* left master output control */
#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
#define AD1845_CLOCK 0x1d /* crystal clock select and total power down */
#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
-1
View File
@@ -154,7 +154,6 @@ int snd_wss_create(struct snd_card *card,
unsigned short hardware,
unsigned short hwshare,
struct snd_wss **rchip);
int snd_wss_free(struct snd_wss *chip);
int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
int snd_wss_mixer(struct snd_wss *chip);
+1 -1
View File
@@ -58,7 +58,7 @@ config SOUND_OSS_CORE_PRECLAIM
Please read Documentation/feature-removal-schedule.txt for
details.
If unusre, say Y.
If unsure, say Y.
source "sound/oss/dmasound/Kconfig"
+5 -14
View File
@@ -18,10 +18,7 @@
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/amba/bus.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/sizes.h>
#include <linux/io.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -513,15 +510,9 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
goto out;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
params_channels(params),
aacirun->pcm->r[0].slots);
else
err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
params_channels(params),
aacirun->pcm->r[0].slots);
err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
params_channels(params),
aacirun->pcm->r[0].slots);
if (err)
goto out;
@@ -537,7 +528,7 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
struct aaci_runtime *aacirun = runtime->private_data;
aacirun->start = (void *)runtime->dma_area;
aacirun->end = aacirun->start + runtime->dma_bytes;
aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream);
aacirun->ptr = aacirun->start;
aacirun->period =
aacirun->bytes = frames_to_bytes(runtime, runtime->period_size);
+1 -1
View File
@@ -1119,7 +1119,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
goto __kctl_end;
}
if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
if (file && vd->owner != NULL && vd->owner != file) {
if (vd->owner != NULL && vd->owner != file) {
err = -EPERM;
goto __kctl_end;
}
+2 -13
View File
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/bitrev.h>
#include <asm/unaligned.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -55,18 +56,6 @@ struct cs8427 {
struct cs8427_stream capture;
};
static unsigned char swapbits(unsigned char val)
{
int bit;
unsigned char res = 0;
for (bit = 0; bit < 8; bit++) {
res <<= 1;
res |= val & 1;
val >>= 1;
}
return res;
}
int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
unsigned char val)
{
@@ -149,7 +138,7 @@ static int snd_cs8427_send_corudata(struct snd_i2c_device *device,
}
data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF;
for (idx = 0; idx < count; idx++)
data[idx + 1] = swapbits(ndata[idx]);
data[idx + 1] = bitrev8(ndata[idx]);
if (snd_i2c_sendbytes(device, data, count + 1) != count + 1)
return -EIO;
return 1;
+1 -1
View File
@@ -225,7 +225,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
case V4L2_CID_AUDIO_MUTE:
if (tea->ops->mute) {
tea->ops->mute(tea, ctrl->value);
tea->mute = 1;
tea->mute = ctrl->value;
return 0;
}
}
+3 -10
View File
@@ -394,21 +394,15 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
return -EBUSY;
}
err = snd_wss_create(card, port[dev], cport[dev],
err = snd_cs4236_create(card, port[dev], cport[dev],
irq[dev],
dma1[dev], dma2[dev],
WSS_HW_DETECT3, 0, &chip);
if (err < 0)
return err;
acard->chip = chip;
if (chip->hardware & WSS_HW_CS4236B_MASK) {
snd_wss_free(chip);
err = snd_cs4236_create(card,
port[dev], cport[dev],
irq[dev], dma1[dev], dma2[dev],
WSS_HW_DETECT, 0, &chip);
if (err < 0)
return err;
acard->chip = chip;
err = snd_cs4236_pcm(chip, 0, &pcm);
if (err < 0)
@@ -418,7 +412,6 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
if (err < 0)
return err;
} else {
acard->chip = chip;
err = snd_wss_pcm(chip, 0, &pcm);
if (err < 0)
return err;
+155 -86
View File
@@ -87,6 +87,8 @@
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
#include <sound/tlv.h>
/*
*
@@ -264,7 +266,10 @@ static void snd_cs4236_resume(struct snd_wss *chip)
}
#endif /* CONFIG_PM */
/*
* This function does no fail if the chip is not CS4236B or compatible.
* It just an equivalent to the snd_wss_create() then.
*/
int snd_cs4236_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
@@ -281,21 +286,17 @@ int snd_cs4236_create(struct snd_card *card,
*rchip = NULL;
if (hardware == WSS_HW_DETECT)
hardware = WSS_HW_DETECT3;
if (cport < 0x100) {
snd_printk(KERN_ERR "please, specify control port "
"for CS4236+ chips\n");
return -ENODEV;
}
err = snd_wss_create(card, port, cport,
irq, dma1, dma2, hardware, hwshare, &chip);
if (err < 0)
return err;
if (!(chip->hardware & WSS_HW_CS4236B_MASK)) {
snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers "
"not available, hardware=0x%x\n", chip->hardware);
snd_device_free(card, chip);
return -ENODEV;
if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) {
snd_printd("chip is not CS4236+, hardware=0x%x\n",
chip->hardware);
*rchip = chip;
return 0;
}
#if 0
{
@@ -308,9 +309,16 @@ int snd_cs4236_create(struct snd_card *card,
idx, snd_cs4236_ctrl_in(chip, idx));
}
#endif
if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "please, specify control port "
"for CS4236+ chips\n");
snd_device_free(card, chip);
return -ENODEV;
}
ver1 = snd_cs4236_ctrl_in(chip, 1);
ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2);
snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n",
cport, ver1, ver2);
if (ver1 != ver2) {
snd_printk(KERN_ERR "CS4236+ chip detected, but "
"control port 0x%lx is not valid\n", cport);
@@ -321,13 +329,17 @@ int snd_cs4236_create(struct snd_card *card,
snd_cs4236_ctrl_out(chip, 2, 0xff);
snd_cs4236_ctrl_out(chip, 3, 0x00);
snd_cs4236_ctrl_out(chip, 4, 0x80);
snd_cs4236_ctrl_out(chip, 5, ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | IEC958_AES0_CON_EMPHASIS_NONE);
reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) |
IEC958_AES0_CON_EMPHASIS_NONE;
snd_cs4236_ctrl_out(chip, 5, reg);
snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
snd_cs4236_ctrl_out(chip, 7, 0x00);
/* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 output */
/* is working with this setup, other hardware should have */
/* different signal paths and this value should be selectable */
/* in the future */
/*
* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958
* output is working with this setup, other hardware should
* have different signal paths and this value should be
* selectable in the future
*/
snd_cs4236_ctrl_out(chip, 8, 0x8c);
chip->rate_constraint = snd_cs4236_xrate;
chip->set_playback_format = snd_cs4236_playback_format;
@@ -339,9 +351,10 @@ int snd_cs4236_create(struct snd_card *card,
/* initialize extended registers */
for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]);
snd_cs4236_ext_out(chip, CS4236_I23VAL(reg),
snd_cs4236_ext_map[reg]);
/* initialize compatible but more featured registers */
/* initialize compatible but more featured registers */
snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
@@ -387,6 +400,14 @@ int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
.get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
#define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.info = snd_cs4236_info_single, \
.get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
.tlv = { .p = (xtlv) } }
static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -490,6 +511,16 @@ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_
.get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
#define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
shift_right, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.info = snd_cs4236_info_double, \
.get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
(shift_right << 19) | (mask << 24) | (invert << 22), \
.tlv = { .p = (xtlv) } }
static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -560,12 +591,23 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return change;
}
#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.info = snd_cs4236_info_double, \
.get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
#define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
shift_right, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.info = snd_cs4236_info_double, \
.get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
(shift_right << 19) | (mask << 24) | (invert << 22), \
.tlv = { .p = (xtlv) } }
static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
@@ -619,16 +661,18 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_
return change;
}
#define CS4236_MASTER_DIGITAL(xname, xindex) \
#define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.info = snd_cs4236_info_double, \
.get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
.private_value = 71 << 24 }
.private_value = 71 << 24, \
.tlv = { .p = (xtlv) } }
static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
{
return (vol < 64) ? 63 - vol : 64 + (71 - vol);
}
}
static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
@@ -661,11 +705,13 @@ static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct s
return change;
}
#define CS4235_OUTPUT_ACCU(xname, xindex) \
#define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.info = snd_cs4236_info_double, \
.get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
.private_value = 3 << 24 }
.private_value = 3 << 24, \
.tlv = { .p = (xtlv) } }
static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
{
@@ -720,41 +766,56 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_
return change;
}
static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
static struct snd_kcontrol_new snd_cs4236_controls[] = {
CS4236_DOUBLE("Master Digital Playback Switch", 0,
CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
CS4236_DOUBLE("Master Digital Capture Switch", 0,
CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
CS4236_DOUBLE("Capture Boost Volume", 0,
CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
db_scale_2bit),
WSS_DOUBLE("PCM Playback Switch", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
WSS_DOUBLE("PCM Playback Volume", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
WSS_DOUBLE_TLV("PCM Playback Volume", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
db_scale_6bit),
CS4236_DOUBLE("DSP Playback Switch", 0,
CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
CS4236_DOUBLE("DSP Playback Volume", 0,
CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1),
CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
db_scale_6bit),
CS4236_DOUBLE("FM Playback Switch", 0,
CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
CS4236_DOUBLE("FM Playback Volume", 0,
CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1),
CS4236_DOUBLE_TLV("FM Playback Volume", 0,
CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
db_scale_6bit),
CS4236_DOUBLE("Wavetable Playback Switch", 0,
CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
CS4236_DOUBLE("Wavetable Playback Volume", 0,
CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1),
CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
db_scale_6bit_12db_max),
WSS_DOUBLE("Synth Playback Switch", 0,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
WSS_DOUBLE("Synth Volume", 0,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
WSS_DOUBLE_TLV("Synth Volume", 0,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_DOUBLE("Synth Capture Switch", 0,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
WSS_DOUBLE("Synth Capture Bypass", 0,
@@ -764,14 +825,16 @@ CS4236_DOUBLE("Mic Playback Switch", 0,
CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
CS4236_DOUBLE("Mic Capture Switch", 0,
CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1),
CS4236_DOUBLE("Mic Playback Boost", 0,
CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
0, 0, 31, 1, db_scale_5bit_22db_max),
CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
WSS_DOUBLE("Line Playback Switch", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE("Line Volume", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
WSS_DOUBLE_TLV("Line Volume", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_DOUBLE("Line Capture Switch", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
WSS_DOUBLE("Line Capture Bypass", 0,
@@ -779,57 +842,63 @@ WSS_DOUBLE("Line Capture Bypass", 0,
WSS_DOUBLE("CD Playback Switch", 0,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE("CD Volume", 0,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
WSS_DOUBLE_TLV("CD Volume", 0,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_DOUBLE("CD Capture Switch", 0,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
CS4236_DOUBLE1("Mono Output Playback Switch", 0,
CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
CS4236_DOUBLE1("Mono Playback Switch", 0,
CS4236_DOUBLE1("Beep Playback Switch", 0,
CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
db_scale_4bit),
WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
WSS_DOUBLE("Capture Volume", 0,
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
0, 0, 15, 0, db_scale_rec_gain),
WSS_DOUBLE("Analog Loopback Capture Switch", 0,
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
CS4236_DOUBLE1("Digital Loopback Playback Volume", 0,
CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
db_scale_6bit),
};
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
static struct snd_kcontrol_new snd_cs4235_controls[] = {
WSS_DOUBLE("Master Switch", 0,
WSS_DOUBLE("Master Playback Switch", 0,
CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
WSS_DOUBLE("Master Volume", 0,
CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
WSS_DOUBLE_TLV("Master Playback Volume", 0,
CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
db_scale_5bit_6db_max),
CS4235_OUTPUT_ACCU("Playback Volume", 0),
CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
CS4236_DOUBLE("Master Digital Playback Switch", 0,
CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
CS4236_DOUBLE("Master Digital Capture Switch", 0,
CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
WSS_DOUBLE("Master Digital Playback Switch", 1,
WSS_DOUBLE("Synth Playback Switch", 1,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
WSS_DOUBLE("Master Digital Capture Switch", 1,
WSS_DOUBLE("Synth Capture Switch", 1,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
WSS_DOUBLE("Master Digital Volume", 1,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
WSS_DOUBLE_TLV("Synth Volume", 1,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
db_scale_5bit_12db_max),
CS4236_DOUBLE("Capture Volume", 0,
CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1),
CS4236_DOUBLE_TLV("Capture Volume", 0,
CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
db_scale_2bit),
WSS_DOUBLE("PCM Switch", 0,
WSS_DOUBLE("PCM Playback Switch", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
WSS_DOUBLE("PCM Volume", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
WSS_DOUBLE("PCM Capture Switch", 0,
CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
WSS_DOUBLE_TLV("PCM Volume", 0,
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
db_scale_6bit),
CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
@@ -842,29 +911,29 @@ CS4236_DOUBLE("Mic Capture Switch", 0,
CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
CS4236_DOUBLE("Mic Playback Switch", 0,
CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1),
CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0),
CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
db_scale_5bit_22db_max),
CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
WSS_DOUBLE("Aux Playback Switch", 0,
WSS_DOUBLE("Line Playback Switch", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE("Aux Capture Switch", 0,
WSS_DOUBLE("Line Capture Switch", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
WSS_DOUBLE("Aux Volume", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
WSS_DOUBLE_TLV("Line Volume", 0,
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_DOUBLE("Aux Playback Switch", 1,
WSS_DOUBLE("CD Playback Switch", 1,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
WSS_DOUBLE("Aux Capture Switch", 1,
WSS_DOUBLE("CD Capture Switch", 1,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
WSS_DOUBLE("Aux Volume", 1,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
WSS_DOUBLE_TLV("CD Volume", 1,
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
CS4236_DOUBLE1("Master Mono Switch", 0,
CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
CS4236_DOUBLE1("Mono Switch", 0,
CS4236_DOUBLE1("Beep Playback Switch", 0,
CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
WSS_DOUBLE("Analog Loopback Switch", 0,
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
+41 -50
View File
@@ -102,8 +102,6 @@
struct snd_es18xx {
unsigned long port; /* port of ESS chip */
unsigned long mpu_port; /* MPU-401 port of ESS chip */
unsigned long fm_port; /* FM port */
unsigned long ctrl_port; /* Control port of ESS chip */
struct resource *res_port;
struct resource *res_mpu_port;
@@ -116,8 +114,6 @@ struct snd_es18xx {
unsigned short audio2_vol; /* volume level of audio2 */
unsigned short active; /* active channel mask */
unsigned int dma1_size;
unsigned int dma2_size;
unsigned int dma1_shift;
unsigned int dma2_shift;
@@ -135,7 +131,6 @@ struct snd_es18xx {
spinlock_t reg_lock;
spinlock_t mixer_lock;
spinlock_t ctrl_lock;
#ifdef CONFIG_PM
unsigned char pm_reg;
#endif
@@ -354,7 +349,7 @@ static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned ch
}
static int snd_es18xx_reset(struct snd_es18xx *chip)
static int __devinit snd_es18xx_reset(struct snd_es18xx *chip)
{
int i;
outb(0x03, chip->port + 0x06);
@@ -490,8 +485,6 @@ static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip,
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
chip->dma2_size = size;
snd_es18xx_rate_set(chip, substream, DAC2);
/* Transfer Count Reload */
@@ -591,8 +584,6 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
chip->dma1_size = size;
snd_es18xx_reset_fifo(chip);
/* Set stereo/mono */
@@ -659,8 +650,6 @@ static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
chip->dma1_size = size;
snd_es18xx_reset_fifo(chip);
/* Set stereo/mono */
@@ -821,17 +810,18 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream)
{
struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
int pos;
if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
if (!(chip->active & DAC2))
return 0;
pos = snd_dma_pointer(chip->dma2, chip->dma2_size);
pos = snd_dma_pointer(chip->dma2, size);
return pos >> chip->dma2_shift;
} else {
if (!(chip->active & DAC1))
return 0;
pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
pos = snd_dma_pointer(chip->dma1, size);
return pos >> chip->dma1_shift;
}
}
@@ -839,11 +829,12 @@ static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *s
static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream)
{
struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
int pos;
if (!(chip->active & ADC1))
return 0;
pos = snd_dma_pointer(chip->dma1, chip->dma1_size);
pos = snd_dma_pointer(chip->dma1, size);
return pos >> chip->dma1_shift;
}
@@ -974,9 +965,6 @@ static int snd_es18xx_capture_close(struct snd_pcm_substream *substream)
static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts4Source[4] = {
"Mic", "CD", "Line", "Master"
};
static char *texts5Source[5] = {
"Mic", "CD", "Line", "Master", "Mix"
};
@@ -994,7 +982,8 @@ static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
uinfo->value.enumerated.items = 4;
if (uinfo->value.enumerated.item > 3)
uinfo->value.enumerated.item = 3;
strcpy(uinfo->value.enumerated.name, texts4Source[uinfo->value.enumerated.item]);
strcpy(uinfo->value.enumerated.name,
texts5Source[uinfo->value.enumerated.item]);
break;
case 0x1887:
case 0x1888:
@@ -1378,11 +1367,9 @@ ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
{
int data;
unsigned long flags;
spin_lock_irqsave(&chip->ctrl_lock, flags);
outb(reg, chip->ctrl_port);
data = inb(chip->ctrl_port + 1);
spin_unlock_irqrestore(&chip->ctrl_lock, flags);
return data;
}
@@ -1398,7 +1385,9 @@ static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
#endif
}
static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip,
unsigned long mpu_port,
unsigned long fm_port)
{
int mask = 0;
@@ -1412,15 +1401,15 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
if (chip->caps & ES18XX_CONTROL) {
/* Hardware volume IRQ */
snd_es18xx_config_write(chip, 0x27, chip->irq);
if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
/* FM I/O */
snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8);
snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff);
snd_es18xx_config_write(chip, 0x62, fm_port >> 8);
snd_es18xx_config_write(chip, 0x63, fm_port & 0xff);
}
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
/* MPU-401 I/O */
snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8);
snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff);
snd_es18xx_config_write(chip, 0x64, mpu_port >> 8);
snd_es18xx_config_write(chip, 0x65, mpu_port & 0xff);
/* MPU-401 IRQ */
snd_es18xx_config_write(chip, 0x28, chip->irq);
}
@@ -1507,11 +1496,12 @@ static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
snd_es18xx_mixer_write(chip, 0x7A, 0x68);
/* Enable and set hardware volume interrupt */
snd_es18xx_mixer_write(chip, 0x64, 0x06);
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
if (mpu_port > 0 && mpu_port != SNDRV_AUTO_PORT) {
/* MPU401 share irq with audio
Joystick enabled
FM enabled */
snd_es18xx_mixer_write(chip, 0x40, 0x43 | (chip->mpu_port & 0xf0) >> 1);
snd_es18xx_mixer_write(chip, 0x40,
0x43 | (mpu_port & 0xf0) >> 1);
}
snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01);
}
@@ -1629,7 +1619,9 @@ static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
return 0;
}
static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
static int __devinit snd_es18xx_probe(struct snd_es18xx *chip,
unsigned long mpu_port,
unsigned long fm_port)
{
if (snd_es18xx_identify(chip) < 0) {
snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1650,8 +1642,6 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
break;
case 0x1887:
chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
break;
case 0x1888:
chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME;
break;
@@ -1666,7 +1656,7 @@ static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
if (chip->dma1 == chip->dma2)
chip->caps &= ~(ES18XX_PCM2 | ES18XX_DUPLEX_SAME);
return snd_es18xx_initialize(chip);
return snd_es18xx_initialize(chip, mpu_port, fm_port);
}
static struct snd_pcm_ops snd_es18xx_playback_ops = {
@@ -1802,10 +1792,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->mixer_lock);
spin_lock_init(&chip->ctrl_lock);
chip->port = port;
chip->mpu_port = mpu_port;
chip->fm_port = fm_port;
chip->irq = -1;
chip->dma1 = -1;
chip->dma2 = -1;
@@ -1841,11 +1828,11 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
}
chip->dma2 = dma2;
if (snd_es18xx_probe(chip) < 0) {
if (snd_es18xx_probe(chip, mpu_port, fm_port) < 0) {
snd_es18xx_free(card);
return -ENODEV;
}
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, NULL, &ops);
return -ENODEV;
}
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_es18xx_free(card);
return err;
@@ -1980,7 +1967,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
#ifndef CONFIG_PNP
@@ -2160,19 +2147,23 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
return err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
snd_printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
if (snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
OPL3_HW_OPL3, 0, &opl3) < 0) {
snd_printk(KERN_WARNING PFX
"opl3 not detected at 0x%lx\n",
fm_port[dev]);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
return err;
}
}
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
chip->mpu_port, 0,
irq[dev], 0,
&chip->rmidi)) < 0)
err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
mpu_port[dev], 0,
irq[dev], 0, &chip->rmidi);
if (err < 0)
return err;
}
+514 -277
View File
File diff suppressed because it is too large Load Diff
+43 -67
View File
@@ -141,15 +141,7 @@ struct snd_opti9xx {
spinlock_t lock;
long wss_base;
int irq;
int dma1;
int dma2;
long fm_port;
long mpu_port;
int mpu_irq;
#ifdef CONFIG_PNP
struct pnp_dev *dev;
@@ -216,13 +208,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
spin_lock_init(&chip->lock);
chip->wss_base = -1;
chip->irq = -1;
chip->dma1 = -1;
chip->dma2 = -1;
chip->fm_port = -1;
chip->mpu_port = -1;
chip->mpu_irq = -1;
switch (hardware) {
#ifndef OPTi93X
@@ -348,7 +334,10 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
(snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
long wss_base,
int irq, int dma1, int dma2,
long mpu_port, int mpu_irq)
{
unsigned char wss_base_bits;
unsigned char irq_bits;
@@ -416,7 +405,7 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
return -EINVAL;
}
switch (chip->wss_base) {
switch (wss_base) {
case 0x530:
wss_base_bits = 0x00;
break;
@@ -430,14 +419,13 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
wss_base_bits = 0x02;
break;
default:
snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n",
chip->wss_base);
snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
goto __skip_base;
}
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
__skip_base:
switch (chip->irq) {
switch (irq) {
//#ifdef OPTi93X
case 5:
irq_bits = 0x05;
@@ -456,11 +444,11 @@ __skip_base:
irq_bits = 0x04;
break;
default:
snd_printk(KERN_WARNING "WSS irq # %d not valid\n", chip->irq);
snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq);
goto __skip_resources;
}
switch (chip->dma1) {
switch (dma1) {
case 0:
dma_bits = 0x01;
break;
@@ -471,38 +459,36 @@ __skip_base:
dma_bits = 0x03;
break;
default:
snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n",
chip->dma1);
snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1);
goto __skip_resources;
}
#if defined(CS4231) || defined(OPTi93X)
if (chip->dma1 == chip->dma2) {
if (dma1 == dma2) {
snd_printk(KERN_ERR "don't want to share dmas\n");
return -EBUSY;
}
switch (chip->dma2) {
switch (dma2) {
case 0:
case 1:
break;
default:
snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n",
chip->dma2);
snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2);
goto __skip_resources;
}
dma_bits |= 0x04;
#endif /* CS4231 || OPTi93X */
#ifndef OPTi93X
outb(irq_bits << 3 | dma_bits, chip->wss_base);
outb(irq_bits << 3 | dma_bits, wss_base);
#else /* OPTi93X */
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
#endif /* OPTi93X */
__skip_resources:
if (chip->hardware > OPTi9XX_HW_82C928) {
switch (chip->mpu_port) {
switch (mpu_port) {
case 0:
case -1:
break;
@@ -520,12 +506,11 @@ __skip_resources:
break;
default:
snd_printk(KERN_WARNING
"MPU-401 port 0x%lx not valid\n",
chip->mpu_port);
"MPU-401 port 0x%lx not valid\n", mpu_port);
goto __skip_mpu;
}
switch (chip->mpu_irq) {
switch (mpu_irq) {
case 5:
mpu_irq_bits = 0x02;
break;
@@ -540,12 +525,12 @@ __skip_resources:
break;
default:
snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
chip->mpu_irq);
mpu_irq);
goto __skip_mpu;
}
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
(chip->mpu_port <= 0) ? 0x00 :
(mpu_port <= 0) ? 0x00 :
0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
0xf8);
}
@@ -701,6 +686,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
int error;
int xdma2;
struct snd_opti9xx *chip = card->private_data;
struct snd_wss *codec;
#ifdef CS4231
@@ -715,31 +701,25 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
"OPTi9xx MC")) == NULL)
return -ENOMEM;
chip->wss_base = port;
chip->fm_port = fm_port;
chip->mpu_port = mpu_port;
chip->irq = irq;
chip->mpu_irq = mpu_irq;
chip->dma1 = dma1;
#if defined(CS4231) || defined(OPTi93X)
chip->dma2 = dma2;
xdma2 = dma2;
#else
chip->dma2 = -1;
xdma2 = -1;
#endif
if (chip->wss_base == SNDRV_AUTO_PORT) {
chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4);
if (chip->wss_base < 0) {
if (port == SNDRV_AUTO_PORT) {
port = snd_legacy_find_free_ioport(possible_ports, 4);
if (port < 0) {
snd_printk(KERN_ERR "unable to find a free WSS port\n");
return -EBUSY;
}
}
error = snd_opti9xx_configure(chip);
error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
mpu_port, mpu_irq);
if (error)
return error;
error = snd_wss_create(card, chip->wss_base + 4, -1,
chip->irq, chip->dma1, chip->dma2,
error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
#ifdef OPTi93X
WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
#else
@@ -763,35 +743,35 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
return error;
#endif
#ifdef OPTi93X
error = request_irq(chip->irq, snd_opti93x_interrupt,
error = request_irq(irq, snd_opti93x_interrupt,
IRQF_DISABLED, DEV_NAME" - WSS", codec);
if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
return error;
}
#endif
chip->irq = irq;
strcpy(card->driver, chip->name);
sprintf(card->shortname, "OPTi %s", card->driver);
#if defined(CS4231) || defined(OPTi93X)
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
card->shortname, pcm->name, chip->wss_base + 4,
chip->irq, chip->dma1, chip->dma2);
card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
#else
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
card->shortname, pcm->name, chip->wss_base + 4,
chip->irq, chip->dma1);
card->shortname, pcm->name, port + 4, irq, dma1);
#endif /* CS4231 || OPTi93X */
if (chip->mpu_port <= 0 || chip->mpu_port == SNDRV_AUTO_PORT)
if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
rmidi = NULL;
else
if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
chip->mpu_port, 0, chip->mpu_irq, IRQF_DISABLED,
&rmidi)))
else {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi);
if (error)
snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
chip->mpu_port);
mpu_port);
}
if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
struct snd_opl3 *opl3 = NULL;
#ifndef OPTi93X
if (chip->hardware == OPTi9XX_HW_82C928 ||
@@ -801,9 +781,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
/* assume we have an OPL4 */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
0x20, 0x20);
if (snd_opl4_create(card,
chip->fm_port,
chip->fm_port - 8,
if (snd_opl4_create(card, fm_port, fm_port - 8,
2, &opl3, &opl4) < 0) {
/* no luck, use OPL3 instead */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
@@ -811,12 +789,10 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
}
}
#endif /* !OPTi93X */
if (!opl3 && snd_opl3_create(card,
chip->fm_port,
chip->fm_port + 2,
if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2,
OPL3_HW_AUTO, 0, &opl3) < 0) {
snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
chip->fm_port, chip->fm_port + 4 - 1);
fm_port, fm_port + 4 - 1);
}
if (opl3) {
error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
+5 -6
View File
@@ -1682,7 +1682,7 @@ static void snd_wss_resume(struct snd_wss *chip)
}
#endif /* CONFIG_PM */
int snd_wss_free(struct snd_wss *chip)
static int snd_wss_free(struct snd_wss *chip)
{
release_and_free_resource(chip->res_port);
release_and_free_resource(chip->res_cport);
@@ -1705,7 +1705,6 @@ int snd_wss_free(struct snd_wss *chip)
kfree(chip);
return 0;
}
EXPORT_SYMBOL(snd_wss_free);
static int snd_wss_dev_free(struct snd_device *device)
{
@@ -2225,7 +2224,7 @@ WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
.get = snd_wss_get_mux,
.put = snd_wss_put_mux,
},
WSS_DOUBLE("Mic Boost", 0,
WSS_DOUBLE("Mic Boost (+20dB)", 0,
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
WSS_SINGLE("Loopback Capture Switch", 0,
CS4231_LOOPBACK, 0, 1, 0),
@@ -2236,14 +2235,14 @@ WSS_DOUBLE("Line Playback Switch", 0,
WSS_DOUBLE_TLV("Line Playback Volume", 0,
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_SINGLE("Mono Playback Switch", 0,
WSS_SINGLE("Beep Playback Switch", 0,
CS4231_MONO_CTRL, 7, 1, 1),
WSS_SINGLE_TLV("Mono Playback Volume", 0,
WSS_SINGLE_TLV("Beep Playback Volume", 0,
CS4231_MONO_CTRL, 0, 15, 1,
db_scale_4bit),
WSS_SINGLE("Mono Output Playback Switch", 0,
CS4231_MONO_CTRL, 6, 1, 1),
WSS_SINGLE("Mono Output Playback Bypass", 0,
WSS_SINGLE("Beep Bypass Playback Switch", 0,
CS4231_MONO_CTRL, 5, 1, 0),
};
+1 -1
View File
@@ -838,7 +838,7 @@ static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
if ((err = audio_devs[dev]->d->prepare_for_input(dev,
dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
spin_unlock_irqrestore(&dmap_in->lock,flags);
return -err;
return err;
}
dmap_in->dma_mode = DMODE_INPUT;
audio_devs[dev]->enable_bits |= PCM_ENABLE_INPUT;
+1 -1
View File
@@ -426,7 +426,7 @@ midi_synth_open(int dev, int mode)
int err;
struct midi_input_info *inc;
if (orig_dev < 0 || orig_dev > num_midis || midi_devs[orig_dev] == NULL)
if (orig_dev < 0 || orig_dev >= num_midis || midi_devs[orig_dev] == NULL)
return -ENXIO;
midi2synth[orig_dev] = dev;
+1 -1
View File
@@ -770,7 +770,7 @@ static int mpu_synth_ioctl(int dev, unsigned int cmd, void __user *arg)
midi_dev = synth_devs[dev]->midi_dev;
if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev] == NULL)
if (midi_dev < 0 || midi_dev >= num_midis || midi_devs[midi_dev] == NULL)
return -ENXIO;
devc = &dev_conf[midi_dev];

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