Files
hisi_SS524V100_SDK/vendor/lt8618sx/lt8618sx.c
T

1329 lines
38 KiB
C

/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include "lt8618sx.h"
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/i2c.h>
#define I2C_INDEX_0 1
/*
* Use the synchronization signal inside the bt1120 signal
*/
#define _Embedded_sync_
/*
* need to provide external h sync, V sync and de signals to lt8618sxb
* #define _External_sync_
*/
/*
* IIC Address If CI2CA pins are low(0~400mV)
*/
#define _LT8618SX_ADR 0x72
#define DEV_NAME "lt8618sx"
#define DEBUG_LEVEL 1
#define DPRINTK(level, fmt, args...) \
do { \
if (level < DEBUG_LEVEL) \
printk(KERN_INFO "%s [%s ,%d]: " fmt "\n", DEV_NAME, __FUNCTION__, __LINE__, ##args); \
} while (0)
static struct i2c_client *lt8168sx_client = NULL;
static struct i2c_board_info lt8168sx_i2c_info = {
I2C_BOARD_INFO("lt8168sx", _LT8618SX_ADR >> 1),
};
static int i2c_client_init(void)
{
struct i2c_adapter *i2c_adap = NULL;
i2c_adap = i2c_get_adapter(I2C_INDEX_0);
if (i2c_adap == NULL) {
DPRINTK(0, "i2c%d get adapter failed.\n", I2C_INDEX_0);
return -1;
}
lt8168sx_client = i2c_new_device(i2c_adap, &lt8168sx_i2c_info);
if (lt8168sx_client == NULL) {
DPRINTK(0, "i2c%d get new device failed.\n", I2C_INDEX_0);
return -1;
}
i2c_put_adapter(i2c_adap);
return 0;
}
static void i2c_client_exit(void)
{
if (lt8168sx_client != NULL) {
i2c_unregister_device(lt8168sx_client);
lt8168sx_client = NULL;
}
}
static unsigned char _i2c_read_byte(unsigned char devaddress, unsigned char address)
{
#ifdef DRV_I2C
return drv_i2c_read(I2C_INDEX_0, devaddress, address, 1, 1);
#else
unsigned char ret_data = 0xFF;
int ret;
struct i2c_client *client = lt8168sx_client;
struct i2c_msg msg[2];
unsigned char buffer;
(void)devaddress;
buffer = address;
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &buffer;
msg[1].addr = client->addr;
msg[1].flags = client->flags | I2C_M_RD;
msg[1].len = 1;
msg[1].buf = &buffer;
ret = bsp_i2c_transfer(client->adapter, msg, 2);
if (ret < 0) {
printk("i2c read failed.\n");
} else {
ret_data = buffer;
}
return ret_data;
#endif
}
static int _i2c_write_byte(unsigned char devaddress, unsigned char address, unsigned char data)
{
#ifdef DRV_I2C
return drv_i2c_write(I2C_INDEX_0, devaddress, address, 1, data, 1);
#else
int ret;
unsigned char buf[2];
struct i2c_client *client = lt8168sx_client;
(void)devaddress;
lt8168sx_client->addr = (_LT8618SX_ADR >> 1);
buf[0] = address;
buf[1] = data;
ret = i2c_master_send(client, buf, 2);
if (ret < 0) {
printk("[%s][%d] i2c write failed.\n", __FUNCTION__, __LINE__);
}
udelay(300); /* 300us */
return ret;
#endif
}
/*
* --------------------------------
* CI2CA I2C address
* --------------------------------
* (0~400mV)----------0x72(default)
* (400mV~800mV)------0x7a
* (800mV~1200mV)-----0x90
* (1200mV~1600mV) ---0x92
*
* (2000mV~2400mV)----0x94
* (2400mV~2800mV)----0x7e
* (2800mV~3300mV)----0x76
* -------------------------------
*/
/*
* The lowest bit 0 of the IIC address 0x72 (0x76) of LT8618SXB is the read-write flag bit.
* In the case of Linux IIC, the highest bit is the read-write flag bit, The IIC address needs to be moved one bit to
* the right, and the IIC address becomes 0x39 (0x3B). IIC rate should not exceed 100K. If the IIC address of LT8618SXB
* is not 0x72, you need to reset LT8618SXB with the master GPIO, pull down 100ms, then pull up, delay 100ms, and
* initialize the LT8618SXB register.
*/
static void HDMI_WriteI2C_Byte(unsigned char reg_addr, unsigned char value)
{
_i2c_write_byte(_LT8618SX_ADR, reg_addr, value);
return;
}
unsigned int HDMI_ReadI2C_Byte(unsigned char reg_addr)
{
unsigned char read_ret = _i2c_read_byte(_LT8618SX_ADR, reg_addr);
return read_ret;
}
/*
* 1 Reset LT8618SX
* 2 LT8618SX Initial setting:
* u16 hfp, hs_width, hbp, h_act, h_tal, v_act, v_tal, vfp, vs_width, vbp;
* u8 HDMI_VIC = 0x00;
* u8 HDMI_Y = 0x00;
* bool hs_pol, vs_pol;
*/
/*
* LT8618SXB_D0_D7_Bit_Swap, 0x01: Red D0 ~ D7 swap enable; 0x00 : Normal
* LT8618SXB_D8_D15_Bit_Swap, 0x02: Red D8 ~ D15 swap enable; 0x00 : Normal
* LT8618SXB_D16_D23_Bit_Swap, 0x04: Red D16 ~ D23 swap enable; 0x00 : Normal
*/
#define LT8618SXB_D0_D7_Bit_Swap 0x00
#define LT8618SXB_D8_D15_Bit_Swap 0x00
#define LT8618SXB_D16_D23_Bit_Swap 0x00
/*
* _D0_D15_In, BT1120 input from D0 to D15 of LT8618SXB pins. D0 ~ D7 Y ; D8 ~ D15 C
* _D8_D23_In, BT1120 input from D8 to D23 of LT8618SXB pins. D8 ~ D15 Y ; D16 ~ D23 C
* _D0_D15_In_2, BT1120 input from D0 to D15 of LT8618SXB pins. D0 ~ D7 C ; D8 ~ D15 Y
* _D8_D23_In_2, BT1120 input from D8 to D23 of LT8618SXB pins. D8 ~ D15 C ; D16 ~ D23 Y
*/
#define _D0_D15_In 0x30
#define _D8_D23_In 0x70
#define _D0_D15_In_2 0x00
#define _D8_D23_In_2 0x60
/*
* 1: DDR mode; 0: SDR (normal) mode
*/
bool Use_DDRCLK = 0;
module_param(Use_DDRCLK, bool, S_IRUGO);
u8 I2CADR;
/*
* vic ,0x10: 1080P ; 0x04 : 720P ; Refer to the following list
*/
u8 VIC_Num = 16;
#ifdef _Read_TV_EDID_
u8 Sink_EDID[256];
#endif
/*
* --------------------------------------
* Resolution VIC_Num
* --------------------------------------
* 640x480 1
* 720x480P 60Hz 2
* 720x480i 60Hz 6
* 720x576P 50Hz 17
* 720x576i 50Hz 21
* 1280x720P 24Hz 60
* 1280x720P 25Hz 61
* 1280x720P 30Hz 62
* 1280x720P 50Hz 19
* 1280x720P 60Hz 4
* 1920x1080P 24Hz 32
* 1920x1080P 25Hz 33
* 1920x1080P 30Hz 34
* 1920x1080i 50Hz 20
* 1920x1080i 60Hz 5
* 1920x1080P 50Hz 31
* 1920x1080P 60Hz 16
* other resolution 0(default)
* --------------------------------------
*/
#define VIC_640X480 1
#define VIC_720X480P60Hz 2
#define VIC_720X480I60Hz 6
#define VIC_720X576P50Hz 17
#define VIC_720X576I50Hz 21
#define VIC_1280X720P24Hz 60
#define VIC_1280X720P25Hz 61
#define VIC_1280X720P30Hz 62
#define VIC_1280X720P50Hz 19
#define VIC_1280X720P60Hz 4
#define VIC_1920X1080P24Hz 32
#define VIC_1920X1080P25Hz 33
#define VIC_1920X1080P30Hz 34
#define VIC_1920X1080I50Hz 20
#define VIC_1920X1080I60Hz 5
#define VIC_1920X1080P50Hz 31
#define VIC_1920X1080P60Hz 16
#define VIC_3840x2160_24Hz 93
#define VIC_3840x2160_25Hz 94
#define VIC_3840x2160_30Hz 95
#define VIC_DEFAULT 0
enum {
_32KHz = 0,
_44d1KHz = 1,
_48KHz = 2,
_88d2KHz = 3,
_96KHz = 4,
_176Khz = 5,
_196KHz = 6,
FREQ_BUTT = 7,
};
/*
* 4096 : 32K
* 6272 : 44.1K
* 6144 : 48K
* 12544 : 88.2K
* 12288 : 96K
* 25088 : 176K
* 24576 : 196K
*/
u16 IIS_N[FREQ_BUTT] = {
4096,
6272,
6144,
12544,
12288,
25088,
24576,
};
/*
* 0x30 : 32K
* 0x00 : 44.1K
* 0x20 : 48K
* 0x80 : 88.2K
* 0xa0 : 96K
* 0xc0 : 176K
* 0xe0 : 196K
*/
u16 Sample_Freq[FREQ_BUTT] = {
0x30,
0x00,
0x20,
0x80,
0xa0,
0xc0,
0xe0,
};
typedef enum {
LT_OUT_PAL = 0, /* PAL standard */
LT_OUT_NTSC = 1, /* NTSC standard */
LT_OUT_960H_PAL = 2, /* ITU-R BT.1302 960 x 576 at 50 Hz (interlaced) */
LT_OUT_960H_NTSC = 3, /* ITU-R BT.1302 960 x 480 at 60 Hz (interlaced) */
LT_OUT_640x480_60 = 4, /* VESA 640 x 480 at 60 Hz (non-interlaced) CVT */
LT_OUT_480P60 = 5, /* 720 x 480 at 60 Hz. */
LT_OUT_576P50 = 6, /* 720 x 576 at 50 Hz. */
LT_OUT_800x600_60 = 7, /* VESA 800 x 600 at 60 Hz (non-interlaced) */
LT_OUT_1024x768_60 = 8, /* VESA 1024 x 768 at 60 Hz (non-interlaced) */
LT_OUT_720P50 = 9, /* 1280 x 720 at 50 Hz. */
LT_OUT_720P60 = 10, /* 1280 x 720 at 60 Hz. */
LT_OUT_1280x800_60 = 11, /* 1280*800@60Hz VGA@60Hz */
LT_OUT_1280x1024_60 = 12, /* VESA 1280 x 1024 at 60 Hz (non-interlaced) */
LT_OUT_1366x768_60 = 13, /* VESA 1366 x 768 at 60 Hz (non-interlaced) */
LT_OUT_1400x1050_60 = 14, /* VESA 1400 x 1050 at 60 Hz (non-interlaced) CVT */
LT_OUT_1440x900_60 = 15, /* VESA 1440 x 900 at 60 Hz (non-interlaced) CVT Compliant */
LT_OUT_1680x1050_60 = 16, /* VESA 1680 x 1050 at 60 Hz (non-interlaced) */
LT_OUT_1080P24 = 17, /* 1920 x 1080 at 24 Hz. */
LT_OUT_1080P25 = 18, /* 1920 x 1080 at 25 Hz. */
LT_OUT_1080P30 = 19, /* 1920 x 1080 at 30 Hz. */
LT_OUT_1080I50 = 20, /* 1920 x 1080 at 50 Hz, interlaced. */
LT_OUT_1080I60 = 21, /* 1920 x 1080 at 60 Hz, interlaced. */
LT_OUT_1080P50 = 22, /* 1920 x 1080 at 50 Hz. */
LT_OUT_1080P60 = 23, /* 1920 x 1080 at 60 Hz. */
LT_OUT_1600x1200_60 = 24, /* VESA 1600 x 1200 at 60 Hz (non-interlaced) */
LT_OUT_1920x1200_60 = 25, /* VESA 1920 x 1600 at 60 Hz (non-interlaced) CVT (Reduced Blanking) */
LT_OUT_1920x2160_30 = 26, /* 1920x2160_30 */
LT_OUT_2560x1440_30 = 27, /* 2560x1440_30 */
LT_OUT_2560x1440_60 = 28, /* 2560x1440_60 */
LT_OUT_2560x1600_60 = 29, /* 2560x1600_60 */
LT_OUT_3840x2160_24 = 30, /* 3840x2160_24 */
LT_OUT_3840x2160_25 = 31, /* 3840x2160_25 */
LT_OUT_3840x2160_30 = 32, /* 3840x2160_30 */
LT_OUT_USER = 33, /* User timing. */
LT_OUT_BUTT = 34,
} lt_intf_sync;
enum {
Less_than_50M = 0,
Bound_50_60M = 1,
Bound_60_90M = 2,
Bound_90_100M = 3,
Bound_100_120M = 4,
Bound_120_150M = 5,
Bound_150_180M = 6,
Bound_180_200M = 7,
Bound_200_210M = 8,
Bound_210_240M = 9,
Bound_240_270M = 10,
More_than_270M = 11,
BOUND_BUTT = 12,
};
static u8 Resolution_Num = 24;
#define _16_9_ 0x2A
#define _4_3_ 0x19
enum {
H_act = 0,
V_act = 1,
H_tol = 2,
V_tol = 3,
H_bp = 4,
H_sync = 5,
H_fp = 6,
V_fp = 7,
V_sync = 8,
V_bp = 9,
Vic = 10,
Pic_Ratio = 11, /* Image proportion */
Clk_bound_SDR = 12, /* SDR */
Clk_bound_DDR = 13, /* DDR */
TIMING_BUTT = 14,
};
static int Format_Timing[LT_OUT_BUTT][TIMING_BUTT] = {
/* H_act V_act H_total V_total H_BP H_sync H_FP V_FP V_sync V_BP Vic Pic_Ratio Clk_bound_SDR Clk_bound_DDR */
{720, 288, 864, 312, 6, 126, 12, 2, 3, 19, VIC_720X576I50Hz, _4_3_, Less_than_50M, Less_than_50M},
{720, 240, 858, 262, 0, 124, 19, 4, 3, 15, VIC_720X480I60Hz, _4_3_, Less_than_50M, Less_than_50M},
{960, 288, 1152, 312, 8, 168, 16, 2, 3, 19, VIC_DEFAULT, _4_3_, Less_than_50M, Less_than_50M},
{960, 240, 1144, 262, 0, 168, 21, 4, 3, 15, VIC_DEFAULT, _4_3_, Less_than_50M, Less_than_50M},
{640, 480, 800, 525, 48, 96, 16, 10, 2, 33, VIC_640X480, _4_3_, Less_than_50M, Less_than_50M},
{720, 480, 858, 525, 60, 62, 16, 9, 6, 30, VIC_720X480P60Hz, _4_3_, Less_than_50M, Less_than_50M},
{720, 576, 864, 625, 68, 64, 12, 5, 5, 39, VIC_720X576P50Hz, _4_3_, Less_than_50M, Less_than_50M},
{800, 600, 1056, 628, 88, 128, 40, 1, 4, 23, VIC_DEFAULT, _4_3_, Less_than_50M, Less_than_50M},
{1024, 768, 1344, 806, 160, 136, 24, 3, 6, 29, VIC_DEFAULT, _4_3_, Bound_60_90M, Less_than_50M},
{1280, 720, 1980, 750, 220, 40, 440, 5, 5, 20, VIC_1280X720P50Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1280, 720, 1650, 750, 220, 40, 110, 5, 5, 20, VIC_1280X720P60Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1280, 800, 1680, 831, 200, 128, 72, 3, 6, 22, VIC_DEFAULT, _4_3_, Bound_60_90M, Less_than_50M},
{1280, 1024, 1688, 1066, 248, 112, 48, 1, 3, 38, VIC_DEFAULT, _4_3_, Bound_100_120M, Bound_50_60M},
{1366, 768, 1792, 798, 213, 143, 70, 3, 3, 24, VIC_DEFAULT, _4_3_, Bound_60_90M, Less_than_50M},
{1400, 1050, 1864, 1089, 232, 144, 88, 3, 4, 32, VIC_DEFAULT, _4_3_, Bound_120_150M, Bound_60_90M},
{1440, 900, 1904, 934, 232, 152, 80, 3, 6, 25, VIC_DEFAULT, _4_3_, Bound_100_120M, Bound_50_60M},
{1680, 1050, 2240, 1089, 280, 176, 104, 3, 6, 30, VIC_DEFAULT, _4_3_, Bound_120_150M, Bound_60_90M},
{1920, 1080, 2750, 1125, 148, 44, 638, 4, 5, 36, VIC_1920X1080P24Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1920, 1080, 2640, 1125, 148, 44, 528, 4, 5, 36, VIC_1920X1080P25Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1920, 1080, 2200, 1125, 148, 44, 88, 4, 5, 36, VIC_1920X1080P30Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1920, 540, 2640, 562, 148, 44, 528, 2, 5, 15, VIC_1920X1080I50Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1920, 540, 2200, 562, 148, 44, 88, 2, 5, 15, VIC_1920X1080I60Hz, _16_9_, Bound_60_90M, Less_than_50M},
{1920, 1080, 2640, 1125, 148, 44, 528, 4, 5, 36, VIC_1920X1080P50Hz, _16_9_, Bound_120_150M, Bound_60_90M},
{1920, 1080, 2200, 1125, 148, 44, 88, 4, 5, 36, VIC_1920X1080P60Hz, _16_9_, Bound_120_150M, Bound_60_90M},
{1600, 1200, 2160, 1250, 304, 192, 64, 1, 3, 46, VIC_DEFAULT, _4_3_, Bound_150_180M, Bound_60_90M},
{1920, 1200, 2080, 1235, 80, 32, 48, 3, 6, 26, VIC_1920X1080P60Hz, _16_9_, Bound_150_180M, Bound_60_90M},
{1920, 2160, 2200, 2240, 148, 44, 88, 8, 5, 67, VIC_1920X1080P60Hz, _4_3_, Bound_120_150M, Bound_60_90M},
{2560, 1440, 2720, 1481, 80, 32, 48, 2, 5, 34, VIC_DEFAULT, _4_3_, Bound_120_150M, Bound_60_90M},
{2560, 1440, 2720, 1481, 80, 32, 48, 2, 5, 34, VIC_DEFAULT, _4_3_, Bound_240_270M, Bound_120_150M},
{2560, 1600, 2720, 1646, 80, 32, 48, 3, 6, 37, VIC_DEFAULT, _4_3_, Bound_240_270M, Bound_120_150M},
{3840, 2160, 5500, 2250, 296, 88, 1276, 8, 10, 72, VIC_3840x2160_24Hz, _16_9_, More_than_270M, Bound_120_150M},
{3840, 2160, 5280, 2250, 296, 88, 1056, 8, 10, 72, VIC_3840x2160_25Hz, _16_9_, More_than_270M, Bound_120_150M},
{3840, 2160, 4400, 2250, 296, 88, 176, 8, 10, 72, VIC_3840x2160_30Hz, _16_9_, More_than_270M, Bound_120_150M},
{0}, /* user */
};
#ifdef _External_sync_
u16 hfp, hs_width, hbp, h_act, h_tal, v_act, v_tal, vfp, vs_width, vbp;
bool hs_pol, vs_pol;
#else
u16 h_act, h_tal, v_act;
#endif
u32 CLK_Cnt;
static u8 LT8618SXB_BT1120_SDR_PLL_setting[BOUND_BUTT][3] = {
{0x00, 0xa8, 0xbb}, /* < 50MHz */
{0x00, 0x94, 0xaa}, /* 50 ~ 59M */
{0x01, 0xa8, 0xaa}, /* 60 ~ 89M */
{0x02, 0xbc, 0xaa}, /* 90 ~ 99M */
{0x02, 0x9e, 0x99}, /* 100 ~ 119M */
{0x03, 0xa8, 0x99}, /* 120 - 149M */
{0x04, 0xb2, 0x99}, /* 150 - 179M */
{0x05, 0xbc, 0x99}, /* 180 - 199M */
{0x05, 0x9e, 0x88}, /* 200 - 209M */
{0x06, 0xa3, 0x88}, /* 210 - 239M */
{0x07, 0xa8, 0x88}, /* 240 - 269M */
{0x08, 0xad, 0x88}, /* >= 270 M */
};
/*
* BT1120 720P 60Hz DDR, D_CLK is 37MHz, select Less_than_50M
* BT1120 1080P 60Hz DDR, D_CLK is 74.25MHz, select Bound_60_90M.
* BT1120 4K30Hz DDR, D_CLK is 148.5MHz, select Bound_120_150M
* {0x00, 0xd0, 0xbb}, < 25MHz
*/
static u8 LT8618SXB_BT1120_DDR_PLL_setting[12][3] = {
{0x00, 0xa8, 0xaa}, /* 25 ~ 50M */
{0x00, 0x94, 0x99}, /* 50 ~ 59M */
{0x01, 0xa8, 0x99}, /* 60 ~ 89M */
{0x02, 0xbc, 0x99}, /* 90 ~ 99M */
{0x02, 0x9e, 0x88}, /* 100 ~ 119M */
{0x03, 0xa8, 0x88}, /* 120 - 149M */
{0x04, 0xb2, 0x88}, /* 150 - 179M */
{0x05, 0xbc, 0x88}, /* 180 - 209M */
{0x06, 0xc6, 0x88}, /* 210 - 239M */
{0x07, 0xd0, 0x88}, /* 240 - 269M */
{0x08, 0xda, 0x88}, /* >= 270M */
};
u8 CLK_bound;
/*
* SDR:1080P 60/50Hz; DDR:4K30Hz. -- 148.5M
*/
u8 CLK_Num = Bound_120_150M;
static unsigned int norm = 24; /* 24: 1080P60 */
module_param(norm, int, S_IRUGO);
static void LT8618SX_VideoSel(unsigned int vmode)
{
if (vmode > LT_OUT_USER) {
/* defalut: 1080P60 */
VIC_Num = VIC_1920X1080P60Hz;
/* 6: HDMI_1080P60 */
Resolution_Num = HDMI_1080P60;
/* 148.5M */
CLK_Num = Bound_120_150M;
printk("Havn't the mode:%d\n", vmode);
return;
}
if (Format_Timing[vmode][H_act] == 0) {
printk("\nwarning: video format(%u)'s timing must be set.\n\n", vmode);
}
Resolution_Num = vmode;
VIC_Num = Format_Timing[vmode][Vic];
CLK_Num = Format_Timing[vmode][Clk_bound_SDR];
}
#if LT_DESC("open/close/ioctl")
static unsigned int open_cnt = 0;
static int lt_open(struct inode *inode, struct file *file)
{
(void)inode;
(void)file;
if ((open_cnt++) == 0) {
return 0;
}
DPRINTK(0, "you should close the device first!");
return -1;
}
static void lt_device_init(u32 norm_tmp)
{
Resolution_change(norm_tmp);
}
static int lt_close(struct inode *inode, struct file *file)
{
(void)inode;
(void)file;
open_cnt--;
return 0;
}
static long lt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
u32 norm_tmp = 0;
u32 use_ddr_clk = 0;
(void)file;
if ((char *)(uintptr_t)arg == NULL) {
return -1;
}
if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
printk("%s %d - input param err, size of cmd is 0!\n", __FUNCTION__, __LINE__);
return -1;
}
if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
printk("%s %d - input param err, arg is null!\n", __FUNCTION__, __LINE__);
return -1;
}
if (_IOC_DIR(cmd) != _IOC_WRITE) {
printk("%s %d - input param err, cmd is not write!\n", __FUNCTION__, __LINE__);
return -1;
}
switch (cmd) {
case (LT_CMD_SETCLK): {
if (copy_from_user(&use_ddr_clk, (void *)(uintptr_t)arg, sizeof(unsigned int))) {
return -1;
}
if ((use_ddr_clk >= LT_CLK_EDGE_SINGLE) && (norm_tmp <= LT_CLK_EDGE_DUAL)) {
Use_DDRCLK = use_ddr_clk;
return 0;
} else {
printk("%s havn't the Use_DDRCLK:%u\n", DEV_NAME, use_ddr_clk);
}
break;
}
case (LT_CMD_SETMODE): {
if (copy_from_user(&norm_tmp, (void *)(uintptr_t)arg, sizeof(unsigned int))) {
return -1;
}
if ((norm_tmp >= LT_OUT_640x480_60) && (norm_tmp < LT_OUT_USER)) {
lt_device_init(norm_tmp);
return 0;
} else {
printk("%s havn't the mode:%u\n", DEV_NAME, norm_tmp);
}
break;
}
default: {
printk("%s havn't the cmd:0x%x\n", DEV_NAME, cmd);
break;
}
}
return 0;
}
static struct file_operations lt_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = lt_ioctl,
.open = lt_open,
.release = lt_close
};
static struct miscdevice lt_dev = {
MISC_DYNAMIC_MINOR,
DEV_NAME,
&lt_fops,
};
#endif
static void lt_reset_ttl(void)
{
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x80);
HDMI_WriteI2C_Byte(0xee, 0x01);
/* reset MIPI Rx logic. */
HDMI_WriteI2C_Byte(0x11, 0x00);
HDMI_WriteI2C_Byte(0x13, 0xf1);
}
static int lt_reboot(struct notifier_block *self, unsigned long event, void *data)
{
(void)self;
(void)event;
(void)data;
lt_reset_ttl();
return NOTIFY_OK;
}
static struct notifier_block lt_reboot_notifier = {
.notifier_call = lt_reboot,
};
static int lt_reboot_init(void)
{
register_reboot_notifier(&lt_reboot_notifier);
return 0;
}
static void lt_reboot_exit(void)
{
unregister_reboot_notifier(&lt_reboot_notifier);
}
#ifdef _LT8618_HDCP_
static void LT8618SX_HDCP_Init(void)
{
HDMI_WriteI2C_Byte(0xff, 0x85);
HDMI_WriteI2C_Byte(0x07, 0x1f);
/*
* [7]=force_hpd, [6]=force_rsen, [5]=vsync_pol, [4]=hsync_pol,
* [3]=hdmi_mode, [2]=no_accs_when_rdy, [1]=skip_wt_hdmi
*/
HDMI_WriteI2C_Byte(0x13, 0xfe);
/*
* [7]=ri_short_read, [3]=sync_pol_mode, [2]=srm_chk_done,
* [1]=bksv_srm_pass, [0]=ksv_list_vld
*/
HDMI_WriteI2C_Byte(0x17, 0x0f);
HDMI_WriteI2C_Byte(0x15, 0x05);
}
static void LT8618SX_HDCP_Enable(void)
{
HDMI_WriteI2C_Byte(0xff, 0x80);
HDMI_WriteI2C_Byte(0x14, 0x7f);
HDMI_WriteI2C_Byte(0x14, 0xff);
HDMI_WriteI2C_Byte(0xff, 0x85);
/* disable HDCP */
HDMI_WriteI2C_Byte(0x15, 0x01);
/* enable HDCP */
HDMI_WriteI2C_Byte(0x15, 0x71);
/* enable HDCP */
HDMI_WriteI2C_Byte(0x15, 0x65);
}
static void LT8618SX_HDCP_Disable(void)
{
HDMI_WriteI2C_Byte(0xff, 0x85);
/* enable HDCP */
HDMI_WriteI2C_Byte(0x15, 0x45);
}
#endif
static void LT8918SXB_Read_EDID(void)
{
#ifdef _Read_TV_EDID_
u8 i, j;
u8 extended_flag = 0x00;
HDMI_WriteI2C_Byte(0xff, 0x85);
/*
* I2C 100K
*/
HDMI_WriteI2C_Byte(0x03, 0xc9);
/* 0xA0 is EDID device address */
HDMI_WriteI2C_Byte(0x04, 0xa0);
/* 0x00 is EDID offset address */
HDMI_WriteI2C_Byte(0x05, 0x00);
/* length for read */
HDMI_WriteI2C_Byte(0x06, 0x20);
HDMI_WriteI2C_Byte(0x14, 0x7f);
/* block 0 & 1 */
for (i = 0; i < 8; i++) {
/* 0x00 is EDID offset address */
HDMI_WriteI2C_Byte(0x05, i * 32);
HDMI_WriteI2C_Byte(0x07, 0x36);
/* 0x31 */
HDMI_WriteI2C_Byte(0x07, 0x34);
/* 0x37 */
HDMI_WriteI2C_Byte(0x07, 0x37);
/* wait 5ms for reading edid data. */
Timer0_Delay1ms(5);
if (HDMI_ReadI2C_Byte(0x40) & 0x02) {
/* DDC No Ack or Abitration lost */
if (HDMI_ReadI2C_Byte(0x40) & 0x50) {
printk("\r\nread edid failed: no ack");
goto end;
} else {
printk("\r\n");
for (j = 0; j < 32; j++) {
Sink_EDID[i * 32 + j] = HDMI_ReadI2C_Byte(0x83);
printk("%u ", Sink_EDID[i * 32 + j]);
if ((i == 3) && (j == 30)) {
extended_flag = Sink_EDID[i * 32 + j] & 0x03;
}
}
if (i == 3) {
/* no block 1, stop reading edid. */
if (extended_flag < 1) {
goto end;
}
}
}
} else {
printk("\r\nread edid failed: accs not done");
goto end;
}
}
/* no block 2, stop reading edid. */
if (extended_flag < 2) {
goto end;
}
/* block 2 & 3 */
for (i = 0; i < 8; i++) {
/* 0x00 is EDID offset address */
HDMI_WriteI2C_Byte(0x05, i * 32);
HDMI_WriteI2C_Byte(0x07, 0x76);
HDMI_WriteI2C_Byte(0x07, 0x74);
HDMI_WriteI2C_Byte(0x07, 0x77);
/* wait 5ms for reading edid data. */
Timer0_Delay1ms(5);
if (HDMI_ReadI2C_Byte(0x40) & 0x02) {
/* DDC No Ack or Abitration lost */
if (HDMI_ReadI2C_Byte(0x40) & 0x50) {
printk("\r\nread edid failed: no ack");
goto end;
} else {
printk("\r\n");
for (j = 0; j < 32; j++) {
Sink_EDID2[i * 32 + j] = HDMI_ReadI2C_Byte(0x83);
printk("%u ", Sink_EDID2[i * 32 + j]);
}
if (i == 3) {
/* no block 1, stop reading edid. */
if (extended_flag < 3) {
goto end;
}
}
}
} else {
printk("\r\nread edid failed: accs not done");
goto end;
}
}
end:
HDMI_WriteI2C_Byte(0x03, 0xc2);
HDMI_WriteI2C_Byte(0x07, 0x1f);
#endif
}
static void LT8618SXB_Video_check(void)
{
/* video */
HDMI_WriteI2C_Byte(0xff, 0x82);
#ifdef _Embedded_sync_
h_tal = HDMI_ReadI2C_Byte(0x8f);
h_tal = (h_tal << 8) + HDMI_ReadI2C_Byte(0x90);
v_act = HDMI_ReadI2C_Byte(0x8b);
v_act = (v_act << 8) + HDMI_ReadI2C_Byte(0x8c);
h_act = HDMI_ReadI2C_Byte(0x8d);
h_act = (h_act << 8) + HDMI_ReadI2C_Byte(0x8e);
CLK_Cnt = (HDMI_ReadI2C_Byte(0x1d) & 0x0f) * 0x10000 + HDMI_ReadI2C_Byte(0x1e) * 0x100 + HDMI_ReadI2C_Byte(0x1f);
#else
u8 temp;
vs_pol = 0;
hs_pol = 0;
/* hs vs polarity */
temp = HDMI_ReadI2C_Byte(0x70);
if (temp & 0x02) {
vs_pol = 1;
}
if (temp & 0x01) {
hs_pol = 1;
}
vs_width = HDMI_ReadI2C_Byte(0x71);
hs_width = HDMI_ReadI2C_Byte(0x72);
hs_width = (hs_width << 8) + HDMI_ReadI2C_Byte(0x73);
vbp = HDMI_ReadI2C_Byte(0x74);
vfp = HDMI_ReadI2C_Byte(0x75);
hbp = HDMI_ReadI2C_Byte(0x76);
hbp = (hbp << 8) + HDMI_ReadI2C_Byte(0x77);
hfp = HDMI_ReadI2C_Byte(0x78);
hfp = (hfp << 8) + HDMI_ReadI2C_Byte(0x79);
v_tal = HDMI_ReadI2C_Byte(0x7a);
v_tal = (v_tal << 8) + HDMI_ReadI2C_Byte(0x7b);
h_tal = HDMI_ReadI2C_Byte(0x7c);
h_tal = (h_tal << 8) + HDMI_ReadI2C_Byte(0x7d);
v_act = HDMI_ReadI2C_Byte(0x7e);
v_act = (v_act << 8) + HDMI_ReadI2C_Byte(0x7f);
h_act = HDMI_ReadI2C_Byte(0x80);
h_act = (h_act << 8) + HDMI_ReadI2C_Byte(0x81);
CLK_Cnt = (HDMI_ReadI2C_Byte(0x1d) & 0x0f) * 0x10000 + HDMI_ReadI2C_Byte(0x1e) * 0x100 + HDMI_ReadI2C_Byte(0x1f);
#endif
}
static void LT8618SXB_TTL_Input_Analog(void)
{
/* TTL mode */
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x81);
HDMI_WriteI2C_Byte(0x02, 0x66);
HDMI_WriteI2C_Byte(0x0a, 0x06);
HDMI_WriteI2C_Byte(0x15, 0x06);
/* for U2 */
HDMI_WriteI2C_Byte(0x4e, 0xa8);
HDMI_WriteI2C_Byte(0xff, 0x82);
HDMI_WriteI2C_Byte(0x1b, 0x77);
/* 25000 */
HDMI_WriteI2C_Byte(0x1c, 0xEC);
}
static void LT8618SXB_TTL_Input_Digtal(void)
{
HDMI_WriteI2C_Byte(0xff, 0x80);
#ifdef _Embedded_sync_
/* Internal generate sync/de control logic clock enable */
HDMI_WriteI2C_Byte(0x0A, 0xF0);
#else
/* _External_sync_ */
HDMI_WriteI2C_Byte(0x0A, 0xC0);
#endif
/* TTL_Input_Digtal */
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x82);
/* YC channel swap */
HDMI_WriteI2C_Byte(0x45, _D8_D23_In + LT8618SXB_D0_D7_Bit_Swap + LT8618SXB_D16_D23_Bit_Swap +
LT8618SXB_D8_D15_Bit_Swap);
if (Use_DDRCLK) {
/* 0x80: dclk */
HDMI_WriteI2C_Byte(0x4f, 0x80);
} else {
/* 0x40: txpll_clk */
HDMI_WriteI2C_Byte(0x4f, 0x40);
}
HDMI_WriteI2C_Byte(0x50, 0x00);
#ifdef _Embedded_sync_
/* Select BT rx decode det_vs/hs/de */
HDMI_WriteI2C_Byte(0x51, 0x42);
/* Embedded sync mode input enable. */
HDMI_WriteI2C_Byte(0x48, 0x08);
#else
/* _External_sync_ */
/* Select TTL process module input video data */
HDMI_WriteI2C_Byte(0x51, 0x00);
HDMI_WriteI2C_Byte(0x48, 0x00);
#endif
}
static void LT8618SXB_PLL_setting(void)
{
HDMI_WriteI2C_Byte(0xff, 0x81);
HDMI_WriteI2C_Byte(0x23, 0x40);
/* icp set */
HDMI_WriteI2C_Byte(0x24, 0x64);
HDMI_WriteI2C_Byte(0x2e, 0x01);
HDMI_WriteI2C_Byte(0x2f, 0x10);
HDMI_WriteI2C_Byte(0x26, 0x55);
/* Parameters required by LT8618SXB_PLL_setting( void ) */
CLK_bound = Format_Timing[Resolution_Num][Clk_bound_SDR + (u8)(Use_DDRCLK)];
if (Use_DDRCLK) {
HDMI_WriteI2C_Byte(0x4d, 0x05);
/* 0x05 pre-divider3 ddr 02 */
HDMI_WriteI2C_Byte(0x25, LT8618SXB_BT1120_DDR_PLL_setting[CLK_bound][0x00]);
/* 9e */
HDMI_WriteI2C_Byte(0x2c, LT8618SXB_BT1120_DDR_PLL_setting[CLK_bound][0x01]);
/* 88 */
HDMI_WriteI2C_Byte(0x2d, LT8618SXB_BT1120_DDR_PLL_setting[CLK_bound][0x02]);
/* 0x60 ddr 0x66 */
HDMI_WriteI2C_Byte(0x27, 0x66);
/* 0x88 */
HDMI_WriteI2C_Byte(0x28, 0x88);
} else {
HDMI_WriteI2C_Byte(0x4d, 0x00);
/* 0x05 pre-divider3 ddr 02 */
HDMI_WriteI2C_Byte(0x25, LT8618SXB_BT1120_SDR_PLL_setting[CLK_bound][0x00]);
/* 9e */
HDMI_WriteI2C_Byte(0x2c, LT8618SXB_BT1120_SDR_PLL_setting[CLK_bound][0x01]);
/* 88 */
HDMI_WriteI2C_Byte(0x2d, LT8618SXB_BT1120_SDR_PLL_setting[CLK_bound][0x02]);
/* 0x60 ddr 0x66 */
HDMI_WriteI2C_Byte(0x27, 0x06);
/* 0x88 */
HDMI_WriteI2C_Byte(0x28, 0x00);
}
/*
* as long as changing the resolution or changing the input clock,
* You need to configure the following registers.
*/
HDMI_WriteI2C_Byte(0xff, 0x82);
HDMI_WriteI2C_Byte(0xde, 0x00);
HDMI_WriteI2C_Byte(0xde, 0xc0);
HDMI_WriteI2C_Byte(0xff, 0x80);
HDMI_WriteI2C_Byte(0x16, 0xf1);
HDMI_WriteI2C_Byte(0x16, 0xf3);
}
static void LT8618SXB_Audio_setting(void)
{
/* IIS Input */
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x82);
/* bit7 = 0 : DVI output; bit7 = 1: HDMI output */
HDMI_WriteI2C_Byte(0xd6, 0x8e);
/* sync polarity */
HDMI_WriteI2C_Byte(0xd7, 0x04);
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x84);
HDMI_WriteI2C_Byte(0x06, 0x08);
/* SD0 channel selected */
HDMI_WriteI2C_Byte(0x07, 0x10);
/* 0x00 :Left justified; default */
HDMI_WriteI2C_Byte(0x09, 0x00);
/* 0x02 :Right justified; */
HDMI_WriteI2C_Byte(0x0f, 0x0b + Sample_Freq[_48KHz]);
/* CTS_N / 2; 32bit */
HDMI_WriteI2C_Byte(0x34, 0xd4);
/* CTS_N / 4; 16bit */
HDMI_WriteI2C_Byte(0x35, (u8)(IIS_N[_48KHz] / 0x10000));
HDMI_WriteI2C_Byte(0x36, (u8)((IIS_N[_48KHz] & 0x00FFFF) / 0x100));
HDMI_WriteI2C_Byte(0x37, (u8)(IIS_N[_48KHz] & 0x0000FF));
/* Null packet enable */
HDMI_WriteI2C_Byte(0x3c, 0x21);
}
static void LT8618SXB_CSC_setting(void)
{
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x82);
/* No csc */
HDMI_WriteI2C_Byte(0xb9, 0x00);
}
static void LT8618SXB_AVI_setting(void)
{
u8 AVI_PB0;
u8 AVI_PB1;
u8 AVI_PB2;
/* PB1,color space: YUV444 0x70;YUV422 0x30; RGB 0x10 */
AVI_PB1 = 0x30;
/* PB2; picture aspect rate: 0x19:4:3 ; 0x2A : 16:9 */
AVI_PB2 = Format_Timing[Resolution_Num][Pic_Ratio];
AVI_PB0 = ((AVI_PB1 + AVI_PB2 + VIC_Num) <= 0x6f) ? (0x6f - AVI_PB1 - AVI_PB2 - VIC_Num) :
(0x16f - AVI_PB1 - AVI_PB2 - VIC_Num);
/* register bank */
HDMI_WriteI2C_Byte(0xff, 0x84);
/* PB0,avi packet checksum */
HDMI_WriteI2C_Byte(0x43, AVI_PB0);
/* PB1,color space: YUV444 0x70;YUV422 0x30; RGB 0x10 */
HDMI_WriteI2C_Byte(0x44, AVI_PB1);
/* PB2;picture aspect rate: 0x19:4:3 ; 0x2A : 16:9 */
HDMI_WriteI2C_Byte(0x45, AVI_PB2);
/* PB4;vic ,0x10: 1080P ; 0x04 : 720P */
HDMI_WriteI2C_Byte(0x47, VIC_Num);
/* data iland */
HDMI_WriteI2C_Byte(0x10, 0x2c);
/* act_h_blank */
HDMI_WriteI2C_Byte(0x12, 0x64);
if (VIC_Num == 95) {
/* UD1 infoframe enable */
HDMI_WriteI2C_Byte(0x3d, 0x2a);
HDMI_WriteI2C_Byte(0x74, 0x81);
HDMI_WriteI2C_Byte(0x75, 0x01);
HDMI_WriteI2C_Byte(0x76, 0x05);
HDMI_WriteI2C_Byte(0x77, 0x49);
HDMI_WriteI2C_Byte(0x78, 0x03);
HDMI_WriteI2C_Byte(0x79, 0x0c);
HDMI_WriteI2C_Byte(0x7a, 0x00);
HDMI_WriteI2C_Byte(0x7b, 0x20);
HDMI_WriteI2C_Byte(0x7c, 0x01);
} else {
/*
* UD1 infoframe disable
*/
HDMI_WriteI2C_Byte(0x3d, 0x0a);
}
}
static void LT8618SXB_TX_Phy(void)
{
/*
* register bank
*/
HDMI_WriteI2C_Byte(0xff, 0x81);
HDMI_WriteI2C_Byte(0x30, 0xea);
HDMI_WriteI2C_Byte(0x31, 0x44);
HDMI_WriteI2C_Byte(0x32, 0x4a);
HDMI_WriteI2C_Byte(0x33, 0x0b);
HDMI_WriteI2C_Byte(0x34, 0x00);
HDMI_WriteI2C_Byte(0x35, 0x00);
HDMI_WriteI2C_Byte(0x36, 0x00);
HDMI_WriteI2C_Byte(0x37, 0x44);
HDMI_WriteI2C_Byte(0x3f, 0x0f);
/*
* 0xa0 -- CLK tap0 swing
*/
HDMI_WriteI2C_Byte(0x40, 0xa0);
/*
* 0xa0 -- D0 tap0 swing
*/
HDMI_WriteI2C_Byte(0x41, 0xa0);
/*
* 0xa0 -- D1 tap0 swing
*/
HDMI_WriteI2C_Byte(0x42, 0xa0);
/*
* 0xa0 -- D2 tap0 swing
*/
HDMI_WriteI2C_Byte(0x43, 0xa0);
HDMI_WriteI2C_Byte(0x44, 0x0a);
}
#ifdef _Embedded_sync_
static void LT8618SXB_BT_Timing_setting(void)
{
HDMI_WriteI2C_Byte(0xff, 0x82);
HDMI_WriteI2C_Byte(0x20, (u8)(Format_Timing[Resolution_Num][H_act] / 256));
HDMI_WriteI2C_Byte(0x21, (u8)(Format_Timing[Resolution_Num][H_act] % 256));
HDMI_WriteI2C_Byte(0x22, (u8)(Format_Timing[Resolution_Num][H_fp] / 256));
HDMI_WriteI2C_Byte(0x23, (u8)(Format_Timing[Resolution_Num][H_fp] % 256));
HDMI_WriteI2C_Byte(0x24, (u8)(Format_Timing[Resolution_Num][H_sync] / 256));
HDMI_WriteI2C_Byte(0x25, (u8)(Format_Timing[Resolution_Num][H_sync] % 256));
HDMI_WriteI2C_Byte(0x26, 0x00);
HDMI_WriteI2C_Byte(0x27, 0x00);
HDMI_WriteI2C_Byte(0x36, (u8)(Format_Timing[Resolution_Num][V_act] / 256));
HDMI_WriteI2C_Byte(0x37, (u8)(Format_Timing[Resolution_Num][V_act] % 256));
HDMI_WriteI2C_Byte(0x38, (u8)(Format_Timing[Resolution_Num][V_fp] / 256));
HDMI_WriteI2C_Byte(0x39, (u8)(Format_Timing[Resolution_Num][V_fp] % 256));
HDMI_WriteI2C_Byte(0x3a, (u8)(Format_Timing[Resolution_Num][V_bp] / 256));
HDMI_WriteI2C_Byte(0x3b, (u8)(Format_Timing[Resolution_Num][V_bp] % 256));
HDMI_WriteI2C_Byte(0x3c, (u8)(Format_Timing[Resolution_Num][V_sync] / 256));
HDMI_WriteI2C_Byte(0x3d, (u8)(Format_Timing[Resolution_Num][V_sync] % 256));
}
static void LT8618SXB_Phase_config(void)
{
u8 Temp = 0x00;
u8 OK_CNT = 0x00;
u8 Jump_CNT = 0x00;
u8 Jump_Num = 0x00;
bool b_OK = 0;
u16 v_active = 0x0000;
u16 h_active = 0x0000;
u16 h_total = 0x0000;
/*
* register bank
*/
HDMI_WriteI2C_Byte(0xff, 0x80);
HDMI_WriteI2C_Byte(0x13, 0xf1);
mdelay(5);
/*
* Reset TTL video process
*/
HDMI_WriteI2C_Byte(0x13, 0xf9);
mdelay(100);
while (Temp <= 0x09) {
HDMI_WriteI2C_Byte(0xff, 0x81);
HDMI_WriteI2C_Byte(0x27, (0x60 + Temp));
HDMI_WriteI2C_Byte(0x4d, 0x0d);
/*
* > 30ms
*/
mdelay(50);
HDMI_WriteI2C_Byte(0xff, 0x82);
h_total = HDMI_ReadI2C_Byte(0x8f);
h_total = (h_total << 8) + HDMI_ReadI2C_Byte(0x90);
v_active = HDMI_ReadI2C_Byte(0x8b);
v_active = (v_active << 8) + HDMI_ReadI2C_Byte(0x8c);
h_active = HDMI_ReadI2C_Byte(0x8d);
h_active = (h_active << 8) + HDMI_ReadI2C_Byte(0x8e);
if ((v_active > (Format_Timing[Resolution_Num][V_act] - 5)) &&
(v_active < (Format_Timing[Resolution_Num][V_act] + 5)) &&
(h_active > (Format_Timing[Resolution_Num][H_act] - 5)) &&
(h_active < (Format_Timing[Resolution_Num][H_act] + 5)) &&
(h_total > (Format_Timing[Resolution_Num][H_tol] - 5)) &&
(h_total < (Format_Timing[Resolution_Num][H_tol] + 5))) {
OK_CNT++;
if (b_OK == 0) {
b_OK = 1;
Jump_CNT++;
if ((Jump_CNT == 1) || (Jump_CNT == 3)) {
Jump_Num = Temp;
}
}
} else {
if (b_OK) {
b_OK = 0;
Jump_CNT++;
}
}
Temp++;
}
HDMI_WriteI2C_Byte(0xff, 0x81);
if ((Jump_CNT == 1) || (Jump_CNT == 2) || (Jump_CNT == 4)) {
HDMI_WriteI2C_Byte(0x27, (0x60 + Jump_Num + (OK_CNT / 2)));
} else if (Jump_CNT == 3) {
HDMI_WriteI2C_Byte(0x27, (0x60 + (Jump_Num + (OK_CNT / 2)) % 0x0a));
}
}
#endif
static bool lt_check_module_param(void)
{
if (norm >= LT_OUT_BUTT) {
printk("module param norm(%u) invalid, it should be in [%u,%u]\n", norm, 0, LT_OUT_USER);
return -1;
}
if ((Use_DDRCLK != LT_CLK_EDGE_SINGLE) && (Use_DDRCLK != LT_CLK_EDGE_DUAL)) {
printk("module param Use_DDRCLK(%u) invalid, it should be 0 or 1\n", Use_DDRCLK);
return -1;
}
return 0;
}
static int __init LT8618SX_Initial(void)
{
s32 ret = 0;
if (lt_check_module_param() != 0) {
return -1;
}
I2CADR = _LT8618SX_ADR;
ret = misc_register(&lt_dev);
if (ret) {
DPRINTK(0, "could not register lt8618sx device\n");
goto end0;
}
lt_reboot_init();
ret = i2c_client_init();
if (ret != 0) {
DPRINTK(0, "could not init i2c client\n");
goto end1;
}
LT8618SX_VideoSel(norm);
/*
* register bank
*/
HDMI_WriteI2C_Byte(0xff, 0x80);
HDMI_WriteI2C_Byte(0xee, 0x01);
/*
* reset MIPI Rx logic.
*/
HDMI_WriteI2C_Byte(0x11, 0x00);
HDMI_WriteI2C_Byte(0x13, 0xf1);
/*
* Reset TTL video process
*/
HDMI_WriteI2C_Byte(0x13, 0xf9);
/*
* TTL mode
*/
LT8618SXB_TTL_Input_Analog();
LT8618SXB_TTL_Input_Digtal();
/*
* Wait for the signal to be stable and decide whether the delay is
* necessary according to the actual situation
*/
mdelay(1000);
/*
* For debug
*/
LT8618SXB_Video_check();
/*
* PLL
*/
LT8618SXB_PLL_setting();
LT8618SXB_Audio_setting();
LT8618SXB_CSC_setting();
#ifdef _LT8618_HDCP_
LT8618SXB_HDCP_Init();
#endif
LT8618SXB_AVI_setting();
LT8618SXB_TX_Phy();
/*
* This operation is not necessary. Read TV EDID if necessary.
* Read TV EDID
*/
LT8918SXB_Read_EDID();
#ifdef _LT8618_HDCP_
LT8618SXB_HDCP_Enable();
#endif
#ifdef _Embedded_sync_
LT8618SXB_BT_Timing_setting();
LT8618SXB_Phase_config();
#endif
printk("load lt8618sx.ko ....OK!\n");
return 0;
end1:
lt_reboot_exit();
misc_deregister(&lt_dev);
end0:
printk("load lt8618sx.ko ....failed!\n");
return -1;
}
/*
* When the lt8618sxb works, the resolution of the bt1120 signal changes.
* The following settings need to be configured.
*/
void Resolution_change(unsigned int Resolution)
{
/*
* Parameters required by LT8618SXB_BT_Timing_setting( void )
*/
Resolution_Num = Resolution;
/*
* Parameters required by LT8618SXB_PLL_setting( void )
*/
CLK_bound = Format_Timing[Resolution_Num][Clk_bound_SDR + (u8)(Use_DDRCLK)];
VIC_Num = Format_Timing[Resolution_Num][Vic];
LT8618SXB_PLL_setting();
LT8618SXB_AVI_setting();
#ifdef _Embedded_sync_
LT8618SXB_BT_Timing_setting();
LT8618SXB_Phase_config();
#endif
}
static void __exit LT8618SX_DeInitial(void)
{
lt_reset_ttl();
i2c_client_exit();
lt_reboot_exit();
misc_deregister(&lt_dev);
printk("unload lt8618sx.ko ....OK!\n");
}
module_init(LT8618SX_Initial);
module_exit(LT8618SX_DeInitial);
MODULE_LICENSE("GPL");