diff options
author | Chao Xu <cxu@nvidia.com> | 2013-07-09 00:55:52 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:05:26 -0400 |
commit | 7b45f842ff16b4c29b5848ae9c9029c2a79e96ab (patch) | |
tree | 3236b64d65b063821886dc62e818b4c85226d79b /drivers/video/tegra/dc/dp.c | |
parent | c845e1b1458d008756f0a310e02b57ee17e8311b (diff) |
video: tegra: dc: Update eDP support
Change-Id: I6ee39c20d4e120926837f84ab3107d6f4bc5a144
Signed-off-by: Chao Xu <cxu@nvidia.com>
Reviewed-on: http://git-master/r/246468
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Diffstat (limited to 'drivers/video/tegra/dc/dp.c')
-rw-r--r-- | drivers/video/tegra/dc/dp.c | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/drivers/video/tegra/dc/dp.c b/drivers/video/tegra/dc/dp.c index fb32b1d1a..c7baed83d 100644 --- a/drivers/video/tegra/dc/dp.c +++ b/drivers/video/tegra/dc/dp.c | |||
@@ -490,18 +490,10 @@ static void tegra_dc_dpaux_enable(struct tegra_dc_dp_data *dp) | |||
490 | DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE); | 490 | DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE); |
491 | } | 491 | } |
492 | 492 | ||
493 | static void tegra_dc_dpaux_disable(struct tegra_dc_dp_data *dp) | ||
494 | { | ||
495 | tegra_dpaux_writel(dp, NV_DPCD_SET_POWER, | ||
496 | NV_DPCD_SET_POWER_VAL_D3_PWRDWN); | ||
497 | |||
498 | /* TODO: power down DPAUX_HYBRID_SPARE too? */ | ||
499 | } | ||
500 | |||
501 | static void tegra_dc_dp_dump_link_cfg(struct tegra_dc_dp_data *dp, | 493 | static void tegra_dc_dp_dump_link_cfg(struct tegra_dc_dp_data *dp, |
502 | const struct tegra_dc_dp_link_config *cfg) | 494 | const struct tegra_dc_dp_link_config *cfg) |
503 | { | 495 | { |
504 | BUG_ON(!cfg || !cfg->is_valid); | 496 | BUG_ON(!cfg); |
505 | 497 | ||
506 | dev_info(&dp->dc->ndev->dev, "DP config: cfg_name cfg_value\n"); | 498 | dev_info(&dp->dc->ndev->dev, "DP config: cfg_name cfg_value\n"); |
507 | dev_info(&dp->dc->ndev->dev, " Lane Count %d\n", | 499 | dev_info(&dp->dc->ndev->dev, " Lane Count %d\n", |
@@ -595,8 +587,8 @@ static bool tegra_dc_dp_calc_config(struct tegra_dc_dp_data *dp, | |||
595 | !cfg->bits_per_pixel) | 587 | !cfg->bits_per_pixel) |
596 | return false; | 588 | return false; |
597 | 589 | ||
598 | if (mode->pclk * cfg->bits_per_pixel >= | 590 | if ((u64)mode->pclk * cfg->bits_per_pixel >= |
599 | 8 * link_rate * cfg->lane_count) | 591 | (u64)link_rate * 8 * cfg->lane_count) |
600 | return false; | 592 | return false; |
601 | 593 | ||
602 | num_linkclk_line = (u32)tegra_div64( | 594 | num_linkclk_line = (u32)tegra_div64( |
@@ -759,6 +751,12 @@ static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp, | |||
759 | 751 | ||
760 | cfg->bits_per_pixel = dp->dc->pdata->default_out->depth; | 752 | cfg->bits_per_pixel = dp->dc->pdata->default_out->depth; |
761 | 753 | ||
754 | /* TODO: need to come from the board file */ | ||
755 | cfg->drive_current = 0x40404040; | ||
756 | cfg->preemphasis = 0x0f0f0f0f; | ||
757 | cfg->postcursor = 0; | ||
758 | cfg->max_link_bw = SOR_LINK_SPEED_G1_62; | ||
759 | |||
762 | CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP, | 760 | CHECK_RET(tegra_dc_dp_dpcd_read(dp, NV_DPCD_EDP_CONFIG_CAP, |
763 | &dpcd_data)); | 761 | &dpcd_data)); |
764 | cfg->alt_scramber_reset_cap = | 762 | cfg->alt_scramber_reset_cap = |
@@ -768,15 +766,11 @@ static int tegra_dc_dp_init_max_link_cfg(struct tegra_dc_dp_data *dp, | |||
768 | (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ? | 766 | (dpcd_data & NV_DPCD_EDP_CONFIG_CAP_FRAMING_CHANGE_YES) ? |
769 | true : false; | 767 | true : false; |
770 | 768 | ||
771 | if (tegra_platform_is_fpga()) /* hardcoded to 1.62G on fpga */ | ||
772 | cfg->max_link_bw = SOR_LINK_SPEED_G1_62; | ||
773 | cfg->lane_count = cfg->max_lane_count; | 769 | cfg->lane_count = cfg->max_lane_count; |
774 | cfg->link_bw = cfg->max_link_bw; | 770 | cfg->link_bw = cfg->max_link_bw; |
775 | cfg->enhanced_framing = cfg->support_enhanced_framing; | 771 | cfg->enhanced_framing = cfg->support_enhanced_framing; |
776 | 772 | ||
777 | tegra_dc_dp_calc_config(dp, dp->mode, cfg); | 773 | tegra_dc_dp_calc_config(dp, dp->mode, cfg); |
778 | tegra_dc_dp_dump_link_cfg(dp, cfg); | ||
779 | |||
780 | return 0; | 774 | return 0; |
781 | } | 775 | } |
782 | 776 | ||
@@ -821,6 +815,7 @@ static int tegra_dp_set_lane_count(struct tegra_dc_dp_data *dp, | |||
821 | tegra_dc_sor_set_lane_count(dp->sor, cfg->lane_count); | 815 | tegra_dc_sor_set_lane_count(dp->sor, cfg->lane_count); |
822 | 816 | ||
823 | /* Also power down lanes that will not be used */ | 817 | /* Also power down lanes that will not be used */ |
818 | return 0; | ||
824 | } | 819 | } |
825 | 820 | ||
826 | static int tegra_dc_dp_set_lane_config(struct tegra_dc_dp_data *dp, | 821 | static int tegra_dc_dp_set_lane_config(struct tegra_dc_dp_data *dp, |
@@ -896,6 +891,7 @@ static int tegra_dc_dp_set_lane_config(struct tegra_dc_dp_data *dp, | |||
896 | temp_edc[0] &= NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK; | 891 | temp_edc[0] &= NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK; |
897 | temp_edc[0] |= (training_pattern & | 892 | temp_edc[0] |= (training_pattern & |
898 | NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK); | 893 | NV_DPCD_TRAINING_PATTERN_SET_TPS_MASK); |
894 | temp_edc[0] |= NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T; | ||
899 | 895 | ||
900 | size = 4; | 896 | size = 4; |
901 | ret = tegra_dc_dpaux_write(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, | 897 | ret = tegra_dc_dpaux_write(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, |
@@ -1197,28 +1193,72 @@ static int tegra_dc_dp_fast_link_training(struct tegra_dc_dp_data *dp, | |||
1197 | const struct tegra_dc_dp_link_config *cfg) | 1193 | const struct tegra_dc_dp_link_config *cfg) |
1198 | { | 1194 | { |
1199 | struct tegra_dc_sor_data *sor = dp->sor; | 1195 | struct tegra_dc_sor_data *sor = dp->sor; |
1200 | u8 link_bw; | 1196 | u8 link_bw; |
1201 | u8 lane_count; | 1197 | u8 lane_count; |
1198 | u32 data; | ||
1199 | u32 size; | ||
1200 | u32 status; | ||
1201 | int j; | ||
1202 | u32 mask = 0xffff >> ((4 - cfg->lane_count) * 4); | ||
1202 | 1203 | ||
1203 | BUG_ON(!cfg || !cfg->is_valid); | 1204 | BUG_ON(!cfg || !cfg->is_valid); |
1204 | tegra_dc_sor_set_link_bandwidth(sor, cfg->link_bw); | 1205 | |
1205 | tegra_dc_sor_set_lane_count(sor, cfg->lane_count); | 1206 | tegra_dc_sor_set_lane_parm(sor, cfg); |
1207 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET, | ||
1208 | NV_DPCD_MAIN_LINK_CHANNEL_CODING_SET_ANSI_8B10B); | ||
1206 | 1209 | ||
1207 | /* Send TP1 */ | 1210 | /* Send TP1 */ |
1208 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_1, cfg); | 1211 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_1, cfg); |
1212 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, | ||
1213 | NV_DPCD_TRAINING_PATTERN_SET_TPS_TP1); | ||
1209 | 1214 | ||
1215 | for (j = 0; j < cfg->lane_count; ++j) | ||
1216 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j, | ||
1217 | 0x24); | ||
1210 | usleep_range(500, 1000); | 1218 | usleep_range(500, 1000); |
1219 | size = 2; | ||
1220 | tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, | ||
1221 | NV_DPCD_LANE0_1_STATUS, (u8 *)&data, &size, &status); | ||
1222 | status = mask & 0x1111; | ||
1223 | if ((data & status) != status) { | ||
1224 | dev_err(&dp->dc->ndev->dev, | ||
1225 | "dp: Link training error for TP1 (0x%x)\n", data); | ||
1226 | return -EFAULT; | ||
1227 | } | ||
1228 | |||
1229 | if ((data & status) != status) { | ||
1230 | dev_err(&dp->dc->ndev->dev, | ||
1231 | "dp: Link training error for TP1 (0x%x)\n", data); | ||
1232 | return -EFAULT; | ||
1233 | } | ||
1234 | |||
1211 | /* enable ASSR */ | 1235 | /* enable ASSR */ |
1212 | tegra_dc_dp_set_assr(dp, true); | 1236 | tegra_dc_dp_set_assr(dp, true); |
1213 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_2, cfg); | 1237 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_3, cfg); |
1214 | 1238 | ||
1239 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, | ||
1240 | cfg->link_bw == 20 ? 0x23 : 0x22); | ||
1241 | for (j = 0; j < cfg->lane_count; ++j) | ||
1242 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_LANE0_SET + j, | ||
1243 | 0x24); | ||
1215 | usleep_range(500, 1000); | 1244 | usleep_range(500, 1000); |
1245 | |||
1246 | size = 4; | ||
1247 | tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, | ||
1248 | NV_DPCD_LANE0_1_STATUS, (u8 *)&data, &size, &status); | ||
1249 | if ((data & mask) != (0x7777 & mask)) { | ||
1250 | dev_info(&dp->dc->ndev->dev, | ||
1251 | "dp: Link training error for TP2/3 (0x%x)\n", data); | ||
1252 | return -EFAULT; | ||
1253 | } | ||
1254 | |||
1216 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_Disabled, cfg); | 1255 | tegra_dc_sor_set_dp_linkctl(sor, true, trainingPattern_Disabled, cfg); |
1256 | tegra_dc_dp_dpcd_write(dp, NV_DPCD_TRAINING_PATTERN_SET, 0); | ||
1217 | 1257 | ||
1218 | if (!tegra_dc_dp_link_trained(dp, cfg)) { | 1258 | if (!tegra_dc_dp_link_trained(dp, cfg)) { |
1219 | tegra_dc_sor_read_link_config(dp->sor, &link_bw, | 1259 | tegra_dc_sor_read_link_config(dp->sor, &link_bw, |
1220 | &lane_count); | 1260 | &lane_count); |
1221 | dev_info(&dp->dc->ndev->dev, | 1261 | dev_err(&dp->dc->ndev->dev, |
1222 | "Fast link trainging failed, link bw %d, lane # %d\n", | 1262 | "Fast link trainging failed, link bw %d, lane # %d\n", |
1223 | link_bw, lane_count); | 1263 | link_bw, lane_count); |
1224 | return -EFAULT; | 1264 | return -EFAULT; |
@@ -1274,7 +1314,6 @@ static int tegra_dp_link_config(struct tegra_dc_dp_data *dp, | |||
1274 | dev_err(&dp->dc->ndev->dev, "dp: Failed to set lane count\n"); | 1314 | dev_err(&dp->dc->ndev->dev, "dp: Failed to set lane count\n"); |
1275 | return ret; | 1315 | return ret; |
1276 | } | 1316 | } |
1277 | tegra_dc_dp_dump_link_cfg(dp, cfg); | ||
1278 | tegra_dc_sor_set_dp_linkctl(dp->sor, true, trainingPattern_None, cfg); | 1317 | tegra_dc_sor_set_dp_linkctl(dp->sor, true, trainingPattern_None, cfg); |
1279 | 1318 | ||
1280 | /* Now do the fast link training for eDP */ | 1319 | /* Now do the fast link training for eDP */ |
@@ -1432,6 +1471,7 @@ static int tegra_dc_dp_init(struct tegra_dc *dc) | |||
1432 | /* TODO: confirm interrupt num is acquired from gpio_to_irq, | 1471 | /* TODO: confirm interrupt num is acquired from gpio_to_irq, |
1433 | Also how to differentiate them from HDMI HPD. | 1472 | Also how to differentiate them from HDMI HPD. |
1434 | */ | 1473 | */ |
1474 | #if 0 | ||
1435 | if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_dp_hpd_irq, | 1475 | if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_dp_hpd_irq, |
1436 | IRQF_DISABLED | IRQF_TRIGGER_RISING | | 1476 | IRQF_DISABLED | IRQF_TRIGGER_RISING | |
1437 | IRQF_TRIGGER_FALLING, dev_name(&dc->ndev->dev), dc)) { | 1477 | IRQF_TRIGGER_FALLING, dev_name(&dc->ndev->dev), dc)) { |
@@ -1440,6 +1480,7 @@ static int tegra_dc_dp_init(struct tegra_dc *dc) | |||
1440 | err = -EBUSY; | 1480 | err = -EBUSY; |
1441 | goto err_get_clk; | 1481 | goto err_get_clk; |
1442 | } | 1482 | } |
1483 | #endif | ||
1443 | 1484 | ||
1444 | 1485 | ||
1445 | dp->dc = dc; | 1486 | dp->dc = dc; |
@@ -1487,8 +1528,6 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc) | |||
1487 | tegra_dc_dpaux_enable(dp); | 1528 | tegra_dc_dpaux_enable(dp); |
1488 | 1529 | ||
1489 | /* Power on panel */ | 1530 | /* Power on panel */ |
1490 | tegra_dc_sor_set_panel_power(dp->sor, true); | ||
1491 | |||
1492 | if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg)) { | 1531 | if (tegra_dc_dp_init_max_link_cfg(dp, &dp->link_cfg)) { |
1493 | dev_err(&dc->ndev->dev, | 1532 | dev_err(&dc->ndev->dev, |
1494 | "dp: failed to init link configuration\n"); | 1533 | "dp: failed to init link configuration\n"); |
@@ -1497,9 +1536,10 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc) | |||
1497 | 1536 | ||
1498 | tegra_dc_sor_enable_dp(dp->sor); | 1537 | tegra_dc_sor_enable_dp(dp->sor); |
1499 | 1538 | ||
1500 | /* Enable backlight -- TODO: need to go through I2C */ | ||
1501 | msleep(DP_LCDVCC_TO_HPD_DELAY_MS); | 1539 | msleep(DP_LCDVCC_TO_HPD_DELAY_MS); |
1502 | 1540 | ||
1541 | tegra_dc_sor_set_panel_power(dp->sor, true); | ||
1542 | |||
1503 | /* Write power on to DPCD */ | 1543 | /* Write power on to DPCD */ |
1504 | data = NV_DPCD_SET_POWER_VAL_D0_NORMAL; | 1544 | data = NV_DPCD_SET_POWER_VAL_D0_NORMAL; |
1505 | retry = 0; | 1545 | retry = 0; |
@@ -1527,14 +1567,9 @@ static void tegra_dc_dp_enable(struct tegra_dc *dc) | |||
1527 | dev_err(&dp->dc->ndev->dev, | 1567 | dev_err(&dp->dc->ndev->dev, |
1528 | "dp: failed to read the revision number from sink\n"); | 1568 | "dp: failed to read the revision number from sink\n"); |
1529 | 1569 | ||
1530 | if (tegra_dp_link_config(dp, &dp->link_cfg)) { | ||
1531 | dev_err(&dp->dc->ndev->dev, "dp: Could not setup link\n"); | ||
1532 | return; | ||
1533 | } | ||
1534 | |||
1535 | tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, dp->mode); | 1570 | tegra_dc_dp_explore_link_cfg(dp, &dp->link_cfg, dp->mode); |
1536 | 1571 | ||
1537 | mdelay(100); | 1572 | tegra_dc_sor_set_power_state(dp->sor, 1); |
1538 | tegra_dc_sor_attach(dp->sor); | 1573 | tegra_dc_sor_attach(dp->sor); |
1539 | 1574 | ||
1540 | error_enable: | 1575 | error_enable: |
@@ -1558,15 +1593,10 @@ static void tegra_dc_dp_disable(struct tegra_dc *dc) | |||
1558 | { | 1593 | { |
1559 | struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc); | 1594 | struct tegra_dc_dp_data *dp = tegra_dc_get_outdata(dc); |
1560 | 1595 | ||
1561 | /* TODO: confirm that dpaux_disable is not needed for eDP */ | ||
1562 | tegra_dc_dpaux_disable(dp); | ||
1563 | |||
1564 | /* Power down SOR */ | 1596 | /* Power down SOR */ |
1565 | tegra_dc_sor_disable(dp->sor, false); | 1597 | tegra_dc_sor_disable(dp->sor, false); |
1566 | 1598 | ||
1567 | clk_disable(dp->clk); | 1599 | clk_disable(dp->clk); |
1568 | /* TODO: Now power down the panel -- through GPIO */ | ||
1569 | /* Make sure the timing meet the eDP specs */ | ||
1570 | } | 1600 | } |
1571 | 1601 | ||
1572 | extern struct clk *tegra_get_clock_by_name(const char *name); | 1602 | extern struct clk *tegra_get_clock_by_name(const char *name); |