/*
 * drivers/extcon/extcon-adc-jack.c
 *
 * Analog Jack extcon driver with ADC-based detection capability.
 *
 * Copyright (C) 2012 Samsung Electronics
 * MyungJoo Ham <myungjoo.ham@samsung.com>
 *
 * Modified for calling to IIO to get adc by <anish.singh@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/iio/consumer.h>
#include <linux/extcon/extcon-adc-jack.h>
#include <linux/extcon.h>

/**
 * struct adc_jack_data - internal data for adc_jack device driver
 * @edev        - extcon device.
 * @cable_names - list of supported cables.
 * @num_cables  - size of cable_names.
 * @adc_conditions       - list of adc value conditions.
 * @num_conditions       - size of adc_conditions.
 * @irq         - irq number of attach/detach event (0 if not exist).
 * @handling_delay      - interrupt handler will schedule extcon event
 *                      handling at handling_delay jiffies.
 * @handler     - extcon event handler called by interrupt handler.
 * @chan       - iio channel being queried.
 */
struct adc_jack_data {
	struct extcon_dev edev;

	const char **cable_names;
	int num_cables;
	struct adc_jack_cond *adc_conditions;
	int num_conditions;

	int irq;
	unsigned long handling_delay; /* in jiffies */
	struct delayed_work handler;

	struct iio_channel *chan;
};

static void adc_jack_handler(struct work_struct *work)
{
	struct adc_jack_data *data = container_of(to_delayed_work(work),
			struct adc_jack_data,
			handler);
	u32 state = 0;
	int ret, adc_val;
	int i;

	ret = iio_read_channel_raw(data->chan, &adc_val);
	if (ret < 0) {
		dev_err(data->edev.dev, "read channel() error: %d\n", ret);
		return;
	}

	/* Get state from adc value with adc_conditions */
	for (i = 0; i < data->num_conditions; i++) {
		struct adc_jack_cond *def = &data->adc_conditions[i];
		if (!def->state)
			break;
		if (def->min_adc <= adc_val && def->max_adc >= adc_val) {
			state = def->state;
			break;
		}
	}
	/* if no def has met, it means state = 0 (no cables attached) */

	extcon_set_state(&data->edev, state);
}

static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
{
	struct adc_jack_data *data = _data;

	schedule_delayed_work(&data->handler, data->handling_delay);
	return IRQ_HANDLED;
}

static int __devinit adc_jack_probe(struct platform_device *pdev)
{
	struct adc_jack_data *data;
	struct adc_jack_pdata *pdata = pdev->dev.platform_data;
	int i, err = 0;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->edev.name = pdata->name;

	if (!pdata->cable_names) {
		err = -EINVAL;
		dev_err(&pdev->dev, "error: cable_names not defined.\n");
		goto out;
	}

	data->edev.supported_cable = pdata->cable_names;

	/* Check the length of array and set num_cables */
	for (i = 0; data->edev.supported_cable[i]; i++)
		;
	if (i == 0 || i > SUPPORTED_CABLE_MAX) {
		err = -EINVAL;
		dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n",
				i - 1);
		goto out;
	}
	data->num_cables = i;

	if (!pdata->adc_conditions ||
			!pdata->adc_conditions[0].state) {
		err = -EINVAL;
		dev_err(&pdev->dev, "error: adc_conditions not defined.\n");
		goto out;
	}
	data->adc_conditions = pdata->adc_conditions;

	/* Check the length of array and set num_conditions */
	for (i = 0; data->adc_conditions[i].state; i++)
		;
	data->num_conditions = i;

	data->chan = iio_channel_get(dev_name(&pdev->dev),
			pdata->consumer_channel);
	if (IS_ERR(data->chan)) {
		err = PTR_ERR(data->chan);
		goto out;
	}

	data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms);

	INIT_DEFERRABLE_WORK(&data->handler, adc_jack_handler);

	platform_set_drvdata(pdev, data);

	err = extcon_dev_register(&data->edev, &pdev->dev);
	if (err)
		goto out;

	data->irq = platform_get_irq(pdev, 0);
	if (!data->irq) {
		dev_err(&pdev->dev, "platform_get_irq failed\n");
		err = -ENODEV;
		goto err_irq;
	}

	err = request_any_context_irq(data->irq, adc_jack_irq_thread,
			pdata->irq_flags, pdata->name, data);

	if (err) {
		dev_err(&pdev->dev, "error: irq %d\n", data->irq);
		err = -EINVAL;
		goto err_irq;
	}

	goto out;

err_irq:
	extcon_dev_unregister(&data->edev);
out:
	return err;
}

static int __devexit adc_jack_remove(struct platform_device *pdev)
{
	struct adc_jack_data *data = platform_get_drvdata(pdev);

	free_irq(data->irq, data);
	cancel_work_sync(&data->handler.work);
	extcon_dev_unregister(&data->edev);

	return 0;
}

static struct platform_driver adc_jack_driver = {
	.probe          = adc_jack_probe,
	.remove         = __devexit_p(adc_jack_remove),
	.driver         = {
		.name   = "adc-jack",
		.owner  = THIS_MODULE,
	},
};

module_platform_driver(adc_jack_driver);
