/*
 * linux/kernel/chr_drv/sound/pcsp.c
 *
 * /dev/pcsp implementation
 *
 * Copyright (C) 1993, 1994  Michael Beck 
 */

#include <linux/pcsp.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/config.h>
#include <linux/kernel.h>

#include "local.h"

extern struct file_operations pcspeaker_pcsp_fops, pcsp_mixer_fops;
extern long pcspeaker_init(long);
extern long pcsp_mixer_init(long);
extern long pcsp_set_format(long);
extern char pcsp_enabled;

static int pcsp_open_dev(struct inode * inode, struct file * file)
{
	int minor = MINOR(inode->i_rdev);

	if (! pcsp_enabled)
		return -ENODEV;

	file->f_op = &pcspeaker_pcsp_fops;
	switch (minor) {
		case PCSP_DSP_MINOR:
	                pcsp_set_format(AFMT_U8);
	                break;
                case PCSP_AUD_MINOR:
                        pcsp_set_format(AFMT_MU_LAW);	/* input is ULAW */
			break;
#ifdef PCSP_16BIT_SUPPORT
		case PCSP_DSP16_MINOR:
			if (pcsp_set_format(AFMT_S16_LE) != AFMT_S16_LE)
				return -ENODEV;
			break;
#endif
#ifdef PCSP_MIXER
		case PCSP_MIXER_MINOR:
			file->f_op = &pcsp_mixer_fops;
			break;
#endif
		default:
			return -ENODEV;
	}
        return file->f_op->open(inode,file);
}

static struct file_operations pcsp_fops = {
        NULL,		/* seek */
	NULL,		/* read */
	NULL,		/* write */
	NULL,		/* readdir */
	NULL,		/* select */
	NULL,		/* ioctl */
	NULL,		/* mmap */
        pcsp_open_dev,
        NULL		/* release */
};

long pcsp_init(long kmem_start)
{
	/* if disabled in commandline */
	if (! pcsp_enabled) {
		printk("PCSP-device disabled\n");
		return kmem_start;
	}

	if (register_chrdev(PCSP_MAJOR, "pcsp", &pcsp_fops))
		printk("unable to get major %d for pcsp devices\n", PCSP_MAJOR);
	else {
		printk("PCSP-device 0.9 init:\n");
		kmem_start = pcspeaker_init(kmem_start);
#ifdef PCSP_MIXER
		if (pcsp_enabled) {
			kmem_start = pcsp_mixer_init(kmem_start);
			printk(", PCSP-Mixer");
		}
#endif
	}
	if (pcsp_enabled)
		printk(" installed\n");
	return kmem_start;
}
