Note: SN65DSI86 的使用與注意事項

来源:互联网 发布:淘宝登录注册流程 编辑:程序博客网 时间:2024/06/05 16:50

https://kunyichen.wordpress.com/2014/06/08/note-sn65dsi86-%E7%9A%84%E4%BD%BF%E7%94%A8%E8%88%87%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85/


Note: SN65DSI86 的使用與注意事項

最近案子用上 TI 出的這顆 DSI to eDP 的Bridge, 搞了一陣子, eDP 方面基本上只有一點要注意, 就是Panel 一定要能支援 ASSR (Alternative scrambler seed reset), 如果想要用再沒有support ASSR 的面板上基本上也是有機會的, 只要TI 願意跟你講保留的測試pin 跟暫存器設定, 另外Colorbar 設定完後, VSTREAM bit 也設定後就可以正常看到 Color bar的畫面, 無關DSI 的信號與否

判讀 eDP Panel 有沒有支援ASSR 可以從下列資訊判讀

DPCD(DisplayPort Configuration Data)
eDP_CONFIGURATION_CAP(000DH) defined at page 19 (VESA Embedded DisplayPort Standard Version 1.2, 2 May 2010)

For Embedded DisplayPort receivers:
Bit 0 = ALTERNATE_SCRAMBLER_RESET_CAPABLE
A setting of 1 indicates that this is a eDP device that can use the eDP
alternat scrambler reset value of FFFEh

Bit 1 = FRAMING_CHANGE_CAPABLE
A setting of 1 indicates that this is an eDP device uses only
Enhanced Framing, independently of the setting by the source of
ENHANCED_FRAME_EN

Bit2 = RESERVED for eDP Read 0s.

Bit3 = DPCD_DISPLAY_CONTROL_CAPABLE
A setting of 1 indicates that display control registers starting at
address 00700h are enabled.

下面是測試程式的片斷, 展示如何讀寫DPCD & 讀取EDID 的資訊解析, 硬體平台用的是之前TI 特價買的 Stellaris Launchpad LM4F120 (現在已經改成Tiva C series Launchpad TM4C123G) , 實際用 ASSR 的panel 時記得要寫入 DPCD eDP_CONFIGURATION_SET (0010Ah)
bit0 為1 , 且要在 eDP traning 之前, 基本上就是eDP 的 Source & Sink 端同步 reset 亂數產生器的初始值為 0FFFEH

完整的程式可以在 http://pastebin.com/fg79hLvz 找到,

輸出則是 http://pastebin.com/rvN9a6iP

(ps. 這個基本上是hello 改過來的, 不過default 的stack size 太小, 要改大)

static void READ_DPCD(uint8_t* buff, uint32_t v_addr, uint32_t cnt){uint8_t tmp[4];// AUX 20bit addresstmp[0] = (v_addr>>16) & 0x0F;tmp[1] = (v_addr>>8) & 0xFF;tmp[2] = (v_addr & 0xFF);// lengthtmp[3] = (cnt & 0x1F);I2C_Write8(tmp, 0x74, 4); // write DPCD register address// AUX_NATIVE_CMD (0x9)tmp[0] = (9<<4) | // AUX_NATIVE_READ (1<<0);  // EN_SEND_AUX     I2C_Write8(tmp, 0x78, 1); ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // waiting for response I2C_Read8(buff, 0x79, (cnt&0x1F)); } static void WRITE_DPCD(uint8_t* buff, uint32_t v_addr, uint32_t cnt) { uint8_t tmp[4]; // AUX 20bit address tmp[0] = (v_addr>>16) & 0x0F;tmp[1] = (v_addr>>8) & 0xFF;tmp[2] = (v_addr & 0xFF);// lengthtmp[3] = (cnt & 0x1F);I2C_Write8(tmp, 0x74, 4); // write DPCD register addressI2C_Write8(buff, 0x64, cnt);// AUX_NATIVE_CMD (0x8)tmp[0] = (8<<4) | // AUX_NATIVE_WRITE (1<<0);  // EN_SEND_AUX     I2C_Write8(tmp, 0x78, 1); ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); } static void opAUX(uint32_t v_addr, uint8_t* buff, uint8_t cnt, uint8_t cmd) { uint8_t tmp[4]; // AUX 20bit address tmp[0] = (v_addr>>16) & 0x0F;tmp[1] = (v_addr>>8) & 0xFF;tmp[2] = (v_addr & 0xFF);// lengthtmp[3] = (cnt & 0x1F);I2C_Write8(tmp, 0x74, 4); // write addressif ((cnt != 0) && cmd != 5)I2C_Write8(buff, 0x64, cnt);tmp[0] = (cmd << 4) | ( 1 << 0); // SEND flagI2C_Write8(tmp, 0x78, 1);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3);}static void readEDID(void){uint8_t buf[2];uint8_t count;memset(buf, 0, sizeof(buf));opAUX(0x50, buf, 0, 4); // Write with MOT, I2C over AUX, SYNCopAUX(0x50, buf, 1, 4); // Write with MOT, Offset 0opAUX(0x50, buf, 0, 5); // Read with MOT, READ STARTfor (count=0; count < 128; count+= 16) {opAUX(0x50, buf, 0x10, 5); // Read with MOT, read 16 byteI2C_Read8((g_ui8EDID+count), 0x79, 0x10);}opAUX(0x50, buf, 0, 1); // read without MOT, read stop}static void dumpEDID(void){uint8_t count;uint8_t vo;count = vo = 0;UARTprintf("--------------------------------------------------------\n");UARTprintf("Dump Panel EDID \n");UARTprintf("--------------------------------------------------------\n");UARTprintf("    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");UARTprintf("--------------------------------------------------------");for(count = 0; count < sizeof(g_ui8EDID); count++) {if ((count % 16) == 0) {UARTprintf("\n%02X|", vo);vo += 0x10;}UARTprintf(" %02x", g_ui8EDID[count]);}UARTprintf("\n");}static void dumpPanelTiming(void){uint32_t t;uint16_t ha;uint16_t hb;uint16_t ho;uint16_t va;uint16_t vb;uint16_t vo;uint16_t hpw;uint16_t vpw;uint16_t hsz;uint16_t vsz;uint16_t hbp;uint16_t vbp;UARTprintf("--------------------------------------------------------\n");UARTprintf("Extract Panel timing from EDID DTD1\n");UARTprintf("--------------------------------------------------------\n");ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintf#define DTD1_OFFSET  (0x36)t = (g_ui8EDID[DTD1_OFFSET+1]<<8) + g_ui8EDID[DTD1_OFFSET+0];ha = ((g_ui8EDID[DTD1_OFFSET+4] & 0xF0)<<4) + g_ui8EDID[DTD1_OFFSET+2];hb = ((g_ui8EDID[DTD1_OFFSET+4] & 0x0F)<<8) + g_ui8EDID[DTD1_OFFSET+3];va = ((g_ui8EDID[DTD1_OFFSET+7] & 0xF0)<<4) + g_ui8EDID[DTD1_OFFSET+5];vb = ((g_ui8EDID[DTD1_OFFSET+7] & 0x0F)<<8) + g_ui8EDID[DTD1_OFFSET+6];ho = ((g_ui8EDID[DTD1_OFFSET+11] & 0xC0)<<2) + g_ui8EDID[DTD1_OFFSET+8];vo = ((g_ui8EDID[DTD1_OFFSET+11] & 0x0C)<<2) + (g_ui8EDID[DTD1_OFFSET+10] >> 4);hpw = ((g_ui8EDID[DTD1_OFFSET+11] & 0x30)<<4) + g_ui8EDID[DTD1_OFFSET+9];vpw = ((g_ui8EDID[DTD1_OFFSET+11] & 0x03)<<4) + (g_ui8EDID[DTD1_OFFSET+10]&0x0F);hsz = ((g_ui8EDID[DTD1_OFFSET+14] & 0xF0)<<4) + g_ui8EDID[DTD1_OFFSET+12];vsz = ((g_ui8EDID[DTD1_OFFSET+14] & 0x0F)<<8) + g_ui8EDID[DTD1_OFFSET+13];hbp = g_ui8EDID[DTD1_OFFSET+15];vbp = g_ui8EDID[DTD1_OFFSET+16];UARTprintf("Pixel Clock %dMHz(%dKHz)\n", t/100, t*10);UARTprintf("Active zone(Hori.xVert.): %dx%d\n", ha, va);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintfUARTprintf("Blinking zone(Hori. & Vert.): %d & %d\n", hb, vb);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintfUARTprintf("Horizontal sync Offset & Pulse width: %d & %d\n", ho, hpw);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintfUARTprintf("Vertical sync Offset & Pulse width: %d & %d\n", vo, vpw);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintfUARTprintf("Border (Hori. & Vert.): %d & %d\n", hbp, vbp);UARTprintf("Display Size(Hori.xVert.): %dx%d mm2\n", hsz, vsz);ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintfif ((g_ui8EDID[DTD1_OFFSET+17] & 0x18) !=  0x18) {UARTprintf("can't support the panel, because we need a digital separate type\n");return;}UARTprintf("Horizontal sync. Polarity: ");if (g_ui8EDID[DTD1_OFFSET+17] & (1<<1)) {UARTprintf("Positive\n");} else {UARTprintf("Negative\n");}UARTprintf("Vertical sync. Polarity: ");if (g_ui8EDID[DTD1_OFFSET+17] & (1<<2)) {UARTprintf("Positive\n");} else {UARTprintf("Negative\n");}}static void dumpDPCD(void){uint8_t count;uint8_t i;uint8_t buf[16];uint16_t lists[] = {0x0000, 0x0100, 0x0200, 0x0210 };UARTprintf("--------------------------------------------------------\n");UARTprintf("dump panel DPCD value\n");UARTprintf("--------------------------------------------------------\n");for (i = 0; i < (sizeof(lists)/sizeof(uint16_t)); i++) {READ_DPCD(buf, lists[i], 16);UARTprintf("DPCD %04xh:", lists[i]);for(count = 0; count < 16; count++) { UARTprintf(" %02X", buf[count]); } UARTprintf("\n"); ROM_SysCtlDelay(ROM_SysCtlClockGet()/10/3); // wating for UARTprintf } } static void showDPCDInfo(void) { uint8_t buf[16]; READ_DPCD(buf, 0, 16); UARTprintf("DPCD: REV:%d.%d, MAX_LINK_RATE:", (buf[0] >> 4), (buf[0]&0xF));if (buf[1] == 0x06) {UARTprintf("1.62Gbps");} else if (buf[1] == 0x0A) {UARTprintf("2.7Gbps");}UARTprintf(" MAX_LINK_LANE:%d\n", buf[2]);if (buf[0x0D] & ASSR_SUPPORT) {UARTprintf(" support ASSR");} else {UARTprintf(" not support ASSR");}if (buf[0x0D] & ENHANCE_FRAMING) {UARTprintf(" support Enhance framing");} else {UARTprintf(" not support Enhance framing");}UARTprintf("\n");}//*****************************************************************************//////*****************************************************************************intmain(void){    //volatile uint32_t ui32Loop;uint32_t count;uint8_t BUF[32];uint32_t tmp;uint32_t vo = 0;tmp = 0;BUF[0] = BUF[1] = BUF[2] = BUF[3] = tmp;tmp = BUF[0];    //    // Enable lazy stacking for interrupt handlers.  This allows floating-point    // instructions to be used within interrupt handlers, but at the expense of    // extra stack usage.    //    ROM_FPULazyStackingEnable();    //    // Set the clocking to run directly from the crystal.    //    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |                       SYSCTL_OSC_MAIN);    //    // Enable the GPIO port that is used for the on-board LED.    //    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);    //    // Enable the GPIO pins for the LED (PF2 & PF3).    //    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);//// Initialize SoftI2C //ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);memset(&g_sI2C, 0, sizeof(g_sI2C));SoftI2CCallbackSet(&g_sI2C, SoftI2CCallback);SoftI2CSCLGPIOSet(&g_sI2C, GPIO_PORTA_BASE, GPIO_PIN_6);SoftI2CSDAGPIOSet(&g_sI2C, GPIO_PORTA_BASE, GPIO_PIN_7);SoftI2CInit(&g_sI2C);SoftI2CIntEnable(&g_sI2C);    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet() / 40000);    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);    TimerEnable(TIMER0_BASE, TIMER_A);    IntEnable(INT_TIMER0A);    //    // Initialize the UART.    //    ConfigureUART();UARTprintf("for ColorBar Test \r\n");BUF[0] = 1;I2C_Write8(BUF, 0x09, 1); // software resetROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 0 ;I2C_Write8(BUF, 0x5A, 1); // disable VSTREAMROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 0x0;I2C_Write8(BUF, 0x0D, 1); // disable DP_PLL_ENROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 1;I2C_Write8(BUF, 0x09, 1); // software resetROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 0x2;I2C_Write8(BUF, 0x0A, 1); // Clock Ref = 19.2MHzreadEDID();dumpEDID();dumpPanelTiming();dumpDPCD();showDPCDInfo();BUF[0] = (1 << 5) | // SINGL CHANNEL DSI (A)(0 << 3) | // Four Lane(0);   // SOT_ERR_TOL_DISI2C_Write8(BUF, 0x10, 1);BUF[0] = 0; // disable ASSRI2C_Write8(BUF, 0x5A, 1);BUF[0] = 1<<1; // 24BPPI2C_Write8(BUF, 0x5B, 1);BUF[0] = 0; // HPD EnableI2C_Write8(BUF, 0x5C, 1);BUF[0] = (0 << 6)  | // DP pre emphasis lv 0(2 << 4)  | // DP 2 lane(2 << 1)  | // Downspread 3750ppm(0 << 0);   // disable SSCI2C_Write8(BUF, 0x93, 1);BUF[0] = (4 << 5) | // 2.70Gbps(0 << 2) | // 61ps(0 << 0);  // Voltage I2C_Write8(BUF, 0x94, 1); // Panel timing  #define  HA(1920) #define  HSPW(39) #define  HFP(59) #define  HBP(62) #define  HSP(0) // Hsyn Polarity:0 POS #define  VA         (1200) #define  VSPW(3) #define  VFP(6) #define  VBP(26) #define  VSP        (1) // Vsyn Polarity: NEG BUF[0] = (HA & 0xFF); BUF[1] = ((HA>>8) & 0xFF);I2C_Write8(BUF, 0x20, 2); // ActiveLineROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = (VA & 0xFF);BUF[1] = ((VA>>8) & 0xFF);I2C_Write8(BUF, 0x24, 2);  // Vertical lineROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = (HSPW & 0xFF);BUF[1] = ((HSPW>>8) & 0x7F) |(HSP << 7); I2C_Write8(BUF, 0x2C, 2); // HSYNC Pulse width ROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3); BUF[0] = (VSPW & 0xFF); BUF[1] = ((VSPW>>8) & 0xFF) |(VSP << 7); // negI2C_Write8(BUF, 0x30, 2); // VSYNC Pulse widthROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = HBP;I2C_Write8(BUF, 0x34, 1); // H_BACK_PORCHROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = VBP;I2C_Write8(BUF, 0x36, 1); // V_BACK_PORCHROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = HFP;I2C_Write8(BUF, 0x38, 1); // H_FRONT_PORCHROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = VFP;I2C_Write8(BUF, 0x3A, 1); // V_FRONT_PORCHROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 0;I2C_Write8(BUF, 0x5B, 1); //24bppROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);BUF[0] = 0x1;I2C_Write8(BUF, 0x0D, 1); // Enable DP_PLL_ENROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);I2C_Read8(BUF, 0x0A, 1);if (BUF[0] & 0x80) UARTprintf("DSI86 PLL has Locked now\n");BUF[0] = 0xA;// ML_TX_MODE,Semi Auto Link TrainingI2C_Write8(BUF, 0x96, 1);ROM_SysCtlDelay(ROM_SysCtlClockGet() / 10 / 3);I2C_Read8(BUF, 0x96, 1);UARTprintf("SemiTraning result:%02X\n", BUF[0]);#if 0BUF[0] = EN_SELF_TEST;WRITE_DPCD(BUF, EDP_CONFIGURATION_SET, 1);#endifBUF[0] = 0x18; // Color Bar enableI2C_Write8(BUF, 0x3C, 1);SysCtlDelay(SysCtlClockGet() / 10 / 3);I2C_Read8(BUF, 0x20, 4);BUF[0] = (1<<3) ; // VStream//(0<<2) | // Enhanced FramingI2C_Write8(BUF, 0x5A, 1);SysCtlDelay(SysCtlClockGet() / 10 / 3);UARTprintf("--------------------------------------------------------\n");UARTprintf("    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");UARTprintf("--------------------------------------------------------");#if 1for (tmp = 0; tmp < 8; tmp++) {I2C_Read8(BUF, tmp*sizeof(BUF), sizeof(BUF));for(count = 0; count < sizeof(BUF); count++) {if ((count % 16) == 0) {UARTprintf("\n%02X|", vo);vo += 0x10;}UARTprintf(" %02x", BUF[count]);}}#endifUARTprintf("\n");dumpDPCD();    while(1)    {        //        // Turn on the BLUE LED.        //        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);        //        // Delay for a bit.        // SysCtlDelay(SysCtlClockGet() / 10 / 3);        //        // Turn off the BLUE LED.        //        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);        //        // Delay for a bit.        //        SysCtlDelay(SysCtlClockGet() / 10 / 3);}}ref. eDP Standard v1.2 
0 0
原创粉丝点击