/*
 *  ALSA interface to cx18 PCM capture streams
 *
 *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
 *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
 *
 *  Portions of this work were sponsored by ONELAN Limited.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/spinlock.h>

#include <media/v4l2-device.h>

#include <sound/core.h>
#include <sound/initval.h>

#include "cx18-driver.h"
#include "cx18-version.h"
#include "cx18-alsa.h"
#include "cx18-alsa-mixer.h"
#include "cx18-alsa-pcm.h"

int cx18_alsa_debug;

#define CX18_DEBUG_ALSA_INFO(fmt, arg...) \
	do { \
		if (cx18_alsa_debug & 2) \
			printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \
	} while (0);

module_param_named(debug, cx18_alsa_debug, int, 0644);
MODULE_PARM_DESC(debug,
		 "Debug level (bitmask). Default: 0\n"
		 "\t\t\t  1/0x0001: warning\n"
		 "\t\t\t  2/0x0002: info\n");

MODULE_AUTHOR("Andy Walls");
MODULE_DESCRIPTION("CX23418 ALSA Interface");
MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
MODULE_LICENSE("GPL");

MODULE_VERSION(CX18_VERSION);

static inline
struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
{
	return to_cx18(v4l2_dev)->alsa;
}

static inline
struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
{
	return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
}

static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
{
	if (cxsc == NULL)
		return;

	if (cxsc->v4l2_dev != NULL)
		to_cx18(cxsc->v4l2_dev)->alsa = NULL;

	/* FIXME - take any other stopping actions needed */

	kfree(cxsc);
}

static void snd_cx18_card_private_free(struct snd_card *sc)
{
	if (sc == NULL)
		return;
	snd_cx18_card_free(sc->private_data);
	sc->private_data = NULL;
	sc->private_free = NULL;
}

static int snd_cx18_card_create(struct v4l2_device *v4l2_dev,
				       struct snd_card *sc,
				       struct snd_cx18_card **cxsc)
{
	*cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL);
	if (*cxsc == NULL)
		return -ENOMEM;

	(*cxsc)->v4l2_dev = v4l2_dev;
	(*cxsc)->sc = sc;

	sc->private_data = *cxsc;
	sc->private_free = snd_cx18_card_private_free;

	return 0;
}

static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
{
	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
	struct snd_card *sc = cxsc->sc;

	/* sc->driver is used by alsa-lib's configurator: simple, unique */
	strlcpy(sc->driver, "CX23418", sizeof(sc->driver));

	/* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
	snprintf(sc->shortname,  sizeof(sc->shortname), "CX18-%d",
		 cx->instance);

	/* sc->longname is read from /proc/asound/cards */
	snprintf(sc->longname, sizeof(sc->longname),
		 "CX23418 #%d %s TV/FM Radio/Line-In Capture",
		 cx->instance, cx->card_name);

	return 0;
}

static int snd_cx18_init(struct v4l2_device *v4l2_dev)
{
	struct cx18 *cx = to_cx18(v4l2_dev);
	struct snd_card *sc = NULL;
	struct snd_cx18_card *cxsc;
	int ret;

	/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */

	/* (1) Check and increment the device index */
	/* This is a no-op for us.  We'll use the cx->instance */

	/* (2) Create a card instance */
	ret = snd_card_new(&cx->pci_dev->dev,
			   SNDRV_DEFAULT_IDX1, /* use first available id */
			   SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
			   THIS_MODULE, 0, &sc);
	if (ret) {
		CX18_ALSA_ERR("%s: snd_card_new() failed with err %d\n",
			      __func__, ret);
		goto err_exit;
	}

	/* (3) Create a main component */
	ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc);
	if (ret) {
		CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n",
			      __func__, ret);
		goto err_exit_free;
	}

	/* (4) Set the driver ID and name strings */
	snd_cx18_card_set_names(cxsc);


	ret = snd_cx18_pcm_create(cxsc);
	if (ret) {
		CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
			      __func__, ret);
		goto err_exit_free;
	}
	/* FIXME - proc files */

	/* (7) Set the driver data and return 0 */
	/* We do this out of normal order for PCI drivers to avoid races */
	cx->alsa = cxsc;

	/* (6) Register the card instance */
	ret = snd_card_register(sc);
	if (ret) {
		cx->alsa = NULL;
		CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
			      __func__, ret);
		goto err_exit_free;
	}

	return 0;

err_exit_free:
	if (sc != NULL)
		snd_card_free(sc);
	kfree(cxsc);
err_exit:
	return ret;
}

static int cx18_alsa_load(struct cx18 *cx)
{
	struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
	struct cx18_stream *s;

	if (v4l2_dev == NULL) {
		printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
		       __func__);
		return 0;
	}

	cx = to_cx18(v4l2_dev);
	if (cx == NULL) {
		printk(KERN_ERR "cx18-alsa cx is NULL\n");
		return 0;
	}

	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
	if (s->video_dev.v4l2_dev == NULL) {
		CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - skipping\n",
				     __func__);
		return 0;
	}

	if (cx->alsa != NULL) {
		CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n",
			      __func__);
		return 0;
	}

	if (snd_cx18_init(v4l2_dev)) {
		CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
			      __func__);
	} else {
		CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance\n",
				     __func__);
	}
	return 0;
}

static int __init cx18_alsa_init(void)
{
	printk(KERN_INFO "cx18-alsa: module loading...\n");
	cx18_ext_init = &cx18_alsa_load;
	return 0;
}

static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc)
{
	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);

	/* FIXME - pointer checks & shutdown cxsc */

	snd_card_free(cxsc->sc);
	cx->alsa = NULL;
}

static int __exit cx18_alsa_exit_callback(struct device *dev, void *data)
{
	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
	struct snd_cx18_card *cxsc;

	if (v4l2_dev == NULL) {
		printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
		       __func__);
		return 0;
	}

	cxsc = to_snd_cx18_card(v4l2_dev);
	if (cxsc == NULL) {
		CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n",
			       __func__);
		return 0;
	}

	snd_cx18_exit(cxsc);
	return 0;
}

static void __exit cx18_alsa_exit(void)
{
	struct device_driver *drv;
	int ret;

	printk(KERN_INFO "cx18-alsa: module unloading...\n");

	drv = driver_find("cx18", &pci_bus_type);
	ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
	(void)ret;	/* suppress compiler warning */

	cx18_ext_init = NULL;
	printk(KERN_INFO "cx18-alsa: module unload complete\n");
}

module_init(cx18_alsa_init);
module_exit(cx18_alsa_exit);
