Skip to content

Commit

Permalink
Merge branch 'topic/misc' into for-linus
Browse files Browse the repository at this point in the history
  • Loading branch information
tiwai committed Dec 4, 2009
2 parents 7959832 + fb716c0 commit 57648cd
Show file tree
Hide file tree
Showing 36 changed files with 1,463 additions and 702 deletions.
18 changes: 18 additions & 0 deletions drivers/media/radio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/media/radio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
270 changes: 270 additions & 0 deletions drivers/media/radio/radio-miropcm20.c
Original file line number Diff line number Diff line change
@@ -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);
23 changes: 20 additions & 3 deletions sound/isa/opti9xx/miro.h → include/sound/aci.h
Original file line number Diff line number Diff line change
@@ -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 */
Expand Down Expand Up @@ -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 change: 0 additions & 1 deletion include/sound/cs4231-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 0 additions & 1 deletion include/sound/wss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion sound/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
19 changes: 5 additions & 14 deletions sound/arm/aaci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down
Loading

0 comments on commit 57648cd

Please sign in to comment.