static inline void _tegra_hdmi_ddc_enable(struct tegra_hdmi *hdmi)
{
+ mutex_lock(&hdmi->ddc_refcount_lock);
if (hdmi->ddc_refcount++)
- return;
+ goto fail;
tegra_hdmi_get(hdmi->dc);
/*
* hdmi uses i2c lane muxed on dpaux1 pad.
*/
tegra_dpaux_config_pad_mode(hdmi->dc, TEGRA_DPAUX_INSTANCE_1,
TEGRA_DPAUX_PAD_MODE_I2C);
+
+fail:
+ mutex_unlock(&hdmi->ddc_refcount_lock);
}
static inline void _tegra_hdmi_ddc_disable(struct tegra_hdmi *hdmi)
{
+ mutex_lock(&hdmi->ddc_refcount_lock);
+
if (WARN_ONCE(hdmi->ddc_refcount <= 0, "ddc refcount imbalance"))
- return;
+ goto fail;
if (--hdmi->ddc_refcount != 0)
- return;
+ goto fail;
+
/*
* hdmi uses i2c lane muxed on dpaux1 pad.
* Disable dpaux1 pads.
*/
tegra_dpaux_pad_power(hdmi->dc, TEGRA_DPAUX_INSTANCE_1, false);
tegra_hdmi_put(hdmi->dc);
+
+fail:
+ mutex_unlock(&hdmi->ddc_refcount_lock);
}
static int tegra_hdmi_ddc_i2c_xfer(struct tegra_dc *dc,
goto fail_edid_free;
}
- mutex_init(&hdmi->ddc_lock);
-
return 0;
fail_edid_free:
tegra_edid_destroy(hdmi->edid);
{
int err;
- mutex_lock(&hdmi->ddc_lock);
err = tegra_hdmi_get_mon_spec(hdmi);
- mutex_unlock(&hdmi->ddc_lock);
return err;
}
hdmi->dc = dc;
dc_hdmi = hdmi;
hdmi->ddc_refcount = 0; /* assumes this is disabled when starting */
+ mutex_init(&hdmi->ddc_refcount_lock);
hdmi->nvhdcp = NULL;
hdmi->mon_spec_valid = false;
hdmi->eld_valid = false;
} else {
hdmi->enabled = false;
hdmi->clock_refcount = 0;
+ mutex_init(&hdmi->clock_refcount_lock);
}
#ifdef CONFIG_TEGRA_HDMIHDCP
static int tegra_hdmi_v2_x_config(struct tegra_hdmi *hdmi)
{
- mutex_lock(&hdmi->ddc_lock);
_tegra_hdmi_v2_x_config(hdmi);
- mutex_unlock(&hdmi->ddc_lock);
return 0;
}
if (hdmi->dc->vedid)
goto skip_scdc_i2c;
- mutex_lock(&hdmi->ddc_lock);
-
tegra_hdmi_scdc_read(hdmi, rd_tmds_config, ARRAY_SIZE(rd_tmds_config));
if (!rd_tmds_config[0][1] && (hdmi->dc->mode.pclk > 340000000)) {
dev_info(&hdmi->dc->ndev->dev, "hdmi: scdc tmds_config lost, "
_tegra_hdmi_v2_x_config(hdmi);
}
- mutex_unlock(&hdmi->ddc_lock);
-
skip_scdc_i2c:
/* reschedule the worker */
cancel_delayed_work(&hdmi->scdc_work);
{
struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
+ mutex_lock(&hdmi->clock_refcount_lock);
+
if (hdmi->clock_refcount++)
- return;
+ goto fail;
_tegra_hdmi_clock_enable(hdmi);
+
+fail:
+ mutex_unlock(&hdmi->clock_refcount_lock);
}
static void tegra_hdmi_put(struct tegra_dc *dc)
{
-
struct tegra_hdmi *hdmi = tegra_dc_get_outdata(dc);
if (WARN_ONCE(hdmi->clock_refcount <= 0,
"hdmi: clock refcount imbalance"))
- return;
+ goto fail;
if (--hdmi->clock_refcount != 0)
- return;
+ goto fail;
_tegra_hdmi_clock_disable(hdmi);
+
+fail:
+ mutex_unlock(&hdmi->clock_refcount_lock);
}
/* TODO: add support for other deep colors */