static int exynos_dp_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_dp_platdata *pdata = pdev->dev.platform_data; struct exynos_dp_device *dp = platform_get_drvdata(pdev); if (pdata && pdata->phy_init) pdata->phy_init(); clk_enable(dp->clock); exynos_dp_init_dp(dp); exynos_dp_detect_hpd(dp); exynos_dp_handle_edid(dp); exynos_dp_set_link_train(dp, dp->video_info->lane_count, dp->video_info->link_rate); exynos_dp_enable_scramble(dp, 1); exynos_dp_enable_rx_to_enhanced_mode(dp, 1); exynos_dp_enable_enhanced_mode(dp, 1); exynos_dp_set_lane_count(dp, dp->video_info->lane_count); exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); exynos_dp_init_video(dp); exynos_dp_config_video(dp, dp->video_info); return 0; }
static void exynos_dp_commit(struct drm_encoder *encoder) { struct exynos_dp_device *dp = encoder_to_dp(encoder); int ret; /* Keep the panel disabled while we configure video */ if (dp->panel) { if (drm_panel_disable(dp->panel)) DRM_ERROR("failed to disable the panel\n"); } ret = exynos_dp_detect_hpd(dp); if (ret) { /* Cable has been disconnected, we're done */ return; } ret = exynos_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n"); return; } ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { dev_err(dp->dev, "unable to do link train\n"); return; } exynos_dp_enable_scramble(dp, 1); exynos_dp_enable_rx_to_enhanced_mode(dp, 1); exynos_dp_enable_enhanced_mode(dp, 1); exynos_dp_set_lane_count(dp, dp->video_info->lane_count); exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); exynos_dp_init_video(dp); ret = exynos_dp_config_video(dp); if (ret) dev_err(dp->dev, "unable to config video\n"); /* Safe to enable the panel now */ if (dp->panel) { if (drm_panel_enable(dp->panel)) DRM_ERROR("failed to enable the panel\n"); } /* Enable video */ exynos_dp_start_video(dp); }
static void exynos_dp_link_start(struct exynos_dp_device *dp) { u8 buf[5]; int lane; int lane_count; lane_count = dp->link_train.lane_count; dp->link_train.lt_state = CLOCK_RECOVERY; dp->link_train.eq_loop = 0; for (lane = 0; lane < lane_count; lane++) dp->link_train.cr_loop[lane] = 0; /* Set sink to D0 (Sink Not Ready) mode. */ exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, DPCD_SET_POWER_STATE_D0); /* Set link rate and count as you want to establish*/ exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); exynos_dp_set_lane_count(dp, dp->link_train.lane_count); /* Setup RX configuration */ buf[0] = dp->link_train.link_rate; buf[1] = dp->link_train.lane_count; exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET, 2, buf); /* Set TX pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, lane); /* Set training pattern 1 */ exynos_dp_set_training_pattern(dp, TRAINING_PTN1); /* Set RX training pattern */ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]); for (lane = 0; lane < lane_count; lane++) buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET, lane_count, buf); }
static void exynos_dp_hotplug(struct work_struct *work) { struct exynos_dp_device *dp; int ret; dp = container_of(work, struct exynos_dp_device, hotplug_work); ret = exynos_dp_detect_hpd(dp); if (ret) { /* Cable has been disconnected, we're done */ //return; } ret = exynos_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n"); //return; } ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { dev_err(dp->dev, "unable to do link train\n"); return; } exynos_dp_enable_scramble(dp, 1); exynos_dp_enable_rx_to_enhanced_mode(dp, 1); exynos_dp_enable_enhanced_mode(dp, 1); exynos_dp_set_lane_count(dp, dp->video_info->lane_count); exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); exynos_dp_init_video(dp); ret = exynos_dp_config_video(dp); if (ret) dev_err(dp->dev, "unable to config video\n"); }
static int exynos_dp_link_start(struct exynos_dp_device *dp) { u8 buf[4]; int lane, lane_count, pll_tries, retval; lane_count = dp->link_train.lane_count; dp->link_train.lt_state = CLOCK_RECOVERY; dp->link_train.eq_loop = 0; for (lane = 0; lane < lane_count; lane++) dp->link_train.cr_loop[lane] = 0; /* Set link rate and count as you want to establish*/ exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); exynos_dp_set_lane_count(dp, dp->link_train.lane_count); /* Setup RX configuration */ buf[0] = dp->link_train.link_rate; buf[1] = dp->link_train.lane_count; retval = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); if (retval) return retval; /* Set TX pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, lane); /* Wait for PLL lock */ pll_tries = 0; while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { dev_err(dp->dev, "Wait for PLL lock timed out\n"); return -ETIMEDOUT; } pll_tries++; usleep_range(90, 120); } /* Set training pattern 1 */ exynos_dp_set_training_pattern(dp, TRAINING_PTN1); /* Set RX training pattern */ retval = exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1); if (retval) return retval; for (lane = 0; lane < lane_count; lane++) buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | DP_TRAIN_VOLTAGE_SWING_LEVEL_0; retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, lane_count, buf); return retval; }
static int __devinit exynos_dp_probe(struct platform_device *pdev) { struct resource *res; struct exynos_dp_device *dp; struct exynos_dp_platdata *pdata; int ret = 0; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; } dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) { dev_err(&pdev->dev, "no memory for device data\n"); return -ENOMEM; } dp->dev = &pdev->dev; dp->clock = clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(dp->clock); goto err_dp; } clk_enable(dp->clock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to get registers\n"); ret = -EINVAL; goto err_clock; } res = request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev)); if (!res) { dev_err(&pdev->dev, "failed to request registers region\n"); ret = -EINVAL; goto err_clock; } dp->res = res; dp->reg_base = ioremap(res->start, resource_size(res)); if (!dp->reg_base) { dev_err(&pdev->dev, "failed to ioremap\n"); ret = -ENOMEM; goto err_req_region; } dp->irq = platform_get_irq(pdev, 0); if (!dp->irq) { dev_err(&pdev->dev, "failed to get irq\n"); ret = -ENODEV; goto err_ioremap; } ret = request_irq(dp->irq, exynos_dp_irq_handler, 0, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); goto err_ioremap; } dp->video_info = pdata->video_info; if (pdata->phy_init) pdata->phy_init(); exynos_dp_init_dp(dp); ret = exynos_dp_detect_hpd(dp); if (ret) { dev_err(&pdev->dev, "unable to detect hpd\n"); goto err_irq; } exynos_dp_handle_edid(dp); ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { dev_err(&pdev->dev, "unable to do link train\n"); goto err_irq; } exynos_dp_enable_scramble(dp, 1); exynos_dp_enable_rx_to_enhanced_mode(dp, 1); exynos_dp_enable_enhanced_mode(dp, 1); exynos_dp_set_lane_count(dp, dp->video_info->lane_count); exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); exynos_dp_init_video(dp); ret = exynos_dp_config_video(dp, dp->video_info); if (ret) { dev_err(&pdev->dev, "unable to config video\n"); goto err_irq; } platform_set_drvdata(pdev, dp); return 0; err_irq: free_irq(dp->irq, dp); err_ioremap: iounmap(dp->reg_base); err_req_region: release_mem_region(res->start, resource_size(res)); err_clock: clk_put(dp->clock); err_dp: kfree(dp); return ret; }
static int __devinit exynos_dp_probe(struct platform_device *pdev) { struct resource *res; struct exynos_dp_device *dp; struct exynos_dp_platdata *pdata; int ret = 0; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; } dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), GFP_KERNEL); if (!dp) { dev_err(&pdev->dev, "no memory for device data\n"); return -ENOMEM; } dp->dev = &pdev->dev; dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); return PTR_ERR(dp->clock); } clk_prepare_enable(dp->clock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dp->reg_base = devm_request_and_ioremap(&pdev->dev, res); if (!dp->reg_base) { dev_err(&pdev->dev, "failed to ioremap\n"); return -ENOMEM; } dp->irq = platform_get_irq(pdev, 0); if (!dp->irq) { dev_err(&pdev->dev, "failed to get irq\n"); return -ENODEV; } ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; } dp->video_info = pdata->video_info; if (pdata->phy_init) pdata->phy_init(); exynos_dp_init_dp(dp); ret = exynos_dp_detect_hpd(dp); if (ret) { dev_err(&pdev->dev, "unable to detect hpd\n"); return ret; } exynos_dp_handle_edid(dp); ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { dev_err(&pdev->dev, "unable to do link train\n"); return ret; } exynos_dp_enable_scramble(dp, 1); exynos_dp_enable_rx_to_enhanced_mode(dp, 1); exynos_dp_enable_enhanced_mode(dp, 1); exynos_dp_set_lane_count(dp, dp->video_info->lane_count); exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); exynos_dp_init_video(dp); ret = exynos_dp_config_video(dp, dp->video_info); if (ret) { dev_err(&pdev->dev, "unable to config video\n"); return ret; } platform_set_drvdata(pdev, dp); return 0; }