Other Parts Discussed in Thread: DSI-TUNER
Hi, I'm trying to write linux driver for SN65DSI84. I use this files as example.
DSI:
lanes = 4,
format = RGB888,
clock = 280 MHz
display-timings (from device tree):
timing0: timing0 {
clock-frequency = <70000000>;
hactive = <1024>;
vactive = <768>;
hback-porch = <160>;
hfront-porch = <24>;
vback-porch = <29>;
vfront-porch = <3>;
hsync-len = <136>;
vsync-len = <6>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
I set DSI_CLK_DIVIDER to divide by 4 (LVDS clock = 70 MHz)
Test pattern work fine, but for real DSI signal I have an errors. Register 0xE5 bit2 and bit3 (CHA_SOT_BIT_ERR, CHA_LLP_ERR).
#include "sn65dsi84_i2c.h" static int sn65dsi84_config(struct i2c_client *client) { u8 val; const uint32_t mipi_dsi_freq = 280000; // KHz const uint8_t dsi_clock_div = 4; struct sn65dsi84_i2c_data *data = i2c_get_clientdata(client); s32 i2c_read; dev_dbg(&client->dev, "sn65dsi84_config()\n"); if(data == NULL) { dev_dbg(&client->dev, "sn65dsi84_config() data=NULL\n"); return -ENXIO; } // Soft reset and disable PLL (init seq 5) i2c_smbus_write_byte_data(client, DSI85_PLL_EN, 0x00); mdelay(10); i2c_smbus_write_byte_data(client, DSI85_SOFT_RESET, 0x01); mdelay(10); val = 0; #if LVDS_CLK_FROM_DSI_CLK val = 0x1; #endif // data->timings.pixel_clock = 70000 // user external clock reference with no muliplier if (data->timings.pixel_clock <= 37500) { // Do nothing. } else if (data->timings.pixel_clock <= 62500) { val |= (0x01 << 1); } else if (data->timings.pixel_clock <= 87500) { val |= (0x02 << 1); } else if (data->timings.pixel_clock <= 112500) { val |= (0x03 << 1); } else if (data->timings.pixel_clock <= 137500) { val |= (0x04 << 1); } else { val |= (0x05 << 1); } i2c_smbus_write_byte_data(client, DSI85_CORE_PLL, val); #if LVDS_CLK_FROM_DSI_CLK //i2c_smbus_write_byte_data(client, DSI85_PLL_DIV, 0x10); // Divide DSI_CLK by 3. val = (dsi_clock_div - 1) << 3; // Divide DSI_CLK by 4. i2c_smbus_write_byte_data(client, DSI85_PLL_DIV, val); #else i2c_smbus_write_byte_data(client, DSI85_PLL_DIV, 0x00); // Multiply REFCLK by 1. #endif // four DSI lanes with single channel i2c_smbus_write_byte_data(client, DSI85_DSI_CFG, 0x00); //i2c_smbus_write_byte_data(client, DSI85_DSI_CFG, 0x01); // no SoT bit errors are tolerated i2c_smbus_write_byte_data(client, DSI85_DSI_EQ, 0x00); // set DSI clock range //i2c_smbus_write_byte_data(client, DSI85_CHA_DSI_CLK_RNG, (data->timings.pixel_clock * 4 / 5000)); i2c_smbus_write_byte_data(client, DSI85_CHA_DSI_CLK_RNG, (mipi_dsi_freq / 5000)); // set LVDS for single channel, 24 bit mode, HS/VS low, DE high i2c_smbus_write_byte_data(client, DSI85_LVDS_MODE, 0x7A); // set LVDS 200 Ohm termination and max differential swing voltage i2c_smbus_write_byte_data(client, DSI85_LVDS_SIGN, 0x00); i2c_smbus_write_byte_data(client, DSI85_LVDS_TERM, 0x00); // x resolution high/low for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_LINE_LEN_LO, ((data->timings.x_res) & 0x00FF)); i2c_smbus_write_byte_data(client, DSI85_CHA_LINE_LEN_HI, ((data->timings.x_res) & 0x0F00)>>8); // 12 bit value // y resolution high/low for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_VERT_LINES_LO, (data->timings.y_res & 0x00FF)); i2c_smbus_write_byte_data(client, DSI85_CHA_VERT_LINES_HI, (data->timings.y_res & 0x0F00)>>8); // 12 bit value // SYNC delay high/low for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_SYNC_DELAY_LO, 0x00); i2c_smbus_write_byte_data(client, DSI85_CHA_SYNC_DELAY_HI, 0x02); // HSYNC width high/low for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_HSYNC_WIDTH_LO, (data->timings.hsw & 0x00FF)); i2c_smbus_write_byte_data(client, DSI85_CHA_HSYNC_WIDTH_HI, (data->timings.hsw & 0x0300)>>8); // 10 bit value // VSYNC width high/low for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_VSYNC_WIDTH_LO, (data->timings.vsw & 0x00FF)); i2c_smbus_write_byte_data(client, DSI85_CHA_VSYNC_WIDTH_HI, (data->timings.vsw & 0x0300)>>8); // 10 bit value // Horizontal BackPorch for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_HORZ_BACKPORCH, (data->timings.hbp & 0x00FF)); // Vertical BackPorch for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_VERT_BACKPORCH, (data->timings.vbp & 0x00FF)); // Horizontal FrontPorch for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_HORZ_FRONTPORCH, (data->timings.hfp & 0x00FF)); // Vertical FrontPorch for channel A i2c_smbus_write_byte_data(client, DSI85_CHA_VERT_FRONTPORCH, (data->timings.vbp & 0x00FF)); // debug //i2c_smbus_write_byte_data(client, DSI85_CHA_TEST_PATTERN, 0x10); // Soft reset and enable PLL //i2c_smbus_write_byte_data(client, DSI85_SOFT_RESET, 0x01); //i2c_smbus_write_byte_data(client, DSI85_PLL_EN, 0x01); i2c_smbus_write_byte_data(client, DSI85_PLL_EN, 0x01); // init seq 6 mdelay(10); i2c_smbus_write_byte_data(client, DSI85_SOFT_RESET, 0x01); // init seq 7 mdelay(10); // clear errors i2c_smbus_write_byte_data(client, DSI85_ERRORS, 0xFF); // init seq 10 mdelay(10); i2c_read = i2c_smbus_read_byte_data(client, DSI85_ERRORS); // init seq 11 if(i2c_read < 0) { dev_err(&client->dev, "sn65dsi84_config() fun i2c_smbus_read_byte_data return %d\n", i2c_read); return i2c_read; } dev_dbg(&client->dev, "sn65dsi84_config() errors = %d\n", i2c_read); return 0; }