/* 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 (drivers/sound/aci.c)
 * Look there for further info...
 */

/* Revision history:
 *
 *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
 *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
 *        removed unfinished volume control (maybe adding it later again)
 *        use OSS-mixer; added stereo control
 */

/* 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/videodev.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include "oss/aci.h"
#include "miropcm20-rds-core.h"

static int radio_nr = -1;
module_param(radio_nr, int, 0);

struct pcm20_device {
	unsigned long freq;
	int muted;
	int stereo;
};


static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
{
	dev->muted = mute;
	return aci_write_cmd(ACI_SET_TUNERMUTE, mute);
}

static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
{
	dev->stereo = stereo;
	return aci_write_cmd(ACI_SET_TUNERMONO, !stereo);
}

static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
{
	unsigned char freql;
	unsigned char freqh;

	dev->freq=freq;

	freq /= 160;
	if (!(aci_version==0x07 || aci_version>=0xb0))
		freq /= 10;  /* I don't know exactly which version
			      * needs this hack */
	freql = freq & 0xff;
	freqh = freq >> 8;

	aci_rds_cmd(RDS_RESET, NULL, 0);
	pcm20_stereo(dev, 1);

	return aci_rw_cmd(ACI_WRITE_TUNE, freql, freqh);
}

static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
{
	/* okay, check for signal, stereo and rds here... */
	int i;
	unsigned char buf;

	if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
		return i;
	pr_debug("check_sig: 0x%x\n", i);
	if (i & 0x80) {
		/* no signal from tuner */
		*flags=0;
		*signal=0;
		return 0;
	} else
		*signal=0xffff;

	if ((i=aci_rw_cmd(ACI_READ_TUNERSTEREO, -1, -1))<0)
		return i;
	if (i & 0x40) {
		*flags=0;
	} else {
		/* stereo */
		*flags=VIDEO_TUNER_STEREO_ON;
		/* I can't see stereo, when forced to mono */
		dev->stereo=1;
	}

	if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
		return i;
	if (buf & 1)
		/* RDS available */
		*flags|=VIDEO_TUNER_RDS_ON;
	else
		return 0;

	if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
		return i;
	pr_debug("rds-signal: %d\n", buf);
	if (buf > 15) {
		printk("miropcm20-radio: RX strengths unexpected high...\n");
		buf=15;
	}
	/* refine signal */
	if ((*signal=SCALE(15, 0xffff, buf))==0)
		*signal = 1;

	return 0;
}

static int pcm20_do_ioctl(struct inode *inode, struct file *file,
			  unsigned int cmd, void *arg)
{
	struct video_device *dev = video_devdata(file);
	struct pcm20_device *pcm20 = dev->priv;
	int i;

	switch(cmd)
	{
		case VIDIOCGCAP:
		{
			struct video_capability *v = arg;
			memset(v,0,sizeof(*v));
			v->type=VID_TYPE_TUNER;
			strcpy(v->name, "Miro PCM20");
			v->channels=1;
			v->audios=1;
			return 0;
		}
		case VIDIOCGTUNER:
		{
			struct video_tuner *v = arg;
			if(v->tuner)	/* Only 1 tuner */
				return -EINVAL;
			v->rangelow=87*16000;
			v->rangehigh=108*16000;
			pcm20_getflags(pcm20, &v->flags, &v->signal);
			v->flags|=VIDEO_TUNER_LOW;
			v->mode=VIDEO_MODE_AUTO;
			strcpy(v->name, "FM");
			return 0;
		}
		case VIDIOCSTUNER:
		{
			struct video_tuner *v = arg;
			if(v->tuner!=0)
				return -EINVAL;
			/* Only 1 tuner so no setting needed ! */
			return 0;
		}
		case VIDIOCGFREQ:
		{
			unsigned long *freq = arg;
			*freq = pcm20->freq;
			return 0;
		}
		case VIDIOCSFREQ:
		{
			unsigned long *freq = arg;
			pcm20->freq = *freq;
			i=pcm20_setfreq(pcm20, pcm20->freq);
			pr_debug("First view (setfreq): 0x%x\n", i);
			return i;
		}
		case VIDIOCGAUDIO:
		{
			struct video_audio *v = arg;
			memset(v,0, sizeof(*v));
			v->flags=VIDEO_AUDIO_MUTABLE;
			if (pcm20->muted)
				v->flags|=VIDEO_AUDIO_MUTE;
			v->mode=VIDEO_SOUND_STEREO;
			if (pcm20->stereo)
				v->mode|=VIDEO_SOUND_MONO;
			/* v->step=2048; */
			strcpy(v->name, "Radio");
			return 0;
		}
		case VIDIOCSAUDIO:
		{
			struct video_audio *v = arg;
			if(v->audio)
				return -EINVAL;

			pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE));
			if(v->flags&VIDEO_SOUND_MONO)
				pcm20_stereo(pcm20, 0);
			if(v->flags&VIDEO_SOUND_STEREO)
				pcm20_stereo(pcm20, 1);

			return 0;
		}
		default:
			return -ENOIOCTLCMD;
	}
}

static int pcm20_ioctl(struct inode *inode, struct file *file,
		       unsigned int cmd, unsigned long arg)
{
	return video_usercopy(inode, file, cmd, arg, pcm20_do_ioctl);
}

static struct pcm20_device pcm20_unit = {
	.freq   = 87*16000,
	.muted  = 1,
};

static const struct file_operations pcm20_fops = {
	.owner		= THIS_MODULE,
	.open           = video_exclusive_open,
	.release        = video_exclusive_release,
	.ioctl		= pcm20_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= v4l_compat_ioctl32,
#endif
	.llseek         = no_llseek,
};

static struct video_device pcm20_radio = {
	.name		= "Miro PCM 20 radio",
	.fops           = &pcm20_fops,
	.priv		= &pcm20_unit
};

static int __init pcm20_init(void)
{
	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
		goto video_register_device;

	if(attach_aci_rds()<0)
		goto attach_aci_rds;

	printk(KERN_INFO "Miro PCM20 radio card driver.\n");

	return 0;

 attach_aci_rds:
	video_unregister_device(&pcm20_radio);
 video_register_device:
	return -EINVAL;
}

MODULE_AUTHOR("Ruurd Reitsma");
MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
MODULE_LICENSE("GPL");

static void __exit pcm20_cleanup(void)
{
	unload_aci_rds();
	video_unregister_device(&pcm20_radio);
}

module_init(pcm20_init);
module_exit(pcm20_cleanup);
