/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License 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 https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author: jiewen.zhou $
 * $Date: 2015/06/05 $
 * $RCSfile: drv_tcon.c,v $
 * $Revision: #2 $
 *
 *---------------------------------------------------------------------------*/
#include "sv_const.h"
#include "feature.h"

#include "hw_tg.h"

#include "sif_if.h"

#include "drv_tcon.h"

#ifdef DEFINE_IS_LOG
#undef DEFINE_IS_LOG
#endif
#ifdef CC_MTK_LOADER
#define DEFINE_IS_LOG(level, fmt...)   Printf(fmt)
#else /* CC_MTK_LOADER */
#define DEFINE_IS_LOG   IR_IsLog
#endif /* CC_MTK_LOADER */

// for gamma IC
#define GAMMAIC_BUS 0
#define GAMMAIC_CLK_RATE 0x100
#define GAMMAIC_ID (0x74 << 1)
#define GAMMAIC_DATA_CNT 2

// Gamma
struct sTCONREGTABLE sRegCustGamma[] = {
  // Gamma voltage
  0x0000, 0x6B03, 0xffffffff,
  0x0001, 0xEB03, 0xffffffff,
  0x0002, 0x6B03, 0xffffffff,
  0x0003, 0x3E03, 0xffffffff,
  0x0004, 0xFD02, 0xffffffff,
  0x0005, 0xB602, 0xffffffff,
  0x0006, 0x8402, 0xffffffff,
  0x0007, 0x0902, 0xffffffff,
  0x0008, 0xEF01, 0xffffffff,
  0x0009, 0x7601, 0xffffffff,
  0x000A, 0x4201, 0xffffffff,
  0x000B, 0xFB00, 0xffffffff,
  0x000C, 0xB900, 0xffffffff,
  0x000D, 0x8E00, 0xffffffff,
  0x000E, 0x1300, 0xffffffff,
  0x000F, 0x8E00, 0xffffffff,
  0x0012, 0xB581, 0xffffffff,
};

struct sTCONREGTABLE sRegCustTg[] = {
// LGDV4

  // SOE, TG0
  IO_VIRT + 0x34820, 0x00C807d0, 0xffffffff,
  IO_VIRT + 0x34824, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34828, 0x00C807d0, 0xffffffff,  
  IO_VIRT + 0x3482c, 0x04430007, 0xffffffff,
  IO_VIRT + 0x34830, 0x20000000, 0xffffffff,
  IO_VIRT + 0x34834, 0x80000000, 0xffffffff,
  IO_VIRT + 0x34838, 0x00000007, 0xffffffff,
  IO_VIRT + 0x3483c, 0x00000000, 0xffffffff,

  // POL, TG1
  IO_VIRT + 0x34840, 0x07080708, 0xffffffff,
  IO_VIRT + 0x34844, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34848, 0x07080708, 0xffffffff,  
  IO_VIRT + 0x3484c, 0x04430007, 0xffffffff,
  IO_VIRT + 0x34850, 0x80000404, 0xffffffff,
  IO_VIRT + 0x34854, 0x80020004, 0xffffffff,
  IO_VIRT + 0x34858, 0x00000007, 0xffffffff,
  IO_VIRT + 0x3485c, 0x10000000, 0xffffffff,

  // GSP, TG11
  IO_VIRT + 0x34980, 0x04060406, 0xffffffff,
  IO_VIRT + 0x34984, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34988, 0x00000000, 0xffffffff,
  IO_VIRT + 0x3498c, 0x00080007, 0xffffffff,
  IO_VIRT + 0x34990, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34994, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34998, 0x00000004, 0xffffffff,
  IO_VIRT + 0x3499c, 0x00000000, 0xffffffff,

  // GSP_R, TG8
  IO_VIRT + 0x34920, 0x04060406, 0xffffffff,
  IO_VIRT + 0x34924, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34928, 0x00000000, 0xffffffff,
  IO_VIRT + 0x3492c, 0x00080007, 0xffffffff,
  IO_VIRT + 0x34930, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34934, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34938, 0x00000004, 0xffffffff,
  IO_VIRT + 0x3493c, 0x00000000, 0xffffffff,

  // GOE, TG2
  IO_VIRT + 0x34860, 0x07BC062C, 0xffffffff,
  IO_VIRT + 0x34864, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34868, 0x07BC062C, 0xffffffff,
  IO_VIRT + 0x3486c, 0x04420006, 0xffffffff,
  IO_VIRT + 0x34870, 0x20000000, 0xffffffff,
  IO_VIRT + 0x34874, 0x80000000, 0xffffffff,
  IO_VIRT + 0x34878, 0x00000007, 0xffffffff,
  IO_VIRT + 0x3487c, 0x00000000, 0xffffffff,
  
  // GSC, TG12
  IO_VIRT + 0x349a0, 0x07260406, 0xffffffff,
  IO_VIRT + 0x349a4, 0x00000000, 0xffffffff,
  IO_VIRT + 0x349a8, 0x07260406, 0xffffffff,
  IO_VIRT + 0x349ac, 0x04420006, 0xffffffff,
  IO_VIRT + 0x349b0, 0x20000000, 0xffffffff,
  IO_VIRT + 0x349b4, 0x80000000, 0xffffffff,
  IO_VIRT + 0x349b8, 0x00000107, 0xffffffff,
  IO_VIRT + 0x349bc, 0x00000000, 0xffffffff,
   
  // FLK, TG9  
  IO_VIRT + 0x34940, 0x049C0726, 0xffffffff,
  IO_VIRT + 0x34944, 0x00000000, 0xffffffff,
  IO_VIRT + 0x34948, 0x049C0726, 0xffffffff,
  IO_VIRT + 0x3494c, 0x04420006, 0xffffffff,
  IO_VIRT + 0x34950, 0x20000000, 0xffffffff,
  IO_VIRT + 0x34954, 0x80000000, 0xffffffff,
  IO_VIRT + 0x34958, 0x00000007, 0xffffffff,
  IO_VIRT + 0x3495c, 0x00000000, 0xffffffff,
  
  // DPM, TG10
  IO_VIRT + 0x34978, 0x00000030, 0xffffffff,
  
  // H_CONV, TG5
  IO_VIRT + 0x348d8, 0x00000020, 0xffffffff,

  // OPT_N, TG6
  IO_VIRT + 0x348f8, 0x00000030, 0xffffffff,
  
  // 0PT_P , TG7
  IO_VIRT + 0x34918, 0x00000020, 0xffffffff,
};

//-----------------------------------------------------------------------------
// Static functions
//-----------------------------------------------------------------------------
static UINT32 _u4TconCustGammaWrite(UINT8 u1offset, UINT8 *pu1Buf, UINT8 u1Count)
{
	Printf("0x%8x, 0x%8x, 0xffffffff,\n", u1offset, (pu1Buf[0]<<8) | pu1Buf[1]);
	return (SIF_Write(GAMMAIC_CLK_RATE, GAMMAIC_ID, u1offset, (UINT8 *)pu1Buf, GAMMAIC_DATA_CNT));
}

#if 0 // for warning free
static UINT32 _u4TconCustGammaRead(UINT8 u1offset, UINT8 *pu1Buf, UINT8 u1Count)
{
	return (SIF_Read(GAMMAIC_CLK_RATE, GAMMAIC_ID, u1offset, (UINT8 *)pu1Buf, GAMMAIC_DATA_CNT));
}
#endif

//-----------------------------------------------------------------------------
// Public functions
//-----------------------------------------------------------------------------

UINT8 u1TconCustDPMCtrlEN1(UINT8 val)
{
  vIO32WriteFldAlign(TIMAR6, 1, TIMCR6_TCGPOEN);
	
  if (val)
  {
      vIO32WriteFldAlign(TIMAR6, 1, TIMCR6_TCGPO);
  }
  else
  {
      vIO32WriteFldAlign(TIMAR6, 0, TIMCR6_TCGPO);
  }
  
  return(1);
}

UINT8 u1TconCustDPMCtrlEN2(UINT8 val)
{
    if (val)
    {
        // TODO
    }
    else
    {
        // TODO
    }

    return(1);
}

// Gamma
UINT8 u1TconCustGammaInit(void)
{
	UINT8 u1Err = 0;
	UINT8 i = 0;
	UINT8 u1count;
	UINT8 u1tmp[2];
	UINT16 u2GammaVoltage = 0;

	Printf("Tcon Gamma init\n");

	u1count = (sizeof(sRegCustGamma) / sizeof(struct sTCONREGTABLE));

	for ( i = 0 ; i < u1count ; i++)
    {
                //#if  HISENSE_IPS_2010_PANEL 
      		//u1tmp[1] = (UINT8)((sRegCustGamma[i].u4Val) >> 8);
		//u1tmp[0] = (UINT8)((sRegCustGamma[i].u4Val) & 0xff);
		u2GammaVoltage = (((sRegCustGamma[i].u4Val)&0x03FF)|0x4000);
		u1tmp[0] = (UINT8)(u2GammaVoltage >> 8);
		u1tmp[1] = (UINT8)(u2GammaVoltage & 0xff);
		if (_u4TconCustGammaWrite(sRegCustGamma[i].u4Addr, u1tmp, 2) == 0)
		{
		
			u1Err = 1;
			Printf("!!!Tcon Gamma write fail %d, %d, %d \n", \
				              sRegCustGamma[i].u4Addr, \
				              u1tmp[0], \
				              u1tmp[1]);			
		}
		else
		{
    		Printf("Tcon Gamma write ok %d , %d , %d \n", \
                              sRegCustGamma[i].u4Addr, \
                              u1tmp[0], \
                              u1tmp[1]);
		}
    }

    // check if init ok
	if (u1Err == 0)
	{
		Printf("Program Tcon Gamma dacs %d counts, %d / %d\n", i, sizeof(sRegCustGamma), sizeof(struct sTCONREGTABLE));
	}
	else
	{
	    Printf("Program Tcon Gamma dacs fail !!!\n");
	}
	
	return(1);
}

// program gamma value into non-volatile memory
UINT8  u1TconCustGammaFlashing(void)
{
	UINT8 u1Err = 0;
	UINT8 i = 0;
	UINT8 u1count;
	UINT8 u1tmp[2];
	UINT8 u1Ret = 0;
	UINT16 u2GammaVoltage = 0;

#ifdef TCON_DBG_MSG_EN
   	printf("Tcon Gamma init\n");
#endif
	u1count = (sizeof(sRegCustGamma) / sizeof(struct sTCONREGTABLE));

	for ( i = 0 ; i < u1count ; i++)
    {
    
		//when write non-voltial memory  D15 D14 must be 0 1
		u2GammaVoltage = (((sRegCustGamma[i].u4Val)&0x03FF)|0x4000);
		u1tmp[0] = (UINT8)((u2GammaVoltage >> 8) );  // program gamma into non-voilate
		u1tmp[1] = (UINT8)(u2GammaVoltage & 0xff);

		if (_u4TconCustGammaWrite(sRegCustGamma[i].u4Addr, u1tmp, 2) == 0)
		{
		
			u1Err = 1;
#ifdef TCON_DBG_MSG_EN
 		  	printf("!!!Tcon Gamma write fail 0x%x, 0x%x, 0x%x\n",\
				              sRegCustGamma[i].u4Addr,\
				              u1tmp[0],\
				              u1tmp[1]);
#endif
		}
		else
		{
#ifdef TCON_DBG_MSG_EN
		   	printf("Tcon Gamma write ok 0x%x, 0x%x, 0x%x\n", \
                              sRegCustGamma[i].u4Addr, \
                              u1tmp[0], \
                              u1tmp[1]);
#endif
		}
    }

    // check if init ok
	if (u1Err == 0)
	{
#ifdef TCON_DBG_MSG_EN
    	printf("Program Tcon Gamma dacs %d counts, %d / %d\n", i, sizeof(sRegCustGamma), sizeof(struct sTCONREGTABLE));
#endif
	}
	else
	{
#ifdef TCON_DBG_MSG_EN
   	   printf("Program Tcon Gamma dacs fail !!!\n");
#endif
	}

    return (u1Ret);
}

UINT8 u1TconCustTgInit(void)
{
	UINT8 i = 0;
	UINT8 u1count;
	UINT32 u4tmp, u4tmp1;

	LOG(1,"cust tg init\n");

	u1count = (sizeof(sRegCustTg) / sizeof(struct sTCONREGTABLE));

	for ( i = 0 ; i < u1count ; i++)
    {
        u4tmp = sRegCustTg[i].u4Addr;
		u4tmp1 = (u4IO32Read4B(u4tmp) & ~(sRegCustTg[i].u4Msk)) | (sRegCustTg[i].u4Val);

		vIO32Write4B(u4tmp,u4tmp1);
    }

  	LOG(1,"Tcon reg flashing %d counts, %d / %d\n", i, sizeof(sRegCustTg), sizeof(struct sTCONREGTABLE));

  return(1);
}
