// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Abilis Systems Single DVB-T Receiver
 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
 */

#include <linux/kernel.h>
#include "as102_drv.h"
#include "as10x_cmd.h"

/***************************/
/* FUNCTION DEFINITION     */
/***************************/

/**
 * as10x_cmd_get_context - Send get context command to AS10x
 * @adap:      pointer to AS10x bus adapter
 * @tag:       context tag
 * @pvalue:    pointer where to store context value read
 *
 * Return 0 on success or negative value in case of error.
 */
int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
			  uint32_t *pvalue)
{
	int  error;
	struct as10x_cmd_t *pcmd, *prsp;

	pcmd = adap->cmd;
	prsp = adap->rsp;

	/* prepare command */
	as10x_cmd_build(pcmd, (++adap->cmd_xid),
			sizeof(pcmd->body.context.req));

	/* fill command */
	pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
	pcmd->body.context.req.tag = cpu_to_le16(tag);
	pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);

	/* send command */
	if (adap->ops->xfer_cmd) {
		error  = adap->ops->xfer_cmd(adap,
					     (uint8_t *) pcmd,
					     sizeof(pcmd->body.context.req)
					     + HEADER_SIZE,
					     (uint8_t *) prsp,
					     sizeof(prsp->body.context.rsp)
					     + HEADER_SIZE);
	} else {
		error = AS10X_CMD_ERROR;
	}

	if (error < 0)
		goto out;

	/* parse response: context command do not follow the common response */
	/* structure -> specific handling response parse required            */
	error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);

	if (error == 0) {
		/* Response OK -> get response data */
		*pvalue = le32_to_cpu((__force __le32)prsp->body.context.rsp.reg_val.u.value32);
		/* value returned is always a 32-bit value */
	}

out:
	return error;
}

/**
 * as10x_cmd_set_context - send set context command to AS10x
 * @adap:      pointer to AS10x bus adapter
 * @tag:       context tag
 * @value:     value to set in context
 *
 * Return 0 on success or negative value in case of error.
 */
int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
			  uint32_t value)
{
	int error;
	struct as10x_cmd_t *pcmd, *prsp;

	pcmd = adap->cmd;
	prsp = adap->rsp;

	/* prepare command */
	as10x_cmd_build(pcmd, (++adap->cmd_xid),
			sizeof(pcmd->body.context.req));

	/* fill command */
	pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
	/* pcmd->body.context.req.reg_val.mode initialization is not required */
	pcmd->body.context.req.reg_val.u.value32 = (__force u32)cpu_to_le32(value);
	pcmd->body.context.req.tag = cpu_to_le16(tag);
	pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);

	/* send command */
	if (adap->ops->xfer_cmd) {
		error  = adap->ops->xfer_cmd(adap,
					     (uint8_t *) pcmd,
					     sizeof(pcmd->body.context.req)
					     + HEADER_SIZE,
					     (uint8_t *) prsp,
					     sizeof(prsp->body.context.rsp)
					     + HEADER_SIZE);
	} else {
		error = AS10X_CMD_ERROR;
	}

	if (error < 0)
		goto out;

	/* parse response: context command do not follow the common response */
	/* structure -> specific handling response parse required            */
	error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);

out:
	return error;
}

/**
 * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x
 * @adap:      pointer to AS10x bus adapter
 * @mode:      mode selected:
 *		- ON    : 0x0 => eLNA always ON
 *		- OFF   : 0x1 => eLNA always OFF
 *		- AUTO  : 0x2 => eLNA follow hysteresis parameters
 *				 to be ON or OFF
 *
 * Return 0 on success or negative value in case of error.
 */
int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode)
{
	int error;
	struct as10x_cmd_t *pcmd, *prsp;

	pcmd = adap->cmd;
	prsp = adap->rsp;

	/* prepare command */
	as10x_cmd_build(pcmd, (++adap->cmd_xid),
			sizeof(pcmd->body.cfg_change_mode.req));

	/* fill command */
	pcmd->body.cfg_change_mode.req.proc_id =
		cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE);
	pcmd->body.cfg_change_mode.req.mode = mode;

	/* send command */
	if (adap->ops->xfer_cmd) {
		error  = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
				sizeof(pcmd->body.cfg_change_mode.req)
				+ HEADER_SIZE, (uint8_t *) prsp,
				sizeof(prsp->body.cfg_change_mode.rsp)
				+ HEADER_SIZE);
	} else {
		error = AS10X_CMD_ERROR;
	}

	if (error < 0)
		goto out;

	/* parse response */
	error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP);

out:
	return error;
}

/**
 * as10x_context_rsp_parse - Parse context command response
 * @prsp:       pointer to AS10x command response buffer
 * @proc_id:    id of the command
 *
 * Since the contex command response does not follow the common
 * response, a specific parse function is required.
 * Return 0 on success or negative value in case of error.
 */
int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
{
	int err;

	err = prsp->body.context.rsp.error;

	if ((err == 0) &&
	    (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) {
		return 0;
	}
	return AS10X_CMD_ERROR;
}
