aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/tegra/sor.c121
-rw-r--r--drivers/gpu/drm/tegra/sor.h4
2 files changed, 119 insertions, 6 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 1d7f24df0b10..f6313c4d612e 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -22,6 +22,7 @@
22#include <drm/drm_atomic_helper.h> 22#include <drm/drm_atomic_helper.h>
23#include <drm/drm_dp_helper.h> 23#include <drm/drm_dp_helper.h>
24#include <drm/drm_panel.h> 24#include <drm/drm_panel.h>
25#include <drm/drm_scdc_helper.h>
25 26
26#include "dc.h" 27#include "dc.h"
27#include "drm.h" 28#include "drm.h"
@@ -350,11 +351,16 @@ struct tegra_sor {
350 struct regulator *avdd_io_supply; 351 struct regulator *avdd_io_supply;
351 struct regulator *vdd_pll_supply; 352 struct regulator *vdd_pll_supply;
352 struct regulator *hdmi_supply; 353 struct regulator *hdmi_supply;
354
355 struct delayed_work scdc;
356 bool scdc_enabled;
353}; 357};
354 358
355struct tegra_sor_state { 359struct tegra_sor_state {
356 struct drm_connector_state base; 360 struct drm_connector_state base;
357 361
362 unsigned int link_speed;
363 unsigned long pclk;
358 unsigned int bpc; 364 unsigned int bpc;
359}; 365};
360 366
@@ -1489,10 +1495,6 @@ static enum drm_mode_status
1489tegra_sor_connector_mode_valid(struct drm_connector *connector, 1495tegra_sor_connector_mode_valid(struct drm_connector *connector,
1490 struct drm_display_mode *mode) 1496 struct drm_display_mode *mode)
1491{ 1497{
1492 /* HDMI 2.0 modes are not yet supported */
1493 if (mode->clock > 340000)
1494 return MODE_NOCLOCK;
1495
1496 return MODE_OK; 1498 return MODE_OK;
1497} 1499}
1498 1500
@@ -1917,6 +1919,18 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
1917 1919
1918 info = &output->connector.display_info; 1920 info = &output->connector.display_info;
1919 1921
1922 /*
1923 * For HBR2 modes, the SOR brick needs to use the x20 multiplier, so
1924 * the pixel clock must be corrected accordingly.
1925 */
1926 if (pclk >= 340000000) {
1927 state->link_speed = 20;
1928 state->pclk = pclk / 2;
1929 } else {
1930 state->link_speed = 10;
1931 state->pclk = pclk;
1932 }
1933
1920 err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, 1934 err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent,
1921 pclk, 0); 1935 pclk, 0);
1922 if (err < 0) { 1936 if (err < 0) {
@@ -2067,6 +2081,81 @@ tegra_sor_hdmi_find_settings(struct tegra_sor *sor, unsigned long frequency)
2067 return NULL; 2081 return NULL;
2068} 2082}
2069 2083
2084static void tegra_sor_hdmi_disable_scrambling(struct tegra_sor *sor)
2085{
2086 u32 value;
2087
2088 value = tegra_sor_readl(sor, SOR_HDMI2_CTRL);
2089 value &= ~SOR_HDMI2_CTRL_CLOCK_MODE_DIV_BY_4;
2090 value &= ~SOR_HDMI2_CTRL_SCRAMBLE;
2091 tegra_sor_writel(sor, value, SOR_HDMI2_CTRL);
2092}
2093
2094static void tegra_sor_hdmi_scdc_disable(struct tegra_sor *sor)
2095{
2096 struct i2c_adapter *ddc = sor->output.ddc;
2097
2098 drm_scdc_set_high_tmds_clock_ratio(ddc, false);
2099 drm_scdc_set_scrambling(ddc, false);
2100
2101 tegra_sor_hdmi_disable_scrambling(sor);
2102}
2103
2104static void tegra_sor_hdmi_scdc_stop(struct tegra_sor *sor)
2105{
2106 if (sor->scdc_enabled) {
2107 cancel_delayed_work_sync(&sor->scdc);
2108 tegra_sor_hdmi_scdc_disable(sor);
2109 }
2110}
2111
2112static void tegra_sor_hdmi_enable_scrambling(struct tegra_sor *sor)
2113{
2114 u32 value;
2115
2116 value = tegra_sor_readl(sor, SOR_HDMI2_CTRL);
2117 value |= SOR_HDMI2_CTRL_CLOCK_MODE_DIV_BY_4;
2118 value |= SOR_HDMI2_CTRL_SCRAMBLE;
2119 tegra_sor_writel(sor, value, SOR_HDMI2_CTRL);
2120}
2121
2122static void tegra_sor_hdmi_scdc_enable(struct tegra_sor *sor)
2123{
2124 struct i2c_adapter *ddc = sor->output.ddc;
2125
2126 drm_scdc_set_high_tmds_clock_ratio(ddc, true);
2127 drm_scdc_set_scrambling(ddc, true);
2128
2129 tegra_sor_hdmi_enable_scrambling(sor);
2130}
2131
2132static void tegra_sor_hdmi_scdc_work(struct work_struct *work)
2133{
2134 struct tegra_sor *sor = container_of(work, struct tegra_sor, scdc.work);
2135 struct i2c_adapter *ddc = sor->output.ddc;
2136
2137 if (!drm_scdc_get_scrambling_status(ddc)) {
2138 DRM_DEBUG_KMS("SCDC not scrambled\n");
2139 tegra_sor_hdmi_scdc_enable(sor);
2140 }
2141
2142 schedule_delayed_work(&sor->scdc, msecs_to_jiffies(5000));
2143}
2144
2145static void tegra_sor_hdmi_scdc_start(struct tegra_sor *sor)
2146{
2147 struct drm_scdc *scdc = &sor->output.connector.display_info.hdmi.scdc;
2148 struct drm_display_mode *mode;
2149
2150 mode = &sor->output.encoder.crtc->state->adjusted_mode;
2151
2152 if (mode->clock >= 340000 && scdc->supported) {
2153 schedule_delayed_work(&sor->scdc, msecs_to_jiffies(5000));
2154 tegra_sor_hdmi_scdc_enable(sor);
2155 sor->scdc_enabled = true;
2156 }
2157}
2158
2070static void tegra_sor_hdmi_disable(struct drm_encoder *encoder) 2159static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
2071{ 2160{
2072 struct tegra_output *output = encoder_to_output(encoder); 2161 struct tegra_output *output = encoder_to_output(encoder);
@@ -2075,6 +2164,8 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
2075 u32 value; 2164 u32 value;
2076 int err; 2165 int err;
2077 2166
2167 tegra_sor_hdmi_scdc_stop(sor);
2168
2078 err = tegra_sor_detach(sor); 2169 err = tegra_sor_detach(sor);
2079 if (err < 0) 2170 if (err < 0)
2080 dev_err(sor->dev, "failed to detach SOR: %d\n", err); 2171 dev_err(sor->dev, "failed to detach SOR: %d\n", err);
@@ -2114,12 +2205,14 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2114 struct tegra_sor *sor = to_sor(output); 2205 struct tegra_sor *sor = to_sor(output);
2115 struct tegra_sor_state *state; 2206 struct tegra_sor_state *state;
2116 struct drm_display_mode *mode; 2207 struct drm_display_mode *mode;
2208 unsigned long rate, pclk;
2117 unsigned int div, i; 2209 unsigned int div, i;
2118 u32 value; 2210 u32 value;
2119 int err; 2211 int err;
2120 2212
2121 state = to_sor_state(output->connector.state); 2213 state = to_sor_state(output->connector.state);
2122 mode = &encoder->crtc->state->adjusted_mode; 2214 mode = &encoder->crtc->state->adjusted_mode;
2215 pclk = mode->clock * 1000;
2123 2216
2124 pm_runtime_get_sync(sor->dev); 2217 pm_runtime_get_sync(sor->dev);
2125 2218
@@ -2195,10 +2288,13 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2195 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK; 2288 value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
2196 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK; 2289 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
2197 2290
2198 if (mode->clock < 340000) 2291 if (mode->clock < 340000) {
2292 DRM_DEBUG_KMS("setting 2.7 GHz link speed\n");
2199 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70; 2293 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
2200 else 2294 } else {
2295 DRM_DEBUG_KMS("setting 5.4 GHz link speed\n");
2201 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40; 2296 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G5_40;
2297 }
2202 2298
2203 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK; 2299 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_PCLK;
2204 tegra_sor_writel(sor, value, SOR_CLK_CNTRL); 2300 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
@@ -2254,6 +2350,15 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2254 return; 2350 return;
2255 } 2351 }
2256 2352
2353 /* adjust clock rate for HDMI 2.0 modes */
2354 rate = clk_get_rate(sor->clk_parent);
2355
2356 if (mode->clock >= 340000)
2357 rate /= 2;
2358
2359 DRM_DEBUG_KMS("setting clock to %lu Hz, mode: %lu Hz\n", rate, pclk);
2360
2361 clk_set_rate(sor->clk, rate);
2257 2362
2258 if (!sor->soc->has_nvdisplay) { 2363 if (!sor->soc->has_nvdisplay) {
2259 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe); 2364 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
@@ -2465,6 +2570,8 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
2465 err = tegra_sor_wakeup(sor); 2570 err = tegra_sor_wakeup(sor);
2466 if (err < 0) 2571 if (err < 0)
2467 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err); 2572 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err);
2573
2574 tegra_sor_hdmi_scdc_start(sor);
2468} 2575}
2469 2576
2470static const struct drm_encoder_helper_funcs tegra_sor_hdmi_helpers = { 2577static const struct drm_encoder_helper_funcs tegra_sor_hdmi_helpers = {
@@ -2652,6 +2759,8 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
2652 return err; 2759 return err;
2653 } 2760 }
2654 2761
2762 INIT_DELAYED_WORK(&sor->scdc, tegra_sor_hdmi_scdc_work);
2763
2655 return 0; 2764 return 0;
2656} 2765}
2657 2766
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h
index e85ffc8d98e4..fb0854d92a27 100644
--- a/drivers/gpu/drm/tegra/sor.h
+++ b/drivers/gpu/drm/tegra/sor.h
@@ -382,4 +382,8 @@
382#define SOR_HDMI_VSI_INFOFRAME_STATUS 0x124 382#define SOR_HDMI_VSI_INFOFRAME_STATUS 0x124
383#define SOR_HDMI_VSI_INFOFRAME_HEADER 0x125 383#define SOR_HDMI_VSI_INFOFRAME_HEADER 0x125
384 384
385#define SOR_HDMI2_CTRL 0x13e
386#define SOR_HDMI2_CTRL_CLOCK_MODE_DIV_BY_4 (1 << 1)
387#define SOR_HDMI2_CTRL_SCRAMBLE (1 << 0)
388
385#endif 389#endif