// SPDX-License-Identifier: GPL-2.0
/*
 * Support for atomisp driver sysfs interface
 *
 * Copyright (c) 2014 Intel Corporation. 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 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/device.h>
#include <linux/err.h>
#include <linux/kernel.h>

#include "atomisp_compat.h"
#include "atomisp_internal.h"
#include "atomisp_ioctl.h"
#include "atomisp_drvfs.h"
#include "hmm/hmm.h"
#include "ia_css_debug.h"

/*
 * _iunit_debug:
 * dbglvl: iunit css driver trace level
 * dbgopt: iunit debug option:
 *        bit 0: binary list
 *        bit 1: running binary
 *        bit 2: memory statistic
*/
struct _iunit_debug {
	struct device_driver	*drv;
	struct atomisp_device	*isp;
	unsigned int		dbglvl;
	unsigned int		dbgfun;
	unsigned int		dbgopt;
};

#define OPTION_BIN_LIST			BIT(0)
#define OPTION_BIN_RUN			BIT(1)
#define OPTION_MEM_STAT			BIT(2)
#define OPTION_VALID			(OPTION_BIN_LIST \
					| OPTION_BIN_RUN \
					| OPTION_MEM_STAT)

static struct _iunit_debug iunit_debug = {
	.dbglvl = 0,
	.dbgopt = OPTION_BIN_LIST,
};

static inline int iunit_dump_dbgopt(struct atomisp_device *isp,
				    unsigned int opt)
{
	int ret = 0;

	if (opt & OPTION_VALID) {
		if (opt & OPTION_BIN_LIST) {
			ret = atomisp_css_dump_blob_infor(isp);
			if (ret) {
				dev_err(isp->dev, "%s dump blob infor err[ret:%d]\n",
					__func__, ret);
				goto opt_err;
			}
		}

		if (opt & OPTION_BIN_RUN) {
			if (atomisp_streaming_count(isp)) {
				atomisp_css_dump_sp_raw_copy_linecount(true);
				atomisp_css_debug_dump_isp_binary();
			} else {
				ret = -EPERM;
				dev_err(isp->dev, "%s dump running bin err[ret:%d]\n",
					__func__, ret);
				goto opt_err;
			}
		}

		if (opt & OPTION_MEM_STAT)
			hmm_show_mem_stat(__func__, __LINE__);
	} else {
		ret = -EINVAL;
		dev_err(isp->dev, "%s dump nothing[ret=%d]\n", __func__, ret);
	}

opt_err:
	return ret;
}

static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf)
{
	iunit_debug.dbglvl = dbg_level;
	return sysfs_emit(buf, "dtrace level:%u\n", iunit_debug.dbglvl);
}

static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf,
				  size_t size)
{
	if (kstrtouint(buf, 10, &iunit_debug.dbglvl)
	    || iunit_debug.dbglvl < 1
	    || iunit_debug.dbglvl > 9) {
		return -ERANGE;
	}
	ia_css_debug_set_dtrace_level(iunit_debug.dbglvl);

	return size;
}

static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf)
{
	iunit_debug.dbgfun = atomisp_get_css_dbgfunc();
	return sysfs_emit(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun);
}

static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf,
				  size_t size)
{
	unsigned int opt;
	int ret;

	ret = kstrtouint(buf, 10, &opt);
	if (ret)
		return ret;

	ret = atomisp_set_css_dbgfunc(iunit_debug.isp, opt);
	if (ret)
		return ret;

	iunit_debug.dbgfun = opt;

	return size;
}

static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf)
{
	return sysfs_emit(buf, "option:0x%x\n", iunit_debug.dbgopt);
}

static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf,
				  size_t size)
{
	unsigned int opt;
	int ret;

	ret = kstrtouint(buf, 10, &opt);
	if (ret)
		return ret;

	iunit_debug.dbgopt = opt;
	ret = iunit_dump_dbgopt(iunit_debug.isp, iunit_debug.dbgopt);
	if (ret)
		return ret;

	return size;
}

static const struct driver_attribute iunit_drvfs_attrs[] = {
	__ATTR(dbglvl, 0644, iunit_dbglvl_show, iunit_dbglvl_store),
	__ATTR(dbgfun, 0644, iunit_dbgfun_show, iunit_dbgfun_store),
	__ATTR(dbgopt, 0644, iunit_dbgopt_show, iunit_dbgopt_store),
};

static int iunit_drvfs_create_files(struct device_driver *drv)
{
	int i, ret = 0;

	for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
		ret |= driver_create_file(drv, &iunit_drvfs_attrs[i]);

	return ret;
}

static void iunit_drvfs_remove_files(struct device_driver *drv)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(iunit_drvfs_attrs); i++)
		driver_remove_file(drv, &iunit_drvfs_attrs[i]);
}

int atomisp_drvfs_init(struct atomisp_device *isp)
{
	struct device_driver *drv = isp->dev->driver;
	int ret;

	iunit_debug.isp = isp;
	iunit_debug.drv = drv;

	ret = iunit_drvfs_create_files(iunit_debug.drv);
	if (ret) {
		dev_err(isp->dev, "drvfs_create_files error: %d\n", ret);
		iunit_drvfs_remove_files(iunit_debug.drv);
	}

	return ret;
}

void atomisp_drvfs_exit(void)
{
	iunit_drvfs_remove_files(iunit_debug.drv);
}
