]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/sun4i: tcon: Don't rely on encoders to enable the TCON
authorMaxime Ripard <maxime.ripard@free-electrons.com>
Tue, 17 Oct 2017 09:06:12 +0000 (11:06 +0200)
committerMaxime Ripard <maxime.ripard@free-electrons.com>
Tue, 17 Oct 2017 17:49:13 +0000 (19:49 +0200)
So far, we've required all the TCON-connected encoders to call the TCON
enable and disable functions.

This was made this way because in the RGB/LVDS case, the TCON is the CRTC
and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we
have another encoder down the road that needs to be programmed.

We also needed to know which channel the encoder is connected to, which is
encoder-specific.

The CRTC's enable and disable callbacks can work just fine for our use
case, and we can get the channel to use just by looking at the type of
encoder, since that is fixed. Implement those callbacks, which will
remove some of the encoder boilerplate.

Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Link: https://patchwork.freedesktop.org/patch/msgid/90b4396e19b3eca61b2ebfdae0672074b88ad74d.1508231063.git-series.maxime.ripard@free-electrons.com
drivers/gpu/drm/sun4i/sun4i_crtc.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_rgb.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
drivers/gpu/drm/sun4i/sun4i_tv.c

index d097c6f93ad0188ce82494c63e2d722253a05a98..e86baa3746af336cd5bc09dbd34185fe11f909cd 100644 (file)
 #include "sunxi_engine.h"
 #include "sun4i_tcon.h"
 
+/*
+ * While this isn't really working in the DRM theory, in practice we
+ * can only ever have one encoder per TCON since we have a mux in our
+ * TCON.
+ */
+static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
+{
+       struct drm_encoder *encoder;
+
+       drm_for_each_encoder(encoder, crtc->dev)
+               if (encoder->crtc == crtc)
+                       return encoder;
+
+       return NULL;
+}
+
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
@@ -72,11 +88,12 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
                                      struct drm_crtc_state *old_state)
 {
+       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
        DRM_DEBUG_DRIVER("Disabling the CRTC\n");
 
-       sun4i_tcon_disable(scrtc->tcon);
+       sun4i_tcon_set_status(scrtc->tcon, encoder, false);
 
        if (crtc->state->event && !crtc->state->active) {
                spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +107,12 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
 static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
                                     struct drm_crtc_state *old_state)
 {
+       struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
        struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
 
        DRM_DEBUG_DRIVER("Enabling the CRTC\n");
 
-       sun4i_tcon_enable(scrtc->tcon);
+       sun4i_tcon_set_status(scrtc->tcon, encoder, true);
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
index 6ca6e6a74c4ac4f438b8303d3810b10566f3242d..482bf03d55c10720c75d3a125ffd27cd199fdeea 100644 (file)
@@ -86,8 +86,6 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
 static void sun4i_hdmi_disable(struct drm_encoder *encoder)
 {
        struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-       struct sun4i_tcon *tcon = crtc->tcon;
        u32 val;
 
        DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
@@ -95,22 +93,16 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
        val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
        val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
        writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
-
-       sun4i_tcon_channel_disable(tcon, 1);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 {
        struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
        struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
-       struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-       struct sun4i_tcon *tcon = crtc->tcon;
        u32 val = 0;
 
        DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
-       sun4i_tcon_channel_enable(tcon, 1);
-
        sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
index 7cd7090ad63adde22826652674550beca7efc4d5..a7f297ed40c150f8a986e0064152e5843cc770d7 100644 (file)
@@ -134,13 +134,10 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
 
        DRM_DEBUG_DRIVER("Enabling RGB output\n");
 
-       if (!IS_ERR(tcon->panel))
+       if (!IS_ERR(tcon->panel)) {
                drm_panel_prepare(tcon->panel);
-
-       sun4i_tcon_channel_enable(tcon, 0);
-
-       if (!IS_ERR(tcon->panel))
                drm_panel_enable(tcon->panel);
+       }
 }
 
 static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
@@ -150,13 +147,10 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
 
        DRM_DEBUG_DRIVER("Disabling RGB output\n");
 
-       if (!IS_ERR(tcon->panel))
+       if (!IS_ERR(tcon->panel)) {
                drm_panel_disable(tcon->panel);
-
-       sun4i_tcon_channel_disable(tcon, 0);
-
-       if (!IS_ERR(tcon->panel))
                drm_panel_unprepare(tcon->panel);
+       }
 }
 
 static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
index 9b5b21ad837896c395af4f782afb65337e5b7af4..964cf22a1cedf34c8fa3fb28dbfc5960f8cb5b1b 100644 (file)
 #include "sun4i_tcon.h"
 #include "sunxi_engine.h"
 
-void sun4i_tcon_disable(struct sun4i_tcon *tcon)
+static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
+                                         bool enabled)
 {
-       DRM_DEBUG_DRIVER("Disabling TCON\n");
+       struct clk *clk;
 
-       /* Disable the TCON */
-       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-                          SUN4I_TCON_GCTL_TCON_ENABLE, 0);
-}
-EXPORT_SYMBOL(sun4i_tcon_disable);
-
-void sun4i_tcon_enable(struct sun4i_tcon *tcon)
-{
-       DRM_DEBUG_DRIVER("Enabling TCON\n");
-
-       /* Enable the TCON */
-       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
-                          SUN4I_TCON_GCTL_TCON_ENABLE,
-                          SUN4I_TCON_GCTL_TCON_ENABLE);
-}
-EXPORT_SYMBOL(sun4i_tcon_enable);
-
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
-{
-       DRM_DEBUG_DRIVER("Disabling TCON channel %d\n", channel);
-
-       /* Disable the TCON's channel */
-       if (channel == 0) {
+       switch (channel) {
+       case 0:
                regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-                                  SUN4I_TCON0_CTL_TCON_ENABLE, 0);
-               clk_disable_unprepare(tcon->dclk);
+                                  SUN4I_TCON0_CTL_TCON_ENABLE,
+                                  enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
+               clk = tcon->dclk;
+               break;
+       case 1:
+               WARN_ON(!tcon->quirks->has_channel_1);
+               regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+                                  SUN4I_TCON1_CTL_TCON_ENABLE,
+                                  enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
+               clk = tcon->sclk1;
+               break;
+       default:
+               DRM_WARN("Unknown channel... doing nothing\n");
                return;
        }
 
-       WARN_ON(!tcon->quirks->has_channel_1);
-       regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-                          SUN4I_TCON1_CTL_TCON_ENABLE, 0);
-       clk_disable_unprepare(tcon->sclk1);
+       if (enabled)
+               clk_prepare_enable(clk);
+       else
+               clk_disable_unprepare(clk);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_disable);
 
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
+void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
+                          const struct drm_encoder *encoder,
+                          bool enabled)
 {
-       DRM_DEBUG_DRIVER("Enabling TCON channel %d\n", channel);
+       int channel;
 
-       /* Enable the TCON's channel */
-       if (channel == 0) {
-               regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
-                                  SUN4I_TCON0_CTL_TCON_ENABLE,
-                                  SUN4I_TCON0_CTL_TCON_ENABLE);
-               clk_prepare_enable(tcon->dclk);
+       switch (encoder->encoder_type) {
+       case DRM_MODE_ENCODER_NONE:
+               channel = 0;
+               break;
+       case DRM_MODE_ENCODER_TMDS:
+       case DRM_MODE_ENCODER_TVDAC:
+               channel = 1;
+               break;
+       default:
+               DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
                return;
        }
 
-       WARN_ON(!tcon->quirks->has_channel_1);
-       regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
-                          SUN4I_TCON1_CTL_TCON_ENABLE,
-                          SUN4I_TCON1_CTL_TCON_ENABLE);
-       clk_prepare_enable(tcon->sclk1);
+       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+                          SUN4I_TCON_GCTL_TCON_ENABLE,
+                          enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
+
+       sun4i_tcon_channel_set_status(tcon, channel, enabled);
 }
-EXPORT_SYMBOL(sun4i_tcon_channel_enable);
 
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
 {
index d81c6e20efe6f55f2c496fced4a6f9713134a5d1..03f983927baa863f94bf19fe8f71da2a978d682d 100644 (file)
@@ -190,15 +190,9 @@ struct sun4i_tcon {
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
 struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
 
-/* Global Control */
-void sun4i_tcon_disable(struct sun4i_tcon *tcon);
-void sun4i_tcon_enable(struct sun4i_tcon *tcon);
-
-/* Channel Control */
-void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
-void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
-
 void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
+                          const struct drm_encoder *encoder, bool enable);
 
 /* Mode Related Controls */
 void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
index 050cfd43c7a0f1bad292998f0182bb539fa1bdff..2e27ff9fc58f27f50433e84f4c0bb14a4f87810f 100644 (file)
@@ -345,12 +345,9 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 {
        struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
        struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-       struct sun4i_tcon *tcon = crtc->tcon;
 
        DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
-       sun4i_tcon_channel_disable(tcon, 1);
-
        regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
                           SUN4I_TVE_EN_ENABLE,
                           0);
@@ -362,7 +359,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 {
        struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
        struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
-       struct sun4i_tcon *tcon = crtc->tcon;
 
        DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
@@ -371,8 +367,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
        regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
                           SUN4I_TVE_EN_ENABLE,
                           SUN4I_TVE_EN_ENABLE);
-
-       sun4i_tcon_channel_enable(tcon, 1);
 }
 
 static void sun4i_tv_mode_set(struct drm_encoder *encoder,