blob: b4ddb37dc92ceed806e1501de6d2a3f8a8dfdf7f [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <amlogic/media/vout/lcd/aml_lcd.h>
#include "lcd_reg.h"
#include "lcd_phy_config.h"
#include "lcd_common.h"
static struct lcd_phy_ctrl_s *lcd_phy_ctrl;
static void lcd_mipi_phy_set_g12a(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int phy_reg, phy_bit, phy_width;
unsigned int lane_cnt;
if (status) {
/* HHI_MIPI_CNTL0 */
/* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */
lcd_ana_write(HHI_MIPI_CNTL0,
(0xa487 << 16) | (0x8 << 0));
/* HHI_MIPI_CNTL1 */
/* DIF_REF_CTL2:15-0bit; bandgap bit16 */
lcd_ana_write(HHI_MIPI_CNTL1,
(0x1 << 16) | (0x002e << 0));
/* HHI_MIPI_CNTL2 */
/* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */
lcd_ana_write(HHI_MIPI_CNTL2,
(0x2680 << 16) | (0x45a << 0));
phy_reg = HHI_MIPI_CNTL2;
phy_bit = MIPI_PHY_LANE_BIT;
phy_width = MIPI_PHY_LANE_WIDTH;
switch (pdrv->config.control.mipi_cfg.lane_num) {
case 1:
lane_cnt = DSI_LANE_COUNT_1;
break;
case 2:
lane_cnt = DSI_LANE_COUNT_2;
break;
case 3:
lane_cnt = DSI_LANE_COUNT_3;
break;
case 4:
lane_cnt = DSI_LANE_COUNT_4;
break;
default:
lane_cnt = 0;
break;
}
lcd_ana_setb(phy_reg, lane_cnt, phy_bit, phy_width);
} else {
lcd_ana_write(HHI_MIPI_CNTL0, 0);
lcd_ana_write(HHI_MIPI_CNTL1, 0);
lcd_ana_write(HHI_MIPI_CNTL2, 0);
}
}
static void lcd_phy_cntl_set_tl1(int status, unsigned int chreg, int bypass,
unsigned int ckdi)
{
unsigned int tmp = 0;
unsigned int data = 0;
unsigned int cntl16 = 0;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
if (status) {
chreg |= ((lcd_phy_ctrl->ctrl_bit_on << 16) |
(lcd_phy_ctrl->ctrl_bit_on << 0));
if (bypass)
tmp |= ((1 << 18) | (1 << 2));
cntl16 = ckdi | 0x80000000;
} else {
if (lcd_phy_ctrl->ctrl_bit_on)
data = 0;
else
data = 1;
chreg |= ((data << 16) | (data << 0));
cntl16 = 0;
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0);
}
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL15, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL16, cntl16);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL8, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL1, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL9, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL2, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL10, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL3, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL11, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL4, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL12, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL6, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL13, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL7, chreg);
}
void lcd_phy_tcon_chpi_bbc_init_tl1(struct lcd_config_s *pconf)
{
unsigned int data32 = 0x06020602;
unsigned int preem;
unsigned int size;
unsigned int n = 10;
struct p2p_config_s *p2p_conf;
if (!lcd_phy_ctrl)
return;
n = env_get_ulong("tcon_delay", 10, 10);
p2p_conf = &pconf->control.p2p_cfg;
size = sizeof(p2p_low_common_phy_preem_tl1) / sizeof(unsigned int);
/*get tcon tx pre_emphasis*/
preem = p2p_conf->phy_preem & 0xf;
/*check tx pre_emphasis ok or no*/
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
udelay(n);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL1, 1, 19, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL2, 1, 19, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL3, 1, 19, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL4, 1, 19, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL6, 1, 19, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 3, 1);
lcd_ana_setb(HHI_DIF_CSI_PHY_CNTL7, 1, 19, 1);
LCDPR("%s: delay: %dus\n", __func__, n);
/*follow pre-emphasis*/
data32 = p2p_low_common_phy_preem_tl1[preem];
if (lcd_phy_ctrl->ctrl_bit_on)
data32 &= ~((1 << 16) | (1 << 0));
else
data32 |= ((1 << 16) | (1 << 0));
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL1, data32);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL2, data32);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL3, data32);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL4, data32);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL6, data32);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL7, data32);
}
static void lcd_lvds_phy_set_tl1(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int data32 = 0, size;
struct lvds_config_s *lvds_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
lvds_conf = &pdrv->config.control.lvds_cfg;
if (status) {
vswing = lvds_conf->phy_vswing & 0xf;
preem = lvds_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing);
lcd_phy_cntl_set_tl1(status, data32, 0, 0);
} else {
lcd_phy_cntl_set_tl1(status, data32, 0, 0);
}
}
static void lcd_vbyone_phy_set_tl1(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem, ext_pullup;
unsigned int data32 = 0, size;
struct vbyone_config_s *vbyone_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
vbyone_conf = &pdrv->config.control.vbyone_cfg;
if (status) {
ext_pullup = (vbyone_conf->phy_vswing >> 4) & 0x3;
vswing = vbyone_conf->phy_vswing & 0xf;
preem = vbyone_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL) {
LCDPR("vswing=0x%x, preem=0x%x\n",
vbyone_conf->phy_vswing, preem);
}
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
if (ext_pullup) {
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xff2027e0 | vswing);
} else {
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xf02027a0 | vswing);
}
lcd_phy_cntl_set_tl1(status, data32, 1, 0);
} else {
lcd_phy_cntl_set_tl1(status, data32, 1, 0);
}
}
static void lcd_mlvds_phy_set_tl1(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int data32 = 0, size, ckdi;
struct mlvds_config_s *mlvds_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
mlvds_conf = &pdrv->config.control.mlvds_cfg;
if (status) {
vswing = mlvds_conf->phy_vswing & 0xf;
preem = mlvds_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing);
ckdi = (mlvds_conf->pi_clk_sel << 12);
lcd_phy_cntl_set_tl1(status, data32, 0, ckdi);
} else {
lcd_phy_cntl_set_tl1(status, data32, 0, 0);
}
}
static void lcd_p2p_phy_set_tl1(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem, p2p_type;
unsigned int data32 = 0, size;
struct p2p_config_s *p2p_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
p2p_conf = &pdrv->config.control.p2p_cfg;
if (status) {
vswing = p2p_conf->phy_vswing & 0xf;
preem = p2p_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
p2p_type = p2p_conf->p2p_type & 0x1f;
switch (p2p_type) {
case P2P_CEDS:
case P2P_CMPI:
case P2P_ISP:
case P2P_EPI:
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xff2027a0 | vswing);
lcd_phy_cntl_set_tl1(status, data32, 1, 0);
break;
case P2P_CHPI: /* low common mode */
case P2P_CSPI:
case P2P_USIT:
size = sizeof(p2p_low_common_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = p2p_low_common_phy_preem_tl1[preem];
if (p2p_type == P2P_CHPI) {
/* weakly pull down */
data32 &= ~((1 << 19) | (1 << 3));
}
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0xfe60027f);
lcd_phy_cntl_set_tl1(status, data32, 1, 0);
break;
default:
LCDERR("%s: invalid p2p_type %d\n", __func__, p2p_type);
break;
}
} else {
lcd_phy_cntl_set_tl1(status, data32, 1, 0);
}
}
/*
* chreg: channel ctrl
* bypass: 1=bypass
* mode: 1=normal mode, 0=low common mode
* ckdi: clk phase for minilvds
*/
static void lcd_phy_cntl_set_t5(int status, unsigned int chreg, int bypass,
unsigned int mode, unsigned int ckdi)
{
unsigned int cntl15 = 0, cntl16 = 0;
unsigned int data = 0;
unsigned int tmp = 0;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
if (status) {
chreg |= ((lcd_phy_ctrl->ctrl_bit_on << 16) |
(lcd_phy_ctrl->ctrl_bit_on << 0));
if (bypass)
tmp |= ((1 << 18) | (1 << 2));
if (mode)
cntl15 = 0x00070000;
else
cntl15 = 0x000e0000;
cntl16 = ckdi | 0x80000000;
} else {
if (lcd_phy_ctrl->ctrl_bit_on)
data = 0;
else
data = 1;
chreg |= ((data << 16) | (data << 0));
cntl15 = 0;
cntl16 = 0;
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0);
}
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL15, cntl15);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL16, cntl16);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL8, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL1, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL9, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL2, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL10, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL3, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL11, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL4, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL12, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL6, chreg);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL13, tmp);
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL7, chreg);
}
static void lcd_lvds_phy_set_t5(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int data32 = 0, size;
struct lvds_config_s *lvds_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
lvds_conf = &pdrv->config.control.lvds_cfg;
if (status) {
vswing = lvds_conf->phy_vswing & 0xf;
preem = lvds_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing);
lcd_phy_cntl_set_t5(status, data32, 0, 1, 0);
} else {
lcd_phy_cntl_set_t5(status, data32, 0, 0, 0);
}
}
static void lcd_vbyone_phy_set_t5(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem, ext_pullup;
unsigned int data32 = 0, size;
struct vbyone_config_s *vbyone_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
vbyone_conf = &pdrv->config.control.vbyone_cfg;
if (status) {
ext_pullup = (vbyone_conf->phy_vswing >> 4) & 0x3;
vswing = vbyone_conf->phy_vswing & 0xf;
preem = vbyone_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL) {
LCDPR("vswing=0x%x, preem=0x%x\n",
vbyone_conf->phy_vswing, preem);
}
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
if (ext_pullup) {
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xff2027e0 | vswing);
} else {
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xf02027a0 | vswing);
}
lcd_phy_cntl_set_t5(status, data32, 1, 1, 0);
} else {
lcd_phy_cntl_set_t5(status, data32, 1, 0, 0);
}
}
static void lcd_mlvds_phy_set_t5(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int data32 = 0, size, ckdi;
struct mlvds_config_s *mlvds_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
mlvds_conf = &pdrv->config.control.mlvds_cfg;
if (status) {
vswing = mlvds_conf->phy_vswing & 0xf;
preem = mlvds_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14, 0xff2027e0 | vswing);
ckdi = (mlvds_conf->pi_clk_sel << 12);
lcd_phy_cntl_set_t5(status, data32, 0, 1, ckdi);
} else {
lcd_phy_cntl_set_t5(status, data32, 0, 0, 0);
}
}
static void lcd_p2p_phy_set_t5(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem, p2p_type, vcm_flag;
unsigned int data32 = 0, size;
struct p2p_config_s *p2p_conf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
p2p_conf = &pdrv->config.control.p2p_cfg;
if (status) {
vswing = p2p_conf->phy_vswing & 0xf;
preem = p2p_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
p2p_type = p2p_conf->p2p_type & 0x1f;
vcm_flag = (p2p_conf->p2p_type >> 5) & 0x1;
switch (p2p_type) {
case P2P_CEDS:
case P2P_CMPI:
case P2P_ISP:
case P2P_EPI:
size = sizeof(lvds_vx1_p2p_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = lvds_vx1_p2p_phy_preem_tl1[preem];
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xff2027a0 | vswing);
lcd_phy_cntl_set_t5(status, data32, 1, 1, 0);
break;
case P2P_CHPI: /* low common mode */
case P2P_CSPI:
case P2P_USIT:
size = sizeof(p2p_low_common_phy_preem_tl1) /
sizeof(unsigned int);
if (preem >= size) {
LCDERR("%s: invalid preem=0x%x, use default\n",
__func__, preem);
preem = 0x1;
}
data32 = p2p_low_common_phy_preem_tl1[preem];
if (p2p_type == P2P_CHPI) {
/* weakly pull down */
data32 &= ~((1 << 19) | (1 << 3));
}
if (vcm_flag) { /* 580mV */
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xe0600272);
} else {
lcd_ana_write(HHI_DIF_CSI_PHY_CNTL14,
0xfe60027f);
} /* default 385mV */
lcd_phy_cntl_set_t5(status, data32, 1, 0, 0);
break;
default:
LCDERR("%s: invalid p2p_type %d\n", __func__, p2p_type);
break;
}
} else {
lcd_phy_cntl_set_t5(status, data32, 1, 0, 0);
}
}
static void lcd_phy_cntl_set_t7(unsigned int flag,
unsigned int data_lane0_aux,
unsigned int data_lane1_aux,
unsigned int data_lane)
{
if (flag & (1 << 0)) {
lcd_ana_write(ANACTRL_DIF_PHY_CNTL1, data_lane0_aux);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL2, data_lane1_aux);
}
if (flag & (1 << 1))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL3, data_lane);
if (flag & (1 << 2))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL4, data_lane);
if (flag & (1 << 3))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL5, data_lane);
if (flag & (1 << 4))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL6, data_lane);
if (flag & (1 << 5))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL7, data_lane);
if (flag & (1 << 6))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL8, data_lane);
if (flag & (1 << 7))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL9, data_lane);
if (flag & (1 << 8)) {
lcd_ana_write(ANACTRL_DIF_PHY_CNTL10, data_lane0_aux);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL11, data_lane1_aux);
}
if (flag & (1 << 9))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL12, data_lane);
if (flag & (1 << 10))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL13, data_lane);
if (flag & (1 << 11))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL14, data_lane);
if (flag & (1 << 12))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL15, data_lane);
if (flag & (1 << 13))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL16, data_lane);
if (flag & (1 << 14))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL17, data_lane);
if (flag & (1 << 15))
lcd_ana_write(ANACTRL_DIF_PHY_CNTL18, data_lane);
}
static void lcd_lvds_phy_set_t7(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int flag, data_lane0_aux, data_lane1_aux, data_lane;
struct lvds_config_s *lvds_conf;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
lvds_conf = &pdrv->config.control.lvds_cfg;
switch (pdrv->index) {
case 0:
if (lvds_conf->dual_port) {
LCDERR("don't suuport lvds dual_port for drv_index %d\n",
pdrv->index);
return;
}
flag = 0x1f;
break;
case 1:
if (lvds_conf->dual_port) {
LCDERR("don't suuport lvds dual_port for drv_index %d\n",
pdrv->index);
return;
}
flag = (0x1f << 5);
break;
case 2:
if (lvds_conf->dual_port)
flag = (0x3ff << 5);
else
flag = (0x1f << 10);
break;
default:
LCDERR("invalid drv_index %d for lvds\n", pdrv->index);
return;
}
if (status) {
if (lcd_phy_ctrl->lane_lock & flag) {
LCDERR("phy lane already locked: 0x%x, invalid 0x%x\n",
lcd_phy_ctrl->lane_lock, flag);
return;
}
lcd_phy_ctrl->lane_lock |= flag;
vswing = lvds_conf->phy_vswing & 0xf;
preem = lvds_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
data_lane0_aux = 0x16430028;
data_lane1_aux = 0x0100ffff;
data_lane = 0x06530028 | (preem << 28);
lcd_phy_cntl_set_t7(flag, data_lane0_aux, data_lane1_aux, data_lane);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0x00406240 | vswing);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
} else {
lcd_phy_ctrl->lane_lock &= ~flag;
lcd_phy_cntl_set_t7(flag, 0, 0, 0);
if (lcd_phy_ctrl->lane_lock == 0)
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("phy lane_lock: 0x%x\n", lcd_phy_ctrl->lane_lock);
}
static void lcd_vbyone_phy_set_t7(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int flag, data_lane0_aux, data_lane1_aux, data_lane;
struct vbyone_config_s *vbyone_conf;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
switch (pdrv->index) {
case 0:
flag = 0xff;
break;
case 1:
flag = (0xff << 8);
break;
default:
LCDERR("invalid drv_index %d for vbyone\n", pdrv->index);
return;
}
vbyone_conf = &pdrv->config.control.vbyone_cfg;
if (status) {
if (lcd_phy_ctrl->lane_lock & flag) {
LCDERR("phy lane already locked: 0x%x, invalid 0x%x\n",
lcd_phy_ctrl->lane_lock, flag);
return;
}
lcd_phy_ctrl->lane_lock |= flag;
vswing = vbyone_conf->phy_vswing & 0xf;
preem = vbyone_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
data_lane0_aux = 0x26430028;
data_lane1_aux = 0x0000ffff;
data_lane = 0x06530028 | (preem << 28);
lcd_phy_cntl_set_t7(flag, data_lane0_aux, data_lane1_aux, data_lane);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0x00401640 | vswing);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
} else {
lcd_phy_ctrl->lane_lock &= ~flag;
lcd_phy_cntl_set_t7(flag, 0, 0, 0);
if (lcd_phy_ctrl->lane_lock == 0)
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("phy lane_lock: 0x%x\n", lcd_phy_ctrl->lane_lock);
}
static void lcd_mipi_phy_set_t7(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int flag, data_lane0_aux, data_lane1_aux, data_lane;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
switch (pdrv->index) {
case 0:
flag = 0x1f;
break;
case 1:
flag = (0x1f << 8);
break;
default:
LCDERR("invalid drv_index %d for mipi-dsi\n", pdrv->index);
return;
}
if (status) {
if (lcd_phy_ctrl->lane_lock & flag) {
LCDERR("phy lane already locked: 0x%x, invalid 0x%x\n",
lcd_phy_ctrl->lane_lock, flag);
return;
}
lcd_phy_ctrl->lane_lock |= flag;
data_lane0_aux = 0x022a0028;
data_lane1_aux = 0x0000ffcf;
data_lane = 0x022a0028;
lcd_phy_cntl_set_t7(flag, data_lane0_aux, data_lane1_aux, data_lane);
if (pdrv->index)
lcd_ana_write(ANACTRL_DIF_PHY_CNTL13, 0x822a0028);
else
lcd_ana_write(ANACTRL_DIF_PHY_CNTL4, 0x822a0028);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0x1e406253);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0xffff0000);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
} else {
lcd_phy_ctrl->lane_lock &= ~flag;
lcd_phy_cntl_set_t7(flag, 0, 0, 0);
if (lcd_phy_ctrl->lane_lock == 0)
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("phy lane_lock: 0x%x\n", lcd_phy_ctrl->lane_lock);
}
static void lcd_edp_phy_set_t7(struct aml_lcd_drv_s *pdrv, int status)
{
unsigned int vswing, preem;
unsigned int flag, data_lane0_aux, data_lane1_aux, data_lane;
struct edp_config_s *edp_conf;
if (!lcd_phy_ctrl)
return;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("%s: %d\n", __func__, status);
switch (pdrv->index) {
case 0:
flag = 0x1f;
break;
case 1:
flag = (0x1f << 8);
break;
default:
LCDERR("invalid drv_index %d for edp\n", pdrv->index);
return;
}
edp_conf = &pdrv->config.control.edp_cfg;
if (status) {
if (lcd_phy_ctrl->lane_lock & flag) {
LCDERR("phy lane already locked: 0x%x, invalid 0x%x\n",
lcd_phy_ctrl->lane_lock, flag);
return;
}
lcd_phy_ctrl->lane_lock |= flag;
vswing = edp_conf->phy_vswing & 0xf;
preem = edp_conf->phy_preem & 0xf;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("vswing=0x%x, preem=0x%x\n", vswing, preem);
data_lane0_aux = 0x46770038;
data_lane1_aux = 0x0000ffff;
data_lane = 0x06530028 | (preem << 28);
lcd_phy_cntl_set_t7(flag, data_lane0_aux, data_lane1_aux, data_lane);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0x00406240 | vswing);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
} else {
lcd_phy_ctrl->lane_lock &= ~flag;
lcd_phy_cntl_set_t7(flag, 0, 0, 0);
if (lcd_phy_ctrl->lane_lock == 0)
lcd_ana_write(ANACTRL_DIF_PHY_CNTL19, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL20, 0);
lcd_ana_write(ANACTRL_DIF_PHY_CNTL21, 0);
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("phy lane_lock: 0x%x\n", lcd_phy_ctrl->lane_lock);
}
void lcd_phy_set(struct aml_lcd_drv_s *pdrv, int status)
{
if (!pdrv->phy_set)
return;
pdrv->phy_set(pdrv, status);
}
struct lcd_phy_ctrl_s lcd_phy_ctrl_g12a = {
.lane_lock = 0,
.phy_set_lvds = NULL,
.phy_set_vx1 = NULL,
.phy_set_mlvds = NULL,
.phy_set_p2p = NULL,
.phy_set_mipi = lcd_mipi_phy_set_g12a,
.phy_set_edp = NULL,
};
struct lcd_phy_ctrl_s lcd_phy_ctrl_tl1 = {
.lane_lock = 0,
.phy_set_lvds = lcd_lvds_phy_set_tl1,
.phy_set_vx1 = lcd_vbyone_phy_set_tl1,
.phy_set_mlvds = lcd_mlvds_phy_set_tl1,
.phy_set_p2p = lcd_p2p_phy_set_tl1,
.phy_set_mipi = NULL,
.phy_set_edp = NULL,
};
struct lcd_phy_ctrl_s lcd_phy_ctrl_t5 = {
.lane_lock = 0,
.phy_set_lvds = lcd_lvds_phy_set_t5,
.phy_set_vx1 = lcd_vbyone_phy_set_t5,
.phy_set_mlvds = lcd_mlvds_phy_set_t5,
.phy_set_p2p = lcd_p2p_phy_set_t5,
.phy_set_mipi = NULL,
.phy_set_edp = NULL,
};
struct lcd_phy_ctrl_s lcd_phy_ctrl_t7 = {
.lane_lock = 0,
.phy_set_lvds = lcd_lvds_phy_set_t7,
.phy_set_vx1 = lcd_vbyone_phy_set_t7,
.phy_set_mlvds = NULL,
.phy_set_p2p = NULL,
.phy_set_mipi = lcd_mipi_phy_set_t7,
.phy_set_edp = lcd_edp_phy_set_t7,
};
int lcd_phy_probe(struct aml_lcd_drv_s *pdrv)
{
#ifdef CONFIG_AML_LCD_PXP
pdrv->phy_set = NULL;
return 0;
#endif
if (!lcd_phy_ctrl)
return 0;
switch (pdrv->config.basic.lcd_type) {
case LCD_LVDS:
pdrv->phy_set = lcd_phy_ctrl->phy_set_lvds;
break;
case LCD_VBYONE:
pdrv->phy_set = lcd_phy_ctrl->phy_set_vx1;
break;
case LCD_MLVDS:
pdrv->phy_set = lcd_phy_ctrl->phy_set_mlvds;
break;
case LCD_P2P:
pdrv->phy_set = lcd_phy_ctrl->phy_set_p2p;
break;
case LCD_MIPI:
pdrv->phy_set = lcd_phy_ctrl->phy_set_mipi;
break;
case LCD_EDP:
pdrv->phy_set = lcd_phy_ctrl->phy_set_edp;
break;
default:
pdrv->phy_set = NULL;
break;
}
return 0;
}
int lcd_phy_config_init(struct aml_lcd_data_s *pdata)
{
lcd_phy_ctrl = NULL;
switch (pdata->chip_type) {
case LCD_CHIP_G12A:
case LCD_CHIP_G12B:
case LCD_CHIP_SM1:
lcd_phy_ctrl = &lcd_phy_ctrl_g12a;
break;
case LCD_CHIP_TL1:
lcd_phy_ctrl = &lcd_phy_ctrl_tl1;
if (pdata->rev_type == 0xA || pdata->rev_type == 0xB)
lcd_phy_ctrl->ctrl_bit_on = 0;
else
lcd_phy_ctrl->ctrl_bit_on = 1;
break;
case LCD_CHIP_TM2:
lcd_phy_ctrl = &lcd_phy_ctrl_tl1;
if (pdata->rev_type == 0xA)
lcd_phy_ctrl->ctrl_bit_on = 0;
else
lcd_phy_ctrl->ctrl_bit_on = 1;
break;
case LCD_CHIP_T5:
case LCD_CHIP_T5D:
lcd_phy_ctrl = &lcd_phy_ctrl_t5;
break;
case LCD_CHIP_T7:
lcd_phy_ctrl = &lcd_phy_ctrl_t7;
break;
default:
break;
}
return 0;
}