static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) { int ret, testdin, vco, val; vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200; testdin = max_mbps_to_testdin(dsi->lane_mbps); if (testdin < 0) { dev_err(dsi->dev, "failed to get testdin for %dmbps lane clock\n", dsi->lane_mbps); return testdin; } dsi_write(dsi, DSI_PWR_UP, POWERUP); dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE | VCO_RANGE_CON_SEL(vco) | VCO_IN_CAP_CON_LOW | REF_BIAS_CUR_SEL); dw_mipi_dsi_phy_write(dsi, 0x11, CP_CURRENT_3MA); dw_mipi_dsi_phy_write(dsi, 0x12, CP_PROGRAM_EN | LPF_PROGRAM_EN | LPF_RESISTORS_20_KOHM); dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin)); dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div)); dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) | LOW_PROGRAM_EN); dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) | HIGH_PROGRAM_EN); dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT | BIAS_BLOCK_ON | BANDGAP_ON); dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_LOW | TER_CAL_DONE | SETRD_MAX | TER_RESISTORS_ON); dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON | SETRD_MAX | POWER_MANAGE | TER_RESISTORS_ON); dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7)); dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10)); dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | 0xf); dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | 0x55); dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | 0xa); dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK | PHY_UNRSTZ | PHY_UNSHUTDOWNZ); ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS, val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) { dev_err(dsi->dev, "failed to wait for phy lock state\n"); return ret; } ret = readx_poll_timeout(readl, dsi->base + DSI_PHY_STATUS, val, val & STOP_STATE_CLK_LANE, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) { dev_err(dsi->dev, "failed to wait for phy clk lane stop state\n"); return ret; } return ret; }
static int dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) { int ret, testdin, vco, val; vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200; testdin = max_mbps_to_testdin(dsi->lane_mbps); if (testdin < 0) { DRM_DEV_ERROR(dsi->dev, "failed to get testdin for %dmbps lane clock\n", dsi->lane_mbps); return testdin; } /* Start by clearing PHY state */ dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR); dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); ret = clk_prepare_enable(dsi->phy_cfg_clk); if (ret) { DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk\n"); return ret; } dw_mipi_dsi_phy_write(dsi, 0x10, BYPASS_VCO_RANGE | VCO_RANGE_CON_SEL(vco) | VCO_IN_CAP_CON_LOW | REF_BIAS_CUR_SEL); dw_mipi_dsi_phy_write(dsi, 0x11, CP_CURRENT_3MA); dw_mipi_dsi_phy_write(dsi, 0x12, CP_PROGRAM_EN | LPF_PROGRAM_EN | LPF_RESISTORS_20_KOHM); dw_mipi_dsi_phy_write(dsi, 0x44, HSFREQRANGE_SEL(testdin)); dw_mipi_dsi_phy_write(dsi, 0x17, INPUT_DIVIDER(dsi->input_div)); dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_LOW_SEL(dsi->feedback_div) | LOW_PROGRAM_EN); dw_mipi_dsi_phy_write(dsi, 0x18, LOOP_DIV_HIGH_SEL(dsi->feedback_div) | HIGH_PROGRAM_EN); dw_mipi_dsi_phy_write(dsi, 0x19, PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN); dw_mipi_dsi_phy_write(dsi, 0x22, LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7)); dw_mipi_dsi_phy_write(dsi, 0x22, HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10)); dw_mipi_dsi_phy_write(dsi, 0x20, POWER_CONTROL | INTERNAL_REG_CURRENT | BIAS_BLOCK_ON | BANDGAP_ON); dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_LOW | TER_CAL_DONE | SETRD_MAX | TER_RESISTORS_ON); dw_mipi_dsi_phy_write(dsi, 0x21, TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON | SETRD_MAX | POWER_MANAGE | TER_RESISTORS_ON); dw_mipi_dsi_phy_write(dsi, 0x60, TLP_PROGRAM_EN | ns2bc(dsi, 500)); dw_mipi_dsi_phy_write(dsi, 0x61, THS_PRE_PROGRAM_EN | ns2ui(dsi, 40)); dw_mipi_dsi_phy_write(dsi, 0x62, THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300)); dw_mipi_dsi_phy_write(dsi, 0x63, THS_PRE_PROGRAM_EN | ns2ui(dsi, 100)); dw_mipi_dsi_phy_write(dsi, 0x64, BIT(5) | ns2bc(dsi, 100)); dw_mipi_dsi_phy_write(dsi, 0x65, BIT(5) | (ns2bc(dsi, 60) + 7)); dw_mipi_dsi_phy_write(dsi, 0x70, TLP_PROGRAM_EN | ns2bc(dsi, 500)); dw_mipi_dsi_phy_write(dsi, 0x71, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 5)); dw_mipi_dsi_phy_write(dsi, 0x72, THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2)); dw_mipi_dsi_phy_write(dsi, 0x73, THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8)); dw_mipi_dsi_phy_write(dsi, 0x74, BIT(5) | ns2bc(dsi, 100)); dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK | PHY_UNRSTZ | PHY_UNSHUTDOWNZ); ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, val & LOCK, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) { DRM_DEV_ERROR(dsi->dev, "failed to wait for phy lock state\n"); goto phy_init_end; } ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, val & STOP_STATE_CLK_LANE, 1000, PHY_STATUS_TIMEOUT_US); if (ret < 0) DRM_DEV_ERROR(dsi->dev, "failed to wait for phy clk lane stop state\n"); phy_init_end: clk_disable_unprepare(dsi->phy_cfg_clk); return ret; }