/*
 * Abilis Systems Single DVB-T Receiver
 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
 *
 * 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, 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/kref.h>
#include <linux/uaccess.h>
#include <linux/usb.h>

/* header file for usb device driver*/
#include "as102_drv.h"
#include "as102_fw.h"
#include "dvbdev.h"

int as102_debug;
module_param_named(debug, as102_debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");

int dual_tuner;
module_param_named(dual_tuner, dual_tuner, int, 0644);
MODULE_PARM_DESC(dual_tuner, "Activate Dual-Tuner config (default: off)");

static int fw_upload = 1;
module_param_named(fw_upload, fw_upload, int, 0644);
MODULE_PARM_DESC(fw_upload, "Turn on/off default FW upload (default: on)");

static int pid_filtering;
module_param_named(pid_filtering, pid_filtering, int, 0644);
MODULE_PARM_DESC(pid_filtering, "Activate HW PID filtering (default: off)");

static int ts_auto_disable;
module_param_named(ts_auto_disable, ts_auto_disable, int, 0644);
MODULE_PARM_DESC(ts_auto_disable, "Stream Auto Enable on FW (default: off)");

int elna_enable = 1;
module_param_named(elna_enable, elna_enable, int, 0644);
MODULE_PARM_DESC(elna_enable, "Activate eLNA (default: on)");

DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

static void as102_stop_stream(struct as102_dev_t *dev)
{
	struct as10x_bus_adapter_t *bus_adap;

	if (dev != NULL)
		bus_adap = &dev->bus_adap;
	else
		return;

	if (bus_adap->ops->stop_stream != NULL)
		bus_adap->ops->stop_stream(dev);

	if (ts_auto_disable) {
		if (mutex_lock_interruptible(&dev->bus_adap.lock))
			return;

		if (as10x_cmd_stop_streaming(bus_adap) < 0)
			dprintk(debug, "as10x_cmd_stop_streaming failed\n");

		mutex_unlock(&dev->bus_adap.lock);
	}
}

static int as102_start_stream(struct as102_dev_t *dev)
{
	struct as10x_bus_adapter_t *bus_adap;
	int ret = -EFAULT;

	if (dev != NULL)
		bus_adap = &dev->bus_adap;
	else
		return ret;

	if (bus_adap->ops->start_stream != NULL)
		ret = bus_adap->ops->start_stream(dev);

	if (ts_auto_disable) {
		if (mutex_lock_interruptible(&dev->bus_adap.lock))
			return -EFAULT;

		ret = as10x_cmd_start_streaming(bus_adap);

		mutex_unlock(&dev->bus_adap.lock);
	}

	return ret;
}

static int as10x_pid_filter(struct as102_dev_t *dev,
			    int index, u16 pid, int onoff) {

	struct as10x_bus_adapter_t *bus_adap = &dev->bus_adap;
	int ret = -EFAULT;

	if (mutex_lock_interruptible(&dev->bus_adap.lock)) {
		dprintk(debug, "mutex_lock_interruptible(lock) failed !\n");
		return -EBUSY;
	}

	switch (onoff) {
	case 0:
		ret = as10x_cmd_del_PID_filter(bus_adap, (uint16_t) pid);
		dprintk(debug, "DEL_PID_FILTER([%02d] 0x%04x) ret = %d\n",
			index, pid, ret);
		break;
	case 1:
	{
		struct as10x_ts_filter filter;

		filter.type = TS_PID_TYPE_TS;
		filter.idx = 0xFF;
		filter.pid = pid;

		ret = as10x_cmd_add_PID_filter(bus_adap, &filter);
		dprintk(debug,
			"ADD_PID_FILTER([%02d -> %02d], 0x%04x) ret = %d\n",
			index, filter.idx, filter.pid, ret);
		break;
	}
	}

	mutex_unlock(&dev->bus_adap.lock);
	return ret;
}

static int as102_dvb_dmx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
	int ret = 0;
	struct dvb_demux *demux = dvbdmxfeed->demux;
	struct as102_dev_t *as102_dev = demux->priv;

	if (mutex_lock_interruptible(&as102_dev->sem))
		return -ERESTARTSYS;

	if (pid_filtering)
		as10x_pid_filter(as102_dev, dvbdmxfeed->index,
				 dvbdmxfeed->pid, 1);

	if (as102_dev->streaming++ == 0)
		ret = as102_start_stream(as102_dev);

	mutex_unlock(&as102_dev->sem);
	return ret;
}

static int as102_dvb_dmx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
	struct dvb_demux *demux = dvbdmxfeed->demux;
	struct as102_dev_t *as102_dev = demux->priv;

	if (mutex_lock_interruptible(&as102_dev->sem))
		return -ERESTARTSYS;

	if (--as102_dev->streaming == 0)
		as102_stop_stream(as102_dev);

	if (pid_filtering)
		as10x_pid_filter(as102_dev, dvbdmxfeed->index,
				 dvbdmxfeed->pid, 0);

	mutex_unlock(&as102_dev->sem);
	return 0;
}

int as102_dvb_register(struct as102_dev_t *as102_dev)
{
	struct device *dev = &as102_dev->bus_adap.usb_dev->dev;
	int ret;

	ret = dvb_register_adapter(&as102_dev->dvb_adap,
			   as102_dev->name, THIS_MODULE,
			   dev, adapter_nr);
	if (ret < 0) {
		dev_err(dev, "%s: dvb_register_adapter() failed: %d\n",
			__func__, ret);
		return ret;
	}

	as102_dev->dvb_dmx.priv = as102_dev;
	as102_dev->dvb_dmx.filternum = pid_filtering ? 16 : 256;
	as102_dev->dvb_dmx.feednum = 256;
	as102_dev->dvb_dmx.start_feed = as102_dvb_dmx_start_feed;
	as102_dev->dvb_dmx.stop_feed = as102_dvb_dmx_stop_feed;

	as102_dev->dvb_dmx.dmx.capabilities = DMX_TS_FILTERING |
					      DMX_SECTION_FILTERING;

	as102_dev->dvb_dmxdev.filternum = as102_dev->dvb_dmx.filternum;
	as102_dev->dvb_dmxdev.demux = &as102_dev->dvb_dmx.dmx;
	as102_dev->dvb_dmxdev.capabilities = 0;

	ret = dvb_dmx_init(&as102_dev->dvb_dmx);
	if (ret < 0) {
		dev_err(dev, "%s: dvb_dmx_init() failed: %d\n", __func__, ret);
		goto edmxinit;
	}

	ret = dvb_dmxdev_init(&as102_dev->dvb_dmxdev, &as102_dev->dvb_adap);
	if (ret < 0) {
		dev_err(dev, "%s: dvb_dmxdev_init() failed: %d\n",
			__func__, ret);
		goto edmxdinit;
	}

	ret = as102_dvb_register_fe(as102_dev, &as102_dev->dvb_fe);
	if (ret < 0) {
		dev_err(dev, "%s: as102_dvb_register_frontend() failed: %d",
		    __func__, ret);
		goto efereg;
	}

	/* init bus mutex for token locking */
	mutex_init(&as102_dev->bus_adap.lock);

	/* init start / stop stream mutex */
	mutex_init(&as102_dev->sem);

	/*
	 * try to load as102 firmware. If firmware upload failed, we'll be
	 * able to upload it later.
	 */
	if (fw_upload)
		try_then_request_module(as102_fw_upload(&as102_dev->bus_adap),
				"firmware_class");

	pr_info("Registered device %s", as102_dev->name);
	return 0;

efereg:
	dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
edmxdinit:
	dvb_dmx_release(&as102_dev->dvb_dmx);
edmxinit:
	dvb_unregister_adapter(&as102_dev->dvb_adap);
	return ret;
}

void as102_dvb_unregister(struct as102_dev_t *as102_dev)
{
	/* unregister as102 frontend */
	as102_dvb_unregister_fe(&as102_dev->dvb_fe);

	/* unregister demux device */
	dvb_dmxdev_release(&as102_dev->dvb_dmxdev);
	dvb_dmx_release(&as102_dev->dvb_dmx);

	/* unregister dvb adapter */
	dvb_unregister_adapter(&as102_dev->dvb_adap);

	pr_info("Unregistered device %s", as102_dev->name);
}

module_usb_driver(as102_usb_driver);

/* modinfo details */
MODULE_DESCRIPTION(DRIVER_FULL_NAME);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Pierrick Hascoet <pierrick.hascoet@abilis.com>");
