/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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/module.h>
#include <linux/slab.h>
#include <soc/qcom/service-locator.h>
#include <soc/qcom/service-notifier.h>
#include "audio_pdr.h"

static struct pd_qmi_client_data audio_pdr_services[AUDIO_PDR_DOMAIN_MAX] = {
	{	/* AUDIO_PDR_DOMAIN_ADSP */
		.client_name = "audio_pdr_adsp",
		.service_name = "avs/audio"
	}
};

struct srcu_notifier_head audio_pdr_cb_list;

static int audio_pdr_locator_callback(struct notifier_block *this,
				      unsigned long opcode, void *data)
{
	unsigned long pdr_state = AUDIO_PDR_FRAMEWORK_DOWN;

	if (opcode == LOCATOR_DOWN) {
		pr_debug("%s: Service %s is down!", __func__,
			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
			service_name);
		goto done;
	}

	memcpy(&audio_pdr_services, data,
		sizeof(audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP]));
	if (audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].total_domains == 1) {
		pr_debug("%s: Service %s, returned total domains %d, ",
			__func__,
			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
			total_domains);
		pdr_state = AUDIO_PDR_FRAMEWORK_UP;
		goto done;
	} else
		pr_err("%s: Service %s returned invalid total domains %d",
			__func__,
			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
			audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].
			total_domains);
done:
	srcu_notifier_call_chain(&audio_pdr_cb_list, pdr_state, NULL);
	return NOTIFY_OK;
}

static struct notifier_block audio_pdr_locator_nb = {
	.notifier_call = audio_pdr_locator_callback,
	.priority = 0,
};

/**
 * audio_pdr_register -
 *        register to PDR framework
 *
 * @nb: notifier block
 *
 * Returns 0 on success or error on failure
 */
int audio_pdr_register(struct notifier_block *nb)
{
	if (nb == NULL) {
		pr_err("%s: Notifier block is NULL\n", __func__);
		return -EINVAL;
	}
	return srcu_notifier_chain_register(&audio_pdr_cb_list, nb);
}
EXPORT_SYMBOL(audio_pdr_register);

/**
 * audio_pdr_deregister -
 *        Deregister from PDR framework
 *
 * @nb: notifier block
 *
 * Returns 0 on success or error on failure
 */
int audio_pdr_deregister(struct notifier_block *nb)
{
	if (nb == NULL) {
		pr_err("%s: Notifier block is NULL\n", __func__);
		return -EINVAL;
	}
	return srcu_notifier_chain_unregister(&audio_pdr_cb_list, nb);
}
EXPORT_SYMBOL(audio_pdr_deregister);

void *audio_pdr_service_register(int domain_id,
				 struct notifier_block *nb, int *curr_state)
{
	void *handle;

	if ((domain_id < 0) ||
	    (domain_id >= AUDIO_PDR_DOMAIN_MAX)) {
		pr_err("%s: Invalid service ID %d\n", __func__, domain_id);
		return ERR_PTR(-EINVAL);
	}

	handle = service_notif_register_notifier(
		audio_pdr_services[domain_id].domain_list[0].name,
		audio_pdr_services[domain_id].domain_list[0].instance_id,
		nb, curr_state);
	if (IS_ERR_OR_NULL(handle)) {
		pr_err("%s: Failed to register for service %s, instance %d\n",
			__func__,
			audio_pdr_services[domain_id].domain_list[0].name,
			audio_pdr_services[domain_id].domain_list[0].
			instance_id);
	}
	return handle;
}
EXPORT_SYMBOL(audio_pdr_service_register);

int audio_pdr_service_deregister(void *service_handle,
	struct notifier_block *nb)
{
	int ret;

	if (service_handle == NULL) {
		pr_err("%s: service handle is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	ret = service_notif_unregister_notifier(
		service_handle, nb);
	if (ret < 0)
		pr_err("%s: Failed to deregister service ret %d\n",
			__func__, ret);
done:
	return ret;
}
EXPORT_SYMBOL(audio_pdr_service_deregister);

static int __init audio_pdr_subsys_init(void)
{
	srcu_init_notifier_head(&audio_pdr_cb_list);
	return 0;
}

static int __init audio_pdr_late_init(void)
{
	int ret;

	audio_pdr_subsys_init();

	ret = get_service_location(
		audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].client_name,
		audio_pdr_services[AUDIO_PDR_DOMAIN_ADSP].service_name,
		&audio_pdr_locator_nb);
	if (ret < 0) {
		pr_err("%s get_service_location failed ret %d\n",
			__func__, ret);
		srcu_notifier_call_chain(&audio_pdr_cb_list,
					 AUDIO_PDR_FRAMEWORK_DOWN, NULL);
	}

	return ret;
}
module_init(audio_pdr_late_init);

static void __exit audio_pdr_late_exit(void)
{
}
module_exit(audio_pdr_late_exit);

MODULE_DESCRIPTION("PDR framework driver");
MODULE_LICENSE("GPL v2");
