summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge/synopsys/dw-hdmi.c')
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 4e1f54a675d8..ead11242c4b9 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -173,6 +173,8 @@ struct dw_hdmi {
unsigned int reg_shift;
struct regmap *regm;
+ void (*enable_audio)(struct dw_hdmi *hdmi);
+ void (*disable_audio)(struct dw_hdmi *hdmi);
};
#define HDMI_IH_PHY_STAT0_RX_SENSE \
@@ -542,13 +544,41 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
+static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
+{
+ hdmi_modb(hdmi, enable ? 0 : HDMI_MC_CLKDIS_AUDCLK_DISABLE,
+ HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
+}
+
+static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi)
+{
+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+}
+
+static void dw_hdmi_ahb_audio_disable(struct dw_hdmi *hdmi)
+{
+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
+}
+
+static void dw_hdmi_i2s_audio_enable(struct dw_hdmi *hdmi)
+{
+ hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+ hdmi_enable_audio_clk(hdmi, true);
+}
+
+static void dw_hdmi_i2s_audio_disable(struct dw_hdmi *hdmi)
+{
+ hdmi_enable_audio_clk(hdmi, false);
+}
+
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
{
unsigned long flags;
spin_lock_irqsave(&hdmi->audio_lock, flags);
hdmi->audio_enable = true;
- hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+ if (hdmi->enable_audio)
+ hdmi->enable_audio(hdmi);
spin_unlock_irqrestore(&hdmi->audio_lock, flags);
}
EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
@@ -559,7 +589,8 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
spin_lock_irqsave(&hdmi->audio_lock, flags);
hdmi->audio_enable = false;
- hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
+ if (hdmi->disable_audio)
+ hdmi->disable_audio(hdmi);
spin_unlock_irqrestore(&hdmi->audio_lock, flags);
}
EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
@@ -1573,11 +1604,6 @@ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi)
HDMI_MC_FLOWCTRL);
}
-static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi)
-{
- hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
-}
-
/* Workaround to clear the overflow condition */
static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
{
@@ -1691,7 +1717,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
/* HDMI Initialization Step E - Configure audio */
hdmi_clk_regenerator_update_pixel_clock(hdmi);
- hdmi_enable_audio_clk(hdmi);
+ hdmi_enable_audio_clk(hdmi, true);
}
/* not for DVI mode */
@@ -1881,24 +1907,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
return ret;
}
-static enum drm_mode_status
-dw_hdmi_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct dw_hdmi *hdmi = container_of(connector,
- struct dw_hdmi, connector);
- enum drm_mode_status mode_status = MODE_OK;
-
- /* We don't support double-clocked modes */
- if (mode->flags & DRM_MODE_FLAG_DBLCLK)
- return MODE_BAD;
-
- if (hdmi->plat_data->mode_valid)
- mode_status = hdmi->plat_data->mode_valid(connector, mode);
-
- return mode_status;
-}
-
static void dw_hdmi_connector_force(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
@@ -1924,7 +1932,6 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
- .mode_valid = dw_hdmi_connector_mode_valid,
.best_encoder = drm_atomic_helper_best_encoder,
};
@@ -1947,18 +1954,22 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
return 0;
}
-static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *orig_mode,
- struct drm_display_mode *mode)
+static enum drm_mode_status
+dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode)
{
struct dw_hdmi *hdmi = bridge->driver_private;
struct drm_connector *connector = &hdmi->connector;
- enum drm_mode_status status;
+ enum drm_mode_status mode_status = MODE_OK;
- status = dw_hdmi_connector_mode_valid(connector, mode);
- if (status != MODE_OK)
- return false;
- return true;
+ /* We don't support double-clocked modes */
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+ return MODE_BAD;
+
+ if (hdmi->plat_data->mode_valid)
+ mode_status = hdmi->plat_data->mode_valid(connector, mode);
+
+ return mode_status;
}
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
@@ -2002,7 +2013,7 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.enable = dw_hdmi_bridge_enable,
.disable = dw_hdmi_bridge_disable,
.mode_set = dw_hdmi_bridge_mode_set,
- .mode_fixup = dw_hdmi_bridge_mode_fixup,
+ .mode_valid = dw_hdmi_bridge_mode_valid,
};
static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
@@ -2403,6 +2414,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
audio.irq = irq;
audio.hdmi = hdmi;
audio.eld = hdmi->connector.eld;
+ hdmi->enable_audio = dw_hdmi_ahb_audio_enable;
+ hdmi->disable_audio = dw_hdmi_ahb_audio_disable;
pdevinfo.name = "dw-hdmi-ahb-audio";
pdevinfo.data = &audio;
@@ -2415,6 +2428,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
audio.hdmi = hdmi;
audio.write = hdmi_writeb;
audio.read = hdmi_readb;
+ hdmi->enable_audio = dw_hdmi_i2s_audio_enable;
+ hdmi->disable_audio = dw_hdmi_i2s_audio_disable;
pdevinfo.name = "dw-hdmi-i2s-audio";
pdevinfo.data = &audio;