// SPDX-License-Identifier: GPL-2.0
/*
 *  c8sectpfe-dvb.c - C8SECTPFE STi DVB driver
 *
 * Copyright (c) STMicroelectronics 2015
 *
 *  Author Peter Griffin <peter.griffin@linaro.org>
 *
 */
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/version.h>

#include <dt-bindings/media/c8sectpfe.h>

#include "c8sectpfe-common.h"
#include "c8sectpfe-core.h"
#include "c8sectpfe-dvb.h"

#include "dvb-pll.h"
#include "lnbh24.h"
#include "stv0367.h"
#include "stv0367_priv.h"
#include "stv6110x.h"
#include "stv090x.h"
#include "tda18212.h"

static inline const char *dvb_card_str(unsigned int c)
{
	switch (c) {
	case STV0367_TDA18212_NIMA_1:	return "STV0367_TDA18212_NIMA_1";
	case STV0367_TDA18212_NIMA_2:	return "STV0367_TDA18212_NIMA_2";
	case STV0367_TDA18212_NIMB_1:	return "STV0367_TDA18212_NIMB_1";
	case STV0367_TDA18212_NIMB_2:	return "STV0367_TDA18212_NIMB_2";
	case STV0903_6110_LNB24_NIMA:	return "STV0903_6110_LNB24_NIMA";
	case STV0903_6110_LNB24_NIMB:	return "STV0903_6110_LNB24_NIMB";
	default:			return "unknown dvb frontend card";
	}
}

static struct stv090x_config stv090x_config = {
	.device                 = STV0903,
	.demod_mode             = STV090x_SINGLE,
	.clk_mode               = STV090x_CLK_EXT,
	.xtal                   = 16000000,
	.address                = 0x69,

	.ts1_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,
	.ts2_mode               = STV090x_TSMODE_SERIAL_CONTINUOUS,

	.repeater_level         = STV090x_RPTLEVEL_64,

	.tuner_init             = NULL,
	.tuner_set_mode         = NULL,
	.tuner_set_frequency    = NULL,
	.tuner_get_frequency    = NULL,
	.tuner_set_bandwidth    = NULL,
	.tuner_get_bandwidth    = NULL,
	.tuner_set_bbgain       = NULL,
	.tuner_get_bbgain       = NULL,
	.tuner_set_refclk       = NULL,
	.tuner_get_status       = NULL,
};

static struct stv6110x_config stv6110x_config = {
	.addr                   = 0x60,
	.refclk                 = 16000000,
};

#define NIMA 0
#define NIMB 1

static struct stv0367_config stv0367_tda18212_config[] = {
	{
		.demod_address = 0x1c,
		.xtal = 16000000,
		.if_khz = 4500,
		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
	}, {
		.demod_address = 0x1d,
		.xtal = 16000000,
		.if_khz = 4500,
		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
	}, {
		.demod_address = 0x1e,
		.xtal = 16000000,
		.if_khz = 4500,
		.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
		.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
		.clk_pol = STV0367_CLOCKPOLARITY_DEFAULT,
	},
};

static struct tda18212_config tda18212_conf = {
	.if_dvbt_6 = 4150,
	.if_dvbt_7 = 4150,
	.if_dvbt_8 = 4500,
	.if_dvbc = 5000,
};

int c8sectpfe_frontend_attach(struct dvb_frontend **fe,
		struct c8sectpfe *c8sectpfe,
		struct channel_info *tsin, int chan_num)
{
	struct tda18212_config *tda18212;
	const struct stv6110x_devctl *fe2;
	struct i2c_client *client;
	struct i2c_board_info tda18212_info = {
		.type = "tda18212",
		.addr = 0x60,
	};

	if (!tsin)
		return -EINVAL;

	switch (tsin->dvb_card) {

	case STV0367_TDA18212_NIMA_1:
	case STV0367_TDA18212_NIMA_2:
	case STV0367_TDA18212_NIMB_1:
	case STV0367_TDA18212_NIMB_2:
		if (tsin->dvb_card == STV0367_TDA18212_NIMA_1)
			*fe = dvb_attach(stv0367ter_attach,
				 &stv0367_tda18212_config[0],
					tsin->i2c_adapter);
		else if (tsin->dvb_card == STV0367_TDA18212_NIMB_1)
			*fe = dvb_attach(stv0367ter_attach,
				 &stv0367_tda18212_config[1],
					tsin->i2c_adapter);
		else
			*fe = dvb_attach(stv0367ter_attach,
				 &stv0367_tda18212_config[2],
					tsin->i2c_adapter);

		if (!*fe) {
			dev_err(c8sectpfe->device,
				"%s: stv0367ter_attach failed for NIM card %s\n"
				, __func__, dvb_card_str(tsin->dvb_card));
			return -ENODEV;
		}

		/*
		 * init the demod so that i2c gate_ctrl
		 * to the tuner works correctly
		 */
		(*fe)->ops.init(*fe);

		/* Allocate the tda18212 structure */
		tda18212 = devm_kzalloc(c8sectpfe->device,
					sizeof(struct tda18212_config),
					GFP_KERNEL);
		if (!tda18212) {
			dev_err(c8sectpfe->device,
				"%s: devm_kzalloc failed\n", __func__);
			return -ENOMEM;
		}

		memcpy(tda18212, &tda18212_conf,
			sizeof(struct tda18212_config));

		tda18212->fe = (*fe);

		tda18212_info.platform_data = tda18212;

		/* attach tuner */
		request_module("tda18212");
		client = i2c_new_device(tsin->i2c_adapter, &tda18212_info);
		if (!client || !client->dev.driver) {
			dvb_frontend_detach(*fe);
			return -ENODEV;
		}

		if (!try_module_get(client->dev.driver->owner)) {
			i2c_unregister_device(client);
			dvb_frontend_detach(*fe);
			return -ENODEV;
		}

		tsin->i2c_client = client;

		break;

	case STV0903_6110_LNB24_NIMA:
		*fe = dvb_attach(stv090x_attach,	&stv090x_config,
				tsin->i2c_adapter, STV090x_DEMODULATOR_0);
		if (!*fe) {
			dev_err(c8sectpfe->device, "%s: stv090x_attach failed\n"
				"\tfor NIM card %s\n",
				__func__, dvb_card_str(tsin->dvb_card));
			return -ENODEV;
		}

		fe2 = dvb_attach(stv6110x_attach, *fe,
					&stv6110x_config, tsin->i2c_adapter);
		if (!fe2) {
			dev_err(c8sectpfe->device,
				"%s: stv6110x_attach failed for NIM card %s\n"
				, __func__, dvb_card_str(tsin->dvb_card));
			return -ENODEV;
		}

		stv090x_config.tuner_init = fe2->tuner_init;
		stv090x_config.tuner_set_mode = fe2->tuner_set_mode;
		stv090x_config.tuner_set_frequency = fe2->tuner_set_frequency;
		stv090x_config.tuner_get_frequency = fe2->tuner_get_frequency;
		stv090x_config.tuner_set_bandwidth = fe2->tuner_set_bandwidth;
		stv090x_config.tuner_get_bandwidth = fe2->tuner_get_bandwidth;
		stv090x_config.tuner_set_bbgain = fe2->tuner_set_bbgain;
		stv090x_config.tuner_get_bbgain = fe2->tuner_get_bbgain;
		stv090x_config.tuner_set_refclk = fe2->tuner_set_refclk;
		stv090x_config.tuner_get_status = fe2->tuner_get_status;

		dvb_attach(lnbh24_attach, *fe, tsin->i2c_adapter, 0, 0, 0x9);
		break;

	default:
		dev_err(c8sectpfe->device,
			"%s: DVB frontend card %s not yet supported\n",
			__func__, dvb_card_str(tsin->dvb_card));
		return -ENODEV;
	}

	(*fe)->id = chan_num;

	dev_info(c8sectpfe->device,
			"DVB frontend card %s successfully attached",
			dvb_card_str(tsin->dvb_card));
	return 0;
}
