diff options
author | Thierry Reding <treding@nvidia.com> | 2015-09-08 10:09:22 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2016-07-04 05:33:21 -0400 |
commit | c31efa7a30ed04cbd17cac6e8fc91fce425773cd (patch) | |
tree | 74b2215c84be94b01007aa465c84b937a228dd06 | |
parent | 2bd1dd399fcd2e23efb1583df3ba846b20429739 (diff) |
drm/tegra: sor: Do not support deep color modes
Current generations of Tegra do not support deep color modes, so force
8 bits per color even if the connected monitor or panel supports more.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 100 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.h | 3 |
2 files changed, 89 insertions, 14 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 01b31805f719..8c893b6c6a4c 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c | |||
@@ -190,6 +190,18 @@ struct tegra_sor { | |||
190 | struct regulator *hdmi_supply; | 190 | struct regulator *hdmi_supply; |
191 | }; | 191 | }; |
192 | 192 | ||
193 | struct tegra_sor_state { | ||
194 | struct drm_connector_state base; | ||
195 | |||
196 | unsigned int bpc; | ||
197 | }; | ||
198 | |||
199 | static inline struct tegra_sor_state * | ||
200 | to_sor_state(struct drm_connector_state *state) | ||
201 | { | ||
202 | return container_of(state, struct tegra_sor_state, base); | ||
203 | } | ||
204 | |||
193 | struct tegra_sor_config { | 205 | struct tegra_sor_config { |
194 | u32 bits_per_pixel; | 206 | u32 bits_per_pixel; |
195 | 207 | ||
@@ -720,7 +732,7 @@ static void tegra_sor_apply_config(struct tegra_sor *sor, | |||
720 | 732 | ||
721 | static void tegra_sor_mode_set(struct tegra_sor *sor, | 733 | static void tegra_sor_mode_set(struct tegra_sor *sor, |
722 | const struct drm_display_mode *mode, | 734 | const struct drm_display_mode *mode, |
723 | const struct drm_display_info *info) | 735 | struct tegra_sor_state *state) |
724 | { | 736 | { |
725 | struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc); | 737 | struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc); |
726 | unsigned int vbe, vse, hbe, hse, vbs, hbs; | 738 | unsigned int vbe, vse, hbe, hse, vbs, hbs; |
@@ -746,7 +758,19 @@ static void tegra_sor_mode_set(struct tegra_sor *sor, | |||
746 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | 758 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
747 | value |= SOR_STATE_ASY_VSYNCPOL; | 759 | value |= SOR_STATE_ASY_VSYNCPOL; |
748 | 760 | ||
749 | switch (info->bpc) { | 761 | switch (state->bpc) { |
762 | case 16: | ||
763 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_48_444; | ||
764 | break; | ||
765 | |||
766 | case 12: | ||
767 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_36_444; | ||
768 | break; | ||
769 | |||
770 | case 10: | ||
771 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_30_444; | ||
772 | break; | ||
773 | |||
750 | case 8: | 774 | case 8: |
751 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | 775 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; |
752 | break; | 776 | break; |
@@ -756,7 +780,7 @@ static void tegra_sor_mode_set(struct tegra_sor *sor, | |||
756 | break; | 780 | break; |
757 | 781 | ||
758 | default: | 782 | default: |
759 | BUG(); | 783 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; |
760 | break; | 784 | break; |
761 | } | 785 | } |
762 | 786 | ||
@@ -1173,6 +1197,22 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor) | |||
1173 | sor->debugfs = NULL; | 1197 | sor->debugfs = NULL; |
1174 | } | 1198 | } |
1175 | 1199 | ||
1200 | static void tegra_sor_connector_reset(struct drm_connector *connector) | ||
1201 | { | ||
1202 | struct tegra_sor_state *state; | ||
1203 | |||
1204 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
1205 | if (!state) | ||
1206 | return; | ||
1207 | |||
1208 | if (connector->state) { | ||
1209 | __drm_atomic_helper_connector_destroy_state(connector->state); | ||
1210 | kfree(connector->state); | ||
1211 | } | ||
1212 | |||
1213 | __drm_atomic_helper_connector_reset(connector, &state->base); | ||
1214 | } | ||
1215 | |||
1176 | static enum drm_connector_status | 1216 | static enum drm_connector_status |
1177 | tegra_sor_connector_detect(struct drm_connector *connector, bool force) | 1217 | tegra_sor_connector_detect(struct drm_connector *connector, bool force) |
1178 | { | 1218 | { |
@@ -1185,13 +1225,28 @@ tegra_sor_connector_detect(struct drm_connector *connector, bool force) | |||
1185 | return tegra_output_connector_detect(connector, force); | 1225 | return tegra_output_connector_detect(connector, force); |
1186 | } | 1226 | } |
1187 | 1227 | ||
1228 | static struct drm_connector_state * | ||
1229 | tegra_sor_connector_duplicate_state(struct drm_connector *connector) | ||
1230 | { | ||
1231 | struct tegra_sor_state *state = to_sor_state(connector->state); | ||
1232 | struct tegra_sor_state *copy; | ||
1233 | |||
1234 | copy = kmemdup(state, sizeof(*state), GFP_KERNEL); | ||
1235 | if (!copy) | ||
1236 | return NULL; | ||
1237 | |||
1238 | __drm_atomic_helper_connector_duplicate_state(connector, ©->base); | ||
1239 | |||
1240 | return ©->base; | ||
1241 | } | ||
1242 | |||
1188 | static const struct drm_connector_funcs tegra_sor_connector_funcs = { | 1243 | static const struct drm_connector_funcs tegra_sor_connector_funcs = { |
1189 | .dpms = drm_atomic_helper_connector_dpms, | 1244 | .dpms = drm_atomic_helper_connector_dpms, |
1190 | .reset = drm_atomic_helper_connector_reset, | 1245 | .reset = tegra_sor_connector_reset, |
1191 | .detect = tegra_sor_connector_detect, | 1246 | .detect = tegra_sor_connector_detect, |
1192 | .fill_modes = drm_helper_probe_single_connector_modes, | 1247 | .fill_modes = drm_helper_probe_single_connector_modes, |
1193 | .destroy = tegra_output_connector_destroy, | 1248 | .destroy = tegra_output_connector_destroy, |
1194 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | 1249 | .atomic_duplicate_state = tegra_sor_connector_duplicate_state, |
1195 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | 1250 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
1196 | }; | 1251 | }; |
1197 | 1252 | ||
@@ -1329,14 +1384,14 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) | |||
1329 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1384 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
1330 | struct tegra_sor *sor = to_sor(output); | 1385 | struct tegra_sor *sor = to_sor(output); |
1331 | struct tegra_sor_config config; | 1386 | struct tegra_sor_config config; |
1332 | struct drm_display_info *info; | 1387 | struct tegra_sor_state *state; |
1333 | struct drm_dp_link link; | 1388 | struct drm_dp_link link; |
1334 | u8 rate, lanes; | 1389 | u8 rate, lanes; |
1335 | unsigned int i; | 1390 | unsigned int i; |
1336 | int err = 0; | 1391 | int err = 0; |
1337 | u32 value; | 1392 | u32 value; |
1338 | 1393 | ||
1339 | info = &output->connector.display_info; | 1394 | state = to_sor_state(output->connector.state); |
1340 | 1395 | ||
1341 | err = clk_prepare_enable(sor->clk); | 1396 | err = clk_prepare_enable(sor->clk); |
1342 | if (err < 0) | 1397 | if (err < 0) |
@@ -1363,7 +1418,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) | |||
1363 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); | 1418 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); |
1364 | 1419 | ||
1365 | memset(&config, 0, sizeof(config)); | 1420 | memset(&config, 0, sizeof(config)); |
1366 | config.bits_per_pixel = output->connector.display_info.bpc * 3; | 1421 | config.bits_per_pixel = state->bpc * 3; |
1367 | 1422 | ||
1368 | err = tegra_sor_compute_config(sor, mode, &config, &link); | 1423 | err = tegra_sor_compute_config(sor, mode, &config, &link); |
1369 | if (err < 0) | 1424 | if (err < 0) |
@@ -1596,7 +1651,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) | |||
1596 | value |= SOR_STATE_ASY_PROTOCOL_DP_A; | 1651 | value |= SOR_STATE_ASY_PROTOCOL_DP_A; |
1597 | tegra_sor_writel(sor, value, SOR_STATE1); | 1652 | tegra_sor_writel(sor, value, SOR_STATE1); |
1598 | 1653 | ||
1599 | tegra_sor_mode_set(sor, mode, info); | 1654 | tegra_sor_mode_set(sor, mode, state); |
1600 | 1655 | ||
1601 | /* PWM setup */ | 1656 | /* PWM setup */ |
1602 | err = tegra_sor_setup_pwm(sor, 250); | 1657 | err = tegra_sor_setup_pwm(sor, 250); |
@@ -1629,11 +1684,15 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, | |||
1629 | struct drm_connector_state *conn_state) | 1684 | struct drm_connector_state *conn_state) |
1630 | { | 1685 | { |
1631 | struct tegra_output *output = encoder_to_output(encoder); | 1686 | struct tegra_output *output = encoder_to_output(encoder); |
1687 | struct tegra_sor_state *state = to_sor_state(conn_state); | ||
1632 | struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); | 1688 | struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); |
1633 | unsigned long pclk = crtc_state->mode.clock * 1000; | 1689 | unsigned long pclk = crtc_state->mode.clock * 1000; |
1634 | struct tegra_sor *sor = to_sor(output); | 1690 | struct tegra_sor *sor = to_sor(output); |
1691 | struct drm_display_info *info; | ||
1635 | int err; | 1692 | int err; |
1636 | 1693 | ||
1694 | info = &output->connector.display_info; | ||
1695 | |||
1637 | err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, | 1696 | err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, |
1638 | pclk, 0); | 1697 | pclk, 0); |
1639 | if (err < 0) { | 1698 | if (err < 0) { |
@@ -1641,6 +1700,18 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, | |||
1641 | return err; | 1700 | return err; |
1642 | } | 1701 | } |
1643 | 1702 | ||
1703 | switch (info->bpc) { | ||
1704 | case 8: | ||
1705 | case 6: | ||
1706 | state->bpc = info->bpc; | ||
1707 | break; | ||
1708 | |||
1709 | default: | ||
1710 | DRM_DEBUG_KMS("%u bits-per-color not supported\n", info->bpc); | ||
1711 | state->bpc = 8; | ||
1712 | break; | ||
1713 | } | ||
1714 | |||
1644 | return 0; | 1715 | return 0; |
1645 | } | 1716 | } |
1646 | 1717 | ||
@@ -1815,14 +1886,14 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
1815 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); | 1886 | struct tegra_dc *dc = to_tegra_dc(encoder->crtc); |
1816 | struct tegra_sor_hdmi_settings *settings; | 1887 | struct tegra_sor_hdmi_settings *settings; |
1817 | struct tegra_sor *sor = to_sor(output); | 1888 | struct tegra_sor *sor = to_sor(output); |
1889 | struct tegra_sor_state *state; | ||
1818 | struct drm_display_mode *mode; | 1890 | struct drm_display_mode *mode; |
1819 | struct drm_display_info *info; | ||
1820 | unsigned int div; | 1891 | unsigned int div; |
1821 | u32 value; | 1892 | u32 value; |
1822 | int err; | 1893 | int err; |
1823 | 1894 | ||
1895 | state = to_sor_state(output->connector.state); | ||
1824 | mode = &encoder->crtc->state->adjusted_mode; | 1896 | mode = &encoder->crtc->state->adjusted_mode; |
1825 | info = &output->connector.display_info; | ||
1826 | 1897 | ||
1827 | err = clk_prepare_enable(sor->clk); | 1898 | err = clk_prepare_enable(sor->clk); |
1828 | if (err < 0) | 1899 | if (err < 0) |
@@ -2055,7 +2126,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
2055 | value &= ~DITHER_CONTROL_MASK; | 2126 | value &= ~DITHER_CONTROL_MASK; |
2056 | value &= ~BASE_COLOR_SIZE_MASK; | 2127 | value &= ~BASE_COLOR_SIZE_MASK; |
2057 | 2128 | ||
2058 | switch (info->bpc) { | 2129 | switch (state->bpc) { |
2059 | case 6: | 2130 | case 6: |
2060 | value |= BASE_COLOR_SIZE_666; | 2131 | value |= BASE_COLOR_SIZE_666; |
2061 | break; | 2132 | break; |
@@ -2065,7 +2136,8 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
2065 | break; | 2136 | break; |
2066 | 2137 | ||
2067 | default: | 2138 | default: |
2068 | WARN(1, "%u bits-per-color not supported\n", info->bpc); | 2139 | WARN(1, "%u bits-per-color not supported\n", state->bpc); |
2140 | value |= BASE_COLOR_SIZE_888; | ||
2069 | break; | 2141 | break; |
2070 | } | 2142 | } |
2071 | 2143 | ||
@@ -2087,7 +2159,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) | |||
2087 | value |= SOR_HEAD_STATE_COLORSPACE_RGB; | 2159 | value |= SOR_HEAD_STATE_COLORSPACE_RGB; |
2088 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); | 2160 | tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); |
2089 | 2161 | ||
2090 | tegra_sor_mode_set(sor, mode, info); | 2162 | tegra_sor_mode_set(sor, mode, state); |
2091 | 2163 | ||
2092 | tegra_sor_update(sor); | 2164 | tegra_sor_update(sor); |
2093 | 2165 | ||
diff --git a/drivers/gpu/drm/tegra/sor.h b/drivers/gpu/drm/tegra/sor.h index 2d31d027e3f6..865c73b48968 100644 --- a/drivers/gpu/drm/tegra/sor.h +++ b/drivers/gpu/drm/tegra/sor.h | |||
@@ -27,6 +27,9 @@ | |||
27 | #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) | 27 | #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) |
28 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) | 28 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) |
29 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) | 29 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) |
30 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_30_444 (0x6 << 17) | ||
31 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_36_444 (0x8 << 17) | ||
32 | #define SOR_STATE_ASY_PIXELDEPTH_BPP_48_444 (0x9 << 17) | ||
30 | #define SOR_STATE_ASY_VSYNCPOL (1 << 13) | 33 | #define SOR_STATE_ASY_VSYNCPOL (1 << 13) |
31 | #define SOR_STATE_ASY_HSYNCPOL (1 << 12) | 34 | #define SOR_STATE_ASY_HSYNCPOL (1 << 12) |
32 | #define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8) | 35 | #define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8) |