/*
 * Copyright C 2011 by Amlogic, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *
 *
 */
#include <asm/arch/io.h>
#include <asm/cpu_id.h>
#include <common.h>
#include <config.h>
#include <command.h>
#include <amlogic/aml_irblaster.h>
#include <asm/arch/secure_apb.h>

static struct aml_irblaster_drv_s irblaster_drviver;
const char *protocol_name[] = {
	"NEC",
};

/*NEC key value*/
#define NEC_HEADER	9000
#define NEC_IDLE	4500
const static int  NEC_END[] = {
	560,
	560
};
const static int NEC_ONE[] = {
	560,
	1690
};
const static int NEC_ZERO[] = {
	560,
	560
};

static void get_nec_data(unsigned int value)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();
	unsigned int num = 0;
	int index;
	unsigned int *pdata = drv->windows;
	pdata[num++] = NEC_HEADER;
	pdata[num++] = NEC_IDLE;
	/*low bit first*/
	for (index = 0; index < 32; index++) {
		if (value & (0x01 << index)) {
			pdata[num++] = NEC_ONE[0];
			pdata[num++] = NEC_ONE[1];
		} else {
			pdata[num++] = NEC_ZERO[0];
			pdata[num++] = NEC_ZERO[1];
		}
	}
	pdata[num++] = NEC_END[0];
	pdata[num++] = NEC_END[1];
	drv->windows_num = num;
	drv->sendvalue = value;
}

static int send_bit(unsigned int hightime, unsigned int lowtime,
	unsigned int cycle)
{
	unsigned int count_delay;
	uint32_t val;
	int n = 0;
	int tb[3] = {
		1, 10, 100
	};

	/*
	AO_IR_BLASTER_ADDR2
	bit12: output level(or modulation enable/disable:1=enable)
	bit[11:10]: Timebase :
				00=1us
				01=10us
				10=100us
				11=Modulator clock
	bit[9:0]: Count of timebase units to delay
	*/

	count_delay = (((hightime + cycle/2) / cycle) - 1) & 0x3ff;
	val = (0x10000 | (1 << 12)) | (3 << 10) | (count_delay << 0);
	writel(val, AO_IR_BLASTER_ADDR2);

	/*
	lowtime<1024,n=0,timebase=1us
	1024<=lowtime<10240,n=1,timebase=10us
	10240<=lowtime,n=2,timebase=100us
	*/
	n = lowtime >> 10;
	if (n > 0 && n < 10)
		n = 1;
	else if (n >= 10)
		n = 2;
	lowtime = (lowtime + (tb[n] >> 1))/tb[n];
	count_delay = (lowtime-1) & 0x3ff;
	val = (0x10000 | (0 << 12)) |
		(n << 10) | (count_delay << 0);
	writel(val, AO_IR_BLASTER_ADDR2);
	return 0;
}

static void send_frame(void)
{
	int i;
	int exp = 0x00;
	unsigned int* pdata;
	unsigned int high_ct, low_ct;
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();
	unsigned int consumerir_cycle = 1000 / (drv->frequency / 1000);

	/*reset*/
	writel(readl(AO_RTI_GEN_CNTL_REG0) | (1 << 23), AO_IR_BLASTER_ADDR2);
	udelay(2);
	writel(readl(AO_RTI_GEN_CNTL_REG0) & ~(1 << 23), AO_IR_BLASTER_ADDR2);

	/*
	1. disable ir blaster
	2. set the modulator_tb = 2'10; mpeg_1uS_tick 1us
	*/
	writel((1 << 2) | (2 << 12) | (1<<2), AO_IR_BLASTER_ADDR0);
	/*
	1. set mod_high_count = 13
	2. set mod_low_count = 13
	3. 60khz 8, 38k-13us, 12
	*/
	high_ct = consumerir_cycle * drv->dutycycle/100;
	low_ct = consumerir_cycle - high_ct;
	writel(((high_ct - 1) << 16) | ((low_ct - 1) << 0),
		AO_IR_BLASTER_ADDR1);

	/* Setting this bit to 1 initializes the output to be high.*/
	writel(readl(AO_IR_BLASTER_ADDR0) & ~(1 << 2), AO_IR_BLASTER_ADDR0);

	/*enable irblaster*/
	writel(readl(AO_IR_BLASTER_ADDR0) | (1 << 0), AO_IR_BLASTER_ADDR0);
#define SEND_BIT_NUM 64
	exp = drv->windows_num / SEND_BIT_NUM;
	pdata = drv->windows;

	while (exp) {
		for (i = 0; i < SEND_BIT_NUM/2; i++) {
			send_bit(*pdata, *(pdata+1), consumerir_cycle);
			pdata += 2;
		}
		while (!(readl(AO_IR_BLASTER_ADDR0) & (1<<24))) ;
		while (readl(AO_IR_BLASTER_ADDR0) & (1<<26)) ;
		/*reset*/
		writel(readl(AO_RTI_GEN_CNTL_REG0) | (1 << 23),
			AO_RTI_GEN_CNTL_REG0);
		udelay(2);
		/*reset*/
		writel(readl(AO_RTI_GEN_CNTL_REG0) & ~(1 << 23),
			AO_RTI_GEN_CNTL_REG0);
		exp--;
	}
	exp = (drv->windows_num % SEND_BIT_NUM) & (~(1));
	for (i = 0; i < exp; ) {
		send_bit(*pdata, *(pdata+1), consumerir_cycle);
		pdata += 2;
		i += 2;
	}
}

extern void irblaster_pinmux_config(void);
static int open(void)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();

	drv->protocol = 0; /*default NEC*/
	drv->frequency = 38000; /*freq 38k*/

	/*pinmux*/
	irblaster_pinmux_config();
	drv->openflag = 1;
	return 0;
}

static int close(void)
{
	return 0;
}

static int send(unsigned int value)
{
	get_nec_data(value);
	send_frame();
	return 0;
}

static void print_windows(void)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();
	int n;
	unsigned int *pdata;

	pdata = drv->windows;
	n = drv->windows_num;
	printf ("sendvalue:%u\n", drv->sendvalue);
	printf ("windows_number:%d\n", n);
	printf ("windows:\n");
	while (n--)
		printf ("%d\n", *pdata++);
}

static int setprotocol(char *name)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();
	int p = 0;
	int size = sizeof(protocol_name) / sizeof(protocol_name[0]);

	for (p = 0; p < size; p++) {
		if (!strcmp(protocol_name[p], name)) {
			drv->protocol = p;
			return 0;
		}
	}
	return CMD_RET_USAGE;
}

static const char *getprocotol(void)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();
	int size = sizeof(protocol_name) / sizeof(protocol_name[0]);

	if (drv->protocol >= size)
		return NULL;
	return protocol_name[drv->protocol];
}

static int setfrequency(unsigned int freq)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();

	if (freq < 20000 || freq > 60000) {
		printf("20000<freq<60000\n");
		return CMD_RET_USAGE;
	}
	drv->frequency = freq;
	return 0;
}

static unsigned int getfrequency(void)
{
	struct aml_irblaster_drv_s *drv = aml_irblaster_get_driver();

	return drv->frequency;
}

unsigned char ci_nec_fe01[] = {
	0x01,
	0x02,
	0x03,
	0x04,
	0x05,
	0x06,
	0x07,
	0x08,
	0x09,
	0x0a,
	0x1F,
	0x15,
	0x16,
	0x0c,
	0x0d,
	0x0e,
	0x0f,
	0x11,
	0x1c,
	0x1b,
	0x19,
	0x1a,
	0x1d,
	0x17,
	0x49,
	0x43,
	0x12,
	0x14,
	0x18,
	0x59,
	0x5a,
	0x42,
	0x44,
	0x1e,
	0x4b,
	0x58,
	0x46,
	0x40,
	0x38,
	0x57,
	0x5b,
	0x54,
	0x4c,
	0x4e,
	0x55,
	0x53,
	0x52,
	0x39,
	0x41,
	0x0b,
	0x00,
	0x13
};

static int loop_test(unsigned int times)
{
	unsigned int framecode;
	int n, cnt = 0;
	int size = ARRAY_SIZE(ci_nec_fe01);

	printf("test loop...\n");
	for ( ; times--; ) {
		printf("times=%d\n", cnt++);
		for (n = 0; n < size; n++) {
			framecode = 0xfe01 | ((~ci_nec_fe01[n] & 0xff) << 24) |
				(ci_nec_fe01[n] << 16);
			printf("0x%x\n", framecode);
			get_nec_data(framecode);
			send_frame();
			mdelay(500);
		}
	}
	return 0;
}

int read_reg(volatile unsigned int *addr, unsigned int length)
{
	int n;
	int value;

	printf("read_reg\n");
	for (n = 0; n < length; n++) {
		value = readl(addr);
		printf("0x%p=0x%x\n", addr, value);
		++addr;
	}
	return 0;
}

int write_reg(volatile unsigned int *addr, unsigned int value)
{
	writel(value, addr);
	printf("0x%p=0x%x", addr, value);
	return 0;
}

static struct aml_irblaster_drv_s irblaster_drviver = {
	.frequency = 38000,
	.dutycycle = 50,
	.protocol = 0,
	.windows_num = 0,
	.openflag = 0,
	.open = open,
	.close = close,
	.send = send,
	.setprotocol = setprotocol,
	.getprocotol = getprocotol,
	.setfrequency = setfrequency,
	.getfrequency = getfrequency,
	.test = loop_test,
	.print_windows = print_windows,
	.read_reg = read_reg,
	.write_reg = write_reg,
};

struct aml_irblaster_drv_s *aml_irblaster_get_driver(void)
{
	return &irblaster_drviver;
}
