// SPDX-License-Identifier: GPL-2.0-only
/*
 * Apple Onboard Audio pmf GPIOs
 *
 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
 */

#include <linux/slab.h>
#include <asm/pmac_feature.h>
#include <asm/pmac_pfunc.h>
#include "../aoa.h"

#define PMF_GPIO(name, bit)					\
static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
{								\
	struct pmf_args args = { .count = 1, .u[0].v = !on };	\
	int rc;							\
							\
	if (unlikely(!rt)) return;				\
	rc = pmf_call_function(rt->node, #name "-mute", &args);	\
	if (rc && rc != -ENODEV)				\
		printk(KERN_WARNING "pmf_gpio_set_" #name	\
		" failed, rc: %d\n", rc);			\
	rt->implementation_private &= ~(1<<bit);		\
	rt->implementation_private |= (!!on << bit);		\
}								\
static int pmf_gpio_get_##name(struct gpio_runtime *rt)		\
{								\
	if (unlikely(!rt)) return 0;				\
	return (rt->implementation_private>>bit)&1;		\
}

PMF_GPIO(headphone, 0);
PMF_GPIO(amp, 1);
PMF_GPIO(lineout, 2);

static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
{
	struct pmf_args args = { .count = 1, .u[0].v = !!on };
	int rc;

	if (unlikely(!rt)) return;
	rc = pmf_call_function(rt->node, "hw-reset", &args);
	if (rc)
		printk(KERN_WARNING "pmf_gpio_set_hw_reset"
		       " failed, rc: %d\n", rc);
}

static void pmf_gpio_all_amps_off(struct gpio_runtime *rt)
{
	int saved;

	if (unlikely(!rt)) return;
	saved = rt->implementation_private;
	pmf_gpio_set_headphone(rt, 0);
	pmf_gpio_set_amp(rt, 0);
	pmf_gpio_set_lineout(rt, 0);
	rt->implementation_private = saved;
}

static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt)
{
	int s;

	if (unlikely(!rt)) return;
	s = rt->implementation_private;
	pmf_gpio_set_headphone(rt, (s>>0)&1);
	pmf_gpio_set_amp(rt, (s>>1)&1);
	pmf_gpio_set_lineout(rt, (s>>2)&1);
}

static void pmf_handle_notify(struct work_struct *work)
{
	struct gpio_notification *notif =
		container_of(work, struct gpio_notification, work.work);

	mutex_lock(&notif->mutex);
	if (notif->notify)
		notif->notify(notif->data);
	mutex_unlock(&notif->mutex);
}

static void pmf_gpio_init(struct gpio_runtime *rt)
{
	pmf_gpio_all_amps_off(rt);
	rt->implementation_private = 0;
	INIT_DELAYED_WORK(&rt->headphone_notify.work, pmf_handle_notify);
	INIT_DELAYED_WORK(&rt->line_in_notify.work, pmf_handle_notify);
	INIT_DELAYED_WORK(&rt->line_out_notify.work, pmf_handle_notify);
	mutex_init(&rt->headphone_notify.mutex);
	mutex_init(&rt->line_in_notify.mutex);
	mutex_init(&rt->line_out_notify.mutex);
}

static void pmf_gpio_exit(struct gpio_runtime *rt)
{
	pmf_gpio_all_amps_off(rt);
	rt->implementation_private = 0;

	if (rt->headphone_notify.gpio_private)
		pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
	if (rt->line_in_notify.gpio_private)
		pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
	if (rt->line_out_notify.gpio_private)
		pmf_unregister_irq_client(rt->line_out_notify.gpio_private);

	/* make sure no work is pending before freeing
	 * all things */
	cancel_delayed_work_sync(&rt->headphone_notify.work);
	cancel_delayed_work_sync(&rt->line_in_notify.work);
	cancel_delayed_work_sync(&rt->line_out_notify.work);

	mutex_destroy(&rt->headphone_notify.mutex);
	mutex_destroy(&rt->line_in_notify.mutex);
	mutex_destroy(&rt->line_out_notify.mutex);

	kfree(rt->headphone_notify.gpio_private);
	kfree(rt->line_in_notify.gpio_private);
	kfree(rt->line_out_notify.gpio_private);
}

static void pmf_handle_notify_irq(void *data)
{
	struct gpio_notification *notif = data;

	schedule_delayed_work(&notif->work, 0);
}

static int pmf_set_notify(struct gpio_runtime *rt,
			  enum notify_type type,
			  notify_func_t notify,
			  void *data)
{
	struct gpio_notification *notif;
	notify_func_t old;
	struct pmf_irq_client *irq_client;
	char *name;
	int err = -EBUSY;

	switch (type) {
	case AOA_NOTIFY_HEADPHONE:
		notif = &rt->headphone_notify;
		name = "headphone-detect";
		break;
	case AOA_NOTIFY_LINE_IN:
		notif = &rt->line_in_notify;
		name = "linein-detect";
		break;
	case AOA_NOTIFY_LINE_OUT:
		notif = &rt->line_out_notify;
		name = "lineout-detect";
		break;
	default:
		return -EINVAL;
	}

	mutex_lock(&notif->mutex);

	old = notif->notify;

	if (!old && !notify) {
		err = 0;
		goto out_unlock;
	}

	if (old && notify) {
		if (old == notify && notif->data == data)
			err = 0;
		goto out_unlock;
	}

	if (old && !notify) {
		irq_client = notif->gpio_private;
		pmf_unregister_irq_client(irq_client);
		kfree(irq_client);
		notif->gpio_private = NULL;
	}
	if (!old && notify) {
		irq_client = kzalloc(sizeof(struct pmf_irq_client),
				     GFP_KERNEL);
		if (!irq_client) {
			err = -ENOMEM;
			goto out_unlock;
		}
		irq_client->data = notif;
		irq_client->handler = pmf_handle_notify_irq;
		irq_client->owner = THIS_MODULE;
		err = pmf_register_irq_client(rt->node,
					      name,
					      irq_client);
		if (err) {
			printk(KERN_ERR "snd-aoa: gpio layer failed to"
					" register %s irq (%d)\n", name, err);
			kfree(irq_client);
			goto out_unlock;
		}
		notif->gpio_private = irq_client;
	}
	notif->notify = notify;
	notif->data = data;

	err = 0;
 out_unlock:
	mutex_unlock(&notif->mutex);
	return err;
}

static int pmf_get_detect(struct gpio_runtime *rt,
			  enum notify_type type)
{
	char *name;
	int err = -EBUSY, ret;
	struct pmf_args args = { .count = 1, .u[0].p = &ret };

	switch (type) {
	case AOA_NOTIFY_HEADPHONE:
		name = "headphone-detect";
		break;
	case AOA_NOTIFY_LINE_IN:
		name = "linein-detect";
		break;
	case AOA_NOTIFY_LINE_OUT:
		name = "lineout-detect";
		break;
	default:
		return -EINVAL;
	}

	err = pmf_call_function(rt->node, name, &args);
	if (err)
		return err;
	return ret;
}

static struct gpio_methods methods = {
	.init			= pmf_gpio_init,
	.exit			= pmf_gpio_exit,
	.all_amps_off		= pmf_gpio_all_amps_off,
	.all_amps_restore	= pmf_gpio_all_amps_restore,
	.set_headphone		= pmf_gpio_set_headphone,
	.set_speakers		= pmf_gpio_set_amp,
	.set_lineout		= pmf_gpio_set_lineout,
	.set_hw_reset		= pmf_gpio_set_hw_reset,
	.get_headphone		= pmf_gpio_get_headphone,
	.get_speakers		= pmf_gpio_get_amp,
	.get_lineout		= pmf_gpio_get_lineout,
	.set_notify		= pmf_set_notify,
	.get_detect		= pmf_get_detect,
};

struct gpio_methods *pmf_gpio_methods = &methods;
EXPORT_SYMBOL_GPL(pmf_gpio_methods);
