Commit c31efa7a authored by Thierry Reding's avatar Thierry Reding

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: default avatarThierry Reding <treding@nvidia.com>
parent 2bd1dd39
...@@ -190,6 +190,18 @@ struct tegra_sor { ...@@ -190,6 +190,18 @@ struct tegra_sor {
struct regulator *hdmi_supply; struct regulator *hdmi_supply;
}; };
struct tegra_sor_state {
struct drm_connector_state base;
unsigned int bpc;
};
static inline struct tegra_sor_state *
to_sor_state(struct drm_connector_state *state)
{
return container_of(state, struct tegra_sor_state, base);
}
struct tegra_sor_config { struct tegra_sor_config {
u32 bits_per_pixel; u32 bits_per_pixel;
...@@ -720,7 +732,7 @@ static void tegra_sor_apply_config(struct tegra_sor *sor, ...@@ -720,7 +732,7 @@ static void tegra_sor_apply_config(struct tegra_sor *sor,
static void tegra_sor_mode_set(struct tegra_sor *sor, static void tegra_sor_mode_set(struct tegra_sor *sor,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
const struct drm_display_info *info) struct tegra_sor_state *state)
{ {
struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc); struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
unsigned int vbe, vse, hbe, hse, vbs, hbs; unsigned int vbe, vse, hbe, hse, vbs, hbs;
...@@ -746,7 +758,19 @@ static void tegra_sor_mode_set(struct tegra_sor *sor, ...@@ -746,7 +758,19 @@ static void tegra_sor_mode_set(struct tegra_sor *sor,
if (mode->flags & DRM_MODE_FLAG_NVSYNC) if (mode->flags & DRM_MODE_FLAG_NVSYNC)
value |= SOR_STATE_ASY_VSYNCPOL; value |= SOR_STATE_ASY_VSYNCPOL;
switch (info->bpc) { switch (state->bpc) {
case 16:
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_48_444;
break;
case 12:
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_36_444;
break;
case 10:
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_30_444;
break;
case 8: case 8:
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
break; break;
...@@ -756,7 +780,7 @@ static void tegra_sor_mode_set(struct tegra_sor *sor, ...@@ -756,7 +780,7 @@ static void tegra_sor_mode_set(struct tegra_sor *sor,
break; break;
default: default:
BUG(); value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
break; break;
} }
...@@ -1173,6 +1197,22 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor) ...@@ -1173,6 +1197,22 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
sor->debugfs = NULL; sor->debugfs = NULL;
} }
static void tegra_sor_connector_reset(struct drm_connector *connector)
{
struct tegra_sor_state *state;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return;
if (connector->state) {
__drm_atomic_helper_connector_destroy_state(connector->state);
kfree(connector->state);
}
__drm_atomic_helper_connector_reset(connector, &state->base);
}
static enum drm_connector_status static enum drm_connector_status
tegra_sor_connector_detect(struct drm_connector *connector, bool force) tegra_sor_connector_detect(struct drm_connector *connector, bool force)
{ {
...@@ -1185,13 +1225,28 @@ tegra_sor_connector_detect(struct drm_connector *connector, bool force) ...@@ -1185,13 +1225,28 @@ tegra_sor_connector_detect(struct drm_connector *connector, bool force)
return tegra_output_connector_detect(connector, force); return tegra_output_connector_detect(connector, force);
} }
static struct drm_connector_state *
tegra_sor_connector_duplicate_state(struct drm_connector *connector)
{
struct tegra_sor_state *state = to_sor_state(connector->state);
struct tegra_sor_state *copy;
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (!copy)
return NULL;
__drm_atomic_helper_connector_duplicate_state(connector, &copy->base);
return &copy->base;
}
static const struct drm_connector_funcs tegra_sor_connector_funcs = { static const struct drm_connector_funcs tegra_sor_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset, .reset = tegra_sor_connector_reset,
.detect = tegra_sor_connector_detect, .detect = tegra_sor_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = tegra_output_connector_destroy, .destroy = tegra_output_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_duplicate_state = tegra_sor_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
...@@ -1329,14 +1384,14 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1329,14 +1384,14 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
struct tegra_dc *dc = to_tegra_dc(encoder->crtc); struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
struct tegra_sor *sor = to_sor(output); struct tegra_sor *sor = to_sor(output);
struct tegra_sor_config config; struct tegra_sor_config config;
struct drm_display_info *info; struct tegra_sor_state *state;
struct drm_dp_link link; struct drm_dp_link link;
u8 rate, lanes; u8 rate, lanes;
unsigned int i; unsigned int i;
int err = 0; int err = 0;
u32 value; u32 value;
info = &output->connector.display_info; state = to_sor_state(output->connector.state);
err = clk_prepare_enable(sor->clk); err = clk_prepare_enable(sor->clk);
if (err < 0) if (err < 0)
...@@ -1363,7 +1418,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1363,7 +1418,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));
config.bits_per_pixel = output->connector.display_info.bpc * 3; config.bits_per_pixel = state->bpc * 3;
err = tegra_sor_compute_config(sor, mode, &config, &link); err = tegra_sor_compute_config(sor, mode, &config, &link);
if (err < 0) if (err < 0)
...@@ -1596,7 +1651,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder) ...@@ -1596,7 +1651,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
value |= SOR_STATE_ASY_PROTOCOL_DP_A; value |= SOR_STATE_ASY_PROTOCOL_DP_A;
tegra_sor_writel(sor, value, SOR_STATE1); tegra_sor_writel(sor, value, SOR_STATE1);
tegra_sor_mode_set(sor, mode, info); tegra_sor_mode_set(sor, mode, state);
/* PWM setup */ /* PWM setup */
err = tegra_sor_setup_pwm(sor, 250); err = tegra_sor_setup_pwm(sor, 250);
...@@ -1629,11 +1684,15 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, ...@@ -1629,11 +1684,15 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state) struct drm_connector_state *conn_state)
{ {
struct tegra_output *output = encoder_to_output(encoder); struct tegra_output *output = encoder_to_output(encoder);
struct tegra_sor_state *state = to_sor_state(conn_state);
struct tegra_dc *dc = to_tegra_dc(conn_state->crtc); struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
unsigned long pclk = crtc_state->mode.clock * 1000; unsigned long pclk = crtc_state->mode.clock * 1000;
struct tegra_sor *sor = to_sor(output); struct tegra_sor *sor = to_sor(output);
struct drm_display_info *info;
int err; int err;
info = &output->connector.display_info;
err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent, err = tegra_dc_state_setup_clock(dc, crtc_state, sor->clk_parent,
pclk, 0); pclk, 0);
if (err < 0) { if (err < 0) {
...@@ -1641,6 +1700,18 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder, ...@@ -1641,6 +1700,18 @@ tegra_sor_encoder_atomic_check(struct drm_encoder *encoder,
return err; return err;
} }
switch (info->bpc) {
case 8:
case 6:
state->bpc = info->bpc;
break;
default:
DRM_DEBUG_KMS("%u bits-per-color not supported\n", info->bpc);
state->bpc = 8;
break;
}
return 0; return 0;
} }
...@@ -1815,14 +1886,14 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -1815,14 +1886,14 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
struct tegra_dc *dc = to_tegra_dc(encoder->crtc); struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
struct tegra_sor_hdmi_settings *settings; struct tegra_sor_hdmi_settings *settings;
struct tegra_sor *sor = to_sor(output); struct tegra_sor *sor = to_sor(output);
struct tegra_sor_state *state;
struct drm_display_mode *mode; struct drm_display_mode *mode;
struct drm_display_info *info;
unsigned int div; unsigned int div;
u32 value; u32 value;
int err; int err;
state = to_sor_state(output->connector.state);
mode = &encoder->crtc->state->adjusted_mode; mode = &encoder->crtc->state->adjusted_mode;
info = &output->connector.display_info;
err = clk_prepare_enable(sor->clk); err = clk_prepare_enable(sor->clk);
if (err < 0) if (err < 0)
...@@ -2055,7 +2126,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2055,7 +2126,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
value &= ~DITHER_CONTROL_MASK; value &= ~DITHER_CONTROL_MASK;
value &= ~BASE_COLOR_SIZE_MASK; value &= ~BASE_COLOR_SIZE_MASK;
switch (info->bpc) { switch (state->bpc) {
case 6: case 6:
value |= BASE_COLOR_SIZE_666; value |= BASE_COLOR_SIZE_666;
break; break;
...@@ -2065,7 +2136,8 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2065,7 +2136,8 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
break; break;
default: default:
WARN(1, "%u bits-per-color not supported\n", info->bpc); WARN(1, "%u bits-per-color not supported\n", state->bpc);
value |= BASE_COLOR_SIZE_888;
break; break;
} }
...@@ -2087,7 +2159,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) ...@@ -2087,7 +2159,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
value |= SOR_HEAD_STATE_COLORSPACE_RGB; value |= SOR_HEAD_STATE_COLORSPACE_RGB;
tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe)); tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe));
tegra_sor_mode_set(sor, mode, info); tegra_sor_mode_set(sor, mode, state);
tegra_sor_update(sor); tegra_sor_update(sor);
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17) #define SOR_STATE_ASY_PIXELDEPTH_MASK (0xf << 17)
#define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17) #define SOR_STATE_ASY_PIXELDEPTH_BPP_18_444 (0x2 << 17)
#define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17) #define SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 (0x5 << 17)
#define SOR_STATE_ASY_PIXELDEPTH_BPP_30_444 (0x6 << 17)
#define SOR_STATE_ASY_PIXELDEPTH_BPP_36_444 (0x8 << 17)
#define SOR_STATE_ASY_PIXELDEPTH_BPP_48_444 (0x9 << 17)
#define SOR_STATE_ASY_VSYNCPOL (1 << 13) #define SOR_STATE_ASY_VSYNCPOL (1 << 13)
#define SOR_STATE_ASY_HSYNCPOL (1 << 12) #define SOR_STATE_ASY_HSYNCPOL (1 << 12)
#define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8) #define SOR_STATE_ASY_PROTOCOL_MASK (0xf << 8)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment