summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_crtc.c22
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c8
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_rgb.c14
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c87
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.h10
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tv.c6
6 files changed, 67 insertions, 80 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index d097c6f93ad0..e86baa3746af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -30,6 +30,22 @@
#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 = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 6ca6e6a74c4a..482bf03d55c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -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);
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 7cd7090ad63a..a7f297ed40c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -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,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9b5b21ad8378..964cf22a1ced 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,66 +35,61 @@
#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)
{
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d81c6e20efe6..03f983927baa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -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,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 050cfd43c7a0..2e27ff9fc58f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -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,