DO NOT SUBMIT. Estelle display driver. Change-Id: I5f41d0fb144fb6d404680f09aece4e2e47d15a0e
diff --git a/system/dev/board/astro/astro-display.c b/system/dev/board/astro/astro-display.c index e334f5b..eb64f7a 100644 --- a/system/dev/board/astro/astro-display.c +++ b/system/dev/board/astro/astro-display.c
@@ -16,9 +16,30 @@ static const pbus_mmio_t display_mmios[] = { { + // Canvas .base = S905D2_DMC_BASE, .length = S905D2_DMC_LENGTH, }, + { + // DSI Host Controller + .base = S905D2_MIPI_DSI_BASE, + .length = S905D2_MIPI_DSI_LENGTH, + }, + { + // DSI PHY + .base = S905D2_DSI_PHY_BASE, + .length = S905D2_DSI_PHY_LENGTH, + }, + { + // HHI + .base = S905D2_HIU_BASE, + .length = S905D2_HIU_LENGTH, + }, + { + // VBUS/VPU + .base = S905D2_VPU_BASE, + .length = S905D2_VPU_LENGTH, + }, }; static const pbus_irq_t display_irqs[] = {
diff --git a/system/dev/display/astro-display/aml_dsi.h b/system/dev/display/astro-display/aml_dsi.h new file mode 100644 index 0000000..3811e53 --- /dev/null +++ b/system/dev/display/astro-display/aml_dsi.h
@@ -0,0 +1,864 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +/* TOP MIPI_DSI AML Registers */ +#define MIPI_DSI_TOP_SW_RESET (0xF0 << 2) +#define MIPI_DSI_TOP_CLK_CNTL (0xF1 << 2) +#define MIPI_DSI_TOP_CNTL (0xF2 << 2) +#define MIPI_DSI_TOP_SUSPEND_CNTL (0xF3 << 2) +#define MIPI_DSI_TOP_SUSPEND_LINE (0xF4 << 2) +#define MIPI_DSI_TOP_SUSPEND_PIX (0xF5 << 2) +#define MIPI_DSI_TOP_MEAS_CNTL (0xF6 << 2) +#define MIPI_DSI_TOP_STAT (0xF7 << 2) +#define MIPI_DSI_TOP_MEAS_STAT_TE0 (0xF8 << 2) +#define MIPI_DSI_TOP_MEAS_STAT_TE1 (0xF9 << 2) +#define MIPI_DSI_TOP_MEAS_STAT_VS0 (0xFA << 2) +#define MIPI_DSI_TOP_MEAS_STAT_VS1 (0xFB << 2) +#define MIPI_DSI_TOP_INTR_CNTL_STAT (0xFC << 2) +#define MIPI_DSI_TOP_MEM_PD (0xFD << 2) + +#define MIPI_DSI_PHY_CTRL (0x000 << 2) +#define MIPI_DSI_CHAN_CTRL (0x001 << 2) +#define MIPI_DSI_CHAN_STS (0x002 << 2) +#define MIPI_DSI_CLK_TIM (0x003 << 2) +#define MIPI_DSI_HS_TIM (0x004 << 2) +#define MIPI_DSI_LP_TIM (0x005 << 2) +#define MIPI_DSI_ANA_UP_TIM (0x006 << 2) +#define MIPI_DSI_INIT_TIM (0x007 << 2) +#define MIPI_DSI_WAKEUP_TIM (0x008 << 2) +#define MIPI_DSI_LPOK_TIM (0x009 << 2) +#define MIPI_DSI_LP_WCHDOG (0x00a << 2) +#define MIPI_DSI_ANA_CTRL (0x00b << 2) +#define MIPI_DSI_CLK_TIM1 (0x00c << 2) +#define MIPI_DSI_TURN_WCHDOG (0x00d << 2) +#define MIPI_DSI_ULPS_CHECK (0x00e << 2) +#define MIPI_DSI_TEST_CTRL0 (0x00f << 2) +#define MIPI_DSI_TEST_CTRL1 (0x010 << 2) +/* ************************************************************* + * Define MIPI DSI Default config + */ +/* Range [0,3] */ +#define MIPI_DSI_VIRTUAL_CHAN_ID 0 +/* Define DSI command transfer type: high speed or low power */ +#define MIPI_DSI_CMD_TRANS_TYPE DCS_TRANS_LP +/* Define if DSI command need ack: req_ack or no_ack */ +#define MIPI_DSI_DCS_ACK_TYPE MIPI_DSI_DCS_NO_ACK + +#define MIPI_DSI_TEAR_SWITCH MIPI_DCS_DISABLE_TEAR + +/* PLL_CNTL bit: GP0 */ +#define LCD_PLL_LOCK_GP0_G12A (31) +#define LCD_PLL_EN_GP0_G12A (28) +#define LCD_PLL_RST_GP0_G12A (29) +#define LCD_PLL_OD_GP0_G12A (16) +#define LCD_PLL_N_GP0_G12A (10) +#define LCD_PLL_M_GP0_G12A (0) + +/* ******** frequency limit (unit: kHz) ******** */ +#define PLL_FRAC_OD_FB_GP0_G12A 0 +#define SS_LEVEL_MAX_GP0_G12A 5 +#define PLL_FRAC_RANGE_GP0_G12A (1 << 17) +#define PLL_OD_SEL_MAX_GP0_G12A 5 +#define PLL_VCO_MIN_GP0_G12A (3000 * 1000) +#define PLL_VCO_MAX_GP0_G12A (6000 * 1000) + +/* PLL_CNTL bit: hpll */ +#define LCD_PLL_LOCK_HPLL_G12A (31) +#define LCD_PLL_EN_HPLL_G12A (28) +#define LCD_PLL_RST_HPLL_G12A (29) +#define LCD_PLL_N_HPLL_G12A (10) +#define LCD_PLL_M_HPLL_G12A (0) + +#define LCD_PLL_OD3_HPLL_G12A (20) +#define LCD_PLL_OD2_HPLL_G12A (18) +#define LCD_PLL_OD1_HPLL_G12A (16) + +/* ******** frequency limit (unit: kHz) ******** */ +#define PLL_FRAC_OD_FB_HPLL_G12A 0 +#define SS_LEVEL_MAX_HPLL_G12A 1 +#define PLL_FRAC_RANGE_HPLL_G12A (1 << 17) +#define PLL_OD_SEL_MAX_HPLL_G12A 3 +#define PLL_VCO_MIN_HPLL_G12A (3000 * 1000) +#define PLL_VCO_MAX_HPLL_G12A (6000 * 1000) + +/* video */ +#define PLL_M_MIN_G12A 2 +#define PLL_M_MAX_G12A 511 +#define PLL_N_MIN_G12A 1 +#define PLL_N_MAX_G12A 1 +#define PLL_FREF_MIN_G12A (5 * 1000) +#define PLL_FREF_MAX_G12A (25 * 1000) +#define CRT_VID_CLK_IN_MAX_G12A (6000 * 1000) +#define ENCL_CLK_IN_MAX_G12A (200 * 1000) + +#define MIPI_DSI_COLOR_24BIT (0x5) + +#define MIPI_PHY_CLK_MAX (1000) +#define MAX_ERROR (2 * 1000) +#define CRT_VID_DIV_MAX (255) + +/* ********************************** + * clk parameter bit define + * pll_ctrl, div_ctrl, clk_ctrl + * ********************************** */ +/* ******** pll_ctrl ******** */ +#define PLL_CTRL_OD3 20 /* [21:20] */ +#define PLL_CTRL_OD2 18 /* [19:18] */ +#define PLL_CTRL_OD1 16 /* [17:16] */ +#define PLL_CTRL_N 9 /* [13:9] */ +#define PLL_CTRL_M 0 /* [8:0] */ + +/* ******** div_ctrl ******** */ +#define DIV_CTRL_EDP_DIV1 24 /* [26:24] */ +#define DIV_CTRL_EDP_DIV0 20 /* [23:20] */ +#define DIV_CTRL_DIV_SEL 8 /* [15:8] */ +#define DIV_CTRL_XD 0 /* [7:0] */ + +/* ******** clk_ctrl ******** */ +#define CLK_CTRL_LEVEL 28 /* [30:28] */ +#define CLK_CTRL_FRAC 0 /* [18:0] */ + +/* ******** MIPI_DSI_PHY ******** */ +/* bit[15:11] */ +#define MIPI_PHY_LANE_BIT 11 +#define MIPI_PHY_LANE_WIDTH 5 + +/* MIPI-DSI */ +#define DSI_LANE_0 (1 << 4) +#define DSI_LANE_1 (1 << 3) +#define DSI_LANE_CLK (1 << 2) +#define DSI_LANE_2 (1 << 1) +#define DSI_LANE_3 (1 << 0) +#define DSI_LANE_COUNT_1 (DSI_LANE_CLK | DSI_LANE_0) +#define DSI_LANE_COUNT_2 (DSI_LANE_CLK | DSI_LANE_0 | DSI_LANE_1) +#define DSI_LANE_COUNT_3 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2) +#define DSI_LANE_COUNT_4 (DSI_LANE_CLK | DSI_LANE_0 |\ + DSI_LANE_1 | DSI_LANE_2 | DSI_LANE_3) + +#define OPERATION_VIDEO_MODE 0 +#define OPERATION_COMMAND_MODE 1 + +#define SYNC_PULSE 0x0 +#define SYNC_EVENT 0x1 +#define BURST_MODE 0x2 + +/* command config */ +#define DSI_CMD_SIZE_INDEX 1 /* byte[1] */ +#define DSI_GPIO_INDEX 2 /* byte[2] */ + +#define DSI_INIT_ON_MAX 100 +#define DSI_INIT_OFF_MAX 30 + +/* **** DPHY timing parameter Value (unit: 0.01ns) **** */ +/* >100ns (4M) */ +#define DPHY_TIME_LP_TESC(ui) (250 * 100) +/* >50ns */ +#define DPHY_TIME_LP_LPX(ui) (100 * 100) +/* (lpx, 2*lpx) */ +#define DPHY_TIME_LP_TA_SURE(ui) DPHY_TIME_LP_LPX(ui) +/* 4*lpx */ +#define DPHY_TIME_LP_TA_GO(ui) (4 * DPHY_TIME_LP_LPX(ui)) +/* 5*lpx */ +#define DPHY_TIME_LP_TA_GETX(ui) (5 * DPHY_TIME_LP_LPX(ui)) +/* >100ns */ +#define DPHY_TIME_HS_EXIT(ui) (110 * 100) +/* max(8*ui, 60+4*ui), (teot)<105+12*ui */ +#define DPHY_TIME_HS_TRAIL(ui) ((ui > (60 * 100 / 4)) ? \ + (8 * ui) : ((60 * 100) + 4 * ui)) +/* (40+4*ui, 85+6*ui) */ +#define DPHY_TIME_HS_PREPARE(ui) (50 * 100 + 4 * ui) +/* hs_prepare+hs_zero >145+10*ui */ +#define DPHY_TIME_HS_ZERO(ui) (160 * 100 + 10 * ui - \ + DPHY_TIME_HS_PREPARE(ui)) +/* >60ns, (teot)<105+12*ui */ +#define DPHY_TIME_CLK_TRAIL(ui) (70 * 100) +/* >60+52*ui */ +#define DPHY_TIME_CLK_POST(ui) (2 * (60 * 100 + 52 * ui)) +/* (38, 95) */ +#define DPHY_TIME_CLK_PREPARE(ui) (50 * 100) +/* clk_prepare+clk_zero > 300 */ +#define DPHY_TIME_CLK_ZERO(ui) (320 * 100 - DPHY_TIME_CLK_PREPARE(ui)) +/* >8*ui */ +#define DPHY_TIME_CLK_PRE(ui) (10 * ui) +/* >100us */ +#define DPHY_TIME_INIT(ui) (110 * 1000 * 100) +/* >1ms */ +#define DPHY_TIME_WAKEUP(ui) (1020 * 1000 * 100) + +/* MIPI DSI Relative REGISTERs Definitions */ +/* For MIPI_DSI_TOP_CNTL */ +#define BIT_DPI_COLOR_MODE 20 +#define BIT_IN_COLOR_MODE 16 +#define BIT_CHROMA_SUBSAMPLE 14 +#define BIT_COMP2_SEL 12 +#define BIT_COMP1_SEL 10 +#define BIT_COMP0_SEL 8 +#define BIT_DE_POL 6 +#define BIT_HSYNC_POL 5 +#define BIT_VSYNC_POL 4 +#define BIT_DPICOLORM 3 +#define BIT_DPISHUTDN 2 +#define BIT_EDPITE_INTR_PULSE 1 +#define BIT_ERR_INTR_PULSE 0 + +/* For MIPI_DSI_DWC_CLKMGR_CFG_OS */ +#define BIT_TO_CLK_DIV 8 +#define BIT_TX_ESC_CLK_DIV 0 + +/* For MIPI_DSI_DWC_PCKHDL_CFG_OS */ +#define BIT_CRC_RX_EN 4 +#define BIT_ECC_RX_EN 3 +#define BIT_BTA_EN 2 +#define BIT_EOTP_RX_EN 1 +#define BIT_EOTP_TX_EN 0 + +/* For MIPI_DSI_DWC_VID_MODE_CFG_OS */ +#define BIT_LP_CMD_EN 15 +#define BIT_FRAME_BTA_ACK_EN 14 +#define BIT_LP_HFP_EN 13 +#define BIT_LP_HBP_EN 12 +#define BIT_LP_VCAT_EN 11 +#define BIT_LP_VFP_EN 10 +#define BIT_LP_VBP_EN 9 +#define BIT_LP_VSA_EN 8 +#define BIT_VID_MODE_TYPE 0 + +/* For MIPI_DSI_DWC_PHY_STATUS_OS */ +#define BIT_PHY_ULPSACTIVENOT3LANE 12 +#define BIT_PHY_STOPSTATE3LANE 11 +#define BIT_PHY_ULPSACTIVENOT2LANE 10 +#define BIT_PHY_STOPSTATE2LANE 9 +#define BIT_PHY_ULPSACTIVENOT1LANE 8 +#define BIT_PHY_STOPSTATE1LANE 7 +#define BIT_PHY_RXULPSESC0LANE 6 +#define BIT_PHY_ULPSACTIVENOT0LANE 5 +#define BIT_PHY_STOPSTATE0LANE 4 +#define BIT_PHY_ULPSACTIVENOTCLK 3 +#define BIT_PHY_STOPSTATECLKLANE 2 +#define BIT_PHY_DIRECTION 1 +#define BIT_PHY_LOCK 0 + +/* For MIPI_DSI_DWC_PHY_IF_CFG_OS */ +#define BIT_PHY_STOP_WAIT_TIME 8 +#define BIT_N_LANES 0 + +/* For MIPI_DSI_DWC_DPI_COLOR_CODING_OS */ +#define BIT_LOOSELY18_EN 8 +#define BIT_DPI_COLOR_CODING 0 + +/* For MIPI_DSI_DWC_GEN_HDR_OS */ +#define BIT_GEN_WC_MSBYTE 16 +#define BIT_GEN_WC_LSBYTE 8 +#define BIT_GEN_VC 6 +#define BIT_GEN_DT 0 + +/* For MIPI_DSI_DWC_LPCLK_CTRL_OS */ +#define BIT_AUTOCLKLANE_CTRL 1 +#define BIT_TXREQUESTCLKHS 0 + +/* For MIPI_DSI_DWC_DPI_CFG_POL_OS */ +#define BIT_COLORM_ACTIVE_LOW 4 +#define BIT_SHUTD_ACTIVE_LOW 3 +#define BIT_HSYNC_ACTIVE_LOW 2 +#define BIT_VSYNC_ACTIVE_LOW 1 +#define BIT_DATAEN_ACTIVE_LOW 0 + +/* For MIPI_DSI_DWC_CMD_MODE_CFG_OS */ +#define BIT_MAX_RD_PKT_SIZE 24 +#define BIT_DCS_LW_TX 19 +#define BIT_DCS_SR_0P_TX 18 +#define BIT_DCS_SW_1P_TX 17 +#define BIT_DCS_SW_0P_TX 16 +#define BIT_GEN_LW_TX 14 +#define BIT_GEN_SR_2P_TX 13 +#define BIT_GEN_SR_1P_TX 12 +#define BIT_GEN_SR_0P_TX 11 +#define BIT_GEN_SW_2P_TX 10 +#define BIT_GEN_SW_1P_TX 9 +#define BIT_GEN_SW_0P_TX 8 +#define BIT_ACK_RQST_EN 1 +#define BIT_TEAR_FX_EN 0 + +/* For MIPI_DSI_DWC_CMD_PKT_STATUS_OS */ +/* For DBI no use full */ +#define BIT_DBI_RD_CMD_BUSY 14 +#define BIT_DBI_PLD_R_FULL 13 +#define BIT_DBI_PLD_R_EMPTY 12 +#define BIT_DBI_PLD_W_FULL 11 +#define BIT_DBI_PLD_W_EMPTY 10 +#define BIT_DBI_CMD_FULL 9 +#define BIT_DBI_CMD_EMPTY 8 +/* For Generic interface */ +#define BIT_GEN_RD_CMD_BUSY 6 +#define BIT_GEN_PLD_R_FULL 5 +#define BIT_GEN_PLD_R_EMPTY 4 +#define BIT_GEN_PLD_W_FULL 3 +#define BIT_GEN_PLD_W_EMPTY 2 +#define BIT_GEN_CMD_FULL 1 +#define BIT_GEN_CMD_EMPTY 0 + +/* For MIPI_DSI_TOP_MEAS_CNTL */ +/* measure vsync control */ +#define BIT_CNTL_MEAS_VSYNC 10 +/* tear measure enable */ +#define BIT_EDPITE_MEAS_EN 9 +/* not clear the counter */ +#define BIT_EDPITE_ACCUM_MEAS_EN 8 +#define BIT_EDPITE_VSYNC_SPAN 0 + +/* For MIPI_DSI_TOP_STAT */ +/* signal from halt */ +#define BIT_STAT_EDPIHALT 31 +/* line number when edpite pulse */ +#define BIT_STAT_TE_LINE 16 +/* pixel number when edpite pulse */ +#define BIT_STAT_TE_PIXEL 0 + +/* For MIPI_DSI_TOP_INTR_CNTL_STAT */ +/* State/Clear for pic_eof */ +#define BIT_STAT_CLR_DWC_PIC_EOF 21 +/* State/Clear for de_fall */ +#define BIT_STAT_CLR_DWC_DE_FALL 20 +/* State/Clear for de_rise */ +#define BIT_STAT_CLR_DWC_DE_RISE 19 +/* State/Clear for vs_fall */ +#define BIT_STAT_CLR_DWC_VS_FALL 18 +/* State/Clear for vs_rise */ +#define BIT_STAT_CLR_DWC_VS_RISE 17 +/* State/Clear for edpite */ +#define BIT_STAT_CLR_DWC_EDPITE 16 +/* end of picture */ +#define BIT_PIC_EOF 5 +/* data enable fall */ +#define BIT_DE_FALL 4 +/* data enable rise */ +#define BIT_DE_RISE 3 +/* vsync fall */ +#define BIT_VS_FALL 2 +/* vsync rise */ +#define BIT_VS_RISE 1 +/* edpite int enable */ +#define BIT_EDPITE_INT_EN 0 + +/* For MIPI_DSI_TOP_MEAS_CNTL */ +/* vsync measure enable */ +#define BIT_VSYNC_MEAS_EN 19 +/* vsync accumulate measure */ +#define BIT_VSYNC_ACCUM_MEAS_EN 18 +/* vsync span */ +#define BIT_VSYNC_SPAN 10 +/* tearing measure enable */ +#define BIT_TE_MEAS_EN 9 +/* tearing accumulate measure */ +#define BIT_TE_ACCUM_MEAS_EN 8 +/* tearing span */ +#define BIT_TE_SPAN 0 + +/* For MIPI_DSI_DWC_INT_ST0_OS */ +/* LP1 contention error from lane0 */ +#define BIT_DPHY_ERR_4 20 +/* LP0 contention error from lane0 */ +#define BIT_DPHY_ERR_3 19 +/* ErrControl error from lane0 */ +#define BIT_DPHY_ERR_2 18 +/* ErrSyncEsc error from lane0 */ +#define BIT_DPHY_ERR_1 17 +/* ErrEsc escape error lane0 */ +#define BIT_DPHY_ERR_0 16 +#define BIT_ACK_ERR_15 15 +#define BIT_ACK_ERR_14 14 +#define BIT_ACK_ERR_13 13 +#define BIT_ACK_ERR_12 12 +#define BIT_ACK_ERR_11 11 +#define BIT_ACK_ERR_10 10 +#define BIT_ACK_ERR_9 9 +#define BIT_ACK_ERR_8 8 +#define BIT_ACK_ERR_7 7 +#define BIT_ACK_ERR_6 6 +#define BIT_ACK_ERR_5 5 +#define BIT_ACK_ERR_4 4 +#define BIT_ACK_ERR_3 3 +#define BIT_ACK_ERR_2 2 +#define BIT_ACK_ERR_1 1 +#define BIT_ACK_ERR_0 0 + +/* Command transfer type in command mode */ +#define DCS_TRANS_HS 0 +#define DCS_TRANS_LP 1 + +#define MIPI_DSI_DCS_NO_ACK 0 +#define MIPI_DSI_DCS_REQ_ACK 1 + +/* DSI Tear Defines */ +#define MIPI_DCS_SET_TEAR_ON_MODE_0 0 +#define MIPI_DCS_SET_TEAR_ON_MODE_1 1 +#define MIPI_DCS_ENABLE_TEAR 1 +#define MIPI_DCS_DISABLE_TEAR 0 + + +/* MIPI DCS Pixel-to-Byte Format */ +#define DCS_PF_RSVD 0x0 +#define DCS_PF_3BIT 0x1 +#define DCS_PF_8BIT 0x2 +#define DCS_PF_12BIT 0x3 +#define DCS_PF_16BIT 0x5 +#define DCS_PF_18BIT 0x6 +#define DCS_PF_24BIT 0x7 + +/* MIPI DSI/VENC Color Format Definitions */ +#define MIPI_DSI_VENC_COLOR_30B 0x0 +#define MIPI_DSI_VENC_COLOR_24B 0x1 +#define MIPI_DSI_VENC_COLOR_18B 0x2 +#define MIPI_DSI_VENC_COLOR_16B 0x3 + +#define COLOR_16BIT_CFG_1 0x0 +#define COLOR_16BIT_CFG_2 0x1 +#define COLOR_16BIT_CFG_3 0x2 +#define COLOR_18BIT_CFG_1 0x3 +#define COLOR_18BIT_CFG_2 0x4 +#define COLOR_24BIT 0x5 +#define COLOR_20BIT_LOOSE 0x6 +#define COLOR_24_BIT_YCBCR 0x7 +#define COLOR_16BIT_YCBCR 0x8 +#define COLOR_30BIT 0x9 +#define COLOR_36BIT 0xa +#define COLOR_12BIT 0xb +#define COLOR_RGB_111 0xc +#define COLOR_RGB_332 0xd +#define COLOR_RGB_444 0xe + + +enum div_sel_e { + CLK_DIV_SEL_1 = 0, + CLK_DIV_SEL_2, /* 1 */ + CLK_DIV_SEL_3, /* 2 */ + CLK_DIV_SEL_3p5, /* 3 */ + CLK_DIV_SEL_3p75, /* 4 */ + CLK_DIV_SEL_4, /* 5 */ + CLK_DIV_SEL_5, /* 6 */ + CLK_DIV_SEL_6, /* 7 */ + CLK_DIV_SEL_6p25, /* 8 */ + CLK_DIV_SEL_7, /* 9 */ + CLK_DIV_SEL_7p5, /* 10 */ + CLK_DIV_SEL_12, /* 11 */ + CLK_DIV_SEL_14, /* 12 */ + CLK_DIV_SEL_15, /* 13 */ + CLK_DIV_SEL_2p5, /* 14 */ + CLK_DIV_SEL_MAX, +}; + + +typedef struct { + uint32_t lcd_bits; + uint32_t h_active; + uint32_t v_active; + uint32_t h_period; + uint32_t v_period; + + uint32_t fr_adj_type; + uint32_t ss_level; + uint32_t clk_auto_gen; + uint32_t lcd_clock; + + uint32_t clk_ctrl; + uint32_t pll_ctrl; + uint32_t div_ctrl; + uint32_t clk_change; + + uint32_t lcd_clk_dft; + uint32_t hPeriod_dft; + uint32_t vPeriod_dft; + + uint32_t sync_duration_numerator; + uint32_t sync_duration_denominator; + + uint32_t vid_pixel_on; + uint32_t vid_line_on; + + uint32_t hSync_width; + uint32_t hSync_backPorch; + uint32_t hSync_pol; + uint32_t vSync_width; + uint32_t vSync_backPorch; + uint32_t vSync_pol; + + uint32_t hOffset; + uint32_t vOffset; + + uint32_t de_hs_addr; + uint32_t de_he_addr; + uint32_t de_vs_addr; + uint32_t de_ve_addr; + + uint32_t hs_hs_addr; + uint32_t hs_he_addr; + uint32_t hs_vs_addr; + uint32_t hs_ve_addr; + + uint32_t vs_hs_addr; + uint32_t vs_he_addr; + uint32_t vs_vs_addr; + uint32_t vs_ve_addr; +} lcd_timing_t; + +typedef struct { + uint32_t lane_num; + uint32_t bit_rate_max; + uint32_t bit_rate_min; + uint32_t bit_rate; + uint32_t clock_factor; + uint32_t factor_numerator; + uint32_t factor_denominator; + uint32_t opp_mode_init; + uint32_t opp_mode_display; + uint32_t video_mode_type; + uint32_t clk_always_hs; + uint32_t phy_switch; + uint32_t venc_data_width; + uint32_t dpi_data_format; + + uint32_t hLine; // Overall time for each video line + uint32_t hSyncActive; // Horizontal Sync Active Period + uint32_t hBackporch; // Horizontal Back Porch Period + uint32_t vSyncActive; // Vertical Sync Active Period + uint32_t vBackporch; // Vertical Back Porch Period + uint32_t vFrontporch; // Vertical Front Porch Period + uint32_t vActiveLines; // Vertical Active Period + + unsigned char check_en; + unsigned char check_reg; + unsigned char check_cnt; + unsigned char check_state; + +} dsi_config_t; + +typedef struct { + uint32_t lp_tesc; + uint32_t lp_lpx; + uint32_t lp_ta_sure; + uint32_t lp_ta_go; + uint32_t lp_ta_get; + uint32_t hs_exit; + uint32_t hs_trail; + uint32_t hs_zero; + uint32_t hs_prepare; + uint32_t clk_trail; + uint32_t clk_post; + uint32_t clk_zero; + uint32_t clk_prepare; + uint32_t clk_pre; + uint32_t init; + uint32_t wakeup; + uint32_t state_change; +} dsi_phy_config_t; + +typedef struct { + int data_bits; + int vid_num_chunks; + int pixel_per_chunk; /* pkt_size */ + int vid_null_size; + int byte_per_chunk; /* internal usage */ + int multi_pkt_en; /* internal usage */ + + /* vid timing */ + uint32_t hline; + uint32_t hsa; + uint32_t hbp; + uint32_t vsa; + uint32_t vbp; + uint32_t vfp; + uint32_t vact; +} dsi_video_t; + +struct dsi_cmd_request_s { + unsigned char data_type; + unsigned char vc_id; + unsigned char *payload; + unsigned short pld_count; + unsigned int req_ack; +}; + + + + +enum mipi_dsi_data_type_host_e { + DT_VSS = 0x01, + DT_VSE = 0x11, + DT_HSS = 0x21, + DT_HSE = 0x31, + DT_EOTP = 0x08, + DT_CMOFF = 0x02, + DT_CMON = 0x12, + DT_SHUT_DOWN = 0x22, + DT_TURN_ON = 0x32, + DT_GEN_SHORT_WR_0 = 0x03, + DT_GEN_SHORT_WR_1 = 0x13, + DT_GEN_SHORT_WR_2 = 0x23, + DT_GEN_RD_0 = 0x04, + DT_GEN_RD_1 = 0x14, + DT_GEN_RD_2 = 0x24, + DT_DCS_SHORT_WR_0 = 0x05, + DT_DCS_SHORT_WR_1 = 0x15, + DT_DCS_RD_0 = 0x06, + DT_SET_MAX_RET_PKT_SIZE = 0x37, + DT_NULL_PKT = 0x09, + DT_BLANK_PKT = 0x19, + DT_GEN_LONG_WR = 0x29, + DT_DCS_LONG_WR = 0x39, + DT_20BIT_LOOSE_YCBCR = 0x0c, + DT_24BIT_YCBCR = 0x1c, + DT_16BIT_YCBCR = 0x2c, + DT_30BIT_RGB_101010 = 0x0d, + DT_36BIT_RGB_121212 = 0x1d, + DT_12BIT_YCBCR = 0x3d, + DT_16BIT_RGB_565 = 0x0e, + DT_18BIT_RGB_666 = 0x1e, + DT_18BIT_LOOSE_RGB_666 = 0x2e, + DT_24BIT_RGB_888 = 0x3e +}; + +/* DCS Command List */ +#define DCS_ENTER_IDLE_MODE 0x39 +#define DCS_ENTER_INVERT_MODE 0x21 +#define DCS_ENTER_NORMAL_MODE 0x13 +#define DCS_ENTER_PARTIAL_MODE 0x12 +#define DCS_ENTER_SLEEP_MODE 0x10 +#define DCS_EXIT_IDLE_MODE 0x38 +#define DCS_EXIT_INVERT_MODE 0x20 +#define DCS_EXIT_SLEEP_MODE 0x11 +#define DCS_GET_3D_CONTROL 0x3f +#define DCS_GET_ADDRESS_MODE 0x0b +#define DCS_GET_BLUE_CHANNEL 0x08 +#define DCS_GET_DIAGNOSTIC_RESULT 0x0f +#define DCS_GET_DISPLAY_MODE 0x0d +#define DCS_GET_GREEN_CHANNEL 0x07 +#define DCS_GET_PIXEL_FORMAT 0x0c +#define DCS_GET_POWER_MODE 0x0a +#define DCS_GET_RED_CHANNEL 0x06 +#define DCS_GET_SCANLINE 0x45 +#define DCS_GET_SIGNAL_MODE 0x0e +#define DCS_NOP 0x00 +#define DCS_READ_DDB_CONTINUE 0xa8 +#define DCS_READ_DDB_START 0xa1 +#define DCS_READ_MEMORY_CONTINUE 0x3e +#define DCS_READ_MEMORY_START 0x2e +#define DCS_SET_3D_CONTROL 0x3d +#define DCS_SET_ADDRESS_MODE 0x36 +#define DCS_SET_COLUMN_ADDRESS 0x2a +#define DCS_SET_DISPLAY_OFF 0x28 +#define DCS_SET_DISPLAY_ON 0x29 +#define DCS_SET_GAMMA_CURVE 0x26 +#define DCS_SET_PAGE_ADDRESS 0x2b +#define DCS_SET_PARTIAL_COLUMNS 0x31 +#define DCS_SET_PARTIAL_ROWS 0x30 +#define DCS_SET_PIXEL_FORMAT 0x3a +#define DCS_SET_SCROLL_AREA 0x33 +#define DCS_SET_SCROLL_START 0x37 +#define DCS_SET_TEAR_OFF 0x34 +#define DCS_SET_TEAR_ON 0x35 +#define DCS_SET_TEAR_SCANLINE 0x44 +#define DCS_SET_VSYNC_TIMING 0x40 +#define DCS_SOFT_RESET 0x01 +#define DCS_WRITE_LUT 0x2d +#define DCS_WRITE_MEMORY_CONTINUE 0x3c +#define DCS_WRITE_MEMORY_START 0x2c + + + +enum mipi_dsi_data_type_peripheral_e { + DT_RESP_TE = 0xba, + DT_RESP_ACK = 0x84, + DT_RESP_ACK_ERR = 0x02, + DT_RESP_EOT = 0x08, + DT_RESP_GEN_READ_1 = 0x11, + DT_RESP_GEN_READ_2 = 0x12, + DT_RESP_GEN_READ_LONG = 0x1a, + DT_RESP_DCS_READ_LONG = 0x1c, + DT_RESP_DCS_READ_1 = 0x21, + DT_RESP_DCS_READ_2 = 0x22, +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#if 0 +//------------------------------------------------------------------------------ +// Top-level registers: AmLogic proprietary +//------------------------------------------------------------------------------ +// 31: 4 Reserved. Default 0. +// 3 RW ~tim_rst_n: 1=Assert SW reset on mipi_dsi_host_timing block. 0=Release reset. Default 1. +// 2 RW ~dpi_rst_n: 1=Assert SW reset on mipi_dsi_host_dpi block. 0=Release reset. Default 1. +// 1 RW ~intr_rst_n: 1=Assert SW reset on mipi_dsi_host_intr block. 0=Release reset. Default 1. +// 0 RW ~dwc_rst_n: 1=Assert SW reset on IP core. 0=Release reset. Default 1. +#define MIPI_DSI_TOP_SW_RESET (0x1cf0) +// 31: 5 Reserved. Default 0. +// 4 RW manual_edpihalt: 1=Manual suspend VencL; 0=do not suspend VencL. Default 0. +// 3 RW auto_edpihalt_en: 1=Enable IP's edpihalt signal to suspend VencL; 0=IP's edpihalt signal does not affect VencL. Default 0. +// 2 RW clock_freerun: Apply to auto-clock gate only. Default 0. +// 0=Default, use auto-clock gating to save power; +// 1=use free-run clock, disable auto-clock gating, for debug mode. +// 1 RW enable_pixclk: A manual clock gate option, due to DWC IP does not have auto-clock gating. 1=Enable pixclk. Default 0. +// 0 RW enable_sysclk: A manual clock gate option, due to DWC IP does not have auto-clock gating. 1=Enable sysclk. Default 0. +#define MIPI_DSI_TOP_CLK_CNTL (0x1cf1) +// 31:27 Reserved. Default 0. +// 26 RW de_dpi_pol: 1= Invert DE polarity from mipi_dsi_host_dpi. Default 0. +// 25 RW hsync_dpi_pol: 1= Invert HS polarity from mipi_dsi_host_dpi. Default 0. +// 24 RW vsync_dpi_pol: 1= Invert VS polarity from mipi_dsi_host_dpi. Default 0. +// 23:20 RW dpi_color_mode: Define DPI pixel format. Default 0. +// 0=16-bit RGB565 config 1; +// 1=16-bit RGB565 config 2; +// 2=16-bit RGB565 config 3; +// 3=18-bit RGB666 config 1; +// 4=18-bit RGB666 config 2; +// 5=24-bit RGB888; +// 6=20-bit YCbCr 4:2:2; +// 7=24-bit YCbCr 4:2:2; +// 8=16-bit YCbCr 4:2:2; +// 9=30-bit RGB; +// 10=36-bit RGB; +// 11=12-bit YCbCr 4:2:0. +// 19 Reserved. Default 0. +// 18:16 RW in_color_mode: Define VENC data width. Default 0. +// 0=30-bit pixel; +// 1=24-bit pixel; +// 2=18-bit pixel, RGB666; +// 3=16-bit pixel, RGB565. +// 15:14 RW chroma_subsample: Define method of chroma subsampling. Default 0. +// Applicable to YUV422 or YUV420 only. +// 0=Use even pixel's chroma; +// 1=Use odd pixel's chroma; +// 2=Use averaged value between even and odd pair. +// 13:12 RW comp2_sel: Select which component to be Cr or B: 0=comp0; 1=comp1; 2=comp2. Default 2. +// 11:10 RW comp1_sel: Select which component to be Cb or G: 0=comp0; 1=comp1; 2=comp2. Default 1. +// 9: 8 RW comp0_sel: Select which component to be Y or R: 0=comp0; 1=comp1; 2=comp2. Default 0. +// 7 Reserved. Default 0. +// 6 RW de_venc_pol: 1= Invert DE polarity from VENC. Default 0. +// 5 RW hsync_venc_pol: 1= Invert HS polarity from VENC. Default 0. +// 4 RW vsync_venc_pol: 1= Invert VS polarity from VENC. Default 0. +// 3 RW dpicolorm: Signal to IP. Default 0. +// 2 RW dpishutdn: Signal to IP. Default 0. +// 1 Reserved. Default 0. +// 0 Reserved. Default 0. +#define MIPI_DSI_TOP_CNTL (0x1cf2) +// 31:16 Reserved. Default 0. +// 15: 8 RW suspend_frame_rate: Define rate of timed-suspend. Default 0. +// 0=Execute suspend every frame; 1=Every other frame; ...; 255=Every 256 frame. +// 7: 3 Reserved. Default 0. +// 2 RW timed_suspend_en: 1=Enable timed suspend VencL. 0=Disable timed suspend. Default 0. +// 1 RW manual_suspend_en: 1=Enable manual suspend VencL. 1=Cancel manual suspend VencL. Default 0. +// 0 RW suspend_on_edpihalt:1=Enable IP's edpihalt signal to suspend VencL; 0=IP's edpihalt signal does not affect VencL. Default 1. +#define MIPI_DSI_TOP_SUSPEND_CNTL (0x1cf3) +// 31:29 Reserved. Default 0. +// 28:16 RW suspend_line_end: Define timed-suspend region. Suspend from [pix_start,line_start] to [pix_end,line_end]. Default 0. +// 15:13 Reserved. Default 0. +// 12: 0 RW suspend_line_start: Define timed-suspend region. Suspend from [pix_start,line_start] to [pix_end,line_end]. Default 0. +#define MIPI_DSI_TOP_SUSPEND_LINE (0x1cf4) +// 31:29 Reserved. Default 0. +// 28:16 RW suspend_pix_end: Define timed-suspend region. Suspend from [pix_start,line_start] to [pix_end,line_end]. Default 0. +// 15:13 Reserved. Default 0. +// 12: 0 RW suspend_pix_start: Define timed-suspend region. Suspend from [pix_start,line_start] to [pix_end,line_end]. Default 0. +#define MIPI_DSI_TOP_SUSPEND_PIX (0x1cf5) +// 31:20 Reserved. Default 0. +// 19:10 RW meas_vsync: Control on measuring Host Controller's vsync. Default 0. +// [ 19] meas_en: 1=Enable measurement +// [ 18] accum_meas_en: 0=meas_count is cleared at the end of each measure; +// 1=meas_count is accumulated at the end of each measure. +// [17:10] vsync_span: Define the duration of a measure is to last for how many Vsyncs. +// 9: 0 RW meas_edpite: Control on measuring Display Slave's edpite. Default 0. +// [ 9] meas_en: 1=Enable measurement +// [ 8] accum_meas_en: 0=meas_count is cleared at the end of each measure; +// 1=meas_count is accumulated at the end of each measure. +// [ 7: 0] edpite_span: Define the duration of a measure is to last for how many edpite. +#define MIPI_DSI_TOP_MEAS_CNTL (0x1cf6) +// 31 R stat_edpihalt: status of edpihalt signal from IP. Default 0. +// 30:29 Reserved. Default 0. +// 28:16 R stat_te_line: Snapshot of Host's line position at edpite. Default 0. +// 15:13 Reserved. Default 0. +// 12: 0 R stat_te_pix: Snapshot of Host's pixel position at edpite. Default 0. +#define MIPI_DSI_TOP_STAT (0x1cf7) +// To measure display slave's frame rate, we can use a reference clock to measure the duration of one of more edpite pulse(s). +// Measurement control is by register MIPI_DSI_TOP_MEAS_CNTL bit[9:0]. +// Reference clock comes from clk_rst_tst.cts_dsi_meas_clk, and is defined by HIU register HHI_VDIN_MEAS_CLK_CNTL bit[23:12]. +// Mesurement result is in MIPI_DSI_TOP_MEAS_STAT_TE0 and MIPI_DSI_TOP_MEAS_STAT_TE1, as below: +// edpite_meas_count[47:0]: Number of reference clock cycles counted during one measure period (non-incremental measure), or +// during all measure periods so far (incremental measure). +// edpite_meas_count_n[3:0]:Number of measure periods has been done. Number can wrap over. +// +// 31: 0 R edpite_meas_count[31:0]. Default 0. +#define MIPI_DSI_TOP_MEAS_STAT_TE0 (0x1cf8) +// 19:16 R edpite_meas_count_n. Default 0. +// 15: 0 R edpite_meas_count[47:32]. Default 0. +#define MIPI_DSI_TOP_MEAS_STAT_TE1 (0x1cf9) +// To measure Host's frame rate, we can use a reference clock to measure the duration of one of more Vsync pulse(s). +// Measurement control is by register MIPI_DSI_TOP_MEAS_CNTL bit[19:10]. +// Reference clock comes from clk_rst_tst.cts_dsi_meas_clk, and is defined by HIU register HHI_VDIN_MEAS_CLK_CNTL bit[23:12]. +// Mesurement result is in MIPI_DSI_TOP_MEAS_STAT_VS0 and MIPI_DSI_TOP_MEAS_STAT_VS1, as below: +// vsync_meas_count[47:0]: Number of reference clock cycles counted during one measure period (non-incremental measure), or +// during all measure periods so far (incremental measure). +// vsync_meas_count_n[3:0]: Number of measure periods has been done. Number can wrap over. +// +// 31: 0 R vsync_meas_count[31:0]. Default 0. +#define MIPI_DSI_TOP_MEAS_STAT_VS0 (0x1cfa) +// 19:16 R vsync_meas_count_n. Default 0. +// 15: 0 R vsync_meas_count[47:32]. Default 0. +#define MIPI_DSI_TOP_MEAS_STAT_VS1 (0x1cfb) +// 31:16 RW intr_stat/clr. For each bit, read as this interrupt level status, write 1 to clear. Default 0. +// Note: To clear the interrupt level, simply write 1 to the specific bit, no need to write 0 afterwards. +// [31:22] Reserved +// [ 21] stat/clr of EOF interrupt +// [ 20] stat/clr of de_fall interrupt +// [ 19] stat/clr of de_rise interrupt +// [ 18] stat/clr of vs_fall interrupt +// [ 17] stat/clr of vs_rise interrupt +// [ 16] stat/clr of dwc_edpite interrupt +// 15: 0 RW intr_enable. For each bit, 1=enable this interrupt, 0=disable. Default 0. +// [15: 6] Reserved +// [ 5] EOF (End_Of_Field) interrupt +// [ 4] de_fall interrupt +// [ 3] de_rise interrupt +// [ 2] vs_fall interrupt +// [ 1] vs_rise interrupt +// [ 0] dwc_edpite interrupt +#define MIPI_DSI_TOP_INTR_CNTL_STAT (0x1cfc) +// 31: 2 Reserved. Default 0. +// 1: 0 RW mem_pd. Default 3. +#define MIPI_DSI_TOP_MEM_PD (0x1cfd) +#endif \ No newline at end of file
diff --git a/system/dev/display/astro-display/astro-display.c b/system/dev/display/astro-display/astro-display.c index b04a670..88cc716 100644 --- a/system/dev/display/astro-display/astro-display.c +++ b/system/dev/display/astro-display/astro-display.c
@@ -3,24 +3,56 @@ // found in the LICENSE file. #include "astro-display.h" -#include <assert.h> -#include <ddk/binding.h> -#include <ddk/debug.h> -#include <ddk/device.h> -#include <ddk/driver.h> -#include <ddk/io-buffer.h> -#include <ddk/protocol/display.h> -#include <ddk/protocol/platform-defs.h> -#include <ddk/protocol/platform-device.h> -#include <hw/reg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <zircon/assert.h> -#include <zircon/device/display.h> -#include <zircon/syscalls.h> + + +const struct display_setting g_disp_setting = { + .lcd_bits = 8, + .hActive = 600, + .vActive = 1024, + .hPeriod = 680, + .vPeriod = 1194, + .hSync_width = 24, + .hSync_backPorch = 36, + .hSync_pol = 0, + .vSync_width = 10, + .vSync_backPorch = 80, + .vSync_pol = 0, + + // Clock configs + .fr_adj_type = 0, + .ss_level = 0, + .clk_auto_gen = 1, + .lcd_clock = 48715200, + + //mipi vals + .lane_num = 4, + .bit_rate_max = 400, + .factor_numerator = 0, + .opp_mode_init = 1, + .opp_mode_display = 0, + .video_mode_type = 2, + .clk_always_hs = 0, + .phy_switch = 0, +}; + +struct lcd_clk_config g_lcd_clk_cfg = { + .od_fb = PLL_FRAC_OD_FB_HPLL_G12A, + .ss_level_max = SS_LEVEL_MAX_HPLL_G12A, + .pll_frac_range = PLL_FRAC_RANGE_HPLL_G12A, + .pll_od_sel_max = PLL_OD_SEL_MAX_HPLL_G12A, + .pll_vco_fmax = PLL_VCO_MAX_HPLL_G12A, + .pll_vco_fmin = PLL_VCO_MIN_HPLL_G12A, + .pll_m_max = PLL_M_MAX_G12A, + .pll_m_min = PLL_M_MIN_G12A, + .pll_n_max = PLL_N_MAX_G12A, + .pll_n_min = PLL_N_MIN_G12A, + .pll_ref_fmax = PLL_FREF_MAX_G12A, + .pll_ref_fmin = PLL_FREF_MIN_G12A, + .pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A, + .pll_out_fmin = PLL_VCO_MIN_HPLL_G12A / 16, + .div_out_fmax = CRT_VID_CLK_IN_MAX_G12A, + .xd_out_fmax = ENCL_CLK_IN_MAX_G12A, +}; static zx_status_t vc_set_mode(void* ctx, zx_display_info_t* info) { return ZX_OK; @@ -169,54 +201,23 @@ .open = vc_open, }; -/* Table from Linux source */ -/* TODO: Need to separate backlight driver from display driver */ -static const uint8_t backlight_init_table[] = { - 0xa2, 0x20, - 0xa5, 0x54, - 0x00, 0xff, - 0x01, 0x05, - 0xa2, 0x20, - 0xa5, 0x54, - 0xa1, 0xb7, - 0xa0, 0xff, - 0x00, 0x80, -}; - -static void init_backlight(astro_display_t* display) { - - // power on backlight - gpio_config(&display->gpio, 0, GPIO_DIR_OUT); - gpio_write(&display->gpio, 0, 1); - usleep(1000); - - for (size_t i = 0; i < sizeof(backlight_init_table); i+=2) { - if(i2c_transact_sync(&display->i2c, 0, &backlight_init_table[i], 2, NULL, 0) != ZX_OK) { - DISP_ERROR("Backlight write failed: reg[0x%x]: 0x%x\n", backlight_init_table[i], - backlight_init_table[i+1]); - } +static zx_status_t populate_init_config(astro_display_t* display) { + display->disp_setting = calloc(1, sizeof(struct display_setting)); + if (!display->disp_setting) { + DISP_ERROR("Could not allocate disp_setting structure.\n"); + return ZX_ERR_NO_MEMORY; } -} -static void config_canvas(astro_display_t* display) { - uint32_t fbh = display->disp_info.height * 2; - uint32_t fbw = display->disp_info.stride * 2; + display->lcd_clk_cfg = calloc(1, sizeof(struct lcd_clk_config)); + if (!display->lcd_clk_cfg) { + DISP_ERROR("Could not allocate lcd_clk_config structure\n"); + return ZX_ERR_NO_MEMORY; + } - DISP_INFO("Canvas Diminsions: w=%d h=%d\n", fbw, fbh); + memcpy(display->disp_setting, &g_disp_setting, sizeof(struct display_setting)); + memcpy(display->lcd_clk_cfg, &g_lcd_clk_cfg, sizeof(struct lcd_clk_config)); - // set framebuffer address in DMC, read/modify/write - WRITE32_DMC_REG(DMC_CAV_LUT_DATAL, - (((io_buffer_phys(&display->fbuffer) + 7) >> 3) & DMC_CAV_ADDR_LMASK) | - ((((fbw + 7) >> 3) & DMC_CAV_WIDTH_LMASK) << DMC_CAV_WIDTH_LBIT)); - - WRITE32_DMC_REG(DMC_CAV_LUT_DATAH, - ((((fbw + 7) >> 3) >> DMC_CAV_WIDTH_LWID) << DMC_CAV_WIDTH_HBIT) | - ((fbh & DMC_CAV_HEIGHT_MASK) << DMC_CAV_HEIGHT_BIT)); - - WRITE32_DMC_REG(DMC_CAV_LUT_ADDR, DMC_CAV_LUT_ADDR_WR_EN | OSD2_DMC_CAV_INDEX ); - // read a cbus to make sure last write finish. - READ32_DMC_REG(DMC_CAV_LUT_DATAH); - + return ZX_OK; } static zx_status_t setup_display_if(astro_display_t* display) { @@ -240,6 +241,36 @@ return status; } + // Populated internal structures based on predefined tables + if ((status = populate_init_config(display)) != ZX_OK) { + DISP_ERROR("populate_init_config failed!\n"); + return status; + } + + // Populate internal LCD timing structure based on predefined tables + if ((status = astro_lcd_timing(display)) != ZX_OK) { + DISP_ERROR("astro_lcd_timing failed!\n"); + return status; + } + + // Populate internal DSI Config structure based on predefined tables + if ((status = astro_dsi_load_config(display)) != ZX_OK) { + DISP_ERROR("astro_dsi_load_config failed!\n"); + return status; + } + + // Populate dsi clock related values + if ((status = astro_dsi_generate_hpll(display)) != ZX_OK) { + DISP_ERROR("astro_dsi_generate_hpll failed!\n"); + return status; + } + + display_clock_init(display); + lcd_mipi_phy_set(display, true); // enable mipi-phy + aml_dsi_host_on(display); + + // dump_display_info(display); + config_canvas(display); init_backlight(display); @@ -308,10 +339,38 @@ } // Map all the various MMIOs - status = pdev_map_mmio_buffer(&display->pdev, 0, ZX_CACHE_POLICY_UNCACHED_DEVICE, + status = pdev_map_mmio_buffer(&display->pdev, MMIO_CANVAS, ZX_CACHE_POLICY_UNCACHED_DEVICE, &display->mmio_dmc); if (status != ZX_OK) { - DISP_ERROR("Could not map display MMIO DC\n"); + DISP_ERROR("Could not map display MMIO DMC\n"); + goto fail; + } + + status = pdev_map_mmio_buffer(&display->pdev, MMIO_MPI_DSI, ZX_CACHE_POLICY_UNCACHED_DEVICE, + &display->mmio_mipi_dsi); + if (status != ZX_OK) { + DISP_ERROR("Could not map display MMIO MIPI_DSI\n"); + goto fail; + } + + status = pdev_map_mmio_buffer(&display->pdev, MMIO_DSI_PHY, ZX_CACHE_POLICY_UNCACHED_DEVICE, + &display->mmio_dsi_phy); + if (status != ZX_OK) { + DISP_ERROR("Could not map display MMIO DSI PHY\n"); + goto fail; + } + + status = pdev_map_mmio_buffer(&display->pdev, MMIO_HHI, ZX_CACHE_POLICY_UNCACHED_DEVICE, + &display->mmio_hhi); + if (status != ZX_OK) { + DISP_ERROR("Could not map display MMIO HHI\n"); + goto fail; + } + + status = pdev_map_mmio_buffer(&display->pdev, MMIO_VPU, ZX_CACHE_POLICY_UNCACHED_DEVICE, + &display->mmio_vpu); + if (status != ZX_OK) { + DISP_ERROR("Could not map display MMIO VPU\n"); goto fail; }
diff --git a/system/dev/display/astro-display/astro-display.h b/system/dev/display/astro-display/astro-display.h index 016047d..2eb4c2c 100644 --- a/system/dev/display/astro-display/astro-display.h +++ b/system/dev/display/astro-display/astro-display.h
@@ -5,28 +5,67 @@ #pragma once #include <assert.h> -#include <ddk/io-buffer.h> -#include <ddk/protocol/display.h> -#include <ddk/protocol/gpio.h> -#include <ddk/protocol/i2c.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <zircon/device/display.h> +#include <unistd.h> +#include <threads.h> +#include <hw/reg.h> +#include <ddk/binding.h> +#include <ddk/debug.h> #include <ddk/device.h> +#include <ddk/driver.h> #include <ddk/io-buffer.h> +#include <ddk/protocol/display.h> +#include <ddk/protocol/gpio.h> +#include <ddk/protocol/i2c.h> #include <ddk/protocol/platform-device.h> +#include <ddk/protocol/platform-defs.h> +#include <zircon/device/display.h> #include <zircon/listnode.h> #include <zircon/types.h> -#include <threads.h> +#include <zircon/assert.h> +#include <zircon/device/display.h> +#include <zircon/syscalls.h> + +#include "hhi.h" +#include "dw_dsi.h" +#include "aml_dsi.h" #define DISP_ERROR(fmt, ...) zxlogf(ERROR, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__) #define DISP_INFO(fmt, ...) zxlogf(INFO, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__) #define DISP_TRACE zxlogf(INFO, "[%s %d]\n", __func__, __LINE__) -#define READ32_DMC_REG(a) readl(io_buffer_virt(&display->mmio_dmc) + a) -#define WRITE32_DMC_REG(a, v) writel(v, io_buffer_virt(&display->mmio_dmc) + a) +#define DISPLAY_MASK(start, count) (((1 << (count)) - 1) << (start)) +#define DISPLAY_SET_MASK(mask, start, count, value) \ + ((mask & ~DISPLAY_MASK(start, count)) | \ + (((value) << (start)) & DISPLAY_MASK(start, count))) + +#define READ32_DMC_REG(a) readl(io_buffer_virt(&display->mmio_dmc) + a) +#define WRITE32_DMC_REG(a, v) writel(v, io_buffer_virt(&display->mmio_dmc) + a) + +#define READ32_MIPI_DSI_REG(a) readl(io_buffer_virt(&display->mmio_mipi_dsi) + a) +#define WRITE32_MIPI_DSI_REG(a, v) writel(v, io_buffer_virt(&display->mmio_mipi_dsi) + a) + +#define READ32_DSI_PHY_REG(a) readl(io_buffer_virt(&display->mmio_dsi_phy) + a) +#define WRITE32_DSI_PHY_REG(a, v) writel(v, io_buffer_virt(&display->mmio_dsi_phy) + a) + +#define READ32_HHI_REG(a) readl(io_buffer_virt(&display->mmio_hhi) + a) +#define WRITE32_HHI_REG(a, v) writel(v, io_buffer_virt(&display->mmio_hhi) + a) + +#define READ32_VPU_REG(a) readl(io_buffer_virt(&display->mmio_vpu) + a) +#define WRITE32_VPU_REG(a, v) writel(v, io_buffer_virt(&display->mmio_vpu) + a) + +#define SET_BIT32(x, dest, value, start, count) \ + WRITE32_##x##_REG(dest, (READ32_##x##_REG(dest) & ~DISPLAY_MASK(start, count)) | \ + (((value) << (start)) & DISPLAY_MASK(start, count))) + +#define GET_BIT32(x, dest, start, count) \ + ((READ32_##x##_REG(dest) >> (start)) & ((1 << (count)) - 1)) + +#define WRITE32_REG(x, a, v) WRITE32_##x##_REG(a, v) +#define READ32_REG(x, a) READ32_##x##_REG(a) #define DMC_CAV_LUT_DATAL (0x12 << 2) @@ -49,6 +88,93 @@ #define OSD2_DMC_CAV_INDEX 0x40 +// Should match display_mmios table in board driver +enum { + MMIO_CANVAS, + MMIO_MPI_DSI, + MMIO_DSI_PHY, + MMIO_HHI, + MMIO_VPU, +}; + +struct lcd_clk_config { /* unit: kHz */ + /* IN-OUT parameters */ + uint32_t fin; + uint32_t fout; + + /* pll parameters */ + uint32_t pll_mode; /* txl */ + uint32_t od_fb; + uint32_t pll_m; + uint32_t pll_n; + uint32_t pll_fvco; + uint32_t pll_od1_sel; + uint32_t pll_od2_sel; + uint32_t pll_od3_sel; + uint32_t pll_pi_div_sel; /* txhd */ + uint32_t pll_level; + uint32_t pll_frac; + uint32_t pll_fout; + uint32_t ss_level; + uint32_t div_sel; + uint32_t xd; + + /* clk path node parameters */ + uint32_t ss_level_max; + uint32_t pll_m_max; + uint32_t pll_m_min; + uint32_t pll_n_max; + uint32_t pll_n_min; + uint32_t pll_frac_range; + uint32_t pll_od_sel_max; + uint32_t div_sel_max; + uint32_t xd_max; + uint32_t pll_ref_fmax; + uint32_t pll_ref_fmin; + uint32_t pll_vco_fmax; + uint32_t pll_vco_fmin; + uint32_t pll_out_fmax; + uint32_t pll_out_fmin; + uint32_t div_in_fmax; + uint32_t div_out_fmax; + uint32_t xd_out_fmax; + uint32_t err_fmin; +}; + +/* This structure is populated based on hardware/lcd type. Its values come from vendor. + * This table is the top level structure used to populated all Clocks/LCD/DSI/BackLight/etc + * values + */ +struct display_setting { + // DSI/LCD Timings + uint32_t lcd_bits; + uint32_t hActive; + uint32_t vActive; + uint32_t hPeriod; + uint32_t vPeriod; + uint32_t hSync_width; + uint32_t hSync_backPorch; + uint32_t hSync_pol; + uint32_t vSync_width; + uint32_t vSync_backPorch; + uint32_t vSync_pol; + + // LCD configs + uint32_t fr_adj_type; + uint32_t ss_level; + uint32_t clk_auto_gen; + uint32_t lcd_clock; + + // MIPI/DSI configs + uint32_t lane_num; + uint32_t bit_rate_max; + uint32_t factor_numerator; + uint32_t opp_mode_init; + uint32_t opp_mode_display; + uint32_t video_mode_type; + uint32_t clk_always_hs; + uint32_t phy_switch; +}; typedef struct { zx_device_t* zxdev; @@ -64,9 +190,20 @@ thrd_t main_thread; io_buffer_t mmio_dmc; + io_buffer_t mmio_mipi_dsi; + io_buffer_t mmio_dsi_phy; + io_buffer_t mmio_hhi; + io_buffer_t mmio_vpu; io_buffer_t fbuffer; zx_display_info_t disp_info; + lcd_timing_t* lcd_timing; + dsi_config_t* dsi_cfg; + dsi_phy_config_t* dsi_phy_cfg; + dsi_video_t* dsi_vid; + struct display_setting* disp_setting; + struct lcd_clk_config* lcd_clk_cfg; + uint8_t input_color_format; uint8_t output_color_format; uint8_t color_depth; @@ -77,3 +214,13 @@ } astro_display_t; +void init_backlight(astro_display_t* display); +void config_canvas(astro_display_t* display); +zx_status_t astro_lcd_timing(astro_display_t* display); +zx_status_t astro_dsi_generate_hpll(astro_display_t* display); +zx_status_t astro_dsi_load_config(astro_display_t* display); +void dump_display_info(astro_display_t* display); + +zx_status_t display_clock_init(astro_display_t* display); +void lcd_mipi_phy_set(astro_display_t* display, bool enable); +zx_status_t aml_dsi_host_on(astro_display_t* display); \ No newline at end of file
diff --git a/system/dev/display/astro-display/backlight.c b/system/dev/display/astro-display/backlight.c new file mode 100644 index 0000000..cef16b2 --- /dev/null +++ b/system/dev/display/astro-display/backlight.c
@@ -0,0 +1,34 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +/* Table from Linux source */ +/* TODO: Need to separate backlight driver from display driver */ +static const uint8_t backlight_init_table[] = { + 0xa2, 0x20, + 0xa5, 0x54, + 0x00, 0xff, + 0x01, 0x05, + 0xa2, 0x20, + 0xa5, 0x54, + 0xa1, 0xb7, + 0xa0, 0xff, + 0x00, 0x80, +}; + +void init_backlight(astro_display_t* display) { + + // power on backlight + gpio_config(&display->gpio, 0, GPIO_DIR_OUT); + gpio_write(&display->gpio, 0, 1); + usleep(1000); + + for (size_t i = 0; i < sizeof(backlight_init_table); i+=2) { + if(i2c_transact_sync(&display->i2c, 0, &backlight_init_table[i], 2, NULL, 0) != ZX_OK) { + DISP_ERROR("Backlight write failed: reg[0x%x]: 0x%x\n", backlight_init_table[i], + backlight_init_table[i+1]); + } + } +}
diff --git a/system/dev/display/astro-display/canvas.c b/system/dev/display/astro-display/canvas.c new file mode 100644 index 0000000..3afa045 --- /dev/null +++ b/system/dev/display/astro-display/canvas.c
@@ -0,0 +1,26 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +void config_canvas(astro_display_t* display) { + uint32_t fbh = display->disp_info.height * 2; + uint32_t fbw = display->disp_info.stride * 2; + + DISP_INFO("Canvas Diminsions: w=%d h=%d\n", fbw, fbh); + + // set framebuffer address in DMC, read/modify/write + WRITE32_DMC_REG(DMC_CAV_LUT_DATAL, + (((io_buffer_phys(&display->fbuffer) + 7) >> 3) & DMC_CAV_ADDR_LMASK) | + ((((fbw + 7) >> 3) & DMC_CAV_WIDTH_LMASK) << DMC_CAV_WIDTH_LBIT)); + + WRITE32_DMC_REG(DMC_CAV_LUT_DATAH, + ((((fbw + 7) >> 3) >> DMC_CAV_WIDTH_LWID) << DMC_CAV_WIDTH_HBIT) | + ((fbh & DMC_CAV_HEIGHT_MASK) << DMC_CAV_HEIGHT_BIT)); + + WRITE32_DMC_REG(DMC_CAV_LUT_ADDR, DMC_CAV_LUT_ADDR_WR_EN | OSD2_DMC_CAV_INDEX ); + // read a cbus to make sure last write finish. + READ32_DMC_REG(DMC_CAV_LUT_DATAH); + +}
diff --git a/system/dev/display/astro-display/display_clock.c b/system/dev/display/astro-display/display_clock.c new file mode 100644 index 0000000..abc36cf --- /dev/null +++ b/system/dev/display/astro-display/display_clock.c
@@ -0,0 +1,329 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +/************************************************************************************************/ +/* VENC Related Configs */ +/************************************************************************************************/ + +#define STV2_SEL 5 +#define STV1_SEL 4 +static void lcd_encl_tcon_set(astro_display_t* display) +{ + + WRITE32_REG(VPU, L_RGB_BASE_ADDR, 0); + WRITE32_REG(VPU, L_RGB_COEFF_ADDR, 0x400); + + switch (display->lcd_timing->lcd_bits) { + case 6: + WRITE32_REG(VPU, L_DITH_CNTL_ADDR, 0x600); + break; + case 8: + WRITE32_REG(VPU, L_DITH_CNTL_ADDR, 0x400); + break; + case 10: + default: + WRITE32_REG(VPU, L_DITH_CNTL_ADDR, 0x0); + break; + } + + /* DE signal for TTL m8,m8m2 */ + WRITE32_REG(VPU, L_OEH_HS_ADDR, display->lcd_timing->de_hs_addr); + WRITE32_REG(VPU, L_OEH_HE_ADDR, display->lcd_timing->de_he_addr); + WRITE32_REG(VPU, L_OEH_VS_ADDR, display->lcd_timing->de_vs_addr); + WRITE32_REG(VPU, L_OEH_VE_ADDR, display->lcd_timing->de_ve_addr); + /* DE signal for TTL m8b */ + WRITE32_REG(VPU, L_OEV1_HS_ADDR, display->lcd_timing->de_hs_addr); + WRITE32_REG(VPU, L_OEV1_HE_ADDR, display->lcd_timing->de_he_addr); + WRITE32_REG(VPU, L_OEV1_VS_ADDR, display->lcd_timing->de_vs_addr); + WRITE32_REG(VPU, L_OEV1_VE_ADDR, display->lcd_timing->de_ve_addr); + + /* Hsync signal for TTL m8,m8m2 */ + if (display->lcd_timing->hSync_pol == 0) { + WRITE32_REG(VPU, L_STH1_HS_ADDR, display->lcd_timing->hs_he_addr); + WRITE32_REG(VPU, L_STH1_HE_ADDR, display->lcd_timing->hs_hs_addr); + } else { + WRITE32_REG(VPU, L_STH1_HS_ADDR, display->lcd_timing->hs_hs_addr); + WRITE32_REG(VPU, L_STH1_HE_ADDR, display->lcd_timing->hs_he_addr); + } + WRITE32_REG(VPU, L_STH1_VS_ADDR, display->lcd_timing->hs_vs_addr); + WRITE32_REG(VPU, L_STH1_VE_ADDR, display->lcd_timing->hs_ve_addr); + + /* Vsync signal for TTL m8,m8m2 */ + WRITE32_REG(VPU, L_STV1_HS_ADDR, display->lcd_timing->vs_hs_addr); + WRITE32_REG(VPU, L_STV1_HE_ADDR, display->lcd_timing->vs_he_addr); + if (display->lcd_timing->vSync_pol == 0) { + WRITE32_REG(VPU, L_STV1_VS_ADDR, display->lcd_timing->vs_ve_addr); + WRITE32_REG(VPU, L_STV1_VE_ADDR, display->lcd_timing->vs_vs_addr); + } else { + WRITE32_REG(VPU, L_STV1_VS_ADDR, display->lcd_timing->vs_vs_addr); + WRITE32_REG(VPU, L_STV1_VE_ADDR, display->lcd_timing->vs_ve_addr); + } + + /* DE signal */ + WRITE32_REG(VPU, L_DE_HS_ADDR, display->lcd_timing->de_hs_addr); + WRITE32_REG(VPU, L_DE_HE_ADDR, display->lcd_timing->de_he_addr); + WRITE32_REG(VPU, L_DE_VS_ADDR, display->lcd_timing->de_vs_addr); + WRITE32_REG(VPU, L_DE_VE_ADDR, display->lcd_timing->de_ve_addr); + + /* Hsync signal */ + WRITE32_REG(VPU, L_HSYNC_HS_ADDR, display->lcd_timing->hs_hs_addr); + WRITE32_REG(VPU, L_HSYNC_HE_ADDR, display->lcd_timing->hs_he_addr); + WRITE32_REG(VPU, L_HSYNC_VS_ADDR, display->lcd_timing->hs_vs_addr); + WRITE32_REG(VPU, L_HSYNC_VE_ADDR, display->lcd_timing->hs_ve_addr); + + /* Vsync signal */ + WRITE32_REG(VPU, L_VSYNC_HS_ADDR, display->lcd_timing->vs_hs_addr); + WRITE32_REG(VPU, L_VSYNC_HE_ADDR, display->lcd_timing->vs_he_addr); + WRITE32_REG(VPU, L_VSYNC_VS_ADDR, display->lcd_timing->vs_vs_addr); + WRITE32_REG(VPU, L_VSYNC_VE_ADDR, display->lcd_timing->vs_ve_addr); + + WRITE32_REG(VPU, L_INV_CNT_ADDR, 0); + WRITE32_REG(VPU, L_TCON_MISC_SEL_ADDR, ((1 << STV1_SEL) | (1 << STV2_SEL))); + + WRITE32_REG(VPU, VPP_MISC, READ32_REG(VPU, VPP_MISC) & ~(VPP_OUT_SATURATE)); +} + +static void lcd_venc_set(astro_display_t* display) +{ + unsigned int h_active, v_active; + unsigned int video_on_pixel, video_on_line; + + h_active = display->lcd_timing->h_active; + v_active = display->lcd_timing->v_active; + video_on_pixel = display->lcd_timing->vid_pixel_on; + video_on_line = display->lcd_timing->vid_line_on; + + WRITE32_REG(VPU, ENCL_VIDEO_EN, 0); + + WRITE32_REG(VPU, VPU_VIU_VENC_MUX_CTRL, (0 << 0) | (0 << 2)); // viu1 select encl | viu2 select encl + WRITE32_REG(VPU, ENCL_VIDEO_MODE, 0x8000); // bit[15] shadown en + WRITE32_REG(VPU, ENCL_VIDEO_MODE_ADV, 0x0418); // Sampling rate: 1 + + // bypass filter + WRITE32_REG(VPU, ENCL_VIDEO_FILT_CTRL, 0x1000); + WRITE32_REG(VPU, ENCL_VIDEO_MAX_PXCNT, display->lcd_timing->h_period - 1); + WRITE32_REG(VPU, ENCL_VIDEO_MAX_LNCNT, display->lcd_timing->v_period - 1); + WRITE32_REG(VPU, ENCL_VIDEO_HAVON_BEGIN, video_on_pixel); + WRITE32_REG(VPU, ENCL_VIDEO_HAVON_END, h_active - 1 + video_on_pixel); + WRITE32_REG(VPU, ENCL_VIDEO_VAVON_BLINE, video_on_line); + WRITE32_REG(VPU, ENCL_VIDEO_VAVON_ELINE, v_active - 1 + video_on_line); + + WRITE32_REG(VPU, ENCL_VIDEO_HSO_BEGIN, display->lcd_timing->hs_hs_addr); + WRITE32_REG(VPU, ENCL_VIDEO_HSO_END, display->lcd_timing->hs_he_addr); + WRITE32_REG(VPU, ENCL_VIDEO_VSO_BEGIN, display->lcd_timing->vs_hs_addr); + WRITE32_REG(VPU, ENCL_VIDEO_VSO_END, display->lcd_timing->vs_he_addr); + WRITE32_REG(VPU, ENCL_VIDEO_VSO_BLINE, display->lcd_timing->vs_vs_addr); + WRITE32_REG(VPU, ENCL_VIDEO_VSO_ELINE, display->lcd_timing->vs_ve_addr); + WRITE32_REG(VPU, ENCL_VIDEO_RGBIN_CTRL, 3); + + WRITE32_REG(VPU, ENCL_VIDEO_EN, 1); +} + + +/************************************************************************************************/ +/* PLL / CLOCK Related Configs */ +/************************************************************************************************/ +static unsigned int lcd_clk_div_g9_gxtvbb[][3] = { + /* divider, shift_val, shift_sel */ + {CLK_DIV_SEL_1, 0xffff, 0,}, + {CLK_DIV_SEL_2, 0x0aaa, 0,}, + {CLK_DIV_SEL_3, 0x0db6, 0,}, + {CLK_DIV_SEL_3p5, 0x36cc, 1,}, + {CLK_DIV_SEL_3p75, 0x6666, 2,}, + {CLK_DIV_SEL_4, 0x0ccc, 0,}, + {CLK_DIV_SEL_5, 0x739c, 2,}, + {CLK_DIV_SEL_6, 0x0e38, 0,}, + {CLK_DIV_SEL_6p25, 0x0000, 3,}, + {CLK_DIV_SEL_7, 0x3c78, 1,}, + {CLK_DIV_SEL_7p5, 0x78f0, 2,}, + {CLK_DIV_SEL_12, 0x0fc0, 0,}, + {CLK_DIV_SEL_14, 0x3f80, 1,}, + {CLK_DIV_SEL_15, 0x7f80, 2,}, + {CLK_DIV_SEL_2p5, 0x5294, 2,}, + {CLK_DIV_SEL_MAX, 0xffff, 0,}, +}; + +static void lcd_set_vclk_crt(astro_display_t* display) +{ + struct lcd_clk_config *cConf = display->lcd_clk_cfg; + + /* setup the XD divider value */ + SET_BIT32(HHI, HHI_VIID_CLK_DIV, (cConf->xd-1), VCLK2_XD, 8); + usleep(5); + + /* select vid_pll_clk */ + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 0, VCLK2_CLK_IN_SEL, 3); + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 1, VCLK2_EN, 1); + usleep(2); + + /* [15:12] encl_clk_sel, select vclk2_div1 */ + SET_BIT32(HHI, HHI_VIID_CLK_DIV, 8, ENCL_CLK_SEL, 4); + /* release vclk2_div_reset and enable vclk2_div */ + SET_BIT32(HHI, HHI_VIID_CLK_DIV, 1, VCLK2_XD_EN, 2); + usleep(5); + + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 1, VCLK2_DIV1_EN, 1); + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 1, VCLK2_SOFT_RST, 1); + usleep(10); + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 0, VCLK2_SOFT_RST, 1); + usleep(5); + + /* enable CTS_ENCL clk gate */ + SET_BIT32(HHI, HHI_VID_CLK_CNTL2, 1, ENCL_GATE_VCLK, 1); +} + +static void lcd_set_vid_pll_div(astro_display_t* display) +{ + unsigned int shift_val, shift_sel; + int i; + struct lcd_clk_config *cConf = display->lcd_clk_cfg; + + SET_BIT32(HHI, HHI_VIID_CLK_CNTL, 0, VCLK2_EN, 1); + usleep(5); + + /* Disable the div output clock */ + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 19, 1); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 15, 1); + + i = 0; + while (lcd_clk_div_g9_gxtvbb[i][0] != CLK_DIV_SEL_MAX) { + if (cConf->div_sel == lcd_clk_div_g9_gxtvbb[i][0]) + break; + i++; + } + if (lcd_clk_div_g9_gxtvbb[i][0] == CLK_DIV_SEL_MAX) + DISP_ERROR("invalid clk divider\n"); + shift_val = lcd_clk_div_g9_gxtvbb[i][1]; + shift_sel = lcd_clk_div_g9_gxtvbb[i][2]; + + if (shift_val == 0xffff) { /* if divide by 1 */ + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 1, 18, 1); + } else { + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 18, 1); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 16, 2); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 15, 1); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 0, 14); + + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, shift_sel, 16, 2); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 1, 15, 1); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, shift_val, 0, 14); + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 0, 15, 1); + } + /* Enable the final output clock */ + SET_BIT32(HHI, HHI_VID_PLL_CLK_DIV, 1, 19, 1); +} + +#define PLL_WAIT_LOCK_CNT_G12A 1000 +static int lcd_pll_wait_lock_g12a(astro_display_t* display) +{ + // uint32_t pll_ctrl, pll_ctrl3, pll_ctrl6; + uint32_t pll_lock; + int wait_loop = PLL_WAIT_LOCK_CNT_G12A; /* 200 */ + zx_status_t status = ZX_OK; + + // pll_ctrl = HHI_HDMI_PLL_CNTL0; + // pll_ctrl3 = HHI_HDMI_PLL_CNTL3; + // pll_ctrl6 = HHI_HDMI_PLL_CNTL6; + do { + usleep(50); + pll_lock = GET_BIT32(HHI, HHI_HDMI_PLL_CNTL0, 31, 1); + wait_loop--; + } while ((pll_lock != 1) && (wait_loop > 0)); + + if (pll_lock == 1) { + goto pll_lock_end_g12a; + } else { + DISP_ERROR("pll try 1, lock: %d\n", pll_lock); + SET_BIT32(HHI, HHI_HDMI_PLL_CNTL3, 1, 31, 1); + wait_loop = PLL_WAIT_LOCK_CNT_G12A; + do { + usleep(50); + pll_lock = GET_BIT32(HHI, HHI_HDMI_PLL_CNTL0, 31, 1); + wait_loop--; + } while ((pll_lock != 1) && (wait_loop > 0)); + } + + if (pll_lock == 1) { + goto pll_lock_end_g12a; + } else { + DISP_ERROR("pll try 2, lock: %d\n", pll_lock); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL6, 0x55540000); + wait_loop = PLL_WAIT_LOCK_CNT_G12A; + do { + usleep(50); + pll_lock = GET_BIT32(HHI, HHI_HDMI_PLL_CNTL0, 31, 1); + wait_loop--; + } while ((pll_lock != 1) && (wait_loop > 0)); + } + + if (pll_lock != 1) + status = ZX_ERR_CALL_FAILED; + +pll_lock_end_g12a: + DISP_ERROR("pll_lock=%d, wait_loop=%d\n", pll_lock, (PLL_WAIT_LOCK_CNT_G12A - wait_loop)); + return status; +} + +zx_status_t display_clock_init(astro_display_t* display) { + zx_status_t status = ZX_OK; + uint32_t pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6; + struct lcd_clk_config *cConf = display->lcd_clk_cfg; + + pll_ctrl = ((1 << LCD_PLL_EN_HPLL_G12A) | + (1 << 25) | /* clk out gate */ + (cConf->pll_n << LCD_PLL_N_HPLL_G12A) | + (cConf->pll_m << LCD_PLL_M_HPLL_G12A) | + (cConf->pll_od1_sel << LCD_PLL_OD1_HPLL_G12A) | + (cConf->pll_od2_sel << LCD_PLL_OD2_HPLL_G12A) | + (cConf->pll_od3_sel << LCD_PLL_OD3_HPLL_G12A)); + pll_ctrl1 = (cConf->pll_frac << 0); + if (cConf->pll_frac) { + pll_ctrl |= (1 << 27); + pll_ctrl3 = 0x6a285c00; + pll_ctrl4 = 0x65771290; + pll_ctrl6 = 0x56540000; + } else { + pll_ctrl3 = 0x48681c00; + pll_ctrl4 = 0x33771290; + pll_ctrl6 = 0x56540000; + } + + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL0, pll_ctrl); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL1, pll_ctrl1); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL2, 0x00); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL3, pll_ctrl3); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL4, pll_ctrl4); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL5, 0x39272000); + WRITE32_REG(HHI, HHI_HDMI_PLL_CNTL6, pll_ctrl6); + SET_BIT32(HHI, HHI_HDMI_PLL_CNTL0, 1, LCD_PLL_RST_HPLL_G12A, 1); + usleep(100); + SET_BIT32(HHI, HHI_HDMI_PLL_CNTL0, 0, LCD_PLL_RST_HPLL_G12A, 1); + + status = lcd_pll_wait_lock_g12a(display); + if (status != ZX_OK) { + DISP_ERROR("hpll lock failed\n"); + goto exit; + } + + lcd_set_vid_pll_div(display); + + SET_BIT32(HHI, HHI_VDIN_MEAS_CLK_CNTL, 0, 21, 3); + SET_BIT32(HHI, HHI_VDIN_MEAS_CLK_CNTL, 0, 12, 7); + SET_BIT32(HHI, HHI_VDIN_MEAS_CLK_CNTL, 1, 20, 1); + + SET_BIT32(HHI, HHI_MIPIDSI_PHY_CLK_CNTL, 0, 12, 3); + SET_BIT32(HHI, HHI_MIPIDSI_PHY_CLK_CNTL, 1, 8, 1); + SET_BIT32(HHI, HHI_MIPIDSI_PHY_CLK_CNTL, 0, 0, 7); + + lcd_set_vclk_crt(display); + usleep(10000); + + lcd_venc_set(display); + lcd_encl_tcon_set(display); + +exit: + return status; +} \ No newline at end of file
diff --git a/system/dev/display/astro-display/display_config.c b/system/dev/display/astro-display/display_config.c new file mode 100644 index 0000000..d63b000 --- /dev/null +++ b/system/dev/display/astro-display/display_config.c
@@ -0,0 +1,339 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +static const unsigned int od_fb_table[2] = {1, 2}; +static const unsigned int od_table[6] = { + 1, 2, 4, 8, 16, 32 +}; + +static int check_pll(struct lcd_clk_config *cConf, + unsigned int pll_fout) +{ + unsigned int m, n; + unsigned int od1_sel, od2_sel, od3_sel, od1, od2, od3; + unsigned int pll_fod2_in, pll_fod3_in, pll_fvco; + unsigned int od_fb = 0, pll_frac; + int done; + + done = 0; + if ((pll_fout > cConf->pll_out_fmax) || + (pll_fout < cConf->pll_out_fmin)) { + return done; + } + for (od3_sel = cConf->pll_od_sel_max; od3_sel > 0; od3_sel--) { + od3 = od_table[od3_sel - 1]; + pll_fod3_in = pll_fout * od3; + for (od2_sel = od3_sel; od2_sel > 0; od2_sel--) { + od2 = od_table[od2_sel - 1]; + pll_fod2_in = pll_fod3_in * od2; + for (od1_sel = od2_sel; od1_sel > 0; od1_sel--) { + od1 = od_table[od1_sel - 1]; + pll_fvco = pll_fod2_in * od1; + if ((pll_fvco < cConf->pll_vco_fmin) || + (pll_fvco > cConf->pll_vco_fmax)) { + continue; + } + cConf->pll_od1_sel = od1_sel - 1; + cConf->pll_od2_sel = od2_sel - 1; + cConf->pll_od3_sel = od3_sel - 1; + cConf->pll_fout = pll_fout; + cConf->pll_fvco = pll_fvco; + n = 1; + od_fb = cConf->od_fb; + pll_fvco = pll_fvco / od_fb_table[od_fb]; + m = pll_fvco / cConf->fin; + pll_frac = (pll_fvco % cConf->fin) * + cConf->pll_frac_range / cConf->fin; + cConf->pll_m = m; + cConf->pll_n = n; + cConf->pll_frac = pll_frac; + done = 1; + break; + } + } + } + return done; +} + +zx_status_t astro_dsi_generate_hpll(astro_display_t* display) { + uint32_t dsi_bit_rate_min = 0; + uint32_t dsi_bit_rate_max = 0; + uint32_t tmp; + uint32_t pll_fout; + uint32_t clk_div_sel, xd; + int done; + + ZX_DEBUG_ASSERT(display); + ZX_DEBUG_ASSERT(display->dsi_cfg); + ZX_DEBUG_ASSERT(display->lcd_clk_cfg); + + display->lcd_clk_cfg->fout = display->lcd_timing->lcd_clock / 1000; // KHz + display->lcd_clk_cfg->err_fmin = MAX_ERROR; + if (display->lcd_clk_cfg->fout > display->lcd_clk_cfg->xd_out_fmax) { + DISP_ERROR("Invalid LCD Clock value %dKHz\n", display->lcd_clk_cfg->fout); + return ZX_ERR_OUT_OF_RANGE; + } + + display->lcd_clk_cfg->xd_max = CRT_VID_DIV_MAX; + tmp = display->dsi_cfg->bit_rate_max; + dsi_bit_rate_max = tmp * 1000; // change to KHz + dsi_bit_rate_min = dsi_bit_rate_max - display->lcd_clk_cfg->fout; + + clk_div_sel = CLK_DIV_SEL_1; + for (xd = 1; xd <= display->lcd_clk_cfg->xd_max; xd++) { + pll_fout = display->lcd_clk_cfg->fout * xd; + if ((pll_fout > dsi_bit_rate_max) || (pll_fout < dsi_bit_rate_min)) { + continue; + } + display->dsi_cfg->bit_rate = pll_fout * 1000; + display->dsi_cfg->clock_factor = xd; + display->lcd_clk_cfg->xd = xd; + display->lcd_clk_cfg->div_sel = clk_div_sel; + done = check_pll(display->lcd_clk_cfg, pll_fout); + if (done) { + goto generate_clk_done; + } + } + +generate_clk_done: + if (done) { + display->lcd_timing->pll_ctrl = + (display->lcd_clk_cfg->pll_od1_sel << PLL_CTRL_OD1) | + (display->lcd_clk_cfg->pll_od2_sel << PLL_CTRL_OD2) | + (display->lcd_clk_cfg->pll_od3_sel << PLL_CTRL_OD3) | + (display->lcd_clk_cfg->pll_n << PLL_CTRL_N) | + (display->lcd_clk_cfg->pll_m << PLL_CTRL_M); + display->lcd_timing->div_ctrl = + (display->lcd_clk_cfg->div_sel << DIV_CTRL_DIV_SEL) | + (display->lcd_clk_cfg->xd << DIV_CTRL_XD); + display->lcd_timing->clk_ctrl = (display->lcd_clk_cfg->pll_frac << CLK_CTRL_FRAC); + } else { + display->lcd_timing->pll_ctrl = + (1 << PLL_CTRL_OD1) | + (1 << PLL_CTRL_OD2) | + (1 << PLL_CTRL_OD3) | + (1 << PLL_CTRL_N) | + (50 << PLL_CTRL_M); + display->lcd_timing->div_ctrl = + (CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) | + (7 << DIV_CTRL_XD); + display->lcd_timing->clk_ctrl = (0 << CLK_CTRL_FRAC); + DISP_ERROR("Out of clock range, reset to default setting\n"); + } + + display->lcd_clk_cfg->ss_level = + (display->lcd_timing->ss_level > display->lcd_clk_cfg->ss_level_max)? + 0 : display->lcd_timing->ss_level; + + return ZX_OK; +} + +zx_status_t astro_dsi_load_config(astro_display_t* display) { + zx_status_t status = ZX_OK; + + ZX_DEBUG_ASSERT(display); + + if (!display->disp_setting) { + DISP_ERROR("Display Configuration has not been populated! Exiting.\n"); + return ZX_ERR_UNAVAILABLE; + } + + if (!display->lcd_clk_cfg) { + DISP_ERROR("LCD Clock/PLL Configuration has not been populated! Exiting.\n"); + return ZX_ERR_UNAVAILABLE; + } + + // lcd timing should already be populated + if(!display->lcd_timing) { + DISP_ERROR("LCD Timing structure has not been populated! Exiting.\n"); + return ZX_ERR_UNAVAILABLE; + } + + // allocate dsi config structure + if (display->dsi_cfg != NULL) { + DISP_INFO("Re-Populating MIPI DSI Config parameters\n"); + memset(display->dsi_cfg, 0, sizeof(dsi_config_t)); + } else { + display->dsi_cfg = calloc(1, sizeof(dsi_config_t)); + if (!display->dsi_cfg) { + DISP_ERROR("Could not allocate dsi_config structure\n"); + return ZX_ERR_NO_MEMORY; + } + } + + // allocate dsi phy config here as well + if (display->dsi_phy_cfg != NULL) { + DISP_INFO("Re-Populating MIPI DSI PHY Config parameters\n"); + memset(display->dsi_phy_cfg, 0, sizeof(dsi_phy_config_t)); + } else { + display->dsi_phy_cfg = calloc(1, sizeof(dsi_phy_config_t)); + if (!display->dsi_phy_cfg) { + DISP_ERROR("Could not allocate dsi_phy_cfg structure\n"); + return ZX_ERR_NO_MEMORY; + } + } + + display->dsi_cfg->lane_num = display->disp_setting->lane_num; + display->dsi_cfg->bit_rate_max = display->disp_setting->bit_rate_max; + display->dsi_cfg->factor_numerator = display->disp_setting->factor_numerator; + display->dsi_cfg->opp_mode_init = display->disp_setting->opp_mode_init; + display->dsi_cfg->opp_mode_display = display->disp_setting->opp_mode_display; + display->dsi_cfg->video_mode_type = display->disp_setting->video_mode_type; + display->dsi_cfg->clk_always_hs = display->disp_setting->clk_always_hs; + display->dsi_cfg->phy_switch = display->disp_setting->phy_switch; + + if (display->lcd_timing->lcd_bits == 8) { + display->dsi_cfg->venc_data_width = MIPI_DSI_VENC_COLOR_24B; + display->dsi_cfg->dpi_data_format = MIPI_DSI_COLOR_24BIT; + } else { + DISP_ERROR("Unsupported LCD Bits\n"); + return ZX_ERR_NOT_SUPPORTED; + } + + + if (display->dsi_cfg->bit_rate_max == 0) { + DISP_ERROR("Auto bit rate calculation not supported\n"); + return ZX_ERR_NOT_SUPPORTED; + } + + if (display->dsi_cfg->bit_rate_max < (display->lcd_clk_cfg->pll_out_fmin/1000)) { + DISP_ERROR("Bit rate of %dMHz not supported (min = %dMHz)\n", + display->dsi_cfg->bit_rate_max, (display->lcd_clk_cfg->pll_out_fmin/1000)); + return ZX_ERR_OUT_OF_RANGE; + } + + if (display->dsi_cfg->bit_rate_max > MIPI_PHY_CLK_MAX) { + DISP_ERROR("Bit rate of %dMHz out of range (max = %dMHz)\n", + display->dsi_cfg->bit_rate_max, MIPI_PHY_CLK_MAX); + return ZX_ERR_OUT_OF_RANGE; + } + + /* Venc resolution format */ + switch (display->disp_setting->phy_switch) { + case 1: /* standard */ + display->dsi_phy_cfg->state_change = 1; + break; + case 2: /* slow */ + display->dsi_phy_cfg->state_change = 2; + break; + case 0: /* auto */ + default: + if ((display->lcd_timing->h_active != 240) && + (display->lcd_timing->h_active != 768) && + (display->lcd_timing->h_active != 1920) && + (display->lcd_timing->h_active != 2560)) { + display->dsi_phy_cfg->state_change = 2; + } else { + display->dsi_phy_cfg->state_change = 1; + } + break; + } + + return status; +} + +zx_status_t astro_lcd_timing(astro_display_t* display) { + zx_status_t status = ZX_OK; + uint32_t de_hstart, de_vstart; + uint32_t hstart, hend, vstart, vend; + uint32_t hPeriod, vPeriod, hActive, vActive; + uint32_t hSync_backPorch, hSync_width, vSync_width, vSync_backPorch; + uint32_t sync_duration; + uint32_t clk; + ZX_DEBUG_ASSERT(display); + + if (!display->disp_setting) { + DISP_ERROR("Display Configuration has not been populated! Exiting.\n"); + return ZX_ERR_UNAVAILABLE; + } + + // allocate lcd_timing structure + if (display->lcd_timing != NULL) { + DISP_INFO("Re-Populating LCD Timing parameters\n"); + memset(display->lcd_timing, 0, sizeof(lcd_timing_t)); + } else { + display->lcd_timing = calloc(1, sizeof(lcd_timing_t)); + if (!display->lcd_timing) { + DISP_ERROR("Could not allocate lcd_timing structure\n"); + return ZX_ERR_NO_MEMORY; + } + } + + // populate values that match 1:1 + display->lcd_timing->fr_adj_type = display->disp_setting->fr_adj_type; + display->lcd_timing->ss_level = display->disp_setting->ss_level; + display->lcd_timing->clk_auto_gen = display->disp_setting->clk_auto_gen; + display->lcd_timing->lcd_clock = display->disp_setting->lcd_clock; + + display->lcd_timing->hSync_width = display->disp_setting->hSync_width; + display->lcd_timing->hSync_backPorch = display->disp_setting->hSync_backPorch; + display->lcd_timing->hSync_pol = display->disp_setting->hSync_pol; + display->lcd_timing->vSync_width = display->disp_setting->vSync_width; + display->lcd_timing->vSync_backPorch = display->disp_setting->vSync_backPorch; + display->lcd_timing->vSync_pol = display->disp_setting->vSync_pol; + + display->lcd_timing->lcd_bits = display->disp_setting->lcd_bits; + display->lcd_timing->h_active = display->disp_setting->hActive; + display->lcd_timing->v_active = display->disp_setting->vActive; + display->lcd_timing->h_period = display->disp_setting->hPeriod; + display->lcd_timing->v_period = display->disp_setting->vPeriod; + + clk = display->lcd_timing->lcd_clock; + + if (clk < 200) { + sync_duration = clk * 100; + display->lcd_timing->lcd_clock = clk * display->lcd_timing->h_period * + display->lcd_timing->v_period; + } else { + sync_duration = ((clk / display->lcd_timing->h_period) * 100) / + display->lcd_timing->v_period; + } + + display->lcd_timing->lcd_clk_dft = display->lcd_timing->lcd_clock; + display->lcd_timing->hPeriod_dft = display->lcd_timing->h_period; + display->lcd_timing->vPeriod_dft = display->lcd_timing->v_period; + display->lcd_timing->sync_duration_numerator = sync_duration; + display->lcd_timing->sync_duration_denominator = 100; + + + hPeriod = display->lcd_timing->h_period; + vPeriod = display->lcd_timing->v_period; + hActive = display->lcd_timing->h_active; + vActive = display->lcd_timing->v_active; + + hSync_width = display->lcd_timing->hSync_width; + hSync_backPorch = display->lcd_timing->hSync_backPorch; + vSync_width = display->lcd_timing->vSync_width; + vSync_backPorch = display->lcd_timing->vSync_backPorch; + + de_hstart = hPeriod - hActive - 1; + de_vstart = vPeriod - vActive; + + display->lcd_timing->vid_pixel_on = de_hstart; + display->lcd_timing->vid_line_on = de_vstart; + + display->lcd_timing->de_hs_addr = de_hstart; + display->lcd_timing->de_he_addr = de_hstart + hActive; + display->lcd_timing->de_vs_addr = de_vstart; + display->lcd_timing->de_ve_addr = de_vstart + vActive - 1; + + + hstart = (de_hstart + hPeriod - hSync_backPorch - hSync_width) % hPeriod; + hend = (de_hstart + hPeriod - hSync_backPorch) % hPeriod; + display->lcd_timing->hs_hs_addr = hstart; + display->lcd_timing->hs_he_addr = hend; + display->lcd_timing->hs_vs_addr = 0; + display->lcd_timing->hs_ve_addr = vPeriod - 1; + + display->lcd_timing->vs_hs_addr = (hstart + hPeriod) % hPeriod; + display->lcd_timing->vs_he_addr = display->lcd_timing->vs_hs_addr; + vstart = (de_vstart + vPeriod - vSync_backPorch - vSync_width) % vPeriod; + vend = (de_vstart + vPeriod - vSync_backPorch) % vPeriod; + display->lcd_timing->vs_vs_addr = vstart; + display->lcd_timing->vs_ve_addr = vend; + + return status; +} \ No newline at end of file
diff --git a/system/dev/display/astro-display/display_debug.c b/system/dev/display/astro-display/display_debug.c new file mode 100644 index 0000000..7b21c4a --- /dev/null +++ b/system/dev/display/astro-display/display_debug.c
@@ -0,0 +1,194 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +void dump_display_info(astro_display_t* display) { + + if (display->lcd_clk_cfg) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping lcd_clk_cfg structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("fin = 0x%x (%u)\n", display->lcd_clk_cfg->fin,display->lcd_clk_cfg->fin); + DISP_INFO("fout = 0x%x (%u)\n", display->lcd_clk_cfg->fout,display->lcd_clk_cfg->fout); + DISP_INFO("pll_mode = 0x%x (%u)\n", display->lcd_clk_cfg->pll_mode,display->lcd_clk_cfg->pll_mode); + DISP_INFO("od_fb = 0x%x (%u)\n", display->lcd_clk_cfg->od_fb,display->lcd_clk_cfg->od_fb); + DISP_INFO("pll_m = 0x%x (%u)\n", display->lcd_clk_cfg->pll_m,display->lcd_clk_cfg->pll_m); + DISP_INFO("pll_n = 0x%x (%u)\n", display->lcd_clk_cfg->pll_n,display->lcd_clk_cfg->pll_n); + DISP_INFO("pll_fvco = 0x%x (%u)\n", display->lcd_clk_cfg->pll_fvco,display->lcd_clk_cfg->pll_fvco); + DISP_INFO("pll_od1_sel = 0x%x (%u)\n", display->lcd_clk_cfg->pll_od1_sel,display->lcd_clk_cfg->pll_od1_sel); + DISP_INFO("pll_od2_sel = 0x%x (%u)\n", display->lcd_clk_cfg->pll_od2_sel,display->lcd_clk_cfg->pll_od2_sel); + DISP_INFO("pll_od3_sel = 0x%x (%u)\n", display->lcd_clk_cfg->pll_od3_sel,display->lcd_clk_cfg->pll_od3_sel); + DISP_INFO("pll_pi_div_sel = 0x%x (%u)\n", display->lcd_clk_cfg->pll_pi_div_sel,display->lcd_clk_cfg->pll_pi_div_sel); + DISP_INFO("pll_level = 0x%x (%u)\n", display->lcd_clk_cfg->pll_level,display->lcd_clk_cfg->pll_level); + DISP_INFO("pll_frac = 0x%x (%u)\n", display->lcd_clk_cfg->pll_frac,display->lcd_clk_cfg->pll_frac); + DISP_INFO("pll_fout = 0x%x (%u)\n", display->lcd_clk_cfg->pll_fout,display->lcd_clk_cfg->pll_fout); + DISP_INFO("ss_level = 0x%x (%u)\n", display->lcd_clk_cfg->ss_level,display->lcd_clk_cfg->ss_level); + DISP_INFO("div_sel = 0x%x (%u)\n", display->lcd_clk_cfg->div_sel,display->lcd_clk_cfg->div_sel); + DISP_INFO("xd = 0x%x (%u)\n", display->lcd_clk_cfg->xd,display->lcd_clk_cfg->xd); + DISP_INFO("ss_level_max = 0x%x (%u)\n", display->lcd_clk_cfg->ss_level_max,display->lcd_clk_cfg->ss_level_max); + DISP_INFO("pll_m_max = 0x%x (%u)\n", display->lcd_clk_cfg->pll_m_max,display->lcd_clk_cfg->pll_m_max); + DISP_INFO("pll_m_min = 0x%x (%u)\n", display->lcd_clk_cfg->pll_m_min,display->lcd_clk_cfg->pll_m_min); + DISP_INFO("pll_n_max = 0x%x (%u)\n", display->lcd_clk_cfg->pll_n_max,display->lcd_clk_cfg->pll_n_max); + DISP_INFO("pll_n_min = 0x%x (%u)\n", display->lcd_clk_cfg->pll_n_min,display->lcd_clk_cfg->pll_n_min); + DISP_INFO("pll_frac_range = 0x%x (%u)\n", display->lcd_clk_cfg->pll_frac_range,display->lcd_clk_cfg->pll_frac_range); + DISP_INFO("pll_od_sel_max = 0x%x (%u)\n", display->lcd_clk_cfg->pll_od_sel_max,display->lcd_clk_cfg->pll_od_sel_max); + DISP_INFO("div_sel_max = 0x%x (%u)\n", display->lcd_clk_cfg->div_sel_max,display->lcd_clk_cfg->div_sel_max); + DISP_INFO("xd_max = 0x%x (%u)\n", display->lcd_clk_cfg->xd_max,display->lcd_clk_cfg->xd_max); + DISP_INFO("pll_ref_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->pll_ref_fmax,display->lcd_clk_cfg->pll_ref_fmax); + DISP_INFO("pll_ref_fmin = 0x%x (%u)\n", display->lcd_clk_cfg->pll_ref_fmin,display->lcd_clk_cfg->pll_ref_fmin); + DISP_INFO("pll_vco_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->pll_vco_fmax,display->lcd_clk_cfg->pll_vco_fmax); + DISP_INFO("pll_vco_fmin = 0x%x (%u)\n", display->lcd_clk_cfg->pll_vco_fmin,display->lcd_clk_cfg->pll_vco_fmin); + DISP_INFO("pll_out_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->pll_out_fmax,display->lcd_clk_cfg->pll_out_fmax); + DISP_INFO("pll_out_fmin = 0x%x (%u)\n", display->lcd_clk_cfg->pll_out_fmin,display->lcd_clk_cfg->pll_out_fmin); + DISP_INFO("div_in_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->div_in_fmax,display->lcd_clk_cfg->div_in_fmax); + DISP_INFO("div_out_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->div_out_fmax,display->lcd_clk_cfg->div_out_fmax); + DISP_INFO("xd_out_fmax = 0x%x (%u)\n", display->lcd_clk_cfg->xd_out_fmax,display->lcd_clk_cfg->xd_out_fmax); + DISP_INFO("err_fmin = 0x%x (%u)\n", display->lcd_clk_cfg->err_fmin,display->lcd_clk_cfg->err_fmin); + } + + if (display->disp_setting) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping disp_setting structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("lcd_bits = 0x%x (%u)\n", display->disp_setting->lcd_bits, display->disp_setting->lcd_bits); + DISP_INFO("hActive = 0x%x (%u)\n", display->disp_setting->hActive, display->disp_setting->hActive); + DISP_INFO("vActive = 0x%x (%u)\n", display->disp_setting->vActive, display->disp_setting->vActive); + DISP_INFO("hPeriod = 0x%x (%u)\n", display->disp_setting->hPeriod, display->disp_setting->hPeriod); + DISP_INFO("vPeriod = 0x%x (%u)\n", display->disp_setting->vPeriod, display->disp_setting->vPeriod); + DISP_INFO("hSync_width = 0x%x (%u)\n", display->disp_setting->hSync_width, display->disp_setting->hSync_width); + DISP_INFO("hSync_backPorch = 0x%x (%u)\n", display->disp_setting->hSync_backPorch, display->disp_setting->hSync_backPorch); + DISP_INFO("hSync_pol = 0x%x (%u)\n", display->disp_setting->hSync_pol, display->disp_setting->hSync_pol); + DISP_INFO("vSync_width = 0x%x (%u)\n", display->disp_setting->vSync_width, display->disp_setting->vSync_width); + DISP_INFO("vSync_backPorch = 0x%x (%u)\n", display->disp_setting->vSync_backPorch, display->disp_setting->vSync_backPorch); + DISP_INFO("vSync_pol = 0x%x (%u)\n", display->disp_setting->vSync_pol, display->disp_setting->vSync_pol); + DISP_INFO("fr_adj_type = 0x%x (%u)\n", display->disp_setting->fr_adj_type, display->disp_setting->fr_adj_type); + DISP_INFO("ss_level = 0x%x (%u)\n", display->disp_setting->ss_level, display->disp_setting->ss_level); + DISP_INFO("clk_auto_gen = 0x%x (%u)\n", display->disp_setting->clk_auto_gen, display->disp_setting->clk_auto_gen); + DISP_INFO("lcd_clock = 0x%x (%u)\n", display->disp_setting->lcd_clock, display->disp_setting->lcd_clock); + DISP_INFO("lane_num = 0x%x (%u)\n", display->disp_setting->lane_num, display->disp_setting->lane_num); + DISP_INFO("bit_rate_max = 0x%x (%u)\n", display->disp_setting->bit_rate_max, display->disp_setting->bit_rate_max); + DISP_INFO("factor_numerator = 0x%x (%u)\n", display->disp_setting->factor_numerator, display->disp_setting->factor_numerator); + DISP_INFO("opp_mode_init = 0x%x (%u)\n", display->disp_setting->opp_mode_init, display->disp_setting->opp_mode_init); + DISP_INFO("opp_mode_display = 0x%x (%u)\n", display->disp_setting->opp_mode_display, display->disp_setting->opp_mode_display); + DISP_INFO("video_mode_type = 0x%x (%u)\n", display->disp_setting->video_mode_type, display->disp_setting->video_mode_type); + DISP_INFO("clk_always_hs = 0x%x (%u)\n", display->disp_setting->clk_always_hs, display->disp_setting->clk_always_hs); + DISP_INFO("phy_switch = 0x%x (%u)\n", display->disp_setting->phy_switch, display->disp_setting->phy_switch); + } + + if (display->lcd_timing) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping lcd_timing structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("lcd_bits = 0x%x (%u)\n", display->lcd_timing->lcd_bits, display->lcd_timing->lcd_bits); + DISP_INFO("h_active = 0x%x (%u)\n", display->lcd_timing->h_active, display->lcd_timing->h_active); + DISP_INFO("v_active = 0x%x (%u)\n", display->lcd_timing->v_active, display->lcd_timing->v_active); + DISP_INFO("h_period = 0x%x (%u)\n", display->lcd_timing->h_period, display->lcd_timing->h_period); + DISP_INFO("v_period = 0x%x (%u)\n", display->lcd_timing->v_period, display->lcd_timing->v_period); + DISP_INFO("fr_adj_type = 0x%x (%u)\n", display->lcd_timing->fr_adj_type, display->lcd_timing->fr_adj_type); + DISP_INFO("ss_level = 0x%x (%u)\n", display->lcd_timing->ss_level, display->lcd_timing->ss_level); + DISP_INFO("clk_auto_gen = 0x%x (%u)\n", display->lcd_timing->clk_auto_gen, display->lcd_timing->clk_auto_gen); + DISP_INFO("lcd_clock = 0x%x (%u)\n", display->lcd_timing->lcd_clock, display->lcd_timing->lcd_clock); + DISP_INFO("clk_ctrl = 0x%x (%u)\n", display->lcd_timing->clk_ctrl, display->lcd_timing->clk_ctrl); + DISP_INFO("pll_ctrl = 0x%x (%u)\n", display->lcd_timing->pll_ctrl, display->lcd_timing->pll_ctrl); + DISP_INFO("div_ctrl = 0x%x (%u)\n", display->lcd_timing->div_ctrl, display->lcd_timing->div_ctrl); + DISP_INFO("clk_change = 0x%x (%u)\n", display->lcd_timing->clk_change, display->lcd_timing->clk_change); + DISP_INFO("lcd_clk_dft = 0x%x (%u)\n", display->lcd_timing->lcd_clk_dft, display->lcd_timing->lcd_clk_dft); + DISP_INFO("hPeriod_dft = 0x%x (%u)\n", display->lcd_timing->hPeriod_dft, display->lcd_timing->hPeriod_dft); + DISP_INFO("vPeriod_dft = 0x%x (%u)\n", display->lcd_timing->vPeriod_dft, display->lcd_timing->vPeriod_dft); + DISP_INFO("sync_duration_numerator = 0x%x (%u)\n", display->lcd_timing->sync_duration_numerator, display->lcd_timing->sync_duration_numerator); + DISP_INFO("sync_duration_denominator = 0x%x (%u)\n", display->lcd_timing->sync_duration_denominator, display->lcd_timing->sync_duration_denominator); + DISP_INFO("vid_pixel_on = 0x%x (%u)\n", display->lcd_timing->vid_pixel_on, display->lcd_timing->vid_pixel_on); + DISP_INFO("vid_line_on = 0x%x (%u)\n", display->lcd_timing->vid_line_on, display->lcd_timing->vid_line_on); + DISP_INFO("hSync_width = 0x%x (%u)\n", display->lcd_timing->hSync_width, display->lcd_timing->hSync_width); + DISP_INFO("hSync_backPorch = 0x%x (%u)\n", display->lcd_timing->hSync_backPorch, display->lcd_timing->hSync_backPorch); + DISP_INFO("hSync_pol = 0x%x (%u)\n", display->lcd_timing->hSync_pol, display->lcd_timing->hSync_pol); + DISP_INFO("vSync_width = 0x%x (%u)\n", display->lcd_timing->vSync_width, display->lcd_timing->vSync_width); + DISP_INFO("vSync_backPorch = 0x%x (%u)\n", display->lcd_timing->vSync_backPorch, display->lcd_timing->vSync_backPorch); + DISP_INFO("vSync_pol = 0x%x (%u)\n", display->lcd_timing->vSync_pol, display->lcd_timing->vSync_pol); + DISP_INFO("hOffset = 0x%x (%u)\n", display->lcd_timing->hOffset, display->lcd_timing->hOffset); + DISP_INFO("vOffset = 0x%x (%u)\n", display->lcd_timing->vOffset, display->lcd_timing->vOffset); + DISP_INFO("de_hs_addr = 0x%x (%u)\n", display->lcd_timing->de_hs_addr, display->lcd_timing->de_hs_addr); + DISP_INFO("de_he_addr = 0x%x (%u)\n", display->lcd_timing->de_he_addr, display->lcd_timing->de_he_addr); + DISP_INFO("de_vs_addr = 0x%x (%u)\n", display->lcd_timing->de_vs_addr, display->lcd_timing->de_vs_addr); + DISP_INFO("de_ve_addr = 0x%x (%u)\n", display->lcd_timing->de_ve_addr, display->lcd_timing->de_ve_addr); + DISP_INFO("hs_hs_addr = 0x%x (%u)\n", display->lcd_timing->hs_hs_addr, display->lcd_timing->hs_hs_addr); + DISP_INFO("hs_he_addr = 0x%x (%u)\n", display->lcd_timing->hs_he_addr, display->lcd_timing->hs_he_addr); + DISP_INFO("hs_vs_addr = 0x%x (%u)\n", display->lcd_timing->hs_vs_addr, display->lcd_timing->hs_vs_addr); + DISP_INFO("hs_ve_addr = 0x%x (%u)\n", display->lcd_timing->hs_ve_addr, display->lcd_timing->hs_ve_addr); + DISP_INFO("vs_hs_addr = 0x%x (%u)\n", display->lcd_timing->vs_hs_addr, display->lcd_timing->vs_hs_addr); + DISP_INFO("vs_he_addr = 0x%x (%u)\n", display->lcd_timing->vs_he_addr, display->lcd_timing->vs_he_addr); + DISP_INFO("vs_vs_addr = 0x%x (%u)\n", display->lcd_timing->vs_vs_addr, display->lcd_timing->vs_vs_addr); + DISP_INFO("vs_ve_addr = 0x%x (%u)\n", display->lcd_timing->vs_ve_addr, display->lcd_timing->vs_ve_addr); + } + + if (display->dsi_cfg) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping dsi_cfg structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("lane_num = 0x%x (%u)\n", display->dsi_cfg->lane_num ,display->dsi_cfg->lane_num); + DISP_INFO("bit_rate_max = 0x%x (%u)\n", display->dsi_cfg->bit_rate_max ,display->dsi_cfg->bit_rate_max); + DISP_INFO("bit_rate_min = 0x%x (%u)\n", display->dsi_cfg->bit_rate_min ,display->dsi_cfg->bit_rate_min); + DISP_INFO("bit_rate = 0x%x (%u)\n", display->dsi_cfg->bit_rate ,display->dsi_cfg->bit_rate); + DISP_INFO("clock_factor = 0x%x (%u)\n", display->dsi_cfg->clock_factor ,display->dsi_cfg->clock_factor); + DISP_INFO("factor_numerator = 0x%x (%u)\n", display->dsi_cfg->factor_numerator ,display->dsi_cfg->factor_numerator); + DISP_INFO("factor_denominator = 0x%x (%u)\n", display->dsi_cfg->factor_denominator ,display->dsi_cfg->factor_denominator); + DISP_INFO("opp_mode_init = 0x%x (%u)\n", display->dsi_cfg->opp_mode_init ,display->dsi_cfg->opp_mode_init); + DISP_INFO("opp_mode_display = 0x%x (%u)\n", display->dsi_cfg->opp_mode_display ,display->dsi_cfg->opp_mode_display); + DISP_INFO("video_mode_type = 0x%x (%u)\n", display->dsi_cfg->video_mode_type ,display->dsi_cfg->video_mode_type); + DISP_INFO("clk_always_hs = 0x%x (%u)\n", display->dsi_cfg->clk_always_hs ,display->dsi_cfg->clk_always_hs); + DISP_INFO("phy_switch = 0x%x (%u)\n", display->dsi_cfg->phy_switch ,display->dsi_cfg->phy_switch); + DISP_INFO("venc_data_width = 0x%x (%u)\n", display->dsi_cfg->venc_data_width ,display->dsi_cfg->venc_data_width); + DISP_INFO("dpi_data_format = 0x%x (%u)\n", display->dsi_cfg->dpi_data_format ,display->dsi_cfg->dpi_data_format); + DISP_INFO("hLine = 0x%x (%u)\n", display->dsi_cfg->hLine ,display->dsi_cfg->hLine); + DISP_INFO("hSyncActive = 0x%x (%u)\n", display->dsi_cfg->hSyncActive ,display->dsi_cfg->hSyncActive); + DISP_INFO("hBackporch = 0x%x (%u)\n", display->dsi_cfg->hBackporch ,display->dsi_cfg->hBackporch); + DISP_INFO("vSyncActive = 0x%x (%u)\n", display->dsi_cfg->vSyncActive ,display->dsi_cfg->vSyncActive); + DISP_INFO("vBackporch = 0x%x (%u)\n", display->dsi_cfg->vBackporch ,display->dsi_cfg->vBackporch); + DISP_INFO("vFrontporch = 0x%x (%u)\n", display->dsi_cfg->vFrontporch ,display->dsi_cfg->vFrontporch); + DISP_INFO("vActiveLines = 0x%x (%u)\n", display->dsi_cfg->vActiveLines ,display->dsi_cfg->vActiveLines); + } + + if (display->dsi_phy_cfg) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping dsi_phy_cfg structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("lp_tesc = 0x%x (%u)\n", display->dsi_phy_cfg->lp_tesc, display->dsi_phy_cfg->lp_tesc); + DISP_INFO("lp_lpx = 0x%x (%u)\n", display->dsi_phy_cfg->lp_lpx, display->dsi_phy_cfg->lp_lpx); + DISP_INFO("lp_ta_sure = 0x%x (%u)\n", display->dsi_phy_cfg->lp_ta_sure, display->dsi_phy_cfg->lp_ta_sure); + DISP_INFO("lp_ta_go = 0x%x (%u)\n", display->dsi_phy_cfg->lp_ta_go, display->dsi_phy_cfg->lp_ta_go); + DISP_INFO("lp_ta_get = 0x%x (%u)\n", display->dsi_phy_cfg->lp_ta_get, display->dsi_phy_cfg->lp_ta_get); + DISP_INFO("hs_exit = 0x%x (%u)\n", display->dsi_phy_cfg->hs_exit, display->dsi_phy_cfg->hs_exit); + DISP_INFO("hs_trail = 0x%x (%u)\n", display->dsi_phy_cfg->hs_trail, display->dsi_phy_cfg->hs_trail); + DISP_INFO("hs_zero = 0x%x (%u)\n", display->dsi_phy_cfg->hs_zero, display->dsi_phy_cfg->hs_zero); + DISP_INFO("hs_prepare = 0x%x (%u)\n", display->dsi_phy_cfg->hs_prepare, display->dsi_phy_cfg->hs_prepare); + DISP_INFO("clk_trail = 0x%x (%u)\n", display->dsi_phy_cfg->clk_trail, display->dsi_phy_cfg->clk_trail); + DISP_INFO("clk_post = 0x%x (%u)\n", display->dsi_phy_cfg->clk_post, display->dsi_phy_cfg->clk_post); + DISP_INFO("clk_zero = 0x%x (%u)\n", display->dsi_phy_cfg->clk_zero, display->dsi_phy_cfg->clk_zero); + DISP_INFO("clk_prepare = 0x%x (%u)\n", display->dsi_phy_cfg->clk_prepare, display->dsi_phy_cfg->clk_prepare); + DISP_INFO("clk_pre = 0x%x (%u)\n", display->dsi_phy_cfg->clk_pre, display->dsi_phy_cfg->clk_pre); + DISP_INFO("init = 0x%x (%u)\n", display->dsi_phy_cfg->init, display->dsi_phy_cfg->init); + DISP_INFO("wakeup = 0x%x (%u)\n", display->dsi_phy_cfg->wakeup, display->dsi_phy_cfg->wakeup); + DISP_INFO("state_change = 0x%x (%u)\n", display->dsi_phy_cfg->state_change, display->dsi_phy_cfg->state_change); + } + + if (display->dsi_vid) { + DISP_INFO("#############################\n"); + DISP_INFO("Dumping dsi_vid structure:\n"); + DISP_INFO("#############################\n"); + DISP_INFO("data_bits = 0x%x (%d)\n", display->dsi_vid->data_bits, display->dsi_vid->data_bits); + DISP_INFO("vid_num_chunks = 0x%x (%d)\n", display->dsi_vid->vid_num_chunks, display->dsi_vid->vid_num_chunks); + DISP_INFO("pixel_per_chunk = 0x%x (%d)\n", display->dsi_vid->pixel_per_chunk, display->dsi_vid->pixel_per_chunk); + DISP_INFO("vid_null_size = 0x%x (%d)\n", display->dsi_vid->vid_null_size, display->dsi_vid->vid_null_size); + DISP_INFO("byte_per_chunk = 0x%x (%d)\n", display->dsi_vid->byte_per_chunk, display->dsi_vid->byte_per_chunk); + DISP_INFO("multi_pkt_en = 0x%x (%d)\n", display->dsi_vid->multi_pkt_en, display->dsi_vid->multi_pkt_en); + DISP_INFO("hline = 0x%x (%u)\n", display->dsi_vid->hline, display->dsi_vid->hline); + DISP_INFO("hsa = 0x%x (%u)\n", display->dsi_vid->hsa, display->dsi_vid->hsa); + DISP_INFO("hbp = 0x%x (%u)\n", display->dsi_vid->hbp, display->dsi_vid->hbp); + DISP_INFO("vsa = 0x%x (%u)\n", display->dsi_vid->vsa, display->dsi_vid->vsa); + DISP_INFO("vbp = 0x%x (%u)\n", display->dsi_vid->vbp, display->dsi_vid->vbp); + DISP_INFO("vfp = 0x%x (%u)\n", display->dsi_vid->vfp, display->dsi_vid->vfp); + DISP_INFO("vact = 0x%x (%u)\n", display->dsi_vid->vact, display->dsi_vid->vact); + } +}
diff --git a/system/dev/display/astro-display/dsi.c b/system/dev/display/astro-display/dsi.c new file mode 100644 index 0000000..fee0fa5 --- /dev/null +++ b/system/dev/display/astro-display/dsi.c
@@ -0,0 +1,1246 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +#define CMD_TIMEOUT_CNT 3000 + + +void lcd_mipi_phy_set(astro_display_t* display, bool enable) { + uint32_t phy_bit, phy_width; + uint32_t lane_cnt; + + if (enable) { + /* HHI_MIPI_CNTL0 */ + /* DIF_REF_CTL1:31-16bit, DIF_REF_CTL0:15-0bit */ + WRITE32_REG(HHI, HHI_MIPI_CNTL0, (0xa487 << 16) | (0x8 << 0)); + + /* HHI_MIPI_CNTL1 */ + /* DIF_REF_CTL2:15-0bit; bandgap bit16 */ + WRITE32_REG(HHI, HHI_MIPI_CNTL1, (0x1 << 16) | (0x002e << 0)); + + /* HHI_MIPI_CNTL2 */ + /* DIF_TX_CTL1:31-16bit, DIF_TX_CTL0:15-0bit */ + WRITE32_REG(HHI, HHI_MIPI_CNTL2, (0x2680 << 16) | (0x45a << 0)); + + phy_bit = MIPI_PHY_LANE_BIT; + phy_width = MIPI_PHY_LANE_WIDTH; + switch (display->dsi_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; + } + SET_BIT32(HHI, HHI_MIPI_CNTL2, lane_cnt, phy_bit, phy_width); + } else { + WRITE32_REG(HHI, HHI_MIPI_CNTL0, 0); + WRITE32_REG(HHI, HHI_MIPI_CNTL1, 0); + WRITE32_REG(HHI, HHI_MIPI_CNTL2, 0); + } +} + +#define max(x, y) ((x > y)? x : y) + +static void mipi_dsi_phy_config(astro_display_t* display, uint32_t dsi_ui) { + uint32_t temp, t_ui, t_req_min, t_req_max, t_req, n; + + t_ui = (1000000 * 100) / (dsi_ui / 1000); /* 0.01ns*100 */ + temp = t_ui * 8; /* lane_byte cycle time */ + + display->dsi_phy_cfg->lp_tesc = ((DPHY_TIME_LP_TESC(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->lp_lpx = ((DPHY_TIME_LP_LPX(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->lp_ta_sure = ((DPHY_TIME_LP_TA_SURE(t_ui) + temp - 1) / temp) & + 0xff; + display->dsi_phy_cfg->lp_ta_go = ((DPHY_TIME_LP_TA_GO(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->lp_ta_get = ((DPHY_TIME_LP_TA_GETX(t_ui) + temp - 1) / temp) & + 0xff; + display->dsi_phy_cfg->hs_exit = ((DPHY_TIME_HS_EXIT(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->clk_prepare = ((DPHY_TIME_CLK_PREPARE(t_ui) + temp - 1) / temp) & + 0xff; + display->dsi_phy_cfg->clk_zero = ((DPHY_TIME_CLK_ZERO(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->clk_pre = ((DPHY_TIME_CLK_PRE(t_ui) + temp - 1) / temp) & 0xff; + display->dsi_phy_cfg->init = (DPHY_TIME_INIT(t_ui) + temp - 1) / temp; + display->dsi_phy_cfg->wakeup = (DPHY_TIME_WAKEUP(t_ui) + temp - 1) / temp; + + t_req_max = ((105 * 100 + 12 * t_ui) / 100); + for (n = 0; n <= 0xff; n++) { + display->dsi_phy_cfg->clk_trail = n; + if (((temp * display->dsi_phy_cfg->clk_trail / 100) > 70) && + ((temp * display->dsi_phy_cfg->clk_trail / 100) < t_req_max)) { + DISP_INFO("t_ui=%d, t_req=%d\n", t_ui, t_req_max); + DISP_INFO("clk_trail=%d, n=%d\n", display->dsi_phy_cfg->clk_trail, n); + + break; + } + } + + t_req_min = 2 * ((60 * 100 + 52 * t_ui) / 100); + for (n = 0; n <= 0xff; n++) { + display->dsi_phy_cfg->clk_post = n; + if ((temp * display->dsi_phy_cfg->clk_post / 100) >= t_req_min) { + DISP_INFO("t_ui=%d, t_req_min=%d\n", t_ui, t_req_min); + DISP_INFO("clk_post=%d, n=%d\n", display->dsi_phy_cfg->clk_post, n); + + break; + } + } + + t_req_min = max(8 * t_ui / 100, (60 * 100 + 4 * t_ui) / 100) + 10; + t_req_max = ((105 * 100 + 12 * t_ui) / 100); + for (n = 0; n <= 0xff; n++) { + display->dsi_phy_cfg->hs_trail = n; + if (((temp * display->dsi_phy_cfg->hs_trail / 100) > t_req_min) && + ((temp * display->dsi_phy_cfg->hs_trail / 100) < t_req_max)) { + DISP_INFO("t_req_min=%d, t_req_max=%d\n", t_req_min, t_req_max); + DISP_INFO("t_ui=%d, hs_trail=%d, n=%d\n", t_ui, display->dsi_phy_cfg->hs_trail, n); + + break; + } + } + + t_req_min = (40 * 100 + 4 * t_ui) / 100; + t_req_max = ((85 * 100 + 6 * t_ui) / 100); + for (n = 0; n <= 0xff; n++) { + display->dsi_phy_cfg->hs_prepare = n; + if (((temp * display->dsi_phy_cfg->hs_prepare / 100) > t_req_min) && + ((temp * display->dsi_phy_cfg->hs_prepare / 100) < t_req_max)) { + DISP_INFO("t_req_min=%d, t_req_max=%d\n", t_req_min, t_req_max); + DISP_INFO("t_ui=%d, hs_prepare=%d, n=%d\n", t_ui, display->dsi_phy_cfg->hs_prepare, n); + + break; + } + } + + t_req_min = ((145 * 100 + 10 * t_ui) / 100) - ((40 * 100 + 4 * t_ui) / 100); + for (n = 0; n <= 0xff; n++) { + display->dsi_phy_cfg->hs_zero = n; + if ((temp * display->dsi_phy_cfg->hs_zero / 100) > t_req_min) { + DISP_INFO("t_ui=%d, t_req_min=%d\n", t_ui, t_req_min); + DISP_INFO("hs_zero=%d, n=%d\n", display->dsi_phy_cfg->hs_zero, n); + + break; + } + } + + /* check dphy spec: (unit: ns) */ + if ((temp * display->dsi_phy_cfg->lp_tesc / 100) <= 100) + DISP_ERROR("lp_tesc timing error\n"); + if ((temp * display->dsi_phy_cfg->lp_lpx / 100) <= 50) + DISP_ERROR("lp_lpx timing error\n"); + if ((temp * display->dsi_phy_cfg->hs_exit / 100) <= 100) + DISP_ERROR("hs_exit timing error\n"); + t_req = ((t_ui > (60 * 100 / 4)) ? + (8 * t_ui) : ((60 * 100) + 4 * t_ui)); + if ((temp * display->dsi_phy_cfg->hs_trail / 100) <= ((t_req + 50) / 100)) + DISP_ERROR("hs_trail timing error\n"); + t_req = temp * display->dsi_phy_cfg->hs_prepare / 100; + if ((t_req <= (40 + (t_ui * 4 / 100))) || + (t_req >= (85 + (t_ui * 6 / 100)))) + DISP_ERROR("hs_prepare timing error\n"); + t_req = 145 + (t_ui * 10 / 100); + if (((temp * display->dsi_phy_cfg->hs_zero / 100) + + (temp * display->dsi_phy_cfg->hs_prepare / 100)) <= t_req) + DISP_ERROR("hs_zero timing error\n"); + if ((temp * display->dsi_phy_cfg->init / 100) <= 100000) + DISP_ERROR("init timing error\n"); + if ((temp * display->dsi_phy_cfg->wakeup / 100) <= 1000000) + DISP_ERROR("wakeup timing error\n"); + + DISP_INFO("%s:\n" + "lp_tesc = 0x%02x\n" + "lp_lpx = 0x%02x\n" + "lp_ta_sure = 0x%02x\n" + "lp_ta_go = 0x%02x\n" + "lp_ta_get = 0x%02x\n" + "hs_exit = 0x%02x\n" + "hs_trail = 0x%02x\n" + "hs_zero = 0x%02x\n" + "hs_prepare = 0x%02x\n" + "clk_trail = 0x%02x\n" + "clk_post = 0x%02x\n" + "clk_zero = 0x%02x\n" + "clk_prepare = 0x%02x\n" + "clk_pre = 0x%02x\n" + "init = 0x%02x\n" + "wakeup = 0x%02x\n\n", + __func__, + display->dsi_phy_cfg->lp_tesc, display->dsi_phy_cfg->lp_lpx, display->dsi_phy_cfg->lp_ta_sure, + display->dsi_phy_cfg->lp_ta_go, display->dsi_phy_cfg->lp_ta_get, display->dsi_phy_cfg->hs_exit, + display->dsi_phy_cfg->hs_trail, display->dsi_phy_cfg->hs_zero, display->dsi_phy_cfg->hs_prepare, + display->dsi_phy_cfg->clk_trail, display->dsi_phy_cfg->clk_post, + display->dsi_phy_cfg->clk_zero, display->dsi_phy_cfg->clk_prepare, display->dsi_phy_cfg->clk_pre, + display->dsi_phy_cfg->init, display->dsi_phy_cfg->wakeup); +} + +static void mipi_dsi_video_config(astro_display_t* display) +{ + uint32_t h_period, hs_width, hs_bp; + uint32_t den, num; + uint32_t v_period, v_active, vs_width, vs_bp; + + h_period = display->lcd_timing->h_period; + hs_width = display->lcd_timing->hSync_width; + hs_bp = display->lcd_timing->hSync_backPorch; + den = display->dsi_cfg->factor_denominator; + num = display->dsi_cfg->factor_numerator; + + display->dsi_vid->hline = (h_period * den + num - 1) / num; + display->dsi_vid->hsa = (hs_width * den + num - 1) / num; + display->dsi_vid->hbp = (hs_bp * den + num - 1) / num; + + v_period = display->lcd_timing->v_period; + v_active = display->lcd_timing->v_active; + vs_width = display->lcd_timing->vSync_width; + vs_bp = display->lcd_timing->vSync_backPorch; + display->dsi_vid->vsa = vs_width; + display->dsi_vid->vbp = vs_bp; + display->dsi_vid->vfp = v_period - v_active - vs_bp - vs_width; + display->dsi_vid->vact = v_active; + + DISP_INFO("MIPI DSI video timing:\n" + " HLINE = %d\n" + " HSA = %d\n" + " HBP = %d\n" + " VSA = %d\n" + " VBP = %d\n" + " VFP = %d\n" + " VACT = %d\n\n", + display->dsi_vid->hline, display->dsi_vid->hsa, display->dsi_vid->hbp, + display->dsi_vid->vsa, display->dsi_vid->vbp, display->dsi_vid->vfp, display->dsi_vid->vact); +} + +static void mipi_dsi_vid_mode_config(astro_display_t* display) +{ + if (display->dsi_cfg->video_mode_type == BURST_MODE) { + display->dsi_vid->pixel_per_chunk = display->lcd_timing->h_active; + display->dsi_vid->vid_num_chunks = 0; + display->dsi_vid->vid_null_size = 0; + } else { + DISP_ERROR("Non-Burst mode is not supported\n"); + while(1); + } + + mipi_dsi_video_config(display); +} + +static void mipi_dsi_config_post(astro_display_t* display) +{ + uint32_t pclk, lanebyteclk; + uint32_t den, num; + + pclk = display->lcd_timing->lcd_clock / 1000; + + /* pclk lanebyteclk factor */ + if (display->dsi_cfg->factor_numerator == 0) { + lanebyteclk = display->dsi_cfg->bit_rate / 8 / 1000; + DISP_INFO("pixel_clk = %d.%03dMHz, bit_rate = %d.%03dMHz, lanebyteclk = %d.%03dMHz\n", + (pclk / 1000), (pclk % 1000), + (display->dsi_cfg->bit_rate / 1000000), + ((display->dsi_cfg->bit_rate / 1000) % 1000), + (lanebyteclk / 1000), (lanebyteclk % 1000)); + display->dsi_cfg->factor_numerator = 8; + display->dsi_cfg->factor_denominator = display->dsi_cfg->clock_factor; + } + num = display->dsi_cfg->factor_numerator; + den = display->dsi_cfg->factor_denominator; + DISP_INFO("num=%d, den=%d, factor=%d.%02d\n", + num, den, (den / num), ((den % num) * 100 / num)); + + if (display->dsi_cfg->opp_mode_display == OPERATION_VIDEO_MODE) { + mipi_dsi_vid_mode_config(display); + } + + /* phy config */ + mipi_dsi_phy_config(display, display->dsi_cfg->bit_rate); +} + +static void mipi_dcs_set(astro_display_t* display, int trans_type, int req_ack, int tear_en) +{ + WRITE32_REG(MIPI_DSI, DW_DSI_CMD_MODE_CFG, + (trans_type << BIT_MAX_RD_PKT_SIZE) | + (trans_type << BIT_DCS_LW_TX) | + (trans_type << BIT_DCS_SR_0P_TX) | + (trans_type << BIT_DCS_SW_1P_TX) | + (trans_type << BIT_DCS_SW_0P_TX) | + (trans_type << BIT_GEN_LW_TX) | + (trans_type << BIT_GEN_SR_2P_TX) | + (trans_type << BIT_GEN_SR_1P_TX) | + (trans_type << BIT_GEN_SR_0P_TX) | + (trans_type << BIT_GEN_SW_2P_TX) | + (trans_type << BIT_GEN_SW_1P_TX) | + (trans_type << BIT_GEN_SW_0P_TX) | + (req_ack << BIT_ACK_RQST_EN) | + (tear_en << BIT_TEAR_FX_EN)); + + if (tear_en == MIPI_DCS_ENABLE_TEAR) { + /* Enable Tear Interrupt if tear_en is valid */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_INTR_CNTL_STAT, 0x1, BIT_EDPITE_INT_EN, 1); + /* Enable Measure Vsync */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_MEAS_CNTL, 0x1, BIT_VSYNC_MEAS_EN, 1); + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_MEAS_CNTL, 0x1, BIT_TE_MEAS_EN, 1); + } + + /* Packet header settings */ + WRITE32_REG(MIPI_DSI, DW_DSI_PCKHDL_CFG, + (1 << BIT_CRC_RX_EN) | + (1 << BIT_ECC_RX_EN) | + (req_ack << BIT_BTA_EN) | + (0 << BIT_EOTP_RX_EN) | + (0 << BIT_EOTP_TX_EN)); +} + + +static void set_mipi_dsi_host(astro_display_t* display, uint32_t vcid, uint32_t chroma_subsample, + uint32_t operation_mode) +{ + uint32_t dpi_data_format, venc_data_width; + uint32_t lane_num, vid_mode_type; + uint32_t temp; + + venc_data_width = display->dsi_cfg->venc_data_width; + dpi_data_format = display->dsi_cfg->dpi_data_format; + lane_num = (uint32_t)(display->dsi_cfg->lane_num); + vid_mode_type = (uint32_t)(display->dsi_cfg->video_mode_type); + + /* ----------------------------------------------------- */ + /* Standard Configuration for Video Mode Operation */ + /* ----------------------------------------------------- */ + /* 1, Configure Lane number and phy stop wait time */ + if (display->dsi_phy_cfg->state_change == 2) { + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_IF_CFG, + (0x28 << BIT_PHY_STOP_WAIT_TIME) | + ((lane_num-1) << BIT_N_LANES)); + } else { + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_IF_CFG, + (1 << BIT_PHY_STOP_WAIT_TIME) | + ((lane_num-1) << BIT_N_LANES)); + } + + /* 2.1, Configure Virtual channel settings */ + WRITE32_REG(MIPI_DSI, DW_DSI_DPI_VCID, vcid); + /* 2.2, Configure Color format */ + WRITE32_REG(MIPI_DSI, DW_DSI_DPI_COLOR_CODING, + (((dpi_data_format == COLOR_18BIT_CFG_2) ? + 1 : 0) << BIT_LOOSELY18_EN) | + (dpi_data_format << BIT_DPI_COLOR_CODING)); + /* 2.2.1 Configure Set color format for DPI register */ + temp = (READ32_REG(MIPI_DSI, MIPI_DSI_TOP_CNTL) & + ~(0xf<<BIT_DPI_COLOR_MODE) & + ~(0x7<<BIT_IN_COLOR_MODE) & + ~(0x3<<BIT_CHROMA_SUBSAMPLE)); + WRITE32_REG(MIPI_DSI, MIPI_DSI_TOP_CNTL, + (temp | + (dpi_data_format << BIT_DPI_COLOR_MODE) | + (venc_data_width << BIT_IN_COLOR_MODE) | + (chroma_subsample << BIT_CHROMA_SUBSAMPLE))); + /* 2.3 Configure Signal polarity */ + WRITE32_REG(MIPI_DSI, DW_DSI_DPI_CFG_POL, + (0x0 << BIT_COLORM_ACTIVE_LOW) | + (0x0 << BIT_SHUTD_ACTIVE_LOW) | + (0 << BIT_HSYNC_ACTIVE_LOW) | + (0 << BIT_VSYNC_ACTIVE_LOW) | + (0x0 << BIT_DATAEN_ACTIVE_LOW)); + + if (operation_mode == OPERATION_VIDEO_MODE) { + /* 3.1 Configure Low power and video mode type settings */ + WRITE32_REG(MIPI_DSI, DW_DSI_VID_MODE_CFG, + (1 << BIT_LP_HFP_EN) | /* enalbe lp */ + (1 << BIT_LP_HBP_EN) | /* enalbe lp */ + (1 << BIT_LP_VCAT_EN) | /* enalbe lp */ + (1 << BIT_LP_VFP_EN) | /* enalbe lp */ + (1 << BIT_LP_VBP_EN) | /* enalbe lp */ + (1 << BIT_LP_VSA_EN) | /* enalbe lp */ + (0 << BIT_FRAME_BTA_ACK_EN) | + /* enable BTA after one frame, TODO, need check */ + /* (1 << BIT_LP_CMD_EN) | */ + /* enable the command transmission only in lp mode */ + (vid_mode_type << BIT_VID_MODE_TYPE)); + /* burst non burst mode */ + /* [23:16]outvact, [7:0]invact */ + WRITE32_REG(MIPI_DSI, DW_DSI_DPI_LP_CMD_TIM, + (4 << 16) | (4 << 0)); + /* 3.2 Configure video packet size settings */ + WRITE32_REG(MIPI_DSI, DW_DSI_VID_PKT_SIZE, + display->dsi_vid->pixel_per_chunk); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_NUM_CHUNKS, + display->dsi_vid->vid_num_chunks); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_NULL_SIZE, + display->dsi_vid->vid_null_size); + /* 4 Configure the video relative parameters according to + * the output type + */ + /* include horizontal timing and vertical line */ + WRITE32_REG(MIPI_DSI, DW_DSI_VID_HLINE_TIME, display->dsi_vid->hline); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_HSA_TIME, display->dsi_vid->hsa); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_HBP_TIME, display->dsi_vid->hbp); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_VSA_LINES, display->dsi_vid->vsa); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_VBP_LINES, display->dsi_vid->vbp); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_VFP_LINES, display->dsi_vid->vfp); + WRITE32_REG(MIPI_DSI, DW_DSI_VID_VACTIVE_LINES, + display->dsi_vid->vact); + } /* operation_mode == OPERATION_VIDEO_MODE */ + + /* ----------------------------------------------------- */ + /* Finish Configuration */ + /* ----------------------------------------------------- */ + + /* Inner clock divider settings */ + WRITE32_REG(MIPI_DSI, DW_DSI_CLKMGR_CFG, + (0x1 << BIT_TO_CLK_DIV) | + (display->dsi_phy_cfg->lp_tesc << BIT_TX_ESC_CLK_DIV)); + /* Packet header settings //move to mipi_dcs_set */ + /* WRITE32_REG(MIPI_DSI, DW_DSI_PCKHDL_CFG, + * (1 << BIT_CRC_RX_EN) | + * (1 << BIT_ECC_RX_EN) | + * (0 << BIT_BTA_EN) | + * (0 << BIT_EOTP_RX_EN) | + * (0 << BIT_EOTP_TX_EN) ); + */ + /* operation mode setting: video/command mode */ + WRITE32_REG(MIPI_DSI, DW_DSI_MODE_CFG, operation_mode); + + /* Phy Timer */ + if (display->dsi_phy_cfg->state_change == 2) + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TMR_CFG, 0x03320000); + else + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TMR_CFG, 0x090f0000); + + if (display->dsi_phy_cfg->state_change == 2) + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TMR_LPCLK_CFG, 0x870025); + else + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TMR_LPCLK_CFG, 0x260017); +} + +static void dsi_dump_host(astro_display_t* display) { + DISP_INFO("%s: DUMPING DSI HOST REGS\n", __func__); + DISP_INFO("DW_DSI_VERSION = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VERSION)); + DISP_INFO("DW_DSI_PWR_UP = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PWR_UP)); + DISP_INFO("DW_DSI_CLKMGR_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_CLKMGR_CFG)); + DISP_INFO("DW_DSI_DPI_VCID = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DPI_VCID)); + DISP_INFO("DW_DSI_DPI_COLOR_CODING = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DPI_COLOR_CODING)); + DISP_INFO("DW_DSI_DPI_CFG_POL = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DPI_CFG_POL)); + DISP_INFO("DW_DSI_DPI_LP_CMD_TIM = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DPI_LP_CMD_TIM)); + DISP_INFO("DW_DSI_DBI_VCID = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DBI_VCID)); + DISP_INFO("DW_DSI_DBI_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DBI_CFG)); + DISP_INFO("DW_DSI_DBI_PARTITIONING_EN = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DBI_PARTITIONING_EN)); + DISP_INFO("DW_DSI_DBI_CMDSIZE = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_DBI_CMDSIZE)); + DISP_INFO("DW_DSI_PCKHDL_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PCKHDL_CFG)); + DISP_INFO("DW_DSI_GEN_VCID = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_GEN_VCID)); + DISP_INFO("DW_DSI_MODE_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_MODE_CFG)); + DISP_INFO("DW_DSI_VID_MODE_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_MODE_CFG)); + DISP_INFO("DW_DSI_VID_PKT_SIZE = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_PKT_SIZE)); + DISP_INFO("DW_DSI_VID_NUM_CHUNKS = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_NUM_CHUNKS)); + DISP_INFO("DW_DSI_VID_NULL_SIZE = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_NULL_SIZE)); + DISP_INFO("DW_DSI_VID_HSA_TIME = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_HSA_TIME)); + DISP_INFO("DW_DSI_VID_HBP_TIME = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_HBP_TIME)); + DISP_INFO("DW_DSI_VID_HLINE_TIME = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_HLINE_TIME)); + DISP_INFO("DW_DSI_VID_VSA_LINES = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_VSA_LINES)); + DISP_INFO("DW_DSI_VID_VBP_LINES = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_VBP_LINES)); + DISP_INFO("DW_DSI_VID_VFP_LINES = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_VFP_LINES)); + DISP_INFO("DW_DSI_VID_VACTIVE_LINES = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_VID_VACTIVE_LINES)); + DISP_INFO("DW_DSI_EDPI_CMD_SIZE = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_EDPI_CMD_SIZE)); + DISP_INFO("DW_DSI_CMD_MODE_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_CMD_MODE_CFG)); + DISP_INFO("DW_DSI_GEN_HDR = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_GEN_HDR)); + DISP_INFO("DW_DSI_GEN_PLD_DATA = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_GEN_PLD_DATA)); + DISP_INFO("DW_DSI_CMD_PKT_STATUS = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_CMD_PKT_STATUS)); + DISP_INFO("DW_DSI_TO_CNT_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_TO_CNT_CFG)); + DISP_INFO("DW_DSI_HS_RD_TO_CNT = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_HS_RD_TO_CNT)); + DISP_INFO("DW_DSI_LP_RD_TO_CNT = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_LP_RD_TO_CNT)); + DISP_INFO("DW_DSI_HS_WR_TO_CNT = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_HS_WR_TO_CNT)); + DISP_INFO("DW_DSI_LP_WR_TO_CNT = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_LP_WR_TO_CNT)); + DISP_INFO("DW_DSI_BTA_TO_CNT = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_BTA_TO_CNT)); + DISP_INFO("DW_DSI_SDF_3D = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_SDF_3D)); + DISP_INFO("DW_DSI_LPCLK_CTRL = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_LPCLK_CTRL)); + DISP_INFO("DW_DSI_PHY_TMR_LPCLK_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_TMR_LPCLK_CFG)); + DISP_INFO("DW_DSI_PHY_TMR_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_TMR_CFG)); + DISP_INFO("DW_DSI_PHY_RSTZ = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_RSTZ)); + DISP_INFO("DW_DSI_PHY_IF_CFG = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_IF_CFG)); + DISP_INFO("DW_DSI_PHY_ULPS_CTRL = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_ULPS_CTRL)); + DISP_INFO("DW_DSI_PHY_TX_TRIGGERS = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_TX_TRIGGERS)); + DISP_INFO("DW_DSI_PHY_STATUS = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_STATUS)); + DISP_INFO("DW_DSI_PHY_TST_CTRL0 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL0)); + DISP_INFO("DW_DSI_PHY_TST_CTRL1 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL1)); + DISP_INFO("DW_DSI_INT_ST0 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_INT_ST0)); + DISP_INFO("DW_DSI_INT_ST1 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_INT_ST1)); + DISP_INFO("DW_DSI_INT_MSK0 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_INT_MSK0)); + DISP_INFO("DW_DSI_INT_MSK1 = 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_INT_MSK1)); +} + +static void dsi_phy_dump(astro_display_t* display) { + DISP_INFO("%s: DUMPING PHY REGS\n", __func__); + + DISP_INFO("MIPI_DSI_PHY_CTRL = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_PHY_CTRL)); + DISP_INFO("MIPI_DSI_CHAN_CTRL = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_CHAN_CTRL)); + DISP_INFO("MIPI_DSI_CHAN_STS = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_CHAN_STS)); + DISP_INFO("MIPI_DSI_CLK_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_CLK_TIM)); + DISP_INFO("MIPI_DSI_HS_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_HS_TIM)); + DISP_INFO("MIPI_DSI_LP_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_LP_TIM)); + DISP_INFO("MIPI_DSI_ANA_UP_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_ANA_UP_TIM)); + DISP_INFO("MIPI_DSI_INIT_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_INIT_TIM)); + DISP_INFO("MIPI_DSI_WAKEUP_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_WAKEUP_TIM)); + DISP_INFO("MIPI_DSI_LPOK_TIM = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_LPOK_TIM)); + DISP_INFO("MIPI_DSI_LP_WCHDOG = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_LP_WCHDOG)); + DISP_INFO("MIPI_DSI_ANA_CTRL = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_ANA_CTRL)); + DISP_INFO("MIPI_DSI_CLK_TIM1 = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_CLK_TIM1)); + DISP_INFO("MIPI_DSI_TURN_WCHDOG = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_TURN_WCHDOG)); + DISP_INFO("MIPI_DSI_ULPS_CHECK = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_ULPS_CHECK)); + DISP_INFO("MIPI_DSI_TEST_CTRL0 = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_TEST_CTRL0)); + DISP_INFO("MIPI_DSI_TEST_CTRL1 = 0x%x\n", READ32_REG(DSI_PHY, MIPI_DSI_TEST_CTRL1)); + + DISP_INFO("\n"); + +} + +static void dsi_phy_init(astro_display_t* display, uint32_t lane_num) +{ + /* enable phy clock. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_PHY_CTRL, 0x1); /* enable DSI top clock. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_PHY_CTRL, + (1 << 0) | /* enable the DSI PLL clock . */ + (1 << 7) | + /* enable pll clock which connected to + * DDR clock path + */ + (1 << 8) | /* enable the clock divider counter */ + (0 << 9) | /* enable the divider clock out */ + (0 << 10) | /* clock divider. 1: freq/4, 0: freq/2 */ + (0 << 11) | + /* 1: select the mipi DDRCLKHS from clock divider, + * 0: from PLL clock + */ + (0 << 12)); /* enable the byte clock generateion. */ + /* enable the divider clock out */ + SET_BIT32(DSI_PHY, MIPI_DSI_PHY_CTRL, 1, 9, 1); + /* enable the byte clock generateion. */ + SET_BIT32(DSI_PHY, MIPI_DSI_PHY_CTRL, 1, 12, 1); + SET_BIT32(DSI_PHY, MIPI_DSI_PHY_CTRL, 1, 31, 1); + SET_BIT32(DSI_PHY, MIPI_DSI_PHY_CTRL, 0, 31, 1); + + /* 0x05210f08);//0x03211c08 */ + WRITE32_REG(DSI_PHY, MIPI_DSI_CLK_TIM, + (display->dsi_phy_cfg->clk_trail | (display->dsi_phy_cfg->clk_post << 8) | + (display->dsi_phy_cfg->clk_zero << 16) | (display->dsi_phy_cfg->clk_prepare << 24))); + WRITE32_REG(DSI_PHY, MIPI_DSI_CLK_TIM1, display->dsi_phy_cfg->clk_pre); /* ?? */ + /* 0x050f090d */ + WRITE32_REG(DSI_PHY, MIPI_DSI_HS_TIM, + (display->dsi_phy_cfg->hs_exit | (display->dsi_phy_cfg->hs_trail << 8) | + (display->dsi_phy_cfg->hs_zero << 16) | (display->dsi_phy_cfg->hs_prepare << 24))); + /* 0x4a370e0e */ + WRITE32_REG(DSI_PHY, MIPI_DSI_LP_TIM, + (display->dsi_phy_cfg->lp_lpx | (display->dsi_phy_cfg->lp_ta_sure << 8) | + (display->dsi_phy_cfg->lp_ta_go << 16) | (display->dsi_phy_cfg->lp_ta_get << 24))); + /* ?? //some number to reduce sim time. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_ANA_UP_TIM, 0x0100); + /* 0xe20 //30d4 -> d4 to reduce sim time. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_INIT_TIM, display->dsi_phy_cfg->init); + /* 0x8d40 //1E848-> 48 to reduct sim time. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_WAKEUP_TIM, display->dsi_phy_cfg->wakeup); + /* wait for the LP analog ready. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_LPOK_TIM, 0x7C); + /* 1/3 of the tWAKEUP. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_ULPS_CHECK, 0x927C); + /* phy TURN watch dog. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_LP_WCHDOG, 0x1000); + /* phy ESC command watch dog. */ + WRITE32_REG(DSI_PHY, MIPI_DSI_TURN_WCHDOG, 0x1000); + + /* Powerup the analog circuit. */ + switch (lane_num) { + case 1: + WRITE32_REG(DSI_PHY, MIPI_DSI_CHAN_CTRL, 0x0e); + break; + case 2: + WRITE32_REG(DSI_PHY, MIPI_DSI_CHAN_CTRL, 0x0c); + break; + case 3: + WRITE32_REG(DSI_PHY, MIPI_DSI_CHAN_CTRL, 0x08); + break; + case 4: + default: + WRITE32_REG(DSI_PHY, MIPI_DSI_CHAN_CTRL, 0); + break; + } +} + +#define DPHY_TIMEOUT 200000 +static void check_phy_status(astro_display_t* display) +{ + int i = 0; + + while (GET_BIT32(MIPI_DSI, DW_DSI_PHY_STATUS, + BIT_PHY_LOCK, 1) == 0) { + if (i++ >= DPHY_TIMEOUT) { + DISP_ERROR("phy_lock timeout 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_STATUS)); + break; + } + usleep(6); + } + + i = 0; + usleep(10); + while (GET_BIT32(MIPI_DSI, DW_DSI_PHY_STATUS, + BIT_PHY_STOPSTATECLKLANE, 1) == 0) { + if (i == 0) { + DISP_INFO(" Waiting STOP STATE LANE\n"); + } + if (i++ >= DPHY_TIMEOUT) { + DISP_ERROR("lane_state timeout 0x%x\n", READ32_REG(MIPI_DSI, DW_DSI_PHY_STATUS)); + break; + } + usleep(6); + } +} + +static void set_dsi_phy_config(astro_display_t* display) +{ + /* Digital */ + /* Power up DSI */ + WRITE32_REG(MIPI_DSI, DW_DSI_PWR_UP, 1); + + /* Setup Parameters of DPHY */ + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL1, 0x00010044);/*testcode*/ + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL0, 0x2); + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL0, 0x0); + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL1, 0x00000074);/*testwrite*/ + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL0, 0x2); + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_TST_CTRL0, 0x0); + + /* Power up D-PHY */ + WRITE32_REG(MIPI_DSI, DW_DSI_PHY_RSTZ, 0xf); + + /* Analog */ + dsi_phy_init(display, display->dsi_cfg->lane_num); + + /* Check the phylock/stopstateclklane to decide if the DPHY is ready */ + check_phy_status(display); + + /* Trigger a sync active for esc_clk */ + SET_BIT32(DSI_PHY, MIPI_DSI_PHY_CTRL, 1, 1, 1); + + /* Startup transfer, default lpclk */ + WRITE32_REG(MIPI_DSI, DW_DSI_LPCLK_CTRL, + (0x1 << BIT_AUTOCLKLANE_CTRL) | + (0x1 << BIT_TXREQUESTCLKHS)); +} + + + +/* MIPI DSI Specific functions */ +static inline void print_mipi_cmd_status(astro_display_t* display, int cnt, uint32_t status) +{ + if (cnt == 0) +{ DISP_ERROR("cmd error: status=0x%04x, int0=0x%06x, int1=0x%06x\n", + status, + READ32_REG(MIPI_DSI, DW_DSI_INT_ST0), + READ32_REG(MIPI_DSI, DW_DSI_INT_ST1)); + } +} + +static void dsi_bta_control(astro_display_t* display, int en) +{ + if (en) { + SET_BIT32(MIPI_DSI, DW_DSI_CMD_MODE_CFG, + MIPI_DSI_DCS_REQ_ACK, BIT_ACK_RQST_EN, 1); + SET_BIT32(MIPI_DSI, DW_DSI_PCKHDL_CFG, + MIPI_DSI_DCS_REQ_ACK, BIT_BTA_EN, 1); + } else { + SET_BIT32(MIPI_DSI, DW_DSI_PCKHDL_CFG, + MIPI_DSI_DCS_NO_ACK, BIT_BTA_EN, 1); + SET_BIT32(MIPI_DSI, DW_DSI_CMD_MODE_CFG, + MIPI_DSI_DCS_NO_ACK, BIT_ACK_RQST_EN, 1); + } +} + + +static int wait_bta_ack(astro_display_t* display) +{ + uint32_t phy_status; + int i; + + /* Check if phydirection is RX */ + i = CMD_TIMEOUT_CNT; + do { + usleep(10); + i--; + phy_status = READ32_REG(MIPI_DSI, DW_DSI_PHY_STATUS); + } while ((((phy_status & 0x2) >> BIT_PHY_DIRECTION) == 0x0) && (i > 0)); + if (i == 0) { + DISP_ERROR("phy direction error: RX\n"); + return -1; + } + + /* Check if phydirection is return to TX */ + i = CMD_TIMEOUT_CNT; + do { + usleep(10); + i--; + phy_status = READ32_REG(MIPI_DSI, DW_DSI_PHY_STATUS); + } while ((((phy_status & 0x2) >> BIT_PHY_DIRECTION) == 0x1) && (i > 0)); + if (i == 0) { + DISP_ERROR("phy direction error: TX\n"); + return -1; + } + + return 0; +} + +static void wait_cmd_fifo_empty(astro_display_t* display) +{ + uint32_t cmd_status; + int i = CMD_TIMEOUT_CNT; + + do { + usleep(10); + i--; + cmd_status = READ32_REG(MIPI_DSI, DW_DSI_CMD_PKT_STATUS); + } while ((((cmd_status >> BIT_GEN_CMD_EMPTY) & 0x1) != 0x1) && (i > 0)); + print_mipi_cmd_status(display, i, cmd_status); +} +static unsigned short dsi_rx_n; + +static void dsi_set_max_return_pkt_size(astro_display_t* display, struct dsi_cmd_request_s *req) +{ + uint32_t d_para[2]; + + d_para[0] = (uint32_t)(req->payload[2] & 0xff); + d_para[1] = (uint32_t)(req->payload[3] & 0xff); + dsi_rx_n = (unsigned short)((d_para[1] << 8) | d_para[0]); + generic_if_wr(display, DW_DSI_GEN_HDR, + ((d_para[1] << BIT_GEN_WC_MSBYTE) | + (d_para[0] << BIT_GEN_WC_LSBYTE) | + (((uint32_t)req->vc_id) << BIT_GEN_VC) | + (DT_SET_MAX_RET_PKT_SIZE << BIT_GEN_DT))); + if (req->req_ack == MIPI_DSI_DCS_REQ_ACK) { + wait_bta_ack(display); + } else if (req->req_ack == MIPI_DSI_DCS_NO_ACK) { + wait_cmd_fifo_empty(display); + } +} + + +static int dsi_generic_read_packet(astro_display_t* display, struct dsi_cmd_request_s *req, + unsigned char *r_data) +{ + unsigned int d_para[2], read_data; + unsigned int i, j, done; + int ret = 0; + + switch (req->data_type) { + case DT_GEN_RD_1: + d_para[0] = (req->pld_count == 0) ? + 0 : (((unsigned int)req->payload[2]) & 0xff); + d_para[1] = 0; + break; + case DT_GEN_RD_2: + d_para[0] = (req->pld_count == 0) ? + 0 : (((unsigned int)req->payload[2]) & 0xff); + d_para[1] = (req->pld_count < 2) ? + 0 : (((unsigned int)req->payload[3]) & 0xff); + break; + case DT_GEN_RD_0: + default: + d_para[0] = 0; + d_para[1] = 0; + break; + } + + if (MIPI_DSI_DCS_ACK_TYPE == MIPI_DSI_DCS_NO_ACK) + dsi_bta_control(display, 1); + generic_if_wr(display, DW_DSI_GEN_HDR, + ((d_para[1] << BIT_GEN_WC_MSBYTE) | + (d_para[0] << BIT_GEN_WC_LSBYTE) | + (((unsigned int)req->vc_id) << BIT_GEN_VC) | + (((unsigned int)req->data_type) << BIT_GEN_DT))); + ret = wait_bta_ack(display); + if (ret) + return -1; + + i = 0; + done = 0; + while (done == 0) { + read_data = generic_if_rd(display, DW_DSI_GEN_PLD_DATA); + for (j = 0; j < 4; j++) { + if (i < dsi_rx_n) { + r_data[i] = (unsigned char) + ((read_data >> (j*8)) & 0xff); + i++; + } else { + done = 1; + break; + } + } + } + if (MIPI_DSI_DCS_ACK_TYPE == MIPI_DSI_DCS_NO_ACK) + dsi_bta_control(display, 0); + + return dsi_rx_n; +} + +static int dsi_dcs_read_packet(astro_display_t* display, struct dsi_cmd_request_s *req, + unsigned char *r_data) +{ + unsigned int d_command, read_data; + unsigned int i, j, done; + int ret = 0; + + d_command = ((unsigned int)req->payload[2]) & 0xff; + + if (MIPI_DSI_DCS_ACK_TYPE == MIPI_DSI_DCS_NO_ACK) + dsi_bta_control(display, 1); + generic_if_wr(display, DW_DSI_GEN_HDR, + ((0 << BIT_GEN_WC_MSBYTE) | + (d_command << BIT_GEN_WC_LSBYTE) | + (((unsigned int)req->vc_id) << BIT_GEN_VC) | + (((unsigned int)req->data_type) << BIT_GEN_DT))); + ret = wait_bta_ack(display); + if (ret) + return -1; + + i = 0; + done = 0; + while (done == 0) { + read_data = generic_if_rd(display, DW_DSI_GEN_PLD_DATA); + for (j = 0; j < 4; j++) { + if (i < dsi_rx_n) { + r_data[i] = (unsigned char) + ((read_data >> (j*8)) & 0xff); + i++; + } else { + done = 1; + break; + } + } + } + + if (MIPI_DSI_DCS_ACK_TYPE == MIPI_DSI_DCS_NO_ACK) + dsi_bta_control(display, 0); + + return dsi_rx_n; +} + + +/* ************************************************************* + * Function: dcs_write_short_packet + * DCS Write Short Packet with Generic Interface + * Supported Data Type: DT_DCS_SHORT_WR_0, DT_DCS_SHORT_WR_1, + */ +static void dsi_dcs_write_short_packet(astro_display_t* display, struct dsi_cmd_request_s *req) +{ + unsigned int d_command, d_para; + + d_command = ((unsigned int)req->payload[2]) & 0xff; + d_para = (req->pld_count < 2) ? + 0 : (((unsigned int)req->payload[3]) & 0xff); + + generic_if_wr(display, DW_DSI_GEN_HDR, + ((d_para << BIT_GEN_WC_MSBYTE) | + (d_command << BIT_GEN_WC_LSBYTE) | + (((unsigned int)req->vc_id) << BIT_GEN_VC) | + (((unsigned int)req->data_type) << BIT_GEN_DT))); + if (req->req_ack == MIPI_DSI_DCS_REQ_ACK) + wait_bta_ack(display); + else if (req->req_ack == MIPI_DSI_DCS_NO_ACK) + wait_cmd_fifo_empty(display); +} + +/* ************************************************************* + * Function: dsi_write_long_packet + * Write Long Packet with Generic Interface + * Supported Data Type: DT_GEN_LONG_WR, DT_DCS_LONG_WR + */ +static void dsi_write_long_packet(astro_display_t* display, struct dsi_cmd_request_s *req) +{ + unsigned int d_command, payload_data, header_data; + unsigned int cmd_status; + unsigned int i, j, data_index, n, temp; + + /* payload[2] start (payload[0]: data_type, payload[1]: data_cnt) */ + data_index = DSI_CMD_SIZE_INDEX + 1; + d_command = ((unsigned int)req->payload[data_index]) & 0xff; + + /* Write Payload Register First */ + n = (req->pld_count+3)/4; + for (i = 0; i < n; i++) { + payload_data = 0; + if (i < (req->pld_count/4)) + temp = 4; + else + temp = req->pld_count % 4; + for (j = 0; j < temp; j++) { + payload_data |= (((unsigned int) + req->payload[data_index+(i*4)+j]) << (j*8)); + } + + /* Check the pld fifo status before write to it, + * do not need check every word + */ + if ((i == (n/3)) || (i == (n/2))) { + j = CMD_TIMEOUT_CNT; + do { + usleep(10); + j--; + cmd_status = READ32_REG(MIPI_DSI, + DW_DSI_CMD_PKT_STATUS); + } while ((((cmd_status >> BIT_GEN_PLD_W_FULL) & 0x1) == + 0x1) && (j > 0)); + print_mipi_cmd_status(display, j, cmd_status); + } + /* Use direct memory write to save time when in + * WRITE_MEMORY_CONTINUE + */ + if (d_command == DCS_WRITE_MEMORY_CONTINUE) { + WRITE32_REG(MIPI_DSI, DW_DSI_GEN_PLD_DATA, + payload_data); + } else { + generic_if_wr(display, DW_DSI_GEN_PLD_DATA, + payload_data); + } + } + + /* Check cmd fifo status before write to it */ + j = CMD_TIMEOUT_CNT; + do { + usleep(10); + j--; + cmd_status = READ32_REG(MIPI_DSI, DW_DSI_CMD_PKT_STATUS); + } while ((((cmd_status >> BIT_GEN_CMD_FULL) & 0x1) == 0x1) && (j > 0)); + print_mipi_cmd_status(display, j, cmd_status); + /* Write Header Register */ + /* include command */ + header_data = ((((unsigned int)req->pld_count) << BIT_GEN_WC_LSBYTE) | + (((unsigned int)req->vc_id) << BIT_GEN_VC) | + (((unsigned int)req->data_type) << BIT_GEN_DT)); + generic_if_wr(display, DW_DSI_GEN_HDR, header_data); + if (req->req_ack == MIPI_DSI_DCS_REQ_ACK) + wait_bta_ack(display); + else if (req->req_ack == MIPI_DSI_DCS_NO_ACK) + wait_cmd_fifo_empty(display); +} + +int dsi_read_single(astro_display_t* display, unsigned char *payload, unsigned char *rd_data, + unsigned int rd_byte_len) +{ + int num = 0; + unsigned char temp[4]; + unsigned char vc_id = MIPI_DSI_VIRTUAL_CHAN_ID; + unsigned int req_ack; + struct dsi_cmd_request_s dsi_cmd_req; + + req_ack = MIPI_DSI_DCS_ACK_TYPE; + dsi_cmd_req.data_type = DT_SET_MAX_RET_PKT_SIZE; + dsi_cmd_req.vc_id = (vc_id & 0x3); + temp[0] = dsi_cmd_req.data_type; + temp[1] = 2; + temp[2] = (unsigned char)((rd_byte_len >> 0) & 0xff); + temp[3] = (unsigned char)((rd_byte_len >> 8) & 0xff); + dsi_cmd_req.payload = &temp[0]; + dsi_cmd_req.pld_count = 2; + dsi_cmd_req.req_ack = req_ack; + dsi_set_max_return_pkt_size(display, &dsi_cmd_req); + + /* payload struct: */ + /* data_type, data_cnt, command, parameters... */ + req_ack = MIPI_DSI_DCS_REQ_ACK; /* need BTA ack */ + dsi_cmd_req.data_type = payload[0]; + dsi_cmd_req.vc_id = (vc_id & 0x3); + dsi_cmd_req.payload = &payload[0]; + dsi_cmd_req.pld_count = payload[DSI_CMD_SIZE_INDEX]; + dsi_cmd_req.req_ack = req_ack; + switch (dsi_cmd_req.data_type) {/* analysis data_type */ + case DT_GEN_RD_0: + case DT_GEN_RD_1: + case DT_GEN_RD_2: + num = dsi_generic_read_packet(display, &dsi_cmd_req, rd_data); + break; + case DT_DCS_RD_0: + num = dsi_dcs_read_packet(display, &dsi_cmd_req, rd_data); + break; + default: + DISP_ERROR("read un-support data_type: 0x%02x\n", + dsi_cmd_req.data_type); + break; + } + + if (num < 0) { + DISP_ERROR("mipi-dsi read error\n"); + } + + return num; +} + +static void mipi_dsi_check_state(astro_display_t* display, unsigned char reg, unsigned char cnt) +{ + int ret = 0, i; + unsigned char *rd_data; + unsigned char payload[3] = {DT_GEN_RD_1, 1, 0x04}; + + if (display->dsi_cfg->check_en == 0) { + return; + } + + display->dsi_cfg->check_state = 0; + rd_data = (unsigned char *)malloc(sizeof(unsigned char) * cnt); + if (rd_data == NULL) { + DISP_ERROR("%s: rd_data malloc error\n", __func__); + return; + } + + payload[2] = reg; + ret = dsi_read_single(display, payload, rd_data, cnt); + if (ret < 0) { + display->dsi_cfg->check_state = 0; + SET_BIT32(VPU, L_VCOM_VS_ADDR, 0, 12, 1); + free(rd_data); + return; + } + if (ret > cnt) { + DISP_ERROR("%s: read back cnt is wrong\n", __func__); + free(rd_data); + return; + } + + display->dsi_cfg->check_state = 1; + SET_BIT32(VPU, L_VCOM_VS_ADDR, 1, 12, 1); + DISP_INFO("read reg 0x%02x: ", reg); + for (i = 0; i < ret; i++) { + if (i == 0) + DISP_INFO("0x%02x", rd_data[i]); + else + DISP_INFO(",0x%02x", rd_data[i]); + } + DISP_INFO("\n"); + + free(rd_data); +} + +#if 0 +int dsi_write_cmd(unsigned char *payload) +{ + int i = 0, j = 0, num = 0; + int k = 0, n = 0; + unsigned char rd_data[100]; + struct dsi_cmd_request_s dsi_cmd_req; + unsigned char vc_id = MIPI_DSI_VIRTUAL_CHAN_ID; + uint32_t req_ack = MIPI_DSI_DCS_ACK_TYPE; + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + struct lcd_power_ctrl_s *lcd_power; + char *str; + int gpio; + + /* mipi command(payload) */ + /* format: data_type, cmd_size, data.... */ + /* special: data_type=0xff, + * cmd_size<0xff means delay ms, + * cmd_size=0xff means ending. + * data_type=0xf0, + * data0=gpio_index, data1=gpio_value, data2=delay. + */ + while (i < DSI_CMD_SIZE_MAX) { + if (payload[i] == 0xff) { + j = 2; + if (payload[i+1] == 0xff) + break; + else + mdelay(payload[i+1]); + } else if (payload[i] == 0xf0) { /* gpio */ + j = (DSI_CMD_SIZE_INDEX + 1) + + payload[i+DSI_CMD_SIZE_INDEX]; + if (payload[i+DSI_CMD_SIZE_INDEX] < 3) { + DISP_ERROR("wrong cmd_size %d for gpio\n", + payload[i+DSI_CMD_SIZE_INDEX]); + break; + } + lcd_power = lcd_drv->lcd_config->lcd_power; + str = lcd_power->cpu_gpio[payload[i+DSI_GPIO_INDEX]]; + gpio = aml_lcd_gpio_name_map_num(str); + aml_lcd_gpio_set(gpio, payload[i+DSI_GPIO_INDEX+1]); + if (payload[i+DSI_GPIO_INDEX+2]) + mdelay(payload[i+DSI_GPIO_INDEX+2]); + } else if (payload[i] == 0xfc) { /* check state */ + j = (DSI_CMD_SIZE_INDEX + 1) + + payload[i+DSI_CMD_SIZE_INDEX]; + if (payload[i+DSI_CMD_SIZE_INDEX] < 2) { + DISP_ERROR("wrong cmd_size %d for check state\n", + payload[i+DSI_CMD_SIZE_INDEX]); + break; + } + if (payload[i+DSI_GPIO_INDEX+2] > 0) { + mipi_dsi_check_state( + payload[i+DSI_GPIO_INDEX], + payload[i+DSI_GPIO_INDEX+1]); + } + } else if ((payload[i] & 0xf) == 0x0) { + DISP_ERROR("data_type: 0x%02x\n", payload[i]); + break; + } else { + /* payload[i+DSI_CMD_SIZE_INDEX] is data count */ + j = (DSI_CMD_SIZE_INDEX + 1) + + payload[i+DSI_CMD_SIZE_INDEX]; + dsi_cmd_req.data_type = payload[i]; + dsi_cmd_req.vc_id = (vc_id & 0x3); + dsi_cmd_req.payload = &payload[i]; + dsi_cmd_req.pld_count = payload[i+DSI_CMD_SIZE_INDEX]; + dsi_cmd_req.req_ack = req_ack; + switch (dsi_cmd_req.data_type) {/* analysis data_type */ + case DT_GEN_SHORT_WR_0: + case DT_GEN_SHORT_WR_1: + case DT_GEN_SHORT_WR_2: + dsi_generic_write_short_packet(&dsi_cmd_req); + break; + case DT_DCS_SHORT_WR_0: + case DT_DCS_SHORT_WR_1: + dsi_dcs_write_short_packet(&dsi_cmd_req); + break; + case DT_DCS_LONG_WR: + case DT_GEN_LONG_WR: + dsi_write_long_packet(&dsi_cmd_req); + break; + case DT_TURN_ON: + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_CNTL, 1, 2, 1); + mdelay(20); /* wait for vsync trigger */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_CNTL, 0, 2, 1); + mdelay(20); /* wait for vsync trigger */ + break; + case DT_SHUT_DOWN: + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_CNTL, 1, 2, 1); + mdelay(20); /* wait for vsync trigger */ + break; + case DT_SET_MAX_RET_PKT_SIZE: + dsi_set_max_return_pkt_size(&dsi_cmd_req); + break; +#ifdef DSI_CMD_READ_VALID + case DT_GEN_RD_0: + case DT_GEN_RD_1: + case DT_GEN_RD_2: + /* need BTA ack */ + dsi_cmd_req.req_ack = MIPI_DSI_DCS_REQ_ACK; + dsi_cmd_req.pld_count = + (dsi_cmd_req.pld_count > 2) ? + 2 : dsi_cmd_req.pld_count; + n = dsi_generic_read_packet(&dsi_cmd_req, + &rd_data[0]); + DISP_ERROR("generic read data"); + for (k = 0; k < dsi_cmd_req.pld_count; k++) { + DISP_INFO(" 0x%02x", + dsi_cmd_req.payload[k+2]); + } + for (k = 0; k < n; k++) + DISP_INFO("0x%02x ", rd_data[k]); + DISP_INFO("\n"); + break; + case DT_DCS_RD_0: + /* need BTA ack */ + dsi_cmd_req.req_ack = MIPI_DSI_DCS_REQ_ACK; + n = dsi_dcs_read_packet(&dsi_cmd_req, + &rd_data[0]); + DISP_INFO("dcs read data 0x%02x:\n", + dsi_cmd_req.payload[2]); + for (k = 0; k < n; k++) + DISP_INFO("0x%02x ", rd_data[k]); + DISP_INFO("\n"); + break; +#endif + default: + DISP_ERROR("[warning]un-support data_type: 0x%02x\n", + dsi_cmd_req.data_type); + + break; + } + } + i += j; + num++; + } + + return num; +} +#endif + +static void set_mipi_dsi_lpclk_ctrl(astro_display_t* display, uint32_t operation_mode) { + uint32_t lpclk = 1; + + if (operation_mode == OPERATION_VIDEO_MODE) { + if (display->dsi_cfg->clk_always_hs) { /* clk always hs */ + lpclk = 0; + } else { /* enable clk lp state */ + lpclk = 1; + } + } else { /* enable clk lp state */ + lpclk = 1; + } + SET_BIT32(MIPI_DSI, DW_DSI_LPCLK_CTRL, lpclk, BIT_AUTOCLKLANE_CTRL, 1); +} + +static void mipi_dsi_link_on(astro_display_t* display) { + + set_mipi_dsi_lpclk_ctrl(display, display->dsi_cfg->opp_mode_init); + + // dsi_write_cmd(dconf->dsi_init_on); + + // dsi_write_cmd(lcd_ext->config->table_init_on); + + set_mipi_dsi_host(display, MIPI_DSI_VIRTUAL_CHAN_ID, + 0, /* Chroma sub sample, only for + * YUV 422 or 420, even or odd + */ + display->dsi_cfg->opp_mode_display); + set_mipi_dsi_lpclk_ctrl(display, display->dsi_cfg->opp_mode_display); +} + +static void startup_mipi_dsi_host(astro_display_t* display) +{ + + /* Enable dwc mipi_dsi_host's clock */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_CNTL, 0x3, 4, 2); + /* mipi_dsi_host's reset */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_SW_RESET, 0xf, 0, 4); + /* Release mipi_dsi_host's reset */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_SW_RESET, 0x0, 0, 4); + /* Enable dwc mipi_dsi_host's clock */ + SET_BIT32(MIPI_DSI, MIPI_DSI_TOP_CLK_CNTL, 0x3, 0, 2); + + WRITE32_REG(MIPI_DSI, MIPI_DSI_TOP_MEM_PD, 0); + + usleep(10000); +} + + +zx_status_t aml_dsi_host_on(astro_display_t* display) { + + ZX_DEBUG_ASSERT(display); + + display->dsi_vid = calloc(1, sizeof(dsi_video_t)); + if (!display->dsi_vid) { + DISP_ERROR("Could not allocate dsi_video_t\n"); + return ZX_ERR_NO_MEMORY; + } + + mipi_dsi_config_post(display); + + startup_mipi_dsi_host(display); + + mipi_dcs_set(display, MIPI_DSI_CMD_TRANS_TYPE, /* 0: high speed, 1: low power */ + MIPI_DSI_DCS_ACK_TYPE, /* if need bta ack check */ + MIPI_DSI_TEAR_SWITCH); /* enable tear ack */ + + set_mipi_dsi_host(display, MIPI_DSI_VIRTUAL_CHAN_ID, /* Virtual channel id */ + 0, /* Chroma sub sample, only for YUV 422 or 420, even or odd */ + display->dsi_cfg->opp_mode_init); /* DSI operation mode, video or command */ + set_dsi_phy_config(display); + + mipi_dsi_link_on(display); + + + return ZX_OK; +} \ No newline at end of file
diff --git a/system/dev/display/astro-display/dw_dsi.h b/system/dev/display/astro-display/dw_dsi.h new file mode 100644 index 0000000..82ee599 --- /dev/null +++ b/system/dev/display/astro-display/dw_dsi.h
@@ -0,0 +1,57 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#define DW_DSI_VERSION (0x00 << 2) /* contains the vers of the DSI host controller */ +#define DW_DSI_PWR_UP (0x01 << 2) /* controls the power up of the core */ +#define DW_DSI_CLKMGR_CFG (0x02 << 2) /* configs the factor for internal dividers */ +#define DW_DSI_DPI_VCID (0x03 << 2) /* configs the Virt Chan ID for DPI traffic */ +#define DW_DSI_DPI_COLOR_CODING (0x04 << 2) /* configs DPI color coding */ +#define DW_DSI_DPI_CFG_POL (0x05 << 2) /* configs the polarity of DPI signals */ +#define DW_DSI_DPI_LP_CMD_TIM (0x06 << 2) /* configs the timing for lp cmds (in vid mode) */ +#define DW_DSI_DBI_VCID (0x07 << 2) /* configs Virtual Channel ID for DBI traffic */ +#define DW_DSI_DBI_CFG (0x08 << 2) /* configs the bit width of pixels for DBI */ +#define DW_DSI_DBI_PARTITIONING_EN (0x09 << 2) /* host partition DBI traffic automatically */ +#define DW_DSI_DBI_CMDSIZE (0x0A << 2) /* cmd size for auto partitioning of DBI */ +#define DW_DSI_PCKHDL_CFG (0x0B << 2) /* how EoTp, BTA, CRC and ECC are to be used */ +#define DW_DSI_GEN_VCID (0x0C << 2) /* Virtual Channel ID of READ responses to store */ +#define DW_DSI_MODE_CFG (0x0D << 2) /* mode of op between Video or Command Mode */ +#define DW_DSI_VID_MODE_CFG (0x0E << 2) /* Video mode operation config */ +#define DW_DSI_VID_PKT_SIZE (0x0F << 2) /* video packet size */ +#define DW_DSI_VID_NUM_CHUNKS (0x10 << 2) /* number of chunks to use */ +#define DW_DSI_VID_NULL_SIZE (0x11 << 2) /* configs the size of null packets */ +#define DW_DSI_VID_HSA_TIME (0x12 << 2) /* configs the video HSA time */ +#define DW_DSI_VID_HBP_TIME (0x13 << 2) /* configs the video HBP time */ +#define DW_DSI_VID_HLINE_TIME (0x14 << 2) /* configs the overall time for each video line */ +#define DW_DSI_VID_VSA_LINES (0x15 << 2) /* configs the VSA period */ +#define DW_DSI_VID_VBP_LINES (0x16 << 2) /* configs the VBP period */ +#define DW_DSI_VID_VFP_LINES (0x17 << 2) /* configs the VFP period */ +#define DW_DSI_VID_VACTIVE_LINES (0x18 << 2) /* configs the vertical resolution of video */ +#define DW_DSI_EDPI_CMD_SIZE (0x19 << 2) /* configs the size of eDPI packets */ +#define DW_DSI_CMD_MODE_CFG (0x1A << 2) /* command mode operation config */ +#define DW_DSI_GEN_HDR (0x1B << 2) /* header for new packets */ +#define DW_DSI_GEN_PLD_DATA (0x1C << 2) /* payload for packets sent using the Gen i/f */ +#define DW_DSI_CMD_PKT_STATUS (0x1D << 2) /* info about FIFOs related to DBI and Gen i/f */ +#define DW_DSI_TO_CNT_CFG (0x1E << 2) /* counters that trig timeout errors */ +#define DW_DSI_HS_RD_TO_CNT (0x1F << 2) /* Peri Resp timeout after HS Rd operations */ +#define DW_DSI_LP_RD_TO_CNT (0x20 << 2) /* Peri Resp timeout after LP Rd operations */ +#define DW_DSI_HS_WR_TO_CNT (0x21 << 2) /* Peri Resp timeout after HS Wr operations */ +#define DW_DSI_LP_WR_TO_CNT (0x22 << 2) /* Peri Resp timeout after LP Wr operations */ +#define DW_DSI_BTA_TO_CNT (0x23 << 2) /* Peri Resp timeout after Bus Turnaround comp */ +#define DW_DSI_SDF_3D (0x24 << 2) /* 3D cntrl info for VSS packets in video mode. */ +#define DW_DSI_LPCLK_CTRL (0x25 << 2) /* non continuous clock in the clock lane. */ +#define DW_DSI_PHY_TMR_LPCLK_CFG (0x26 << 2) /* time for the clock lane */ +#define DW_DSI_PHY_TMR_CFG (0x27 << 2) /* time for the data lanes */ +#define DW_DSI_PHY_RSTZ (0x28 << 2) /* controls resets and the PLL of the D-PHY. */ +#define DW_DSI_PHY_IF_CFG (0x29 << 2) /* number of active lanes */ +#define DW_DSI_PHY_ULPS_CTRL (0x2A << 2) /* entering and leaving ULPS in the D- PHY. */ +#define DW_DSI_PHY_TX_TRIGGERS (0x2B << 2) /* pins that activate triggers in the D-PHY */ +#define DW_DSI_PHY_STATUS (0x2C << 2) /* contains info about the status of the D- PHY */ +#define DW_DSI_PHY_TST_CTRL0 (0x2D << 2) /* controls clock and clear pins of the D-PHY */ +#define DW_DSI_PHY_TST_CTRL1 (0x2E << 2) /* controls data and enable pins of the D-PHY */ +#define DW_DSI_INT_ST0 (0x3F << 2) /* status of intr from ack and D-PHY */ +#define DW_DSI_INT_ST1 (0x30 << 2) /* status of intr related to timeout, ECC, etc */ +#define DW_DSI_INT_MSK0 (0x31 << 2) /* masks interrupts that affect the INT_ST0 reg */ +#define DW_DSI_INT_MSK1 (0x32 << 2) /* masks interrupts that affect the INT_ST1 reg */
diff --git a/system/dev/display/astro-display/hhi.h b/system/dev/display/astro-display/hhi.h new file mode 100644 index 0000000..8dd7004 --- /dev/null +++ b/system/dev/display/astro-display/hhi.h
@@ -0,0 +1,565 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#define HHI_MIPI_CNTL0 (0x000 << 2) +#define HHI_MIPI_CNTL1 (0x001 << 2) +#define HHI_MIPI_CNTL2 (0x002 << 2) +#define HHI_MIPI_STS (0x003 << 2) +#define HHI_CHECK_CLK_RESULT (0x004 << 2) +#define HHI_GP0_PLL_CNTL0 (0x010 << 2) +#define HHI_GP0_PLL_CNTL1 (0x011 << 2) +#define HHI_GP0_PLL_CNTL2 (0x012 << 2) +#define HHI_GP0_PLL_CNTL3 (0x013 << 2) +#define HHI_GP0_PLL_CNTL4 (0x014 << 2) +#define HHI_GP0_PLL_CNTL5 (0x015 << 2) +#define HHI_GP0_PLL_CNTL6 (0x016 << 2) +#define HHI_GP0_PLL_STS (0x017 << 2) +#define HHI_PCIE_PLL_CNTL0 (0x026 << 2) +#define HHI_PCIE_PLL_CNTL1 (0x027 << 2) +#define HHI_PCIE_PLL_CNTL2 (0x028 << 2) +#define HHI_PCIE_PLL_CNTL3 (0x029 << 2) +#define HHI_PCIE_PLL_CNTL4 (0x02a << 2) +#define HHI_PCIE_PLL_CNTL5 (0x02b << 2) +#define HHI_PCIE_PLL_STS (0x02c << 2) +#define HHI_XTAL_DIVN_CNTL (0x02f << 2) +#define HHI_GCLK2_MPEG0 (0x030 << 2) +#define HHI_GCLK2_MPEG1 (0x031 << 2) +#define HHI_GCLK2_MPEG2 (0x032 << 2) +#define HHI_GCLK2_OTHER (0x034 << 2) +#define HHI_HIFI_PLL_CNTL0 (0x036 << 2) +#define HHI_HIFI_PLL_CNTL1 (0x037 << 2) +#define HHI_HIFI_PLL_CNTL2 (0x038 << 2) +#define HHI_HIFI_PLL_CNTL3 (0x039 << 2) +#define HHI_HIFI_PLL_CNTL4 (0x03a << 2) +#define HHI_HIFI_PLL_CNTL5 (0x03b << 2) +#define HHI_HIFI_PLL_CNTL6 (0x03c << 2) +#define HHI_HIFI_PLL_STS (0x03d << 2) +#define HHI_TIMER90K (0x03f << 2) +#define HHI_MEM_PD_REG0 (0x040 << 2) +#define HHI_VPU_MEM_PD_REG0 (0x041 << 2) +#define HHI_VPU_MEM_PD_REG1 (0x042 << 2) +#define HHI_VIID_CLK_DIV (0x04a << 2) +#define HHI_VIID_CLK_CNTL (0x04b << 2) +#define HHI_VPU_MEM_PD_REG2 (0x04d << 2) +#define HHI_GCLK_LOCK (0x04f << 2) +#define HHI_GCLK_MPEG0 (0x050 << 2) +#define HHI_GCLK_MPEG1 (0x051 << 2) +#define HHI_GCLK_MPEG2 (0x052 << 2) +#define HHI_GCLK_OTHER (0x054 << 2) +#define HHI_GCLK_SP_MPEG (0x055 << 2) +#define HHI_SYS_CPU_CLK_CNTL1 (0x057 << 2) +#define HHI_SYS_CPU_RESET_CNTL (0x058 << 2) +#define HHI_VID_CLK_DIV (0x059 << 2) +#define HHI_MPEG_CLK_CNTL (0x05d << 2) +#define HHI_VID_CLK_CNTL (0x05f << 2) +#define HHI_TS_CLK_CNTL (0x064 << 2) +#define HHI_VID_CLK_CNTL2 (0x065 << 2) +#define HHI_SYS_CPU_CLK_CNTL (0x067 << 2) +#define HHI_VID_PLL_CLK_DIV (0x068 << 2) +#define HHI_MALI_CLK_CNTL (0x06c << 2) +#define HHI_VPU_CLKC_CNTL (0x06d << 2) +#define HHI_VPU_CLK_CNTL (0x06f << 2) +#define HHI_HDMI_CLK_CNTL (0x073 << 2) +#define HHI_ETH_CLK_CNTL (0x076 << 2) +#define HHI_VDEC_CLK_CNTL (0x078 << 2) +#define HHI_VDEC2_CLK_CNTL (0x079 << 2) +#define HHI_VDEC3_CLK_CNTL (0x07a << 2) +#define HHI_VDEC4_CLK_CNTL (0x07b << 2) +#define HHI_HDCP22_CLK_CNTL (0x07c << 2) +#define HHI_VAPBCLK_CNTL (0x07d << 2) +#define HHI_VPU_CLKB_CNTL (0x083 << 2) +#define HHI_GEN_CLK_CNTL (0x08a << 2) +#define HHI_VDIN_MEAS_CLK_CNTL (0x094 << 2) +#define HHI_MIPIDSI_PHY_CLK_CNTL (0x095 << 2) +#define HHI_NAND_CLK_CNTL (0x097 << 2) +#define HHI_SD_EMMC_CLK_CNTL (0x099 << 2) +#define HHI_WAVE420L_CLK_CNTL (0x09a << 2) +#define HHI_WAVE420L_CLK_CNTL2 (0x09b << 2) +#define HHI_MPLL_CNTL0 (0x09e << 2) +#define HHI_MPLL_CNTL1 (0x09f << 2) +#define HHI_MPLL_CNTL2 (0x0a0 << 2) +#define HHI_MPLL_CNTL3 (0x0a1 << 2) +#define HHI_MPLL_CNTL4 (0x0a2 << 2) +#define HHI_MPLL_CNTL5 (0x0a3 << 2) +#define HHI_MPLL_CNTL6 (0x0a4 << 2) +#define HHI_MPLL_CNTL7 (0x0a5 << 2) +#define HHI_MPLL_CNTL8 (0x0a6 << 2) +#define HHI_MPLL_STS (0x0a7 << 2) +#define HHI_FIX_PLL_CNTL0 (0x0a8 << 2) +#define HHI_FIX_PLL_CNTL1 (0x0a9 << 2) +#define HHI_FIX_PLL_CNTL2 (0x0aa << 2) +#define HHI_FIX_PLL_CNTL3 (0x0ab << 2) +#define HHI_FIX_PLL_CNTL4 (0x0ac << 2) +#define HHI_FIX_PLL_CNTL5 (0x0ad << 2) +#define HHI_FIX_PLL_CNTL6 (0x0ae << 2) +#define HHI_FIX_PLL_STS (0x0af << 2) +#define HHI_VDAC_CNTL0 (0x0bb << 2) +#define HHI_VDAC_CNTL1 (0x0bc << 2) +#define HHI_SYS_PLL_CNTL0 (0x0bd << 2) +#define HHI_SYS_PLL_CNTL1 (0x0be << 2) +#define HHI_SYS_PLL_CNTL2 (0x0bf << 2) +#define HHI_SYS_PLL_CNTL3 (0x0c0 << 2) +#define HHI_SYS_PLL_CNTL4 (0x0c1 << 2) +#define HHI_SYS_PLL_CNTL5 (0x0c2 << 2) +#define HHI_SYS_PLL_CNTL6 (0x0c3 << 2) +#define HHI_SYS_PLL_STS (0x0c4 << 2) +#define HHI_HDMI_PLL_CNTL0 (0x0c8 << 2) +#define HHI_HDMI_PLL_CNTL1 (0x0c9 << 2) +#define HHI_HDMI_PLL_CNTL2 (0x0ca << 2) +#define HHI_HDMI_PLL_CNTL3 (0x0cb << 2) +#define HHI_HDMI_PLL_CNTL4 (0x0cc << 2) +#define HHI_HDMI_PLL_CNTL5 (0x0cd << 2) +#define HHI_HDMI_PLL_CNTL6 (0x0ce << 2) +#define HHI_HDMI_PLL_STS (0x0cf << 2) +#define HHI_HDMI_PHY_CNTL0 (0x0e8 << 2) +#define HHI_HDMI_PHY_CNTL1 (0x0e9 << 2) +#define HHI_HDMI_PHY_CNTL2 (0x0ea << 2) +#define HHI_HDMI_PHY_CNTL3 (0x0eb << 2) +#define HHI_HDMI_PHY_CNTL4 (0x0ec << 2) +#define HHI_HDMI_PHY_CNTL5 (0x0ed << 2) +#define HHI_HDMI_PHY_STATUS (0x0ee << 2) +#define HHI_VID_LOCK_CLK_CNTL (0x0f2 << 2) +#define HHI_AXI_PIPEL_CNTL (0x0f4 << 2) +#define HHI_BT656_CLK_CNTL (0x0f5 << 2) +#define HHI_CDAC_CLK_CNTL (0x0f6 << 2) +#define HHI_SPICC_CLK_CNTL (0x0f7 << 2) + + +#define ENCL_TCON_INVERT_CTL (0x1bfd << 2) +#define ENCL_SYNC_LINE_LENGTH (0x1c4c << 2) +#define ENCL_SYNC_PIXEL_EN (0x1c4d << 2) +#define ENCL_SYNC_TO_LINE_EN (0x1c4e << 2) +#define ENCL_SYNC_TO_PIXEL (0x1c4f << 2) +#define ENCL_VFIFO2VD_CTL (0x1c90 << 2) +#define ENCL_VFIFO2VD_PIXEL_START (0x1c91 << 2) +#define ENCL_VFIFO2VD_PIXEL_END (0x1c92 << 2) +#define ENCL_VFIFO2VD_LINE_TOP_START (0x1c93 << 2) +#define ENCL_VFIFO2VD_LINE_TOP_END (0x1c94 << 2) +#define ENCL_VFIFO2VD_LINE_BOT_START (0x1c95 << 2) +#define ENCL_VFIFO2VD_LINE_BOT_END (0x1c96 << 2) +#define ENCL_VFIFO2VD_CTL2 (0x1c97 << 2) +#define ENCL_TST_EN (0x1c98 << 2) +#define ENCL_TST_MDSEL (0x1c99 << 2) +#define ENCL_TST_Y (0x1c9a << 2) +#define ENCL_TST_CB (0x1c9b << 2) +#define ENCL_TST_CR (0x1c9c << 2) +#define ENCL_TST_CLRBAR_STRT (0x1c9d << 2) +#define ENCL_TST_CLRBAR_WIDTH (0x1c9e << 2) +#define ENCL_TST_VDCNT_STSET (0x1c9f << 2) +#define ENCL_VIDEO_EN (0x1ca0 << 2) +#define ENCL_VIDEO_Y_SCL (0x1ca1 << 2) +#define ENCL_VIDEO_PB_SCL (0x1ca2 << 2) +#define ENCL_VIDEO_PR_SCL (0x1ca3 << 2) +#define ENCL_VIDEO_Y_OFFST (0x1ca4 << 2) +#define ENCL_VIDEO_PB_OFFST (0x1ca5 << 2) +#define ENCL_VIDEO_PR_OFFST (0x1ca6 << 2) +#define ENCL_VIDEO_MODE (0x1ca7 << 2) +#define ENCL_VIDEO_MODE_ADV (0x1ca8 << 2) +#define ENCL_DBG_PX_RST (0x1ca9 << 2) +#define ENCL_DBG_LN_RST (0x1caa << 2) +#define ENCL_DBG_PX_INT (0x1cab << 2) +#define ENCL_DBG_LN_INT (0x1cac << 2) +#define ENCL_VIDEO_YFP1_HTIME (0x1cad << 2) +#define ENCL_VIDEO_YFP2_HTIME (0x1cae << 2) +#define ENCL_VIDEO_YC_DLY (0x1caf << 2) +#define ENCL_VIDEO_MAX_PXCNT (0x1cb0 << 2) +#define ENCL_VIDEO_HAVON_END (0x1cb1 << 2) +#define ENCL_VIDEO_HAVON_BEGIN (0x1cb2 << 2) +#define ENCL_VIDEO_VAVON_ELINE (0x1cb3 << 2) +#define ENCL_VIDEO_VAVON_BLINE (0x1cb4 << 2) +#define ENCL_VIDEO_HSO_BEGIN (0x1cb5 << 2) +#define ENCL_VIDEO_HSO_END (0x1cb6 << 2) +#define ENCL_VIDEO_VSO_BEGIN (0x1cb7 << 2) +#define ENCL_VIDEO_VSO_END (0x1cb8 << 2) +#define ENCL_VIDEO_VSO_BLINE (0x1cb9 << 2) +#define ENCL_VIDEO_VSO_ELINE (0x1cba << 2) +#define ENCL_VIDEO_MAX_LNCNT (0x1cbb << 2) +#define ENCL_VIDEO_BLANKY_VAL (0x1cbc << 2) +#define ENCL_VIDEO_BLANKPB_VAL (0x1cbd << 2) +#define ENCL_VIDEO_BLANKPR_VAL (0x1cbe << 2) +#define ENCL_VIDEO_HOFFST (0x1cbf << 2) +#define ENCL_VIDEO_VOFFST (0x1cc0 << 2) +#define ENCL_VIDEO_RGB_CTRL (0x1cc1 << 2) +#define ENCL_VIDEO_FILT_CTRL (0x1cc2 << 2) +#define ENCL_VIDEO_OFLD_VPEQ_OFST (0x1cc3 << 2) +#define ENCL_VIDEO_OFLD_VOAV_OFST (0x1cc4 << 2) +#define ENCL_VIDEO_MATRIX_CB (0x1cc5 << 2) +#define ENCL_VIDEO_MATRIX_CR (0x1cc6 << 2) +#define ENCL_VIDEO_RGBIN_CTRL (0x1cc7 << 2) +#define ENCL_MAX_LINE_SWITCH_POINT (0x1cc8 << 2) +#define ENCL_DACSEL_0 (0x1cc9 << 2) +#define ENCL_DACSEL_1 (0x1cca << 2) +#define ENCL_INFO_READ (0x271f << 2) + +#define VPU_VIU_VENC_MUX_CTRL (0x271a << 2) +#define VPU_HDMI_SETTING (0x271b << 2) +#define VPU_HDMI_DATA_OVR (0x2727 << 2) +#define VPU_HDMI_FMT_CTRL (0x2743 << 2) + +#define L_GAMMA_CNTL_PORT (0x1400 << 2) +#define L_GAMMA_DATA_PORT (0x1401 << 2) +#define L_GAMMA_ADDR_PORT (0x1402 << 2) +#define L_GAMMA_VCOM_HSWITCH_ADDR (0x1403 << 2) +#define L_RGB_BASE_ADDR (0x1405 << 2) +#define L_RGB_COEFF_ADDR (0x1406 << 2) +#define L_POL_CNTL_ADDR (0x1407 << 2) +#define L_DITH_CNTL_ADDR (0x1408 << 2) +#define L_GAMMA_PROBE_CTRL (0x1409 << 2) +#define L_GAMMA_PROBE_COLOR_L (0x140a << 2) +#define L_GAMMA_PROBE_COLOR_H (0x140b << 2) +#define L_GAMMA_PROBE_HL_COLOR (0x140c << 2) +#define L_GAMMA_PROBE_POS_X (0x140d << 2) +#define L_GAMMA_PROBE_POS_Y (0x140e << 2) +#define L_STH1_HS_ADDR (0x1410 << 2) +#define L_STH1_HE_ADDR (0x1411 << 2) +#define L_STH1_VS_ADDR (0x1412 << 2) +#define L_STH1_VE_ADDR (0x1413 << 2) +#define L_STH2_HS_ADDR (0x1414 << 2) +#define L_STH2_HE_ADDR (0x1415 << 2) +#define L_STH2_VS_ADDR (0x1416 << 2) +#define L_STH2_VE_ADDR (0x1417 << 2) +#define L_OEH_HS_ADDR (0x1418 << 2) +#define L_OEH_HE_ADDR (0x1419 << 2) +#define L_OEH_VS_ADDR (0x141a << 2) +#define L_OEH_VE_ADDR (0x141b << 2) +#define L_VCOM_HSWITCH_ADDR (0x141c << 2) +#define L_VCOM_VS_ADDR (0x141d << 2) +#define L_VCOM_VE_ADDR (0x141e << 2) +#define L_CPV1_HS_ADDR (0x141f << 2) +#define L_CPV1_HE_ADDR (0x1420 << 2) +#define L_CPV1_VS_ADDR (0x1421 << 2) +#define L_CPV1_VE_ADDR (0x1422 << 2) +#define L_CPV2_HS_ADDR (0x1423 << 2) +#define L_CPV2_HE_ADDR (0x1424 << 2) +#define L_CPV2_VS_ADDR (0x1425 << 2) +#define L_CPV2_VE_ADDR (0x1426 << 2) +#define L_STV1_HS_ADDR (0x1427 << 2) +#define L_STV1_HE_ADDR (0x1428 << 2) +#define L_STV1_VS_ADDR (0x1429 << 2) +#define L_STV1_VE_ADDR (0x142a << 2) +#define L_STV2_HS_ADDR (0x142b << 2) +#define L_STV2_HE_ADDR (0x142c << 2) +#define L_STV2_VS_ADDR (0x142d << 2) +#define L_STV2_VE_ADDR (0x142e << 2) +#define L_OEV1_HS_ADDR (0x142f << 2) +#define L_OEV1_HE_ADDR (0x1430 << 2) +#define L_OEV1_VS_ADDR (0x1431 << 2) +#define L_OEV1_VE_ADDR (0x1432 << 2) +#define L_OEV2_HS_ADDR (0x1433 << 2) +#define L_OEV2_HE_ADDR (0x1434 << 2) +#define L_OEV2_VS_ADDR (0x1435 << 2) +#define L_OEV2_VE_ADDR (0x1436 << 2) +#define L_OEV3_HS_ADDR (0x1437 << 2) +#define L_OEV3_HE_ADDR (0x1438 << 2) +#define L_OEV3_VS_ADDR (0x1439 << 2) +#define L_OEV3_VE_ADDR (0x143a << 2) +#define L_LCD_PWR_ADDR (0x143b << 2) +#define L_LCD_PWM0_LO_ADDR (0x143c << 2) +#define L_LCD_PWM0_HI_ADDR (0x143d << 2) +#define L_LCD_PWM1_LO_ADDR (0x143e << 2) +#define L_LCD_PWM1_HI_ADDR (0x143f << 2) +#define L_INV_CNT_ADDR (0x1440 << 2) +#define L_TCON_MISC_SEL_ADDR (0x1441 << 2) +#define L_DUAL_PORT_CNTL_ADDR (0x1442 << 2) +#define L_TCON_DOUBLE_CTL (0x1449 << 2) +#define L_TCON_PATTERN_HI (0x144a << 2) +#define L_TCON_PATTERN_LO (0x144b << 2) +#define L_DE_HS_ADDR (0x1451 << 2) +#define L_DE_HE_ADDR (0x1452 << 2) +#define L_DE_VS_ADDR (0x1453 << 2) +#define L_DE_VE_ADDR (0x1454 << 2) +#define L_HSYNC_HS_ADDR (0x1455 << 2) +#define L_HSYNC_HE_ADDR (0x1456 << 2) +#define L_HSYNC_VS_ADDR (0x1457 << 2) +#define L_HSYNC_VE_ADDR (0x1458 << 2) +#define L_VSYNC_HS_ADDR (0x1459 << 2) +#define L_VSYNC_HE_ADDR (0x145a << 2) +#define L_VSYNC_VS_ADDR (0x145b << 2) +#define L_VSYNC_VE_ADDR (0x145c << 2) +#define L_LCD_MCU_CTL (0x145d << 2) + +#define VPP_DUMMY_DATA (0x1d00 << 2) +#define VPP_LINE_IN_LENGTH (0x1d01 << 2) +#define VPP_PIC_IN_HEIGHT (0x1d02 << 2) +#define VPP_SCALE_COEF_IDX (0x1d03 << 2) +#define VPP_SCALE_COEF (0x1d04 << 2) +#define VPP_VSC_REGION12_STARTP (0x1d05 << 2) +#define VPP_VSC_REGION34_STARTP (0x1d06 << 2) +#define VPP_VSC_REGION4_ENDP (0x1d07 << 2) +#define VPP_VSC_START_PHASE_STEP (0x1d08 << 2) +#define VPP_VSC_REGION0_PHASE_SLOPE (0x1d09 << 2) +#define VPP_VSC_REGION1_PHASE_SLOPE (0x1d0a << 2) +#define VPP_VSC_REGION3_PHASE_SLOPE (0x1d0b << 2) +#define VPP_VSC_REGION4_PHASE_SLOPE (0x1d0c << 2) +#define VPP_VSC_PHASE_CTRL (0x1d0d << 2) +#define VPP_VSC_INI_PHASE (0x1d0e << 2) +#define VPP_HSC_REGION12_STARTP (0x1d10 << 2) +#define VPP_HSC_REGION34_STARTP (0x1d11 << 2) +#define VPP_HSC_REGION4_ENDP (0x1d12 << 2) +#define VPP_HSC_START_PHASE_STEP (0x1d13 << 2) +#define VPP_HSC_REGION0_PHASE_SLOPE (0x1d14 << 2) +#define VPP_HSC_REGION1_PHASE_SLOPE (0x1d15 << 2) +#define VPP_HSC_REGION3_PHASE_SLOPE (0x1d16 << 2) +#define VPP_HSC_REGION4_PHASE_SLOPE (0x1d17 << 2) +#define VPP_HSC_PHASE_CTRL (0x1d18 << 2) +#define VPP_SC_MISC (0x1d19 << 2) +#define VPP_PREBLEND_VD1_H_START_END (0x1d1a << 2) +#define VPP_PREBLEND_VD1_V_START_END (0x1d1b << 2) +#define VPP_POSTBLEND_VD1_H_START_END (0x1d1c << 2) +#define VPP_POSTBLEND_VD1_V_START_END (0x1d1d << 2) +#define VPP_BLEND_VD2_H_START_END (0x1d1e << 2) +#define VPP_BLEND_VD2_V_START_END (0x1d1f << 2) +#define VPP_PREBLEND_H_SIZE (0x1d20 << 2) +#define VPP_POSTBLEND_H_SIZE (0x1d21 << 2) +#define VPP_HOLD_LINES (0x1d22 << 2) +#define VPP_BLEND_ONECOLOR_CTRL (0x1d23 << 2) +#define VPP_PREBLEND_CURRENT_XY (0x1d24 << 2) +#define VPP_POSTBLEND_CURRENT_XY (0x1d25 << 2) +#define VPP_MISC (0x1d26 << 2) +#define VPP_OFIFO_SIZE (0x1d27 << 2) +#define VPP_FIFO_STATUS (0x1d28 << 2) +#define VPP_SMOKE_CTRL (0x1d29 << 2) +#define VPP_SMOKE1_VAL (0x1d2a << 2) +#define VPP_SMOKE2_VAL (0x1d2b << 2) +#define VPP_SMOKE3_VAL (0x1d2c << 2) +#define VPP_SMOKE1_H_START_END (0x1d2d << 2) +#define VPP_SMOKE1_V_START_END (0x1d2e << 2) +#define VPP_SMOKE2_H_START_END (0x1d2f << 2) +#define VPP_SMOKE2_V_START_END (0x1d30 << 2) +#define VPP_SMOKE3_H_START_END (0x1d31 << 2) +#define VPP_SMOKE3_V_START_END (0x1d32 << 2) +#define VPP_SCO_FIFO_CTRL (0x1d33 << 2) +#define VPP_HSC_PHASE_CTRL1 (0x1d34 << 2) +#define VPP_HSC_INI_PAT_CTRL (0x1d35 << 2) +#define VPP_VADJ_CTRL (0x1d40 << 2) +#define VPP_VADJ1_Y (0x1d41 << 2) +#define VPP_VADJ1_MA_MB (0x1d42 << 2) +#define VPP_VADJ1_MC_MD (0x1d43 << 2) +#define VPP_VADJ2_Y (0x1d44 << 2) +#define VPP_VADJ2_MA_MB (0x1d45 << 2) +#define VPP_VADJ2_MC_MD (0x1d46 << 2) +#define VPP_HSHARP_CTRL (0x1d50 << 2) +#define VPP_HSHARP_LUMA_THRESH01 (0x1d51 << 2) +#define VPP_HSHARP_LUMA_THRESH23 (0x1d52 << 2) +#define VPP_HSHARP_CHROMA_THRESH01 (0x1d53 << 2) +#define VPP_HSHARP_CHROMA_THRESH23 (0x1d54 << 2) +#define VPP_HSHARP_LUMA_GAIN (0x1d55 << 2) +#define VPP_HSHARP_CHROMA_GAIN (0x1d56 << 2) +#define VPP_MATRIX_PROBE_COLOR (0x1d5c << 2) +#define VPP_MATRIX_PROBE_COLOR1 (0x1dd7 << 2) +#define VPP_MATRIX_HL_COLOR (0x1d5d << 2) +#define VPP_MATRIX_PROBE_POS (0x1d5e << 2) +#define VPP_MATRIX_CTRL (0x1d5f << 2) +#define VPP_MATRIX_COEF00_01 (0x1d60 << 2) +#define VPP_MATRIX_COEF02_10 (0x1d61 << 2) +#define VPP_MATRIX_COEF11_12 (0x1d62 << 2) +#define VPP_MATRIX_COEF20_21 (0x1d63 << 2) +#define VPP_MATRIX_COEF22 (0x1d64 << 2) +#define VPP_MATRIX_OFFSET0_1 (0x1d65 << 2) +#define VPP_MATRIX_OFFSET2 (0x1d66 << 2) +#define VPP_MATRIX_PRE_OFFSET0_1 (0x1d67 << 2) +#define VPP_MATRIX_PRE_OFFSET2 (0x1d68 << 2) +#define VPP_DUMMY_DATA1 (0x1d69 << 2) +#define VPP_GAINOFF_CTRL0 (0x1d6a << 2) +#define VPP_GAINOFF_CTRL1 (0x1d6b << 2) +#define VPP_GAINOFF_CTRL2 (0x1d6c << 2) +#define VPP_GAINOFF_CTRL3 (0x1d6d << 2) +#define VPP_GAINOFF_CTRL4 (0x1d6e << 2) +#define VPP_CHROMA_ADDR_PORT (0x1d70 << 2) +#define VPP_CHROMA_DATA_PORT (0x1d71 << 2) +#define VPP_GCLK_CTRL0 (0x1d72 << 2) +#define VPP_GCLK_CTRL1 (0x1d73 << 2) +#define VPP_SC_GCLK_CTRL (0x1d74 << 2) +#define VPP_MISC1 (0x1d76 << 2) +#define VPP_SRSCL_GCLK_CTRL (0x1d77 << 2) +#define VPP_OSDSR_GCLK_CTRL (0x1d78 << 2) +#define VPP_XVYCC_GCLK_CTRL (0x1d79 << 2) +#define VPP_BLACKEXT_CTRL (0x1d80 << 2) +#define VPP_DNLP_CTRL_00 (0x1d81 << 2) +#define VPP_DNLP_CTRL_01 (0x1d82 << 2) +#define VPP_DNLP_CTRL_02 (0x1d83 << 2) +#define VPP_DNLP_CTRL_03 (0x1d84 << 2) +#define VPP_DNLP_CTRL_04 (0x1d85 << 2) +#define VPP_DNLP_CTRL_05 (0x1d86 << 2) +#define VPP_DNLP_CTRL_06 (0x1d87 << 2) +#define VPP_DNLP_CTRL_07 (0x1d88 << 2) +#define VPP_DNLP_CTRL_08 (0x1d89 << 2) +#define VPP_DNLP_CTRL_09 (0x1d8a << 2) +#define VPP_DNLP_CTRL_10 (0x1d8b << 2) +#define VPP_DNLP_CTRL_11 (0x1d8c << 2) +#define VPP_DNLP_CTRL_12 (0x1d8d << 2) +#define VPP_DNLP_CTRL_13 (0x1d8e << 2) +#define VPP_DNLP_CTRL_14 (0x1d8f << 2) +#define VPP_DNLP_CTRL_15 (0x1d90 << 2) +#define VPP_SRSHARP0_CTRL (0x1d91 << 2) +#define VPP_SRSHARP1_CTRL (0x1d92 << 2) +#define VPP_DOLBY_CTRL (0x1d93 << 2) +#define VPP_DAT_CONV_PARA0 (0x1d94 << 2) +#define VPP_DAT_CONV_PARA1 (0x1d95 << 2) +#define VPP_SYNC_SEL0 (0x1d96 << 2) +#define VPP_VADJ1_BLACK_VAL (0x1d97 << 2) +#define VPP_VADJ2_BLACK_VAL (0x1d98 << 2) +#define VPP_BLUE_STRETCH_1 (0x1d9c << 2) +#define VPP_BLUE_STRETCH_2 (0x1d9d << 2) +#define VPP_BLUE_STRETCH_3 (0x1d9e << 2) +#define VPP_CCORING_CTRL (0x1da0 << 2) +#define VPP_VE_ENABLE_CTRL (0x1da1 << 2) +#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH (0x1da2 << 2) +#define VPP_VE_DEMO_CENTER_BAR (0x1da3 << 2) +#define VPP_VE_H_V_SIZE (0x1da4 << 2) +#define VPP_OUT_H_V_SIZE (0x1da5 << 2) +#define VPP_IN_H_V_SIZE (0x1da6 << 2) +#define VPP_VDO_MEAS_CTRL (0x1da8 << 2) +#define VPP_VDO_MEAS_VS_COUNT_HI (0x1da9 << 2) +#define VPP_VDO_MEAS_VS_COUNT_LO (0x1daa << 2) +#define VPP_INPUT_CTRL (0x1dab << 2) +#define VPP_CTI_CTRL2 (0x1dac << 2) +#define VPP_PEAKING_SAT_THD1 (0x1dad << 2) +#define VPP_PEAKING_SAT_THD2 (0x1dae << 2) +#define VPP_PEAKING_SAT_THD3 (0x1daf << 2) +#define VPP_PEAKING_SAT_THD4 (0x1db0 << 2) +#define VPP_PEAKING_SAT_THD5 (0x1db1 << 2) +#define VPP_PEAKING_SAT_THD6 (0x1db2 << 2) +#define VPP_PEAKING_SAT_THD7 (0x1db3 << 2) +#define VPP_PEAKING_SAT_THD8 (0x1db4 << 2) +#define VPP_PEAKING_SAT_THD9 (0x1db5 << 2) +#define VPP_PEAKING_GAIN_ADD1 (0x1db6 << 2) +#define VPP_PEAKING_GAIN_ADD2 (0x1db7 << 2) +#define VPP_PEAKING_DNLP (0x1db8 << 2) +#define VPP_SHARP_DEMO_WIN_CTRL1 (0x1db9 << 2) +#define VPP_SHARP_DEMO_WIN_CTRL2 (0x1dba << 2) +#define VPP_FRONT_HLTI_CTRL (0x1dbb << 2) +#define VPP_FRONT_CTI_CTRL (0x1dbc << 2) +#define VPP_FRONT_CTI_CTRL2 (0x1dbd << 2) +#define VPP_OSD_VSC_PHASE_STEP (0x1dc0 << 2) +#define VPP_OSD_VSC_INI_PHASE (0x1dc1 << 2) +#define VPP_OSD_VSC_CTRL0 (0x1dc2 << 2) +#define VPP_OSD_HSC_PHASE_STEP (0x1dc3 << 2) +#define VPP_OSD_HSC_INI_PHASE (0x1dc4 << 2) +#define VPP_OSD_HSC_CTRL0 (0x1dc5 << 2) +#define VPP_OSD_HSC_INI_PAT_CTRL (0x1dc6 << 2) +#define VPP_OSD_SC_DUMMY_DATA (0x1dc7 << 2) +#define VPP_OSD_SC_CTRL0 (0x1dc8 << 2) +#define VPP_OSD_SCI_WH_M1 (0x1dc9 << 2) +#define VPP_OSD_SCO_H_START_END (0x1dca << 2) +#define VPP_OSD_SCO_V_START_END (0x1dcb << 2) +#define VPP_OSD_SCALE_COEF_IDX (0x1dcc << 2) +#define VPP_OSD_SCALE_COEF (0x1dcd << 2) +#define VPP_INT_LINE_NUM (0x1dce << 2) +#define VPP_XVYCC_MISC (0x1dcf << 2) +#define VPP_HLTI_DN_FLT (0x1dd0 << 2) +#define VPP_HLTI_GAIN (0x1dd1 << 2) +#define VPP_HLTI_PARA (0x1dd2 << 2) +#define VPP_HCTI_DN_FLT (0x1dd3 << 2) +#define VPP_HCTI_GAIN (0x1dd4 << 2) +#define VPP_HCTI_PARA (0x1dd5 << 2) +#define VPP_VCTI_PARA (0x1dd6 << 2) +#define VPP_OFIFO_URG_CTRL (0x1dd8 << 2) +#define VPP_CLIP_MISC0 (0x1dd9 << 2) +#define VPP_CLIP_MISC1 (0x1dda << 2) +#define VPP_MATRIX_COEF13_14 (0x1ddb << 2) +#define VPP_MATRIX_COEF23_24 (0x1ddc << 2) +#define VPP_MATRIX_COEF15_25 (0x1ddd << 2) +#define VPP_MATRIX_CLIP (0x1dde << 2) +#define VPP_XVYCC_MISC0 (0x1ddf << 2) +#define VPP_XVYCC_MISC1 (0x1de0 << 2) +#define VPP_VD1_CLIP_MISC0 (0x1de1 << 2) +#define VPP_VD1_CLIP_MISC1 (0x1de2 << 2) +#define VPP_VD2_CLIP_MISC0 (0x1de3 << 2) +#define VPP_VD2_CLIP_MISC1 (0x1de4 << 2) +#define VPP_VE_DITHER_CTRL (0x3120 << 2) +#define VPP_VE_DITHER_LUT_1 (0x3121 << 2) +#define VPP_VE_DITHER_LUT_2 (0x3122 << 2) +#define VPP_VE_DITHER_LUT_3 (0x3123 << 2) +#define VPP_VE_DITHER_LUT_4 (0x3124 << 2) +#define VPP_VE_DITHER_LUT_5 (0x3125 << 2) +#define VPP_VE_DITHER_LUT_6 (0x3126 << 2) +#define VPP_VE_DITHER_LUT_7 (0x3127 << 2) +#define VPP_VE_DITHER_LUT_8 (0x3128 << 2) +#define VPP_VE_DITHER_LUT_9 (0x3129 << 2) +#define VPP_VE_DITHER_LUT_10 (0x312a << 2) +#define VPP_VE_DITHER_LUT_11 (0x312b << 2) +#define VPP_VE_DITHER_LUT_12 (0x312c << 2) +#define VPP_OSDSC_DITHER_CTRL (0x3130 << 2) +#define VPP_OSDSC_DITHER_LUT_1 (0x3131 << 2) +#define VPP_OSDSC_DITHER_LUT_2 (0x3132 << 2) +#define VPP_OSDSC_DITHER_LUT_3 (0x3133 << 2) +#define VPP_OSDSC_DITHER_LUT_4 (0x3134 << 2) +#define VPP_OSDSC_DITHER_LUT_5 (0x3135 << 2) +#define VPP_OSDSC_DITHER_LUT_6 (0x3136 << 2) +#define VPP_OSDSC_DITHER_LUT_7 (0x3137 << 2) +#define VPP_OSDSC_DITHER_LUT_8 (0x3138 << 2) +#define VPP_OSDSC_DITHER_LUT_9 (0x3139 << 2) +#define VPP_OSDSC_DITHER_LUT_10 (0x313a << 2) +#define VPP_OSDSC_DITHER_LUT_11 (0x313b << 2) +#define VPP_OSDSC_DITHER_LUT_12 (0x313c << 2) +#define VPP_OSDSC_DITHER_LUT_13 (0x313d << 2) +#define VPP_OSDSC_DITHER_LUT_14 (0x313e << 2) +#define VPP_OSDSC_DITHER_LUT_15 (0x313f << 2) +#define VPP_EOTF_CTL (0x31d0 << 2) +#define VPP_EOTF_COEF00_01 (0x31d1 << 2) +#define VPP_EOTF_COEF02_10 (0x31d2 << 2) +#define VPP_EOTF_COEF11_12 (0x31d3 << 2) +#define VPP_EOTF_COEF20_21 (0x31d4 << 2) +#define VPP_EOTF_COEF22_RS (0x31d5 << 2) +#define VPP_EOTF_LUT_ADDR_PORT (0x31d6 << 2) +#define VPP_EOTF_LUT_DATA_PORT (0x31d7 << 2) +#define VPP_EOTF_3X3_OFST_0 (0x31d8 << 2) +#define VPP_EOTF_3X3_OFST_1 (0x31d9 << 2) + +#define VPP_OUT_SATURATE (1 << 0) + + /*#define HHI_VIID_CLK_DIV 0x4a*/ +#define DAC0_CLK_SEL 28 +#define DAC1_CLK_SEL 24 +#define DAC2_CLK_SEL 20 +#define VCLK2_XD_RST 17 +#define VCLK2_XD_EN 16 +#define ENCL_CLK_SEL 12 +#define VCLK2_XD 0 + + /*#define HHI_VIID_CLK_CNTL 0x4b*/ +#define VCLK2_EN 19 +#define VCLK2_CLK_IN_SEL 16 +#define VCLK2_SOFT_RST 15 +#define VCLK2_DIV12_EN 4 +#define VCLK2_DIV6_EN 3 +#define VCLK2_DIV4_EN 2 +#define VCLK2_DIV2_EN 1 +#define VCLK2_DIV1_EN 0 + + /*#define HHI_VIID_DIVIDER_CNTL 0x4c*/ +#define DIV_CLK_IN_EN 16 +#define DIV_CLK_SEL 15 +#define DIV_POST_TCNT 12 +#define DIV_LVDS_CLK_EN 11 +#define DIV_LVDS_DIV2 10 +#define DIV_POST_SEL 8 +#define DIV_POST_SOFT_RST 7 +#define DIV_PRE_SEL 4 +#define DIV_PRE_SOFT_RST 3 +#define DIV_POST_RST 1 +#define DIV_PRE_RST 0 + + /*#define HHI_VID_CLK_DIV 0x59*/ +#define ENCI_CLK_SEL 28 +#define ENCP_CLK_SEL 24 +#define ENCT_CLK_SEL 20 +#define VCLK_XD_RST 17 +#define VCLK_XD_EN 16 +#define ENCL_CLK_SEL 12 +#define VCLK_XD1 8 +#define VCLK_XD0 0 + + /*#define HHI_VID_CLK_CNTL2 0x65*/ +#define HDMI_TX_PIXEL_GATE_VCLK 5 +#define VDAC_GATE_VCLK 4 +#define ENCL_GATE_VCLK 3 +#define ENCP_GATE_VCLK 2 +#define ENCT_GATE_VCLK 1 +#define ENCI_GATE_VCLK 0 + +
diff --git a/system/dev/display/astro-display/lcd.c b/system/dev/display/astro-display/lcd.c new file mode 100644 index 0000000..239b412 --- /dev/null +++ b/system/dev/display/astro-display/lcd.c
@@ -0,0 +1,6 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" +
diff --git a/system/dev/display/astro-display/mipi_dsi.c b/system/dev/display/astro-display/mipi_dsi.c new file mode 100644 index 0000000..28ca6d0 --- /dev/null +++ b/system/dev/display/astro-display/mipi_dsi.c
@@ -0,0 +1,67 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "astro-display.h" + +static uint32_t mipi_dsi_generic_read(astro_display_t* display, uint32_t address) +{ + uint32_t data_out; + + if (address != DW_DSI_GEN_PLD_DATA) { + DISP_ERROR(" Error Address : %x\n", address); + } + + data_out = READ32_REG(MIPI_DSI, address); + return data_out; +} + + +static uint32_t generic_if_wr(astro_display_t* display, uint32_t address, uint32_t data_in) +{ + if ((address != DW_DSI_GEN_HDR) && + (address != DW_DSI_GEN_PLD_DATA)) { + DISP_ERROR(" Error Address : 0x%x\n", address); + } + + DISP_INFO("address 0x%x = 0x%08x\n", address, data_in); + + WRITE32_REG(MIPI_DSI, address, data_in); + + return 0; +} + + +static void dsi_generic_write_short_packet(astro_display_t* display, struct dsi_cmd_request_s *req) +{ + unsigned int d_para[2]; + + switch (req->data_type) { + case DT_GEN_SHORT_WR_1: + d_para[0] = (req->pld_count == 0) ? + 0 : (((unsigned int)req->payload[2]) & 0xff); + d_para[1] = 0; + break; + case DT_GEN_SHORT_WR_2: + d_para[0] = (req->pld_count == 0) ? + 0 : (((unsigned int)req->payload[2]) & 0xff); + d_para[1] = (req->pld_count < 2) ? + 0 : (((unsigned int)req->payload[3]) & 0xff); + break; + case DT_GEN_SHORT_WR_0: + default: + d_para[0] = 0; + d_para[1] = 0; + break; + } + + generic_if_wr(display, DW_DSI_GEN_HDR, + ((d_para[1] << BIT_GEN_WC_MSBYTE) | + (d_para[0] << BIT_GEN_WC_LSBYTE) | + (((unsigned int)req->vc_id) << BIT_GEN_VC) | + (((unsigned int)req->data_type) << BIT_GEN_DT))); + if (req->req_ack == MIPI_DSI_DCS_REQ_ACK) + wait_bta_ack(display); + else if (req->req_ack == MIPI_DSI_DCS_NO_ACK) + wait_cmd_fifo_empty(display); +}
diff --git a/system/dev/display/astro-display/rules.mk b/system/dev/display/astro-display/rules.mk index 43b2d73..fdee69d 100644 --- a/system/dev/display/astro-display/rules.mk +++ b/system/dev/display/astro-display/rules.mk
@@ -10,6 +10,14 @@ MODULE_SRCS += \ $(LOCAL_DIR)/astro-display.c \ + $(LOCAL_DIR)/backlight.c \ + $(LOCAL_DIR)/canvas.c \ + $(LOCAL_DIR)/dsi.c \ + $(LOCAL_DIR)/lcd.c \ + $(LOCAL_DIR)/display_debug.c \ + $(LOCAL_DIR)/display_config.c \ + $(LOCAL_DIR)/display_clock.c \ + $(LOCAL_DIR)/mipi_dsi.c \ MODULE_STATIC_LIBS := system/ulib/ddk system/ulib/sync
diff --git a/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h b/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h index 8c4a265..1407178 100644 --- a/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h +++ b/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h
@@ -23,6 +23,12 @@ #define S905D2_RESET_BASE 0xffd01000 #define S905D2_RESET_LENGTH 0x1000 +#define S905D2_MIPI_DSI_BASE 0xffd07000 +#define S905D2_MIPI_DSI_LENGTH 0x1000 + +#define S905D2_DSI_PHY_BASE 0xff644000 +#define S905D2_DSI_PHY_LENGTH 0x1000 + #define S905D2_USBPHY20_BASE 0xff636000 #define S905D2_USBPHY20_LENGTH 0x2000 @@ -32,6 +38,9 @@ #define S905D2_HIU_BASE 0xff63c000 #define S905D2_HIU_LENGTH 0x2000 +#define S905D2_VPU_BASE 0xff900000 +#define S905D2_VPU_LENGTH 0x10000 + #define S905D2_MALI_BASE 0xffe40000 #define S905D2_MALI_LENGTH 0x40000