Skip to content
Snippets Groups Projects
Unverified Commit cb87894a authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno
Browse files

hdmi fixes and tests

parent d4e1f4ea
Branches
Tags
No related merge requests found
Pipeline #131360 failed
...@@ -99,25 +99,25 @@ sink_supports_format_bpc(const struct drm_connector *connector, ...@@ -99,25 +99,25 @@ sink_supports_format_bpc(const struct drm_connector *connector,
* VIC1), the bpc must be 8. * VIC1), the bpc must be 8.
*/ */
if (vic == 1 && bpc != 8) { if (vic == 1 && bpc != 8) {
drm_dbg_kms(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); drm_info(dev, "VIC1 requires a bpc of 8, got %u\n", bpc);
return false; return false;
} }
if (!info->is_hdmi && if (!info->is_hdmi &&
(format != HDMI_COLORSPACE_RGB || bpc != 8)) { (format != HDMI_COLORSPACE_RGB || bpc != 8)) {
drm_dbg_kms(dev, "DVI Monitors require an RGB output at 8 bpc\n"); drm_info(dev, "DVI Monitors require an RGB output at 8 bpc\n");
return false; return false;
} }
if (!(connector->hdmi.supported_formats & BIT(format))) { if (!(connector->hdmi.supported_formats & BIT(format))) {
drm_dbg_kms(dev, "%s format unsupported by the connector.\n", drm_info(dev, "%s format unsupported by the connector.\n",
drm_hdmi_connector_get_output_format_name(format)); drm_hdmi_connector_get_output_format_name(format));
return false; return false;
} }
switch (format) { switch (format) {
case HDMI_COLORSPACE_RGB: case HDMI_COLORSPACE_RGB:
drm_dbg_kms(dev, "RGB Format, checking the constraints.\n"); drm_info(dev, "RGB Format, checking the constraints.\n");
/* /*
* In some cases, like when the EDID readout fails, or * In some cases, like when the EDID readout fails, or
...@@ -127,38 +127,40 @@ sink_supports_format_bpc(const struct drm_connector *connector, ...@@ -127,38 +127,40 @@ sink_supports_format_bpc(const struct drm_connector *connector,
* supported so we can keep things going and light up * supported so we can keep things going and light up
* the display. * the display.
*/ */
if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) {
drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n"); drm_warn(dev, "HDMI Sink doesn't support RGB, something's wrong.\n");
return false;
}
if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) {
drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); drm_info(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
return false; return false;
} }
if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) {
drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); drm_info(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
return false; return false;
} }
drm_dbg_kms(dev, "RGB format supported in that configuration.\n"); drm_info(dev, "RGB format supported in that configuration.\n");
return true; return true;
case HDMI_COLORSPACE_YUV420: case HDMI_COLORSPACE_YUV420:
/* TODO: YUV420 is unsupported at the moment. */ /* TODO: YUV420 is unsupported at the moment. */
drm_dbg_kms(dev, "YUV420 format isn't supported yet.\n"); drm_info(dev, "YUV420 format isn't supported yet.\n");
return false; return false;
case HDMI_COLORSPACE_YUV422: case HDMI_COLORSPACE_YUV422:
drm_dbg_kms(dev, "YUV422 format, checking the constraints.\n"); drm_info(dev, "YUV422 format, checking the constraints.\n");
if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) {
drm_dbg_kms(dev, "Sink doesn't support YUV422.\n"); drm_info(dev, "Sink doesn't support YUV422.\n");
return false; return false;
} }
if (bpc > 12) { if (bpc > 12) {
drm_dbg_kms(dev, "YUV422 only supports 12 bpc or lower.\n"); drm_info(dev, "YUV422 only supports 12 bpc or lower.\n");
return false; return false;
} }
...@@ -168,34 +170,34 @@ sink_supports_format_bpc(const struct drm_connector *connector, ...@@ -168,34 +170,34 @@ sink_supports_format_bpc(const struct drm_connector *connector,
* don't need to check the Deep Color bits in the EDIDs here. * don't need to check the Deep Color bits in the EDIDs here.
*/ */
drm_dbg_kms(dev, "YUV422 format supported in that configuration.\n"); drm_info(dev, "YUV422 format supported in that configuration.\n");
return true; return true;
case HDMI_COLORSPACE_YUV444: case HDMI_COLORSPACE_YUV444:
drm_dbg_kms(dev, "YUV444 format, checking the constraints.\n"); drm_info(dev, "YUV444 format, checking the constraints.\n");
if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) {
drm_dbg_kms(dev, "Sink doesn't support YUV444.\n"); drm_info(dev, "Sink doesn't support YUV444.\n");
return false; return false;
} }
if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) {
drm_dbg_kms(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); drm_info(dev, "10 BPC but sink doesn't support Deep Color 30.\n");
return false; return false;
} }
if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) {
drm_dbg_kms(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); drm_info(dev, "12 BPC but sink doesn't support Deep Color 36.\n");
return false; return false;
} }
drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n"); drm_info(dev, "YUV444 format supported in that configuration.\n");
return true; return true;
} }
drm_dbg_kms(dev, "Unsupported pixel format.\n"); drm_info(dev, "Unsupported pixel format.\n");
return false; return false;
} }
...@@ -253,11 +255,11 @@ hdmi_try_format_bpc(const struct drm_connector *connector, ...@@ -253,11 +255,11 @@ hdmi_try_format_bpc(const struct drm_connector *connector,
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
int ret; int ret;
drm_dbg_kms(dev, "Trying %s output format\n", drm_info(dev, "Trying %s output format\n",
drm_hdmi_connector_get_output_format_name(fmt)); drm_hdmi_connector_get_output_format_name(fmt));
if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) { if (!sink_supports_format_bpc(connector, info, mode, fmt, bpc)) {
drm_dbg_kms(dev, "%s output format not supported with %u bpc\n", drm_info(dev, "%s output format not supported with %u bpc\n",
drm_hdmi_connector_get_output_format_name(fmt), drm_hdmi_connector_get_output_format_name(fmt),
bpc); bpc);
return false; return false;
...@@ -265,13 +267,13 @@ hdmi_try_format_bpc(const struct drm_connector *connector, ...@@ -265,13 +267,13 @@ hdmi_try_format_bpc(const struct drm_connector *connector,
ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt); ret = hdmi_compute_clock(connector, conn_state, mode, bpc, fmt);
if (ret) { if (ret) {
drm_dbg_kms(dev, "Couldn't compute clock for %s output format and %u bpc\n", drm_info(dev, "Couldn't compute clock for %s output format and %u bpc\n",
drm_hdmi_connector_get_output_format_name(fmt), drm_hdmi_connector_get_output_format_name(fmt),
bpc); bpc);
return false; return false;
} }
drm_dbg_kms(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n", drm_info(dev, "%s output format supported with %u (TMDS char rate: %llu Hz)\n",
drm_hdmi_connector_get_output_format_name(fmt), drm_hdmi_connector_get_output_format_name(fmt),
bpc, conn_state->hdmi.tmds_char_rate); bpc, conn_state->hdmi.tmds_char_rate);
...@@ -295,7 +297,7 @@ hdmi_compute_format(const struct drm_connector *connector, ...@@ -295,7 +297,7 @@ hdmi_compute_format(const struct drm_connector *connector,
return 0; return 0;
} }
drm_dbg_kms(dev, "Failed. No Format Supported for that bpc count.\n"); drm_info(dev, "Failed. No Format Supported for that bpc count.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -313,7 +315,7 @@ hdmi_compute_config(const struct drm_connector *connector, ...@@ -313,7 +315,7 @@ hdmi_compute_config(const struct drm_connector *connector,
int ret; int ret;
for (bpc = max_bpc; bpc >= 8; bpc -= 2) { for (bpc = max_bpc; bpc >= 8; bpc -= 2) {
drm_dbg_kms(dev, "Trying with a %d bpc output\n", bpc); drm_info(dev, "Trying with a %d bpc output\n", bpc);
ret = hdmi_compute_format(connector, conn_state, mode, bpc); ret = hdmi_compute_format(connector, conn_state, mode, bpc);
if (ret) if (ret)
...@@ -321,7 +323,7 @@ hdmi_compute_config(const struct drm_connector *connector, ...@@ -321,7 +323,7 @@ hdmi_compute_config(const struct drm_connector *connector,
conn_state->hdmi.output_bpc = bpc; conn_state->hdmi.output_bpc = bpc;
drm_dbg_kms(dev, drm_info(dev,
"Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n",
mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode),
conn_state->hdmi.output_bpc, conn_state->hdmi.output_bpc,
...@@ -561,16 +563,16 @@ static int clear_device_infoframe(struct drm_connector *connector, ...@@ -561,16 +563,16 @@ static int clear_device_infoframe(struct drm_connector *connector,
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
int ret; int ret;
drm_dbg_kms(dev, "Clearing infoframe type 0x%x\n", type); drm_info(dev, "Clearing infoframe type 0x%x\n", type);
if (!funcs || !funcs->clear_infoframe) { if (!funcs || !funcs->clear_infoframe) {
drm_dbg_kms(dev, "Function not implemented, bailing.\n"); drm_info(dev, "Function not implemented, bailing.\n");
return 0; return 0;
} }
ret = funcs->clear_infoframe(connector, type); ret = funcs->clear_infoframe(connector, type);
if (ret) { if (ret) {
drm_dbg_kms(dev, "Call failed: %d\n", ret); drm_info(dev, "Call failed: %d\n", ret);
return ret; return ret;
} }
...@@ -598,10 +600,10 @@ static int write_device_infoframe(struct drm_connector *connector, ...@@ -598,10 +600,10 @@ static int write_device_infoframe(struct drm_connector *connector,
int ret; int ret;
int len; int len;
drm_dbg_kms(dev, "Writing infoframe type %x\n", frame->any.type); drm_info(dev, "Writing infoframe type %x\n", frame->any.type);
if (!funcs || !funcs->write_infoframe) { if (!funcs || !funcs->write_infoframe) {
drm_dbg_kms(dev, "Function not implemented, bailing.\n"); drm_info(dev, "Function not implemented, bailing.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -611,7 +613,7 @@ static int write_device_infoframe(struct drm_connector *connector, ...@@ -611,7 +613,7 @@ static int write_device_infoframe(struct drm_connector *connector,
ret = funcs->write_infoframe(connector, frame->any.type, buffer, len); ret = funcs->write_infoframe(connector, frame->any.type, buffer, len);
if (ret) { if (ret) {
drm_dbg_kms(dev, "Call failed: %d\n", ret); drm_info(dev, "Call failed: %d\n", ret);
return ret; return ret;
} }
......
...@@ -422,6 +422,8 @@ struct mtk_hdmi *mtk_hdmi_common_probe(struct platform_device *pdev) ...@@ -422,6 +422,8 @@ struct mtk_hdmi *mtk_hdmi_common_probe(struct platform_device *pdev)
hdmi->bridge.product = "On-Chip HDMI"; hdmi->bridge.product = "On-Chip HDMI";
hdmi->bridge.interlace_allowed = ver_conf->interlace_allowed; hdmi->bridge.interlace_allowed = ver_conf->interlace_allowed;
hdmi->bridge.supported_formats = BIT(HDMI_COLORSPACE_RGB) | BIT(HDMI_COLORSPACE_YUV444);
ret = devm_drm_bridge_add(dev, &hdmi->bridge); ret = devm_drm_bridge_add(dev, &hdmi->bridge);
if (ret) if (ret)
return dev_err_ptr_probe(dev, ret, "Failed to add bridge\n"); return dev_err_ptr_probe(dev, ret, "Failed to add bridge\n");
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <drm/display/drm_hdmi_helper.h> #include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_hdmi_state_helper.h> #include <drm/display/drm_hdmi_state_helper.h>
#include <drm/display/drm_scdc_helper.h> #include <drm/display/drm_scdc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
...@@ -259,22 +260,21 @@ static int mtk_hdmi_v2_setup_audio_infoframe(struct mtk_hdmi *hdmi) ...@@ -259,22 +260,21 @@ static int mtk_hdmi_v2_setup_audio_infoframe(struct mtk_hdmi *hdmi)
return 0; return 0;
} }
static inline void mtk_hdmi_v2_hw_reset_av_mute_regs(struct mtk_hdmi *hdmi)
{
/* GCP packet */
regmap_clear_bits(hdmi->regs, TOP_CFG01, CP_CLR_MUTE_EN | CP_SET_MUTE_EN);
regmap_clear_bits(hdmi->regs, TOP_INFO_RPT, CP_RPT_EN);
regmap_clear_bits(hdmi->regs, TOP_INFO_EN, CP_EN | CP_EN_WR);
}
static inline void mtk_hdmi_v2_hw_gcp_avmute(struct mtk_hdmi *hdmi, bool mute) static inline void mtk_hdmi_v2_hw_gcp_avmute(struct mtk_hdmi *hdmi, bool mute)
{ {
mtk_hdmi_v2_hw_reset_av_mute_regs(hdmi); u32 val;
if (mute) regmap_read(hdmi->regs, TOP_CFG01, &val);
regmap_set_bits(hdmi->regs, TOP_CFG01, CP_SET_MUTE_EN); val &= ~(CP_CLR_MUTE_EN | CP_SET_MUTE_EN);
else
regmap_set_bits(hdmi->regs, TOP_CFG01, CP_CLR_MUTE_EN); if (mute) {
val |= CP_SET_MUTE_EN;
val &= ~CP_CLR_MUTE_EN;
} else {
val |= CP_CLR_MUTE_EN;
val &= ~CP_SET_MUTE_EN;
}
regmap_write(hdmi->regs, TOP_CFG01, val);
regmap_set_bits(hdmi->regs, TOP_INFO_RPT, CP_RPT_EN); regmap_set_bits(hdmi->regs, TOP_INFO_RPT, CP_RPT_EN);
regmap_set_bits(hdmi->regs, TOP_INFO_EN, CP_EN | CP_EN_WR); regmap_set_bits(hdmi->regs, TOP_INFO_EN, CP_EN | CP_EN_WR);
...@@ -686,7 +686,10 @@ static void mtk_hdmi_v2_change_video_resolution(struct mtk_hdmi *hdmi) ...@@ -686,7 +686,10 @@ static void mtk_hdmi_v2_change_video_resolution(struct mtk_hdmi *hdmi)
regmap_write(hdmi->regs, HDCP_TOP_CTRL, 0); regmap_write(hdmi->regs, HDCP_TOP_CTRL, 0);
/* Enable HDCP reauthentication interrupt */ /*
* Enable HDCP reauthentication interrupt: the HW uses this internally
* for the HPD state machine even if HDCP encryption is not enabled.
*/
regmap_set_bits(hdmi->regs, TOP_INT_ENABLE00, HDCP2X_RX_REAUTH_REQ_DDCM_INT); regmap_set_bits(hdmi->regs, TOP_INT_ENABLE00, HDCP2X_RX_REAUTH_REQ_DDCM_INT);
/* Enable hotplug and pord interrupts */ /* Enable hotplug and pord interrupts */
...@@ -781,14 +784,32 @@ static void mtk_hdmi_v2_clk_disable(struct mtk_hdmi *hdmi) ...@@ -781,14 +784,32 @@ static void mtk_hdmi_v2_clk_disable(struct mtk_hdmi *hdmi)
clk_disable_unprepare(hdmi->clk[MTK_HDMI_V2_CLK_HDCP_SEL]); clk_disable_unprepare(hdmi->clk[MTK_HDMI_V2_CLK_HDCP_SEL]);
} }
static void mtk_hdmi_hpd_event(enum hdmi_hpd_state hpd, struct device *dev) static int mtk_hdmi_v2_reset_link(struct drm_bridge *bridge)
{ {
struct mtk_hdmi *hdmi = dev_get_drvdata(dev); struct drm_encoder *encoder = bridge->encoder;
struct drm_crtc *crtc = encoder->crtc;
struct drm_device *dev = encoder->dev;
struct drm_modeset_acquire_ctx ctx;
int ret;
if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev) /* No crtc attached means no outputs to reset, don't do anything! */
drm_helper_hpd_irq_event(hdmi->bridge.encoder->dev); if (!crtc) {
pr_err("NO CRTC NO RESET :-)\n");
return 0;
} }
pr_err("HDMI RESET LINK\n");
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
ret = drm_atomic_helper_reset_crtc(crtc, &ctx);
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
return ret;
}
static enum hdmi_hpd_state mtk_hdmi_v2_hpd_pord_status(struct mtk_hdmi *hdmi) static enum hdmi_hpd_state mtk_hdmi_v2_hpd_pord_status(struct mtk_hdmi *hdmi)
{ {
u8 hpd_pin_sta, pord_pin_sta; u8 hpd_pin_sta, pord_pin_sta;
...@@ -798,6 +819,21 @@ static enum hdmi_hpd_state mtk_hdmi_v2_hpd_pord_status(struct mtk_hdmi *hdmi) ...@@ -798,6 +819,21 @@ static enum hdmi_hpd_state mtk_hdmi_v2_hpd_pord_status(struct mtk_hdmi *hdmi)
hpd_pin_sta = FIELD_GET(HPD_PIN_STA, hpd_status); hpd_pin_sta = FIELD_GET(HPD_PIN_STA, hpd_status);
pord_pin_sta = FIELD_GET(PORD_PIN_STA, hpd_status); pord_pin_sta = FIELD_GET(PORD_PIN_STA, hpd_status);
/*
* Inform that the cable is plugged in (hpd_pin_sta) so that the
* sink can be powered on by switching the 5V VBUS as required by
* the HDMI spec for reading EDID and for HDMI Audio registers to
* be accessible.
*
* PORD detection succeeds only when the cable is plugged in and
* the sink is powered on: reaching that state means that the
* communication with the sink can be started.
*
* Please note that when the cable is plugged out the HPD pin will
* be the first one to fall, while PORD may still be in rise state
* for a few more milliseconds, so we decide HDMI_PLUG_OUT without
* checking PORD at all (we check only HPD falling for that).
*/
if (hpd_pin_sta && pord_pin_sta) if (hpd_pin_sta && pord_pin_sta)
return HDMI_PLUG_IN_AND_SINK_POWER_ON; return HDMI_PLUG_IN_AND_SINK_POWER_ON;
else if (hpd_pin_sta) else if (hpd_pin_sta)
...@@ -814,22 +850,19 @@ static irqreturn_t mtk_hdmi_v2_isr(int irq, void *arg) ...@@ -814,22 +850,19 @@ static irqreturn_t mtk_hdmi_v2_isr(int irq, void *arg)
regmap_read(hdmi->regs, TOP_INT_STA00, &irq_sta); regmap_read(hdmi->regs, TOP_INT_STA00, &irq_sta);
/* Handle Hotplug Detection interrupt */ /* Handle Hotplug Detection interrupts */
if (irq_sta & (HTPLG_R_INT | HTPLG_F_INT | PORD_F_INT | PORD_R_INT)) { if (irq_sta & HPD_PORD_HWIRQS) {
mtk_hdmi_v2_enable_hpd_pord_irq(hdmi, false);
ret = IRQ_WAKE_THREAD;
}
/* /*
* Clear all 32 + 19 interrupts in CLR00 and CLR01: this is important * Disable the HPD/PORD IRQs now and until thread done to
* to avoid unwanted retriggering of any interrupts * avoid interrupt storm that could happen with bad cables
*/ */
regmap_write(hdmi->regs, TOP_INT_CLR00, GENMASK(31, 0)); mtk_hdmi_v2_enable_hpd_pord_irq(hdmi, false);
regmap_write(hdmi->regs, TOP_INT_CLR01, GENMASK(18, 0)); ret = IRQ_WAKE_THREAD;
/* Restore interrupt clearing registers to zero */ /* Clear HPD/PORD irqs to avoid unwanted retriggering */
regmap_write(hdmi->regs, TOP_INT_CLR00, 0); regmap_write(hdmi->regs, TOP_INT_CLR00, HPD_PORD_HWIRQS);
regmap_write(hdmi->regs, TOP_INT_CLR01, 0); regmap_write(hdmi->regs, TOP_INT_CLR00, 0);;
}
return ret; return ret;
} }
...@@ -840,8 +873,12 @@ static irqreturn_t __mtk_hdmi_v2_isr_thread(struct mtk_hdmi *hdmi) ...@@ -840,8 +873,12 @@ static irqreturn_t __mtk_hdmi_v2_isr_thread(struct mtk_hdmi *hdmi)
hpd = mtk_hdmi_v2_hpd_pord_status(hdmi); hpd = mtk_hdmi_v2_hpd_pord_status(hdmi);
if (hpd != hdmi->hpd) { if (hpd != hdmi->hpd) {
struct drm_encoder *encoder = hdmi->bridge.encoder;
hdmi->hpd = hpd; hdmi->hpd = hpd;
mtk_hdmi_hpd_event(hpd, hdmi->dev);
if (encoder && encoder->dev)
drm_helper_hpd_irq_event(hdmi->bridge.encoder->dev);
} }
mtk_hdmi_v2_enable_hpd_pord_irq(hdmi, true); mtk_hdmi_v2_enable_hpd_pord_irq(hdmi, true);
...@@ -1049,10 +1086,38 @@ static void mtk_hdmi_v2_bridge_post_disable(struct drm_bridge *bridge, ...@@ -1049,10 +1086,38 @@ static void mtk_hdmi_v2_bridge_post_disable(struct drm_bridge *bridge,
mtk_hdmi_v2_disable(hdmi); mtk_hdmi_v2_disable(hdmi);
} }
static void mtk_hdmi_v2_hpd_notify(struct drm_bridge *bridge,
enum drm_connector_status status)
{
//struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
// if (status == connector_status_connected)
// mtk_hdmi_v2_reset_link(bridge);
return;
}
static enum drm_connector_status mtk_hdmi_v2_bridge_detect(struct drm_bridge *bridge) static enum drm_connector_status mtk_hdmi_v2_bridge_detect(struct drm_bridge *bridge)
{ {
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
switch (hdmi->hpd) {
default:
case HDMI_PLUG_IN_ONLY:
pr_err("UNKNOWN CONNECTOR STATUS\n");
//return connector_status_unknown;
return connector_status_disconnected;
case HDMI_PLUG_OUT:
pr_err("PLUGOUT CONNECTOR STATUS\n");
return connector_status_disconnected;
case HDMI_PLUG_IN_AND_SINK_POWER_ON:
pr_err("PLUGIN SINK POWERON CONNECTOR STATUS\n");
return connector_status_connected;
}
return hdmi->hpd != HDMI_PLUG_OUT ? return hdmi->hpd != HDMI_PLUG_OUT ?
connector_status_connected : connector_status_disconnected; connector_status_connected : connector_status_disconnected;
} }
...@@ -1293,6 +1358,7 @@ static const struct drm_bridge_funcs mtk_v2_hdmi_bridge_funcs = { ...@@ -1293,6 +1358,7 @@ static const struct drm_bridge_funcs mtk_v2_hdmi_bridge_funcs = {
.edid_read = mtk_hdmi_v2_bridge_edid_read, .edid_read = mtk_hdmi_v2_bridge_edid_read,
.hpd_enable = mtk_hdmi_v2_hpd_enable, .hpd_enable = mtk_hdmi_v2_hpd_enable,
.hpd_disable = mtk_hdmi_v2_hpd_disable, .hpd_disable = mtk_hdmi_v2_hpd_disable,
.hpd_notify = mtk_hdmi_v2_hpd_notify,
.hdmi_tmds_char_rate_valid = mtk_hdmi_v2_hdmi_tmds_char_rate_valid, .hdmi_tmds_char_rate_valid = mtk_hdmi_v2_hdmi_tmds_char_rate_valid,
.hdmi_clear_infoframe = mtk_hdmi_v2_hdmi_clear_infoframe, .hdmi_clear_infoframe = mtk_hdmi_v2_hdmi_clear_infoframe,
.hdmi_write_infoframe = mtk_hdmi_v2_hdmi_write_infoframe, .hdmi_write_infoframe = mtk_hdmi_v2_hdmi_write_infoframe,
...@@ -1420,13 +1486,26 @@ static int mtk_hdmi_v2_probe(struct platform_device *pdev) ...@@ -1420,13 +1486,26 @@ static int mtk_hdmi_v2_probe(struct platform_device *pdev)
hdmi->hpd = HDMI_PLUG_OUT; hdmi->hpd = HDMI_PLUG_OUT;
/* Disable all HW interrupts at probe stage */
mtk_hdmi_v2_hwirq_disable(hdmi);
/* /*
* Disable all HW interrupts at probe stage and install the ISR * In case bootloader leaves HDMI enabled before booting, make
* but keep it disabled, as the rest of the interrupts setup is * sure that any interrupt that was left is cleared by setting
* done in the .bridge_attach() callback, which will enable both * all bits in the INT_CLR registers for all 32+19 interrupts.
* the right HW IRQs and the ISR. */
regmap_write(hdmi->regs, TOP_INT_CLR00, GENMASK(31, 0));
regmap_write(hdmi->regs, TOP_INT_CLR01, GENMASK(18, 0));
/* Restore interrupt clearing registers to zero */
regmap_write(hdmi->regs, TOP_INT_CLR00, 0);
regmap_write(hdmi->regs, TOP_INT_CLR01, 0);
/*
* Install the ISR but keep it disabled: as the interrupts are
* being set up in the .bridge_attach() callback which will
* enable both the right HW IRQs and the ISR.
*/ */
mtk_hdmi_v2_hwirq_disable(hdmi);
irq_set_status_flags(hdmi->irq, IRQ_NOAUTOEN); irq_set_status_flags(hdmi->irq, IRQ_NOAUTOEN);
ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq, mtk_hdmi_v2_isr, ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq, mtk_hdmi_v2_isr,
mtk_hdmi_v2_isr_thread, mtk_hdmi_v2_isr_thread,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment