Hi,all
Plateform: yocto linux-4.14.98_2.0.0ga + iMX8MM.
Using SN65DSI83 to bridge iMX8MM mipi dsi on my customized board for single-link LVDS LCD,which works fine with variouse resolutions. Then replace SN65DSI83 with SN65DSI84 to bring up dual-link LVDS LCD with resulotion of 1920x1080 with following dts code:
dsi_lvds_bridge: sn65dsi83@2c {
compatible = "ti,sn65dsi83";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mipi_dsi_en>;
reg = <0x2c>;
ti,dsi-lanes = <4>;
ti,lvds-format = <1>;
ti,lvds-bpp = <24>;
ti,width-mm = <154>;
ti,height-mm = <87>;
enable-gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
lcd-bl = <&gpio1 15 GPIO_ACTIVE_HIGH>;
status = "okay";
port {
sn65dsi83_from_dsim: endpoint {
remote-endpoint = <&dsim_to_sn65dsi83>;
};
};
display-timings {
native-mode = <&timing0>;
timing0: 1920x1080 {
clock-frequency = <149800000>; // LCD clock * 2
hactive = <1920>;
vactive = <1080>; //
hfront-porch = <60>; // DE mode, Blanking 90*2
hback-porch = <60>;
hsync-len = <60>;
vback-porch = <20>;
vfront-porch = <20>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
with config code as follows:
static int sn65dsi83_brg_configure(struct sn65dsi83_brg *brg)
{
int regval = 0;
struct i2c_client *client = I2C_CLIENT(brg);
struct videomode *vm = VM(brg);
u32 dlink = (VACTIVE > 1000) ? 2 : 1; // VACTIVE > 1000 => dual-link LVDS
u32 lvds_clk = PIXCLK / dlink;
u32 dsi_clk = (((PIXCLK * BPP(brg)) / DSI_LANES(brg)) >> 1);
dev_info(&client->dev, "DSI clock [ %u ] Hz\n",dsi_clk);
dev_info(&client->dev, "GeoMetry [ %d x %d ] \n",HACTIVE,VACTIVE);
/* Reset PLL_EN and SOFT_RESET registers */
SN65DSI83_WRITE(SN65DSI83_SOFT_RESET,0x00);
SN65DSI83_WRITE(SN65DSI83_PLL_EN,0x00);
/* LVDS clock setup */
if ((25000000 <= lvds_clk) && (lvds_clk < 37500000))
regval = 0;
else
regval = sn65dsi83_calk_clk_range(0x01, 0x05, 37500000, 25000000, lvds_clk);
if (regval < 0) {
dev_err(&client->dev, "failed to configure LVDS clock");
return -EINVAL;
}
regval = (regval << LVDS_CLK_RANGE_SHIFT);
regval |= (1 << HS_CLK_SRC_SHIFT); /* Use DSI clock */
SN65DSI83_WRITE(SN65DSI83_CORE_PLL,regval);
/* DSI clock range, max value = 500MHz */
regval = sn65dsi83_calk_clk_range(0x08, 0x64, 40000000, 5000000, dsi_clk);
if (regval < 0) {
dev_err(&client->dev, "failed to configure DSI clock range\n");
return -EINVAL;
}
SN65DSI83_WRITE(SN65DSI83_CHA_DSI_CLK_RNG,regval);
/* DSI clock divider */
regval = sn65dsi83_calk_div(0x0, 0x18, 1, 1, dsi_clk, lvds_clk);
if (regval < 0) {
dev_err(&client->dev, "failed to calculate DSI clock divider");
return -EINVAL;
}
regval = regval << DSI_CLK_DIV_SHIFT;
SN65DSI83_WRITE(SN65DSI83_PLL_DIV,regval);
/* Configure DSI_LANES */
regval = SN65DSI83_READ(SN65DSI83_DSI_CFG);
regval &= ~(3 << CHA_DSI_LANES_SHIFT);
regval |= ((4 - DSI_LANES(brg)) << CHA_DSI_LANES_SHIFT);
SN65DSI83_WRITE(SN65DSI83_DSI_CFG,regval);
/* CHA_DSI_DATA_EQ - No Equalization */
/* CHA_DSI_CLK_EQ - No Equalization */
SN65DSI83_WRITE(SN65DSI83_DSI_EQ,0x00);
/* Video formats */
regval = 0;
if (FLAGS & DISPLAY_FLAGS_HSYNC_LOW)
regval |= (1 << HS_NEG_POLARITY_SHIFT);
if (FLAGS & DISPLAY_FLAGS_VSYNC_LOW)
regval |= (1 << VS_NEG_POLARITY_SHIFT);
if (FLAGS & DISPLAY_FLAGS_DE_LOW)
regval |= (1 << DE_NEG_POLARITY_SHIFT);
if (BPP(brg) == 24) {
regval |= (1 << CHA_24BPP_MODE_SHIFT);
if(dlink == 2)
regval |= (1 << CHA_24BPP_MODE_SHIFT);
}
if (FORMAT(brg) == 1) {
regval |= (1 << CHA_24BPP_FMT1_SHIFT);
if(dlink == 2) {
regval |= (1 << CHB_24BPP_FMT1_SHIFT);
}
}
if(dlink == 1) {
regval |= (1 << LVDS_LINK_CFG_SHIFT);
}
dev_info(&client->dev, "video formats: 0x%x\n",regval);
SN65DSI83_WRITE(SN65DSI83_LVDS_MODE,regval);
/* Voltage and pins */
SN65DSI83_WRITE(SN65DSI83_LVDS_SIGN,0x00);
SN65DSI83_WRITE(SN65DSI83_LVDS_TERM,0x03);
SN65DSI83_WRITE(SN65DSI83_LVDS_CM_ADJ,0x00);
/* Configure sync delay to minimal allowed value */
SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_LO,0x21);
SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_HI,0x00);
/* Geometry */
SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_LO,LOW(HACTIVE/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_HI,HIGH(HACTIVE/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_LO,LOW(VACTIVE));
SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_HI,HIGH(VACTIVE));
SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_LO,LOW(HPW/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_HI,HIGH(HPW/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_LO,LOW(VPW));
SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_HI,HIGH(VPW));
SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_BACKPORCH,LOW(HBP/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_VERT_BACKPORCH,LOW(VBP));
SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_FRONTPORCH,LOW(HFP/dlink));
SN65DSI83_WRITE(SN65DSI83_CHA_VERT_FRONTPORCH,LOW(VFP));
SN65DSI83_WRITE(SN65DSI83_TEST_PATTERN,0x00);
// CS&ZHL NOV-25-2020: testing -> dual-link LVDS does wrking!
//SN65DSI83_WRITE(SN65DSI83_TEST_PATTERN,(1 << CHA_TEST_PATTERN_SHIFT));
return 0;
}
wih above setting => lvds_clk = 74.9MHz, dsi_clk = 449.4MHz
The test pattern of SN65DSI84 are fine, but with DSI input, only left half side display is on, right half side just blank. It's appreciated for any help, thanks very much.
ChengShi
已解决! 转到解答。