From 72d302861530bcdb780ea57ebfc3dff6ec4f802c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 12 Dec 2013 11:06:55 +0100 Subject: [PATCH] drm/tegra: Relocate some output-specific code Some of the code in the CRTC's mode setting code is specific to the RGB output or needs to be called slightly differently depending on the type of output. Push that code down into the output drivers. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 18 --------------- drivers/gpu/drm/tegra/dc.h | 2 ++ drivers/gpu/drm/tegra/dsi.c | 22 ++++++++++++------ drivers/gpu/drm/tegra/hdmi.c | 45 ++++++++++++++++++++++++++++-------- drivers/gpu/drm/tegra/rgb.c | 45 ++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index f89445d3cab7..386f3b4b0094 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -669,20 +669,6 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL); } - value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; - tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS); - - value = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY(1)); - value &= ~LVS_OUTPUT_POLARITY_LOW; - value &= ~LHS_OUTPUT_POLARITY_LOW; - tegra_dc_writel(dc, value, DC_COM_PIN_OUTPUT_POLARITY(1)); - - value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB | - DISP_ORDER_RED_BLUE; - tegra_dc_writel(dc, value, DC_DISP_DISP_INTERFACE_CONTROL); - - tegra_dc_writel(dc, 0x00010001, DC_DISP_SHIFT_CLOCK_OPTIONS); - value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1; tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); @@ -746,10 +732,6 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); - value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); - value |= DISP_CTRL_MODE_C_DISPLAY; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); - /* initialize timer */ value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) | WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20); diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index e6a9df0abe68..3c2c0ea1cd87 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -240,6 +240,8 @@ #define DITHER_CONTROL_ERRDIFF (3 << 8) #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) #define DC_DISP_DATA_ENABLE_OPTIONS 0x432 #define DE_SELECT_ACTIVE_BLANK (0 << 0) diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 844818f3e2d5..d452faab0235 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -450,15 +450,16 @@ static int tegra_output_dsi_enable(struct tegra_output *output) value |= DSI_ENABLE; tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); - value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | - PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); - value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); value &= ~DISP_CTRL_MODE_MASK; value |= DISP_CTRL_MODE_C_DISPLAY; tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); + value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); @@ -482,11 +483,15 @@ static int tegra_output_dsi_disable(struct tegra_output *output) tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL); /* - * FIXME: The output isn't attached to any CRTC when it's being - * disabled, so the following will never be executed. + * The following accesses registers of the display controller, so make + * sure it's only executed when the output is attached to one. */ if (dc) { - /* disable display controller */ + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); + value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); value &= ~DISP_CTRL_MODE_MASK; tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); @@ -494,6 +499,9 @@ static int tegra_output_dsi_disable(struct tegra_output *output) value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); value &= ~DSI_ENABLE; tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); + + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); + tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); } clk_disable(dsi->clk); diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 19ce750e4856..bc9cb1ac709b 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -843,10 +843,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) value |= SOR_CSTM_ROTCLK(2); tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_CSTM); - tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND); - tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); - tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); - /* start SOR */ tegra_hdmi_writel(hdmi, SOR_PWR_NORMAL_STATE_PU | @@ -896,15 +892,20 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) HDMI_NV_PDISP_SOR_STATE1); tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0); - tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS); + value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); + value |= HDMI_ENABLE; + tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); - value = PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | - PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); - - value = DISP_CTRL_MODE_C_DISPLAY; + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); + value &= ~DISP_CTRL_MODE_MASK; + value |= DISP_CTRL_MODE_C_DISPLAY; tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); + value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); @@ -917,11 +918,35 @@ static int tegra_output_hdmi_enable(struct tegra_output *output) static int tegra_output_hdmi_disable(struct tegra_output *output) { + struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); struct tegra_hdmi *hdmi = to_hdmi(output); + unsigned long value; if (!hdmi->enabled) return 0; + /* + * The following accesses registers of the display controller, so make + * sure it's only executed when the output is attached to one. + */ + if (dc) { + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL); + value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + + value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND); + value &= ~DISP_CTRL_MODE_MASK; + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND); + + value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); + value &= ~HDMI_ENABLE; + tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); + + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); + tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); + } + reset_control_assert(hdmi->rst); clk_disable(hdmi->clk); regulator_disable(hdmi->pll); diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 3b29018913a5..03885bb8dcc0 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -87,15 +87,60 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, static int tegra_output_rgb_enable(struct tegra_output *output) { struct tegra_rgb *rgb = to_rgb(output); + unsigned long value; tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable)); + value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; + tegra_dc_writel(rgb->dc, value, DC_DISP_DATA_ENABLE_OPTIONS); + + /* XXX: parameterize? */ + value = tegra_dc_readl(rgb->dc, DC_COM_PIN_OUTPUT_POLARITY(1)); + value &= ~LVS_OUTPUT_POLARITY_LOW; + value &= ~LHS_OUTPUT_POLARITY_LOW; + tegra_dc_writel(rgb->dc, value, DC_COM_PIN_OUTPUT_POLARITY(1)); + + /* XXX: parameterize? */ + value = DISP_DATA_FORMAT_DF1P1C | DISP_ALIGNMENT_MSB | + DISP_ORDER_RED_BLUE; + tegra_dc_writel(rgb->dc, value, DC_DISP_DISP_INTERFACE_CONTROL); + + /* XXX: parameterize? */ + value = SC0_H_QUALIFIER_NONE | SC1_H_QUALIFIER_NONE; + tegra_dc_writel(rgb->dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS); + + value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND); + value &= ~DISP_CTRL_MODE_MASK; + value |= DISP_CTRL_MODE_C_DISPLAY; + tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND); + + value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL); + value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE; + tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + + tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); + tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); + return 0; } static int tegra_output_rgb_disable(struct tegra_output *output) { struct tegra_rgb *rgb = to_rgb(output); + unsigned long value; + + value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_POWER_CONTROL); + value &= ~(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); + tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_POWER_CONTROL); + + value = tegra_dc_readl(rgb->dc, DC_CMD_DISPLAY_COMMAND); + value &= ~DISP_CTRL_MODE_MASK; + tegra_dc_writel(rgb->dc, value, DC_CMD_DISPLAY_COMMAND); + + tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); + tegra_dc_writel(rgb->dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); -- 2.30.2