static void _set_resc_clkgen_pre(struct nxp_resc *me, bool enable, bool sink_is_hdmi) { NX_DISPTOP_CLKGEN_SetBaseAddress(ResConv_CLKGEN, (U32)IO_ADDRESS(NX_DISPTOP_CLKGEN_GetPhysicalAddress(ResConv_CLKGEN))); NX_DISPTOP_CLKGEN_SetClockDivisorEnable(ResConv_CLKGEN, CFALSE); if (enable) { NX_DISPTOP_CLKGEN_SetClockPClkMode(ResConv_CLKGEN, NX_PCLKMODE_ALWAYS); if (sink_is_hdmi) { NX_DISPTOP_CLKGEN_SetClockSource(ResConv_CLKGEN, ResConv_ICLK, 4); // HDMI CLK NX_DISPTOP_CLKGEN_SetClockDivisor(ResConv_CLKGEN, ResConv_ICLK, 1); } else { /* TODO : select iclk by sink */ pr_err("%s: TODO ==> select iclk for not hdmi\n", __func__); } NX_DISPTOP_CLKGEN_SetClockSource(ResConv_CLKGEN, ResConv_CCLK, 2); // PLL2 NX_DISPTOP_CLKGEN_SetClockDivisor(ResConv_CLKGEN, ResConv_CCLK, 1); NX_DISPTOP_CLKGEN_SetClockDivisorEnable(ResConv_CLKGEN, CTRUE); NX_DISPTOP_CLKGEN_SetBaseAddress(LCDIF_CLKGEN, (U32)IO_ADDRESS(NX_DISPTOP_CLKGEN_GetPhysicalAddress(LCDIF_CLKGEN))); NX_DISPTOP_CLKGEN_SetClockDivisorEnable ( LCDIF_CLKGEN, CFALSE); NX_DISPTOP_CLKGEN_SetClockPClkMode ( LCDIF_CLKGEN, NX_PCLKMODE_ALWAYS ); NX_DISPTOP_CLKGEN_SetClockDivisorEnable ( LCDIF_CLKGEN, CFALSE ); NX_DISPTOP_CLKGEN_SetClockSource ( LCDIF_CLKGEN, 0, 4 ); NX_DISPTOP_CLKGEN_SetClockDivisor ( LCDIF_CLKGEN, 0, 1 ); NX_DISPTOP_CLKGEN_SetClockSource ( LCDIF_CLKGEN, 1, 7 ); NX_DISPTOP_CLKGEN_SetClockDivisor ( LCDIF_CLKGEN, 1, 1 ); NX_DISPTOP_CLKGEN_SetClockDivisorEnable ( LCDIF_CLKGEN, CTRUE); } else { NX_DISPTOP_CLKGEN_SetClockDivisorEnable ( LCDIF_CLKGEN, CFALSE); NX_DISPTOP_CLKGEN_SetClockDivisorEnable(ResConv_CLKGEN, CFALSE); } }
/* default : clk_src 0, clk_divide 4 */ static void _set_resc_clkgen_post(struct nxp_resc *me, int clk_src, int clk_divide) { NX_DISPTOP_CLKGEN_SetClockDivisorEnable(ResConv_CLKGEN, CFALSE); NX_DISPTOP_CLKGEN_SetClockSource(ResConv_CLKGEN, ResConv_CCLK, clk_src); NX_DISPTOP_CLKGEN_SetClockDivisor(ResConv_CLKGEN, ResConv_CCLK, clk_divide); NX_DISPTOP_CLKGEN_SetClockDivisorEnable(ResConv_CLKGEN, CTRUE); }
static int lvds_prepare(struct disp_process_dev *pdev) { struct disp_vsync_info *psync = &pdev->vsync; struct disp_lvds_param *plvds = pdev->dev_param; int input = pdev->dev_in; int clkid = DISP_CLOCK_LVDS; unsigned int val; int format = 1; // 1: JEiDA, 0: VESA, 2:User //-------- 미리 정의된 형식. // VESA에서 iTA만 iTE로 교체한 형식으로 넣어준다. // wire [34:0] loc_VideoIn = {4'hf, 4'h0, i_VDEN, i_VSYNC, i_HSYNC, i_VD[23:0] }; U32 VSYNC = 25; U32 HSYNC = 24; U32 VDEN = 26; // bit 위치. U32 ONE = 34; U32 ZERO = 27; //==================================================== // 일단 현재는 location은 사용하고 있지 않다. //==================================================== U32 LOC_A[7] = {ONE,ONE,ONE,ONE,ONE,ONE,ONE}; U32 LOC_B[7] = {ONE,ONE,ONE,ONE,ONE,ONE,ONE}; U32 LOC_C[7] = {VDEN,VSYNC,HSYNC,ONE, HSYNC, VSYNC, VDEN}; U32 LOC_D[7] = {ZERO,ZERO,ZERO,ZERO,ZERO,ZERO,ZERO}; U32 LOC_E[7] = {ZERO,ZERO,ZERO,ZERO,ZERO,ZERO,ZERO}; RET_ASSERT_VAL(DISP_DEVICE_END > pdev->dev_id, -EINVAL); RET_ASSERT_VAL(pdev->dev_in == DISP_DEVICE_SYNCGEN0 || pdev->dev_in == DISP_DEVICE_SYNCGEN1 || pdev->dev_in == DISP_DEVICE_RESCONV, -EINVAL); if (plvds) format = plvds->lcd_format; DBGOUT("%s: [%d]=%s, in[%d]=%s, %s\n", __func__, pdev->dev_id, dev_to_str(pdev->dev_id), input, dev_to_str(input), (format==0?"VESA":(format==1?"JEIDA":"LOC"))); switch (input) { case DISP_DEVICE_SYNCGEN0: input = 0; break; case DISP_DEVICE_SYNCGEN1: input = 1; break; case DISP_DEVICE_RESCONV : input = 2; break; default: return -EINVAL; } /* if (LVDS_PCLK_L_MIN > psync->pixel_clock_hz) { printk(KERN_ERR "Fail, invalid pixel clock %u (min: %u)\n", psync->pixel_clock_hz, LVDS_PCLK_L_MIN); return -EINVAL; } if (psync->pixel_clock_hz > LVDS_PCLK_H_MAX) { printk(KERN_ERR "Fail, invalid pixel clock %u (max: %u)\n", psync->pixel_clock_hz, LVDS_PCLK_H_MAX); return -EINVAL; } */ /* * select TOP MUX */ NX_DISPTOP_CLKGEN_SetClockPClkMode(clkid, NX_PCLKMODE_ALWAYS); NX_DISPTOP_CLKGEN_SetClockDivisorEnable (clkid, CFALSE); NX_DISPTOP_CLKGEN_SetClockSource (clkid, 0, psync->clk_src_lv0); NX_DISPTOP_CLKGEN_SetClockDivisor(clkid, 0, psync->clk_div_lv0); NX_DISPTOP_CLKGEN_SetClockSource (clkid, 1, psync->clk_src_lv1); // CLKSRC_PLL0 NX_DISPTOP_CLKGEN_SetClockDivisor(clkid, 1, psync->clk_div_lv1); // NX_DISPTOP_CLKGEN_SetClockDivisorEnable(clkid, CTRUE); DBGOUT("%s: clkid=%d, src0=%d, div0=%d, src1=%d, div1=%d\n", __func__, clkid, psync->clk_src_lv0, psync->clk_div_lv0, psync->clk_src_lv1, psync->clk_div_lv1); //=============== // LVDS Control Pin Setting //=============== val = (0<<30) // CPU_I_VBLK_FLAG_SEL | (0<<29) // CPU_I_BVLK_FLAG | (1<<28) // SKINI_BST | (1<<27) // DLYS_BST | (0<<26) // I_AUTO_SEL | (format<<19) // JEiDA data packing | (0x1B<<13) // I_LOCK_PPM_SET, PPM setting for PLL lock | (0x638<<1) // I_DESKEW_CNT_SEL, period of de-skew region ; NX_LVDS_SetLVDSCTRL0( 0, val ); val = (0<<28) // I_ATE_MODE, funtion mode | (0<<27) // I_TEST_CON_MODE, DA (test ctrl mode) | (0<<24) // I_TX4010X_DUMMY | (0<<15) // SKCCK 0 | (0<<12) // SKC4 (TX output skew control pin at ODD ch4) | (0<<9) // SKC3 (TX output skew control pin at ODD ch3) | (0<<6) // SKC2 (TX output skew control pin at ODD ch2) | (0<<3) // SKC1 (TX output skew control pin at ODD ch1) | (0<<0) // SKC0 (TX output skew control pin at ODD ch0) ; NX_LVDS_SetLVDSCTRL1( 0, val ); val = (0<<15) // CK_POL_SEL, Input clock, bypass | (0<<14) // VSEL, VCO Freq. range. 0: Low(40MHz~90MHz), 1:High(90MHz~160MHz) | (0x1<<12) // S (Post-scaler) | (0xA<<6) // M (Main divider) | (0xA<<0) // P (Pre-divider) ; NX_LVDS_SetLVDSCTRL2( 0, val ); val = (0x03<<6) // SK_BIAS, Bias current ctrl pin | (0<<5) // SKEWINI, skew selection pin, 0 : bypass, 1 : skew enable | (0<<4) // SKEW_EN_H, skew block power down, 0 : power down, 1 : operating | (1<<3) // CNTB_TDLY, delay control pin | (0<<2) // SEL_DATABF, input clock 1/2 division control pin | (0x3<<0) // SKEW_REG_CUR, regulator bias current selection in in SKEW block ; NX_LVDS_SetLVDSCTRL3( 0, val ); val = (0<<28) // FLT_CNT, filter control pin for PLL | (0<<27) // VOD_ONLY_CNT, the pre-emphasis's pre-diriver control pin (VOD only) | (0<<26) // CNNCT_MODE_SEL, connectivity mode selection, 0:TX operating, 1:con check | (0<<24) // CNNCT_CNT, connectivity ctrl pin, 0:tx operating, 1: con check | (0<<23) // VOD_HIGH_S, VOD control pin, 1 : Vod only | (0<<22) // SRC_TRH, source termination resistor select pin | (0x3F<<14) // CNT_VOD_H, TX driver output differential volatge level control pin | (0x01<<6) // CNT_PEN_H, TX driver pre-emphasis level control | (0x4<<3) // FC_CODE, vos control pin | (0<<2) // OUTCON, TX Driver state selectioin pin, 0:Hi-z, 1:Low | (0<<1) // LOCK_CNT, Lock signal selection pin, enable | (0<<0) // AUTO_DSK_SEL, auto deskew selection pin, normal ; NX_LVDS_SetLVDSCTRL4( 0, val ); val = (0<<24) // I_BIST_RESETB | (0<<23) // I_BIST_EN | (0<<21) // I_BIST_PAT_SEL | (0<<14) // I_BIST_USER_PATTERN | (0<<13) // I_BIST_FORCE_ERROR | (0<<7) // I_BIST_SKEW_CTRL | (0<<5) // I_BIST_CLK_INV | (0<<3) // I_BIST_DATA_INV | (0<<0) // I_BIST_CH_SEL ; NX_LVDS_SetLVDSTMODE0( 0, val ); // user do not need to modify this codes. val = (LOC_A[4] <<24) | (LOC_A[3] <<18) | (LOC_A[2] <<12) | (LOC_A[1] <<6) | (LOC_A[0] <<0); NX_LVDS_SetLVDSLOC0( 0, val ); val = (LOC_B[2] <<24) | (LOC_B[1] <<18) | (LOC_B[0] <<12) | (LOC_A[6] <<6) | (LOC_A[5] <<0); NX_LVDS_SetLVDSLOC1( 0, val ); val = (LOC_C[0] <<24) | (LOC_B[6] <<18) | (LOC_B[5] <<12) | (LOC_B[4] <<6) | (LOC_B[3] <<0); NX_LVDS_SetLVDSLOC2( 0, val ); val = (LOC_C[5] <<24) | (LOC_C[4] <<18) | (LOC_C[3] <<12) | (LOC_C[2] <<6) | (LOC_C[1] <<0); NX_LVDS_SetLVDSLOC3( 0, val ); val = (LOC_D[3] <<24) | (LOC_D[2] <<18) | (LOC_D[1] <<12) | (LOC_D[0] <<6) | (LOC_C[6] <<0); NX_LVDS_SetLVDSLOC4( 0, val ); val = (LOC_E[1] <<24) | (LOC_E[0] <<18) | (LOC_D[6] <<12) | (LOC_D[5] <<6) | (LOC_D[4] <<0); NX_LVDS_SetLVDSLOC5( 0, val ); val = (LOC_E[6] <<24) | (LOC_E[5] <<18) | (LOC_E[4] <<12) | (LOC_E[3] <<6) | (LOC_E[2] <<0); NX_LVDS_SetLVDSLOC6( 0, val ); NX_LVDS_SetLVDSLOCMASK0( 0, 0xffffffff ); NX_LVDS_SetLVDSLOCMASK1( 0, 0xffffffff ); NX_LVDS_SetLVDSLOCPOL0( 0, (0<<19) | ( 0<<18) ); /* * select TOP MUX */ NX_DISPLAYTOP_SetLVDSMUX(CTRUE, input); return 0; }
static int mipi_prepare(struct disp_process_dev *pdev) { struct disp_vsync_info *psync = &pdev->vsync; struct disp_mipi_param *pmipi = pdev->dev_param; int input = pdev->dev_in; int index = 0; int clkid = DISP_CLOCK_MIPI; int width = psync->h_active_len; int height = psync->v_active_len; int ret = 0; int HFP = psync->h_front_porch; int HBP = psync->h_back_porch; int HS = psync->h_sync_width; int VFP = psync->v_front_porch; int VBP = psync->v_back_porch; int VS = psync->v_sync_width; unsigned int pllpms, bandctl, pllctl, phyctl; RET_ASSERT_VAL(pmipi, -EINVAL); RET_ASSERT_VAL(DISP_DEVICE_END > pdev->dev_id, -EINVAL); RET_ASSERT_VAL(pdev->dev_in == DISP_DEVICE_SYNCGEN0 || pdev->dev_in == DISP_DEVICE_SYNCGEN1 || pdev->dev_in == DISP_DEVICE_RESCONV, -EINVAL); DBGOUT("%s: [%d]=%s, in[%d]=%s\n", __func__, pdev->dev_id, dev_to_str(pdev->dev_id), input, dev_to_str(input)); pllpms = pmipi->pllpms; bandctl = pmipi->bandctl; pllctl = pmipi->pllctl; phyctl = pmipi->phyctl; switch (input) { case DISP_DEVICE_SYNCGEN0: input = 0; break; case DISP_DEVICE_SYNCGEN1: input = 1; break; case DISP_DEVICE_RESCONV : input = 2; break; default: return -EINVAL; } NX_MIPI_DSI_SetPLL(index ,CTRUE // CBOOL Enable , ,0xFFFFFFFF // U32 PLLStableTimer, ,pllpms // 19'h033E8: 1Ghz // Use LN28LPP_MipiDphyCore1p5Gbps_Supplement. ,bandctl // 4'hF : 1Ghz // Use LN28LPP_MipiDphyCore1p5Gbps_Supplement. ,pllctl // U32 M_PLLCTL , // Refer to 10.2.2 M_PLLCTL of MIPI_D_PHY_USER_GUIDE.pdf Default value is all "0". If you want to change register values, it need to confirm from IP Design Team ,phyctl // U32 B_DPHYCTL // Refer to 10.2.3 M_PLLCTL of MIPI_D_PHY_USER_GUIDE.pdf or NX_MIPI_PHY_B_DPHYCTL enum or LN28LPP_MipiDphyCore1p5Gbps_Supplement. default value is all "0". If you want to change register values, it need to confirm from IP Design Team ); NX_MIPI_DSI_SoftwareReset(index); NX_MIPI_DSI_SetClock (index ,1 // CBOOL EnableTXHSClock , ,0 // CBOOL UseExternalClock , // CFALSE: PLL clock CTRUE: External clock ,1 // CBOOL EnableByteClock , // ByteClock means (D-PHY PLL clock / 8) ,1 // CBOOL EnableESCClock_ClockLane, ,1 // CBOOL EnableESCClock_DataLane0, ,1 // CBOOL EnableESCClock_DataLane1, ,1 // CBOOL EnableESCClock_DataLane2, ,1 // CBOOL EnableESCClock_DataLane3, ,1 // CBOOL EnableESCPrescaler , // ESCClock = ByteClock / ESCPrescalerValue ,5 // U32 ESCPrescalerValue ); NX_MIPI_DSI_SetPhy( index ,3 // U32 NumberOfDataLanes , // 0~3 ,1 // CBOOL EnableClockLane , ,1 // CBOOL EnableDataLane0 , ,1 // CBOOL EnableDataLane1 , ,1 // CBOOL EnableDataLane2 , ,1 // CBOOL EnableDataLane3 , ,0 // CBOOL SwapClockLane , ,0 // CBOOL SwapDataLane ) ); NX_MIPI_DSI_SetConfigVideoMode (index ,1 // CBOOL EnableAutoFlushMainDisplayFIFO , ,0 // CBOOL EnableAutoVerticalCount , ,1,NX_MIPI_DSI_SYNCMODE_EVENT // CBOOL EnableBurst, NX_MIPI_DSI_SYNCMODE SyncMode, //,0,NX_MIPI_DSI_SYNCMODE_PULSE // CBOOL EnableBurst, NX_MIPI_DSI_SYNCMODE SyncMode, ,1 // CBOOL EnableEoTPacket , ,1 // CBOOL EnableHsyncEndPacket , // Set HSEMode=1 ,1 // CBOOL EnableHFP , // Set HFPMode=0 ,1 // CBOOL EnableHBP , // Set HBPMode=0 ,1 // CBOOL EnableHSA , // Set HSAMode=0 ,0 // U32 NumberOfVirtualChannel , // 0~3 ,NX_MIPI_DSI_FORMAT_RGB888 // NX_MIPI_DSI_FORMAT Format , ,HFP // U32 NumberOfWordsInHFP , // ~65535 ,HBP // U32 NumberOfWordsInHBP , // ~65535 ,HS // U32 NumberOfWordsInHSYNC , // ~65535 ,VFP // U32 NumberOfLinesInVFP , // ~2047 ,VBP // U32 NumberOfLinesInVBP , // ~2047 ,VS // U32 NumberOfLinesInVSYNC , // ~1023 ,0 // U32 NumberOfLinesInCommandAllow ); if (pmipi->lcd_init) { ret = pmipi->lcd_init(width, height, pmipi->private_data); if (0 > ret) return ret; } NX_MIPI_DSI_SoftwareReset(index); NX_MIPI_DSI_SetClock (index ,1 // CBOOL EnableTXHSClock , ,0 // CBOOL UseExternalClock , // CFALSE: PLL clock CTRUE: External clock ,1 // CBOOL EnableByteClock , // ByteClock means (D-PHY PLL clock / 8) ,1 // CBOOL EnableESCClock_ClockLane, ,1 // CBOOL EnableESCClock_DataLane0, ,1 // CBOOL EnableESCClock_DataLane1, ,1 // CBOOL EnableESCClock_DataLane2, ,1 // CBOOL EnableESCClock_DataLane3, ,1 // CBOOL EnableESCPrescaler , // ESCClock = ByteClock / ESCPrescalerValue ,5 // U32 ESCPrescalerValue ); NX_MIPI_DSI_SetPhy( index ,3 // U32 NumberOfDataLanes , // 0~3 ,1 // CBOOL EnableClockLane , ,1 // CBOOL EnableDataLane0 , ,1 // CBOOL EnableDataLane1 , ,1 // CBOOL EnableDataLane2 , ,1 // CBOOL EnableDataLane3 , ,0 // CBOOL SwapClockLane , ,0 // CBOOL SwapDataLane ) ); NX_MIPI_DSI_SetConfigVideoMode (index ,1 // CBOOL EnableAutoFlushMainDisplayFIFO , ,0 // CBOOL EnableAutoVerticalCount , ,1,NX_MIPI_DSI_SYNCMODE_EVENT // CBOOL EnableBurst, NX_MIPI_DSI_SYNCMODE SyncMode, //,0,NX_MIPI_DSI_SYNCMODE_PULSE // CBOOL EnableBurst, NX_MIPI_DSI_SYNCMODE SyncMode, ,1 // CBOOL EnableEoTPacket , ,1 // CBOOL EnableHsyncEndPacket , // Set HSEMode=1 ,1 // CBOOL EnableHFP , // Set HFPMode=0 ,1 // CBOOL EnableHBP , // Set HBPMode=0 ,1 // CBOOL EnableHSA , // Set HSAMode=0 ,0 // U32 NumberOfVirtualChannel , // 0~3 ,NX_MIPI_DSI_FORMAT_RGB888 // NX_MIPI_DSI_FORMAT Format , ,HFP // U32 NumberOfWordsInHFP , // ~65535 ,HBP // U32 NumberOfWordsInHBP , // ~65535 ,HS // U32 NumberOfWordsInHSYNC , // ~65535 ,VFP // U32 NumberOfLinesInVFP , // ~2047 ,VBP // U32 NumberOfLinesInVBP , // ~2047 ,VS // U32 NumberOfLinesInVSYNC , // ~1023 ,0 // U32 NumberOfLinesInCommandAllow ); NX_MIPI_DSI_SetSize(index, width, height); NX_DISPLAYTOP_SetMIPIMUX(CTRUE, input); // 0 is spdif, 1 is mipi vclk NX_DISPTOP_CLKGEN_SetClockSource (clkid, 0, psync->clk_src_lv0); NX_DISPTOP_CLKGEN_SetClockDivisor(clkid, 0, psync->clk_div_lv0); NX_DISPTOP_CLKGEN_SetClockSource (clkid, 1, psync->clk_src_lv1); // CLKSRC_PLL0 NX_DISPTOP_CLKGEN_SetClockDivisor(clkid, 1, psync->clk_div_lv1); return 0; }