blob: 5a242a698163a418255b8de2a9dc67f69d35765d [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <common.h>
#include <malloc.h>
#include <asm/arch/io.h>
#include <amlogic/media/vpp/vpp.h>
#include <amlogic/media/vout/lcd/aml_lcd.h>
#include "../lcd_reg.h"
#include "../lcd_common.h"
#include "lcd_tablet.h"
#include "mipi_dsi_util.h"
static int lcd_type_supported(struct lcd_config_s *pconf)
{
int lcd_type = pconf->basic.lcd_type;
int ret = -1;
switch (lcd_type) {
case LCD_TTL:
case LCD_LVDS:
case LCD_VBYONE:
case LCD_MIPI:
case LCD_EDP:
ret = 0;
break;
default:
LCDERR("invalid lcd type: %s(%d)\n",
lcd_type_type_to_str(lcd_type), lcd_type);
break;
}
return ret;
}
static void lcd_ttl_control_set(struct aml_lcd_drv_s *pdrv)
{
struct lcd_config_s *pconf = &pdrv->config;
unsigned int clk_pol, rb_swap, bit_swap;
clk_pol = pconf->control.ttl_cfg.clk_pol;
rb_swap = (pconf->control.ttl_cfg.swap_ctrl >> 1) & 1;
bit_swap = (pconf->control.ttl_cfg.swap_ctrl >> 0) & 1;
lcd_vcbus_setb(L_POL_CNTL_ADDR, clk_pol, 6, 1);
lcd_vcbus_setb(L_DUAL_PORT_CNTL_ADDR, rb_swap, 1, 1);
lcd_vcbus_setb(L_DUAL_PORT_CNTL_ADDR, bit_swap, 0, 1);
}
static void lcd_mipi_control_set(struct aml_lcd_drv_s *pdrv)
{
unsigned int bit_lane_sel;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
if (pdrv->data->chip_type == LCD_CHIP_T7) {
switch (pdrv->index) {
case 0:
bit_lane_sel = 0;
break;
case 1:
bit_lane_sel = 16;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n",
pdrv->index, __func__);
return;
}
// sel dphy lane
lcd_combo_dphy_setb(COMBO_DPHY_CNTL1, 0x0, bit_lane_sel, 10);
}
mipi_dsi_tx_ctrl(pdrv, 1);
}
static void lcd_mipi_disable(struct aml_lcd_drv_s *pdrv)
{
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
mipi_dsi_tx_ctrl(pdrv, 0);
}
static void lcd_edp_control_set(struct aml_lcd_drv_s *pdrv)
{
unsigned int reg_dphy_tx_ctrl0, reg_dphy_tx_ctrl1;
unsigned int bit_data_in_lvds, bit_data_in_edp, bit_lane_sel;
switch (pdrv->index) {
case 0:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
bit_data_in_lvds = 0;
bit_data_in_edp = 1;
bit_lane_sel = 0;
break;
case 1:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
bit_data_in_lvds = 2;
bit_data_in_edp = 3;
bit_lane_sel = 16;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__);
return;
}
// sel dphy data_in
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 0, bit_data_in_lvds, 1);
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 1, bit_data_in_edp, 1);
// sel dphy lane
lcd_combo_dphy_setb(COMBO_DPHY_CNTL1, 0x155, bit_lane_sel, 10);
// sel edp fifo clkdiv 20, enable lane
lcd_combo_dphy_write(reg_dphy_tx_ctrl0, ((0x4 << 5) | (0x1f << 16)));
// fifo enable
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 1, 6, 10);
// fifo wr enable
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 1, 7, 10);
edp_tx_ctrl(pdrv, 1);
}
static void lcd_edp_disable(struct aml_lcd_drv_s *pdrv)
{
unsigned int reg_dphy_tx_ctrl0, reg_dphy_tx_ctrl1;
switch (pdrv->index) {
case 0:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
break;
case 1:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__);
return;
}
edp_tx_ctrl(pdrv, 0);
// fifo wr disable
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 0, 7, 10);
// fifo disable
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 0, 6, 10);
// lane disable
lcd_combo_dphy_setb(reg_dphy_tx_ctrl0, 0, 16, 8);
}
static void lcd_lvds_clk_util_set(struct aml_lcd_drv_s *pdrv)
{
unsigned int reg_phy_tx_ctrl0, reg_phy_tx_ctrl1;
unsigned int bit_data_in_lvds, bit_data_in_edp, bit_lane_sel;
unsigned int phy_div, val_lane_sel, len_lane_sel;
if (pdrv->config.control.lvds_cfg.dual_port)
phy_div = 2;
else
phy_div = 1;
if (pdrv->data->chip_type == LCD_CHIP_T7) {
switch (pdrv->index) {
case 0:
reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
bit_data_in_lvds = 0;
bit_data_in_edp = 1;
bit_lane_sel = 0;
val_lane_sel = 0x155;
len_lane_sel = 10;
break;
case 1:
reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
bit_data_in_lvds = 2;
bit_data_in_edp = 3;
bit_lane_sel = 10;
val_lane_sel = 0x155;
len_lane_sel = 10;
break;
case 2:
reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL0;
reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL1;
bit_data_in_lvds = 4;
bit_data_in_edp = 0xff;
if (pdrv->config.control.lvds_cfg.dual_port) {
bit_lane_sel = 10;
val_lane_sel = 0xaaaaa;
len_lane_sel = 20;
} else {
bit_lane_sel = 20;
val_lane_sel = 0x2aa;
len_lane_sel = 10;
}
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n",
pdrv->index, __func__);
return;
}
// sel dphy data_in
if (bit_data_in_edp < 0xff)
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 0, bit_data_in_edp, 1);
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 1, bit_data_in_lvds, 1);
// sel dphy lane
lcd_combo_dphy_setb(COMBO_DPHY_CNTL1, val_lane_sel,
bit_lane_sel, len_lane_sel);
/* set fifo_clk_sel: div 7 */
lcd_combo_dphy_write(reg_phy_tx_ctrl0, (1 << 5));
/* set cntl_ser_en: 8-channel */
lcd_combo_dphy_setb(reg_phy_tx_ctrl0, 0x3ff, 16, 10);
/* decoupling fifo enable, gated clock enable */
lcd_combo_dphy_write(reg_phy_tx_ctrl1, (1 << 6) | (1 << 0));
/* decoupling fifo write enable after fifo enable */
lcd_combo_dphy_setb(reg_phy_tx_ctrl1, 1, 7, 1);
} else {
/* set fifo_clk_sel: div 7 */
lcd_ana_write(HHI_LVDS_TX_PHY_CNTL0, (1 << 6));
/* set cntl_ser_en: 8-channel to 1 */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12);
/* pn swap */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL0, 1, 2, 1);
/* decoupling fifo enable, gated clock enable */
lcd_ana_write(HHI_LVDS_TX_PHY_CNTL1,
(1 << 30) | ((phy_div - 1) << 25) | (1 << 24));
/* decoupling fifo write enable after fifo enable */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1);
}
}
static void lcd_lvds_control_set(struct aml_lcd_drv_s *pdrv)
{
unsigned int bit_num, pn_swap, port_swap, lane_reverse;
unsigned int dual_port, fifo_mode, lvds_repack;
unsigned int offset;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
lcd_lvds_clk_util_set(pdrv);
offset = pdrv->data->offset_venc_if[pdrv->index];
lvds_repack = (pdrv->config.control.lvds_cfg.lvds_repack) & 0x3;
pn_swap = (pdrv->config.control.lvds_cfg.pn_swap) & 0x1;
dual_port = (pdrv->config.control.lvds_cfg.dual_port) & 0x1;
port_swap = (pdrv->config.control.lvds_cfg.port_swap) & 0x1;
lane_reverse = (pdrv->config.control.lvds_cfg.lane_reverse) & 0x1;
switch (pdrv->config.basic.lcd_bits) {
case 10:
bit_num = 0;
break;
case 6:
bit_num = 2;
break;
case 8:
default:
bit_num = 1;
break;
}
if (dual_port)
fifo_mode = 0x3;
else
fifo_mode = 0x1;
if (pdrv->data->chip_type == LCD_CHIP_T7)
lcd_vcbus_write(LVDS_SER_EN + offset, 0xfff);
lcd_vcbus_write(LVDS_PACK_CNTL_ADDR + offset,
(lvds_repack << 0) | // repack //[1:0]
(0 << 3) | // reserve
(0 << 4) | // lsb first
(pn_swap << 5) | // pn swap
(dual_port << 6) | // dual port
(0 << 7) | // use tcon control
(bit_num << 8) | // 0:10bits, 1:8bits, 2:6bits, 3:4bits.
(0 << 10) | //r_select //0:R, 1:G, 2:B, 3:0
(1 << 12) | //g_select //0:R, 1:G, 2:B, 3:0
(2 << 14)); //b_select //0:R, 1:G, 2:B, 3:0;
/* lvsd swap */
switch (pdrv->data->chip_type) {
case LCD_CHIP_TL1:
case LCD_CHIP_TM2:
/* lvds channel: //tx 12 channels
* 0: d0_a
* 1: d1_a
* 2: d2_a
* 3: clk_a
* 4: d3_a
* 5: d4_a
* 6: d0_b
* 7: d1_b
* 8: d2_b
* 9: clk_b
* a: d3_b
* b: d4_b
*/
if (port_swap) {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0, 0x456789ab);
lcd_vcbus_write(P2P_CH_SWAP1, 0x0123);
} else {
lcd_vcbus_write(P2P_CH_SWAP0, 0x10ba9876);
lcd_vcbus_write(P2P_CH_SWAP1, 0x5432);
}
} else {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0, 0xab012345);
lcd_vcbus_write(P2P_CH_SWAP1, 0x6789);
} else {
lcd_vcbus_write(P2P_CH_SWAP0, 0x76543210);
lcd_vcbus_write(P2P_CH_SWAP1, 0xba98);
}
}
break;
case LCD_CHIP_T5:
case LCD_CHIP_T5D:
/* lvds channel: //tx 12 channels
* 0: d0_a
* 1: d1_a
* 2: d2_a
* 3: clk_a
* 4: d3_a
* 5: d4_a
* 6: d0_b
* 7: d1_b
* 8: d2_b
* 9: clk_b
* a: d3_b
* b: d4_b
*/
if (port_swap) {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0, 0x345789ab);
lcd_vcbus_write(P2P_CH_SWAP1, 0x0612);
} else {
lcd_vcbus_write(P2P_CH_SWAP0, 0x210a9876);
lcd_vcbus_write(P2P_CH_SWAP1, 0x5b43);
}
} else {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0, 0xab12345);
lcd_vcbus_write(P2P_CH_SWAP1, 0x60789);
} else {
lcd_vcbus_write(P2P_CH_SWAP0, 0x87643210);
lcd_vcbus_write(P2P_CH_SWAP1, 0xb5a9);
}
}
break;
case LCD_CHIP_T7:
/* lvds channel: //tx 12 channels
* 0: d0_a
* 1: d1_a
* 2: d2_a
* 3: clk_a
* 4: d3_a
* 5: d4_a
* 6: d0_b
* 7: d1_b
* 8: d2_b
* 9: clk_b
* a: d3_b
* b: d4_b
*/
if (port_swap) {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0 + offset, 0x345789ab);
lcd_vcbus_write(P2P_CH_SWAP1 + offset, 0x0612);
} else {
lcd_vcbus_write(P2P_CH_SWAP0 + offset, 0x210a9876);
lcd_vcbus_write(P2P_CH_SWAP1 + offset, 0x5b43);
}
} else {
if (lane_reverse) {
lcd_vcbus_write(P2P_CH_SWAP0 + offset, 0xab12345);
lcd_vcbus_write(P2P_CH_SWAP1 + offset, 0x60789);
} else {
lcd_vcbus_write(P2P_CH_SWAP0 + offset, 0x87643210);
lcd_vcbus_write(P2P_CH_SWAP1 + offset, 0xb5a9);
}
}
lcd_vcbus_write(P2P_BIT_REV + offset, 2);
break;
default:
break;
}
lcd_vcbus_write(LVDS_GEN_CNTL + offset,
(lcd_vcbus_read(LVDS_GEN_CNTL + offset) | (1 << 4) | (fifo_mode << 0)));
lcd_vcbus_setb(LVDS_GEN_CNTL + offset, 1, 3, 1);
}
static void lcd_lvds_disable(struct aml_lcd_drv_s *pdrv)
{
unsigned int reg_dphy_tx_ctrl0, reg_dphy_tx_ctrl1, offset = 0;
if (pdrv->data->chip_type == LCD_CHIP_T7) {
switch (pdrv->index) {
case 0:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
break;
case 1:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
break;
case 2:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL1;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__);
return;
}
offset = pdrv->data->offset_venc_if[pdrv->index];
/* disable lvds fifo */
lcd_vcbus_setb(LVDS_GEN_CNTL + offset, 0, 3, 1);
/* disable fifo */
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 0, 6, 2);
/* disable lane */
lcd_combo_dphy_setb(reg_dphy_tx_ctrl0, 0, 16, 10);
} else {
/* disable lvds fifo */
lcd_vcbus_setb(LVDS_GEN_CNTL, 0, 3, 1);
/* disable fifo */
lcd_clk_setb(HHI_LVDS_TX_PHY_CNTL1, 0, 30, 2);
/* disable lane */
lcd_clk_setb(HHI_LVDS_TX_PHY_CNTL0, 0, 16, 12);
}
}
static void lcd_vbyone_sync_pol(unsigned int offset, int hsync_pol, int vsync_pol)
{
lcd_vcbus_setb(VBO_VIN_CTRL + offset, hsync_pol, 4, 1);
lcd_vcbus_setb(VBO_VIN_CTRL + offset, vsync_pol, 5, 1);
lcd_vcbus_setb(VBO_VIN_CTRL + offset, hsync_pol, 6, 1);
lcd_vcbus_setb(VBO_VIN_CTRL + offset, vsync_pol, 7, 1);
}
static void lcd_vbyone_clk_util_set(struct aml_lcd_drv_s *pdrv)
{
unsigned int lcd_bits, div_sel, phy_div;
unsigned int reg_phy_tx_ctrl0, reg_phy_tx_ctrl1;
unsigned int bit_data_in_lvds, bit_data_in_edp, bit_lane_sel;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
phy_div = pdrv->config.control.vbyone_cfg.phy_div;
lcd_bits = pdrv->config.basic.lcd_bits;
switch (lcd_bits) {
case 6:
div_sel = 0;
break;
case 8:
div_sel = 2;
break;
case 10:
default:
div_sel = 3;
break;
}
if (pdrv->data->chip_type == LCD_CHIP_T7) {
switch (pdrv->index) {
case 0:
reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
bit_data_in_lvds = 0;
bit_data_in_edp = 1;
bit_lane_sel = 0;
break;
case 1:
reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
bit_data_in_lvds = 2;
bit_data_in_edp = 3;
bit_lane_sel = 16;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n",
pdrv->index, __func__);
return;
}
// sel dphy data_in
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 0, bit_data_in_edp, 1);
lcd_combo_dphy_setb(COMBO_DPHY_CNTL0, 1, bit_data_in_lvds, 1);
// sel dphy lane
lcd_combo_dphy_setb(COMBO_DPHY_CNTL1, 0x5555, bit_lane_sel, 16);
/* set fifo_clk_sel: div 7 */
lcd_combo_dphy_write(reg_phy_tx_ctrl0, (div_sel << 5));
/* set cntl_ser_en: 8-channel to 1 */
lcd_combo_dphy_setb(reg_phy_tx_ctrl0, 0xff, 16, 8);
/* decoupling fifo enable, gated clock enable */
lcd_combo_dphy_write(reg_phy_tx_ctrl1, (1 << 6) | (1 << 0));
/* decoupling fifo write enable after fifo enable */
lcd_combo_dphy_setb(reg_phy_tx_ctrl1, 1, 7, 1);
} else {
/* set fifo_clk_sel: div 10 */
lcd_ana_write(HHI_LVDS_TX_PHY_CNTL0, (div_sel << 6));
/* set cntl_ser_en: 8-channel to 1 */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL0, 0xfff, 16, 12);
/* pn swap */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL0, 1, 2, 1);
/* decoupling fifo enable, gated clock enable */
lcd_ana_write(HHI_LVDS_TX_PHY_CNTL1,
(1 << 30) | ((phy_div - 1) << 25) | (1 << 24));
/* decoupling fifo write enable after fifo enable */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL1, 1, 31, 1);
}
}
static int lcd_vbyone_lanes_set(unsigned int offset, int lane_num, int byte_mode,
int region_num, int hsize, int vsize)
{
int sublane_num;
int region_size[4];
int tmp;
switch (lane_num) {
case 1:
case 2:
case 4:
case 8:
break;
default:
return -1;
}
switch (region_num) {
case 1:
case 2:
case 4:
break;
default:
return -1;
}
if (lane_num % region_num)
return -1;
switch (byte_mode) {
case 3:
case 4:
break;
default:
return -1;
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL) {
LCDPR("byte_mode=%d, lane_num=%d, region_num=%d\n",
byte_mode, lane_num, region_num);
}
sublane_num = lane_num / region_num; /* lane num in each region */
lcd_vcbus_setb(VBO_LANES + offset, (lane_num - 1), 0, 3);
lcd_vcbus_setb(VBO_LANES + offset, (region_num - 1), 4, 2);
lcd_vcbus_setb(VBO_LANES + offset, (sublane_num - 1), 8, 3);
lcd_vcbus_setb(VBO_LANES + offset, (byte_mode - 1), 11, 2);
if (region_num > 1) {
region_size[3] = (hsize / lane_num) * sublane_num;
tmp = (hsize % lane_num);
region_size[0] = region_size[3] + (((tmp / sublane_num) > 0) ?
sublane_num : (tmp % sublane_num));
region_size[1] = region_size[3] + (((tmp / sublane_num) > 1) ?
sublane_num : (tmp % sublane_num));
region_size[2] = region_size[3] + (((tmp / sublane_num) > 2) ?
sublane_num : (tmp % sublane_num));
lcd_vcbus_write(VBO_REGION_00 + offset, region_size[0]);
lcd_vcbus_write(VBO_REGION_01 + offset, region_size[1]);
lcd_vcbus_write(VBO_REGION_02 + offset, region_size[2]);
lcd_vcbus_write(VBO_REGION_03 + offset, region_size[3]);
}
lcd_vcbus_write(VBO_ACT_VSIZE + offset, vsize);
/* different from FBC code!!! */
/* lcd_vcbus_setb(VBO_CTRL_H + offset,0x80,11,5); */
/* different from simulation code!!! */
lcd_vcbus_setb(VBO_CTRL_H + offset, 0x0, 0, 4);
lcd_vcbus_setb(VBO_CTRL_H + offset, 0x1, 9, 1);
/* lcd_vcbus_setb(VBO_CTRL_L + offset,enable,0,1); */
return 0;
}
static void lcd_vbyone_control_set(struct aml_lcd_drv_s *pdrv)
{
int lane_count, byte_mode, region_num, hsize, vsize;
/* int color_fmt; */
int vin_color, vin_bpp;
unsigned int offset;
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s\n", pdrv->index, __func__);
offset = pdrv->data->offset_venc_if[pdrv->index];
hsize = pdrv->config.basic.h_active;
vsize = pdrv->config.basic.v_active;
lane_count = pdrv->config.control.vbyone_cfg.lane_count; /* 8 */
region_num = pdrv->config.control.vbyone_cfg.region_num; /* 2 */
byte_mode = pdrv->config.control.vbyone_cfg.byte_mode; /* 4 */
/* color_fmt = pdrv->config.control.vbyone_cfg.color_fmt; // 4 */
vin_color = 4; /* fixed RGB */
switch (pdrv->config.basic.lcd_bits) {
case 6:
vin_bpp = 2; /* 18bbp 4:4:4 */
break;
case 8:
vin_bpp = 1; /* 24bbp 4:4:4 */
break;
case 10:
default:
vin_bpp = 0; /* 30bbp 4:4:4 */
break;
}
lcd_vbyone_clk_util_set(pdrv);
/* set Vbyone vin color format */
lcd_vcbus_setb(VBO_VIN_CTRL + offset, vin_color, 8, 3);
lcd_vcbus_setb(VBO_VIN_CTRL + offset, vin_bpp, 11, 2);
lcd_vbyone_lanes_set(offset, lane_count, byte_mode, region_num, hsize, vsize);
/*set hsync/vsync polarity to let the polarity is low active
inside the VbyOne */
lcd_vbyone_sync_pol(offset, 0, 0);
/* below line copy from simulation */
/* gate the input when vsync asserted */
lcd_vcbus_setb(VBO_VIN_CTRL + offset, 1, 0, 2);
/* lcd_vcbus_write(VBO_VBK_CTRL_0 + offset,0x13);
//lcd_vcbus_write(VBO_VBK_CTRL_1 + offset,0x56);
//lcd_vcbus_write(VBO_HBK_CTRL + offset,0x3478);
//lcd_vcbus_setb(VBO_PXL_CTRL + offset,0x2,0,4);
//lcd_vcbus_setb(VBO_PXL_CTRL + offset,0x3,VBO_PXL_CTR1_BIT,VBO_PXL_CTR1_WID);
//set_vbyone_ctlbits(1,0,0); */
/* VBO_RGN_GEN clk always on */
lcd_vcbus_setb(VBO_GCLK_MAIN + offset, 2, 2, 2);
/* PAD select: */
if ((lane_count == 1) || (lane_count == 2))
lcd_vcbus_setb(LCD_PORT_SWAP + offset, 1, 9, 2);
else if (lane_count == 4)
lcd_vcbus_setb(LCD_PORT_SWAP + offset, 2, 9, 2);
else
lcd_vcbus_setb(LCD_PORT_SWAP + offset, 0, 9, 2);
/* lcd_vcbus_setb(LCD_PORT_SWAP + offset, 1, 8, 1);//reverse lane output order */
lcd_vbyone_hw_filter(pdrv, 1);
lcd_vcbus_setb(VBO_INSGN_CTRL + offset, 0, 2, 2);
lcd_vcbus_setb(VBO_CTRL_L + offset, 1, 0, 1);
lcd_vbyone_wait_timing_stable(pdrv);
lcd_vbyone_sw_reset(pdrv);
/* training hold */
if ((pdrv->config.control.vbyone_cfg.ctrl_flag) & 0x4)
lcd_vbyone_cdr_training_hold(pdrv, 1);
}
static void lcd_vbyone_disable(struct aml_lcd_drv_s *pdrv)
{
unsigned int reg_dphy_tx_ctrl0, reg_dphy_tx_ctrl1, offset;
if (pdrv->data->chip_type == LCD_CHIP_T7) {
switch (pdrv->index) {
case 0:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1;
break;
case 1:
reg_dphy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0;
reg_dphy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1;
break;
default:
LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__);
return;
}
offset = pdrv->data->offset_venc_if[pdrv->index];
lcd_vcbus_setb(VBO_CTRL_L + offset, 0, 0, 1);
/* clear insig setting */
lcd_vcbus_setb(VBO_INSGN_CTRL + offset, 0, 2, 1);
lcd_vcbus_setb(VBO_INSGN_CTRL + offset, 0, 0, 1);
/* disable fifo */
lcd_combo_dphy_setb(reg_dphy_tx_ctrl1, 0, 6, 2);
/* disable lane */
lcd_combo_dphy_setb(reg_dphy_tx_ctrl0, 0, 16, 8);
} else {
lcd_vcbus_setb(VBO_CTRL_L, 0, 0, 1);
/* clear insig setting */
lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 2, 1);
lcd_vcbus_setb(VBO_INSGN_CTRL, 0, 0, 1);
/* disable fifo */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL1, 0, 30, 2);
/* disable lane */
lcd_ana_setb(HHI_LVDS_TX_PHY_CNTL0, 0, 16, 12);
}
}
void lcd_tablet_config_update(struct aml_lcd_drv_s *pdrv)
{
/* update interface timing */
switch (pdrv->config.basic.lcd_type) {
case LCD_VBYONE:
lcd_vbyone_config_set(pdrv);
break;
case LCD_MIPI:
lcd_mipi_dsi_config_set(pdrv);
break;
case LCD_EDP:
lcd_edp_config_set(pdrv);
break;
default:
break;
}
}
void lcd_tablet_driver_init_pre(struct aml_lcd_drv_s *pdrv)
{
int ret;
LCDPR("[%d]: tablet driver init(ver %s): %s\n",
pdrv->index,
LCD_DRV_VERSION,
lcd_type_type_to_str(pdrv->config.basic.lcd_type));
ret = lcd_type_supported(&pdrv->config);
if (ret)
return;
lcd_set_clk(pdrv);
lcd_set_venc(pdrv);
}
int lcd_tablet_driver_init(struct aml_lcd_drv_s *pdrv)
{
int ret;
ret = lcd_type_supported(&pdrv->config);
if (ret)
return -1;
/* init driver */
switch (pdrv->config.basic.lcd_type) {
case LCD_TTL:
lcd_ttl_control_set(pdrv);
lcd_pinmux_set(pdrv, 1);
break;
case LCD_LVDS:
lcd_lvds_control_set(pdrv);
lcd_phy_set(pdrv, 1);
break;
case LCD_VBYONE:
lcd_pinmux_set(pdrv, 1);
lcd_vbyone_control_set(pdrv);
lcd_vbyone_wait_hpd(pdrv);
lcd_phy_set(pdrv, 1);
lcd_vbyone_wait_stable(pdrv);
break;
case LCD_MIPI:
lcd_phy_set(pdrv, 1);
lcd_mipi_control_set(pdrv);
break;
case LCD_EDP:
lcd_pinmux_set(pdrv, 1);
lcd_phy_set(pdrv, 1);
lcd_edp_control_set(pdrv);
break;
default:
break;
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s finished\n", pdrv->index, __func__);
return 0;
}
void lcd_tablet_driver_disable(struct aml_lcd_drv_s *pdrv)
{
int ret;
LCDPR("[%d]: disable driver\n", pdrv->index);
ret = lcd_type_supported(&pdrv->config);
if (ret)
return;
switch (pdrv->config.basic.lcd_type) {
case LCD_TTL:
lcd_pinmux_set(pdrv, 0);
break;
case LCD_LVDS:
lcd_phy_set(pdrv, 0);
lcd_lvds_disable(pdrv);
break;
case LCD_VBYONE:
lcd_phy_set(pdrv, 0);
lcd_pinmux_set(pdrv, 0);
lcd_vbyone_disable(pdrv);
break;
case LCD_MIPI:
mipi_dsi_link_off(pdrv);
lcd_phy_set(pdrv, 0);
lcd_mipi_disable(pdrv);
break;
case LCD_EDP:
lcd_edp_disable(pdrv);
lcd_phy_set(pdrv, 0);
lcd_pinmux_set(pdrv, 0);
break;
default:
break;
}
if (lcd_debug_print_flag & LCD_DBG_PR_NORMAL)
LCDPR("[%d]: %s finished\n", pdrv->index, __func__);
}