static void s5p_dp_disable(struct s5p_dp_device *dp) { struct s5p_dp_platdata *pdata = dp->dev->platform_data; mutex_lock(&dp->lock); if (!dp->enabled) goto out; dp->enabled = 0; s5p_dp_reset(dp); s5p_dp_set_pll_power_down(dp, 1); s5p_dp_set_analog_power_down(dp, POWER_ALL, 1); #ifdef CONFIG_S5P_DP_PSR if (dp->psr_enter_state != PSR_ENTER_DONE) clk_disable(dp->clock); #else clk_disable(dp->clock); #endif pm_runtime_put_sync(dp->dev); out: mutex_unlock(&dp->lock); }
static void s5p_dp_disable(struct s5p_dp_device *dp) { struct s5p_dp_platdata *pdata = dp->dev->platform_data; #if defined(CONFIG_SOC_EXYNOS5260) if ((pdata->clock_reinit == true) && (dp->clock_status == true)) dp->clock_status = false; #endif mutex_lock(&dp->lock); if (!dp->enabled) goto out; dp->enabled = 0; s5p_dp_reset(dp); s5p_dp_set_pll_power_down(dp, 1); s5p_dp_set_analog_power_down(dp, POWER_ALL, 1); if (pdata && pdata->phy_exit) pdata->phy_exit(); clk_disable(dp->clock); pm_runtime_put_sync(dp->dev); out: mutex_unlock(&dp->lock); }
static int s5p_dp_init_training(struct s5p_dp_device *dp, enum link_lane_count_type max_lane, enum link_rate_type max_rate) { int retval; /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ s5p_dp_reset_macro(dp); /* Initialize by reading RX's DPCD */ retval = s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); if (retval < 0) return retval; retval = s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); if (retval < 0) return retval; if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS; } if (dp->link_train.lane_count == 0) { dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n", dp->link_train.lane_count); dp->link_train.lane_count = (u8)LANE_COUNT1; } /* Setup TX lane count & rate */ if (dp->link_train.lane_count > max_lane) dp->link_train.lane_count = max_lane; if (dp->link_train.link_rate > max_rate) dp->link_train.link_rate = max_rate; /* All DP analog module power up */ s5p_dp_set_analog_power_down(dp, POWER_ALL, 0); return 0; }
static void s5p_dp_disable(struct s5p_dp_device *dp) { struct s5p_dp_platdata *pdata = dp->dev->platform_data; mutex_lock(&dp->lock); if (!dp->enabled) goto out; dp->enabled = 0; s5p_dp_reset(dp); s5p_dp_set_pll_power_down(dp, 1); s5p_dp_set_analog_power_down(dp, POWER_ALL, 1); if (pdata && pdata->phy_exit) pdata->phy_exit(); clk_disable(dp->clock); pm_runtime_put_sync(dp->dev); out: mutex_unlock(&dp->lock); }
static int s5p_dp_init_training(struct s5p_dp_device *dp, enum link_lane_count_type max_lane, enum link_rate_type max_rate) { int retval; #ifdef CONFIG_S5P_DP_PSR u8 data; #endif /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ s5p_dp_reset_macro(dp); #ifdef CONFIG_S5P_DP_PSR s5p_dp_enable_rx_to_enhanced_mode(dp, 0); s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_EDP_CONFIGURATION_SET, &data); s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_EDP_CONFIGURATION_SET, data | (1<<1)); s5p_dp_enable_enhanced_mode(dp, 1); #endif /* Initialize by reading RX's DPCD */ retval = s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); if (retval < 0) return retval; retval = s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); if (retval < 0) return retval; if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS; } if (dp->link_train.lane_count == 0) { dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n", dp->link_train.lane_count); dp->link_train.lane_count = (u8)LANE_COUNT1; } /* Setup TX lane count & rate */ if (dp->link_train.lane_count > max_lane) dp->link_train.lane_count = max_lane; if (dp->link_train.link_rate > max_rate) dp->link_train.link_rate = max_rate; #ifdef CONFIG_S5P_DP_PSR s5p_dp_enable_ssc(dp, 0); #endif /* All DP analog module power up */ s5p_dp_set_analog_power_down(dp, POWER_ALL, 0); return 0; }
int s5p_dp_psr_exit(struct s5p_dp_device *dp) { struct platform_device *pdev; struct s5p_dp_platdata *pdata; int timeout_loop = 0; u8 data; u32 reg; int ret = 0; pdev = to_platform_device(dp->dev); pdata = pdev->dev.platform_data; mutex_lock(&dp->lock); dev_dbg(dp->dev, "%s +\n", __func__); if (dp->psr_enter_state == PSR_NONE) { dev_info(dp->dev, "%s: Already edP PSR_EXIT state\n", __func__); dp->psr_exit_state = PSR_NONE; mutex_unlock(&dp->lock); return 0; } clk_enable(dp->clock); s5p_dp_exit_psr(dp); s5p_dp_set_fifo_reset(dp); s5p_dp_reset_macro_onoff(dp, 1); s5p_dp_set_analog_power_down(dp, ANALOG_TOTAL, 0); if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { timeout_loop++; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "failed to get pll lock status\n"); ret = -ETIMEDOUT; goto err_exit; } udelay(10); } } ndelay(600); s5p_dp_clear_fifo_reset(dp); s5p_dp_reset_macro_onoff(dp, 0); s5p_dp_reset_serdes_fifo(dp); /* Set sink to D0 (Normal operation) mode. */ s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, DPCD_SET_POWER_STATE_D0); s5p_dp_set_link_train_for_psr(dp, dp->video_info->lane_count, dp->video_info->link_rate); s5p_dp_set_idle_en(dp); timeout_loop = 0; for (;;) { timeout_loop++; if (s5p_dp_get_psr_status(dp) == PSR_STATUS_INACTIVE) break; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "DP: Timeout of PSR inactive\n"); ret = -ETIMEDOUT; goto err_exit; } usleep_range(100, 110); } s5p_dp_set_force_stream_valid(dp); timeout_loop = 0; for (;;) { timeout_loop++; if (s5p_dp_is_video_stream_on(dp) == 0) break; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "Timeout of video streamclk ok\n"); ret = -ETIMEDOUT; goto err_exit; } usleep_range(1000, 1100); } timeout_loop = 0; for (;;) { timeout_loop++; s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_SINK_PSR_STATUS, &data); if (data == SINK_PSR_INACTIVE_STATE || data == 4) { break; } if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "LCD: Timeout of Sink PSR inactive\n"); ret = -ETIMEDOUT; goto err_exit; } usleep_range(100, 110); } dp->psr_enter_state = PSR_NONE; dp->psr_exit_state = PSR_EXIT_DONE; dev_dbg(dp->dev, "%s -\n", __func__); mutex_unlock(&dp->lock); return ret; err_exit: dp->psr_exit_state = PSR_NONE; dev_dbg(dp->dev, "%s -\n", __func__); mutex_unlock(&dp->lock); return ret; }
static int s5p_dp_psr_enter(struct s5p_dp_device *dp) { struct platform_device *pdev; struct s5p_dp_platdata *pdata; int timeout_loop = 0; struct fb_event event; int ret = 0; u8 data; pdev = to_platform_device(dp->dev); pdata = pdev->dev.platform_data; mutex_lock(&dp->lock); dev_dbg(dp->dev, "%s +\n", __func__); if (dp->psr_enter_state == PSR_ENTER_DONE) { dev_info(dp->dev, "%s: Already edP PSR_ENTER state\n", __func__); goto err_exit; } if (dp->psr_exit_state == PSR_PRE_EXIT) { dev_info(dp->dev, "%s: edP does not need to PSR_ENTER\n", __func__); goto err_exit; } dp->psr_enter_state = PSR_PRE_ENTER; s5p_dp_enable_psr(dp); for (;;) { timeout_loop++; if (s5p_dp_get_psr_status(dp) == PSR_STATUS_ACTIVE) break; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "DP: Timeout of PSR active\n"); ret = -ETIMEDOUT; dp->psr_enter_state = PSR_NONE; dp->psr_error_count++; goto err_exit; } mdelay(1); } mdelay(2); dev_dbg(dp->dev, "PSR ENTER DP timeout_loop: %d\n", timeout_loop); s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_SINK_PSR_STATUS, &data); if (data == 0) dev_info(dp->dev, "%s: SINK_PSR_STATUS = 0x%02X\n", __func__, data); s5p_dp_set_analog_power_down(dp, ANALOG_TOTAL, 1); clk_disable(dp->clock); fb_notifier_call_chain(FB_EVENT_PSR_DONE, &event); dp->psr_enter_state = PSR_ENTER_DONE; err_exit: dev_dbg(dp->dev, "%s -\n", __func__); mutex_unlock(&dp->lock); return ret; }