From: Hans Verkuil hans.verkuil@cisco.com
This patch series adds CEC support for the omap4. It is based on the 4.13-rc2 kernel with this patch series applied:
http://www.spinics.net/lists/dri-devel/msg143440.html
It is virtually identical to the first patch series posted in April:
http://www.spinics.net/lists/dri-devel/msg138950.html
The only two changes are in the Kconfig due to CEC Kconfig changes in 4.13 (it now selects CEC_CORE instead of depending on CEC_CORE) and a final patch was added adding a lost_hotplug op since for proper CEC support I have to know when the hotplug signal goes away.
Tested with my Pandaboard.
The lost_hotplug op is called only when the hotplug is lost, but I am happy to change it to an op that is called whenever the hotplug signal changes. Just let me know. I just implemented the minimal solution that I needed.
Regards,
Hans
Hans Verkuil (9): omapdrm: encoder-tpd12s015: keep ls_oe_gpio high omapdrm: hdmi.h: extend hdmi_core_data with CEC fields omapdrm: hdmi4: make low-level functions available omapdrm: hdmi4: prepare irq handling for HDMI CEC support omapdrm: hdmi4: move hdmi4_core_powerdown_disable to hdmi_power_on_core() omapdrm: hdmi4: refcount hdmi_power_on/off_core omapdrm: hdmi4_cec: add OMAP4 HDMI CEC support omapdrm: hdmi4: hook up the HDMI CEC support omapdrm: omapdss_hdmi_ops: add lost_hotplug op
drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 8 +- .../gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 18 +- drivers/gpu/drm/omapdrm/dss/Kconfig | 8 + drivers/gpu/drm/omapdrm/dss/Makefile | 1 + drivers/gpu/drm/omapdrm/dss/hdmi.h | 6 +- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 62 +++- drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c | 381 +++++++++++++++++++++ drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h | 55 +++ drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 7 +- drivers/gpu/drm/omapdrm/dss/hdmi4_core.h | 4 + drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 + 11 files changed, 521 insertions(+), 30 deletions(-) create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
From: Hans Verkuil hans.verkuil@cisco.com
For OMAP4 CEC support the CEC pin should always be on. So keep ls_oe_gpio high all the time in order to support CEC.
Background: even if the HPD is low it should still be possible to use CEC. Some displays will set the HPD low when they go into standby or when they switch to another input, but CEC is still available and able to wake up/change input for such a display.
This is explicitly allowed by the CEC standard.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index a9e9d667c55e..293b8fd07cfc 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -51,6 +51,8 @@ static int tpd_connect(struct omap_dss_device *dssdev, dssdev->dst = dst;
gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); + /* DC-DC converter needs at max 300us to get to 90% of 5V */ udelay(300);
@@ -69,6 +71,7 @@ static void tpd_disconnect(struct omap_dss_device *dssdev, return;
gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0);
dst->src = NULL; dssdev->dst = NULL; @@ -146,18 +149,11 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - int r;
if (!gpiod_get_value_cansleep(ddata->hpd_gpio)) return -ENODEV;
- gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); - - r = in->ops.hdmi->read_edid(in, edid, len); - - gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0); - - return r; + return in->ops.hdmi->read_edid(in, edid, len); }
static bool tpd_detect(struct omap_dss_device *dssdev)
From: Hans Verkuil hans.verkuil@cisco.com
Extend the hdmi_core_data struct with the additional fields needed for CEC.
Also fix a simple typo in a comment.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h index fb6cccd02374..3913859146b9 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/hdmi.h> #include <sound/omap-hdmi-audio.h> +#include <media/cec.h>
#include "omapdss.h" #include "dss.h" @@ -254,6 +255,9 @@ struct hdmi_phy_data {
struct hdmi_core_data { void __iomem *base; + struct hdmi_wp_data *wp; + unsigned int core_pwr_cnt; + struct cec_adapter *adap; };
static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx, @@ -361,7 +365,7 @@ struct omap_hdmi { bool audio_configured; struct omap_dss_audio audio_config;
- /* This lock should be taken when booleans bellow are touched. */ + /* This lock should be taken when booleans below are touched. */ spinlock_t audio_playing_lock; bool audio_playing; bool display_enabled;
From: Hans Verkuil hans.verkuil@cisco.com
Three low-level functions in hdmi4.c and hdmi4_core.c are made available for use by the OMAP4 CEC support.
Renamed the prefix to hdmi4 since these are OMAP4 specific.
These function deal with the HDMI core and are needed to power it up for use with CEC, even when the HPD is low.
Background: even if the HPD is low it should still be possible to use CEC. Some displays will set the HPD low when they go into standby or when they switch to another input, but CEC is still available and able to wake up/change input for such a display.
This is explicitly allowed by the CEC standard.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 12 ++++++------ drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 6 +++--- drivers/gpu/drm/omapdrm/dss/hdmi4_core.h | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 284b4942b9ac..99af926ca0f5 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -394,11 +394,11 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev) mutex_unlock(&hdmi.lock); }
-static int hdmi_core_enable(struct omap_dss_device *dssdev) +int hdmi4_core_enable(struct omap_dss_device *dssdev) { int r = 0;
- DSSDBG("ENTER omapdss_hdmi_core_enable\n"); + DSSDBG("ENTER omapdss_hdmi4_core_enable\n");
mutex_lock(&hdmi.lock);
@@ -416,9 +416,9 @@ static int hdmi_core_enable(struct omap_dss_device *dssdev) return r; }
-static void hdmi_core_disable(struct omap_dss_device *dssdev) +void hdmi4_core_disable(struct omap_dss_device *dssdev) { - DSSDBG("Enter omapdss_hdmi_core_disable\n"); + DSSDBG("Enter omapdss_hdmi4_core_disable\n");
mutex_lock(&hdmi.lock);
@@ -476,7 +476,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, need_enable = hdmi.core_enabled == false;
if (need_enable) { - r = hdmi_core_enable(dssdev); + r = hdmi4_core_enable(dssdev); if (r) return r; } @@ -484,7 +484,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, r = read_edid(edid, len);
if (need_enable) - hdmi_core_disable(dssdev); + hdmi4_core_disable(dssdev);
return r; } diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index ed6001613405..b91244378ed1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -208,9 +208,9 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg) video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; }
-static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) +void hdmi4_core_powerdown_disable(struct hdmi_core_data *core) { - DSSDBG("Enter hdmi_core_powerdown_disable\n"); + DSSDBG("Enter hdmi4_core_powerdown_disable\n"); REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0); }
@@ -336,7 +336,7 @@ void hdmi4_configure(struct hdmi_core_data *core, hdmi_core_swreset_assert(core);
/* power down off */ - hdmi_core_powerdown_disable(core); + hdmi4_core_powerdown_disable(core);
v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; v_core_cfg.hdmi_dvi = cfg->hdmi_dvi_mode; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h index a069f96ec6f6..b6ab579e44d2 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h @@ -266,6 +266,10 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
+int hdmi4_core_enable(struct omap_dss_device *dssdev); +void hdmi4_core_disable(struct omap_dss_device *dssdev); +void hdmi4_core_powerdown_disable(struct hdmi_core_data *core); + int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
From: Hans Verkuil hans.verkuil@cisco.com
Pass struct omap_hdmi to the irq handler since it will need access to hdmi.core.
Do not clear the IRQ_HDMI_CORE bit: that will be controlled by the HDMI CEC code.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 99af926ca0f5..eb9c6636f660 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -71,7 +71,8 @@ static void hdmi_runtime_put(void)
static irqreturn_t hdmi_irq_handler(int irq, void *data) { - struct hdmi_wp_data *wp = data; + struct omap_hdmi *hdmi = data; + struct hdmi_wp_data *wp = &hdmi->wp; u32 irqstatus;
irqstatus = hdmi_wp_get_irqstatus(wp); @@ -167,8 +168,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) return r;
/* disable and clear irqs */ - hdmi_wp_clear_irqenable(wp, 0xffffffff); - hdmi_wp_set_irqstatus(wp, 0xffffffff); + hdmi_wp_clear_irqenable(wp, ~HDMI_IRQ_CORE); + hdmi_wp_set_irqstatus(wp, ~HDMI_IRQ_CORE);
vm = &hdmi.cfg.vm;
@@ -243,7 +244,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) { enum omap_channel channel = dssdev->dispc_channel;
- hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); + hdmi_wp_clear_irqenable(&hdmi.wp, ~HDMI_IRQ_CORE);
hdmi_wp_video_stop(&hdmi.wp);
@@ -725,7 +726,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
r = devm_request_threaded_irq(&pdev->dev, irq, NULL, hdmi_irq_handler, - IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); + IRQF_ONESHOT, "OMAP HDMI", &hdmi); if (r) { DSSERR("HDMI IRQ request failed\n"); goto err;
From: Hans Verkuil hansverk@cisco.com
Call hdmi4_core_powerdown_disable() in hdmi_power_on_core() to power up the HDMI core (needed for CEC). The same call can now be dropped in hdmi4_configure().
Signed-off-by: Hans Verkuil hansverk@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 2 ++ drivers/gpu/drm/omapdrm/dss/hdmi4_core.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index eb9c6636f660..bf91cbef78c1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -133,6 +133,8 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev) if (r) goto err_runtime_get;
+ hdmi4_core_powerdown_disable(&hdmi.core); + /* Make selection of HDMI in DSS */ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index b91244378ed1..ca3f2cf773d1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -335,9 +335,6 @@ void hdmi4_configure(struct hdmi_core_data *core, */ hdmi_core_swreset_assert(core);
- /* power down off */ - hdmi4_core_powerdown_disable(core); - v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; v_core_cfg.hdmi_dvi = cfg->hdmi_dvi_mode;
From: Hans Verkuil hans.verkuil@cisco.com
The hdmi_power_on/off_core functions can be called multiple times: when the HPD changes and when the HDMI CEC support needs to power the HDMI core.
So use a counter to know when to really power on or off the HDMI core.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index bf91cbef78c1..166aa4df7688 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -125,9 +125,12 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev) { int r;
+ if (hdmi.core.core_pwr_cnt++) + return 0; + r = regulator_enable(hdmi.vdda_reg); if (r) - return r; + goto err_reg_enable;
r = hdmi_runtime_get(); if (r) @@ -144,12 +147,17 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
err_runtime_get: regulator_disable(hdmi.vdda_reg); +err_reg_enable: + hdmi.core.core_pwr_cnt--;
return r; }
static void hdmi_power_off_core(struct omap_dss_device *dssdev) { + if (--hdmi.core.core_pwr_cnt) + return; + hdmi.core_enabled = false;
hdmi_runtime_put();
From: Hans Verkuil hans.verkuil@cisco.com
Add the source and header for the OMAP4 HDMI CEC support.
This code is not yet hooked up, that will happen in the next patch.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c | 381 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h | 55 +++++ 2 files changed, 436 insertions(+) create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c create mode 100644 drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c new file mode 100644 index 000000000000..d86873f2abe6 --- /dev/null +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c @@ -0,0 +1,381 @@ +/* + * HDMI CEC + * + * Based on the CEC code from hdmi_ti_4xxx_ip.c from Android. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Yong Zhi + * Mythri pk mythripk@ti.com + * + * Heavily modified to use the linux CEC framework: + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "dss.h" +#include "hdmi.h" +#include "hdmi4_core.h" +#include "hdmi4_cec.h" + +/* HDMI CEC */ +#define HDMI_CEC_DEV_ID 0x900 +#define HDMI_CEC_SPEC 0x904 + +/* Not really a debug register, more a low-level control register */ +#define HDMI_CEC_DBG_3 0x91C +#define HDMI_CEC_TX_INIT 0x920 +#define HDMI_CEC_TX_DEST 0x924 +#define HDMI_CEC_SETUP 0x938 +#define HDMI_CEC_TX_COMMAND 0x93C +#define HDMI_CEC_TX_OPERAND 0x940 +#define HDMI_CEC_TRANSMIT_DATA 0x97C +#define HDMI_CEC_CA_7_0 0x988 +#define HDMI_CEC_CA_15_8 0x98C +#define HDMI_CEC_INT_STATUS_0 0x998 +#define HDMI_CEC_INT_STATUS_1 0x99C +#define HDMI_CEC_INT_ENABLE_0 0x990 +#define HDMI_CEC_INT_ENABLE_1 0x994 +#define HDMI_CEC_RX_CONTROL 0x9B0 +#define HDMI_CEC_RX_COUNT 0x9B4 +#define HDMI_CEC_RX_CMD_HEADER 0x9B8 +#define HDMI_CEC_RX_COMMAND 0x9BC +#define HDMI_CEC_RX_OPERAND 0x9C0 + +#define HDMI_CEC_TX_FIFO_INT_MASK 0x64 +#define HDMI_CEC_RETRANSMIT_CNT_INT_MASK 0x2 + +#define HDMI_CORE_CEC_RETRY 200 + +static void hdmi_cec_received_msg(struct hdmi_core_data *core) +{ + u32 cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff; + + /* While there are CEC frames in the FIFO */ + while (cnt & 0x70) { + /* and the frame doesn't have an error */ + if (!(cnt & 0x80)) { + struct cec_msg msg = {}; + unsigned int i; + + /* then read the message */ + msg.len = cnt & 0xf; + msg.msg[0] = hdmi_read_reg(core->base, + HDMI_CEC_RX_CMD_HEADER); + msg.msg[1] = hdmi_read_reg(core->base, + HDMI_CEC_RX_COMMAND); + for (i = 0; i < msg.len; i++) { + unsigned int reg = HDMI_CEC_RX_OPERAND + i * 4; + + msg.msg[2 + i] = + hdmi_read_reg(core->base, reg); + } + msg.len += 2; + cec_received_msg(core->adap, &msg); + } + /* Clear the current frame from the FIFO */ + hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 1); + /* Wait until the current frame is cleared */ + while (hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL) & 1) + udelay(1); + /* + * Re-read the count register and loop to see if there are + * more messages in the FIFO. + */ + cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff; + } +} + +static void hdmi_cec_transmit_fifo_empty(struct hdmi_core_data *core, u32 stat1) +{ + if (stat1 & 2) { + u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + + cec_transmit_done(core->adap, + CEC_TX_STATUS_NACK | + CEC_TX_STATUS_MAX_RETRIES, + 0, (dbg3 >> 4) & 7, 0, 0); + } else if (stat1 & 1) { + cec_transmit_done(core->adap, + CEC_TX_STATUS_ARB_LOST | + CEC_TX_STATUS_MAX_RETRIES, + 0, 0, 0, 0); + } else if (stat1 == 0) { + cec_transmit_done(core->adap, CEC_TX_STATUS_OK, + 0, 0, 0, 0); + } +} + +void hdmi4_cec_irq(struct hdmi_core_data *core) +{ + u32 stat0 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0); + u32 stat1 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1); + + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, stat0); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, stat1); + + if (stat0 & 0x40) + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); + else if (stat0 & 0x24) + hdmi_cec_transmit_fifo_empty(core, stat1); + if (stat1 & 2) { + u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + + cec_transmit_done(core->adap, + CEC_TX_STATUS_NACK | + CEC_TX_STATUS_MAX_RETRIES, + 0, (dbg3 >> 4) & 7, 0, 0); + } else if (stat1 & 1) { + cec_transmit_done(core->adap, + CEC_TX_STATUS_ARB_LOST | + CEC_TX_STATUS_MAX_RETRIES, + 0, 0, 0, 0); + } + if (stat0 & 0x02) + hdmi_cec_received_msg(core); + if (stat1 & 0x3) + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); +} + +static bool hdmi_cec_clear_tx_fifo(struct cec_adapter *adap) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int retry = HDMI_CORE_CEC_RETRY; + int temp; + + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); + while (retry) { + temp = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + if (FLD_GET(temp, 7, 7) == 0) + break; + retry--; + } + return retry != 0; +} + +static bool hdmi_cec_clear_rx_fifo(struct cec_adapter *adap) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int retry = HDMI_CORE_CEC_RETRY; + int temp; + + hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 0x3); + retry = HDMI_CORE_CEC_RETRY; + while (retry) { + temp = hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL); + if (FLD_GET(temp, 1, 0) == 0) + break; + retry--; + } + return retry != 0; +} + +static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int temp, err; + + if (!enable) { + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0); + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0); + REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3); + hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE); + hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE); + hdmi4_core_disable(NULL); + return 0; + } + err = hdmi4_core_enable(NULL); + if (err) + return err; + + /* Clear TX FIFO */ + if (!hdmi_cec_clear_tx_fifo(adap)) { + pr_err("cec-%s: could not clear TX FIFO\n", adap->name); + return -EIO; + } + + /* Clear RX FIFO */ + if (!hdmi_cec_clear_rx_fifo(adap)) { + pr_err("cec-%s: could not clear RX FIFO\n", adap->name); + return -EIO; + } + + /* Clear CEC interrupts */ + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, + hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1)); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, + hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0)); + + /* Enable HDMI core interrupts */ + hdmi_wp_set_irqenable(core->wp, HDMI_IRQ_CORE); + /* Unmask CEC interrupt */ + REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0x1, 3, 3); + /* + * Enable CEC interrupts: + * Transmit Buffer Full/Empty Change event + * Transmitter FIFO Empty event + * Receiver FIFO Not Empty event + */ + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0x26); + /* + * Enable CEC interrupts: + * RX FIFO Overrun Error event + * Short Pulse Detected event + * Frame Retransmit Count Exceeded event + * Start Bit Irregularity event + */ + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0x0f); + + /* cec calibration enable (self clearing) */ + hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x03); + msleep(20); + hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x04); + + temp = hdmi_read_reg(core->base, HDMI_CEC_SETUP); + if (FLD_GET(temp, 4, 4) != 0) { + temp = FLD_MOD(temp, 0, 4, 4); + hdmi_write_reg(core->base, HDMI_CEC_SETUP, temp); + + /* + * If we enabled CEC in middle of a CEC message on the bus, + * we could have start bit irregularity and/or short + * pulse event. Clear them now. + */ + temp = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1); + temp = FLD_MOD(0x0, 0x5, 2, 0); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp); + } + return 0; +} + +static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + u32 v; + + if (log_addr == CEC_LOG_ADDR_INVALID) { + hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, 0); + hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, 0); + return 0; + } + if (log_addr <= 7) { + v = hdmi_read_reg(core->base, HDMI_CEC_CA_7_0); + v |= 1 << log_addr; + hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, v); + } else { + v = hdmi_read_reg(core->base, HDMI_CEC_CA_15_8); + v |= 1 << (log_addr - 8); + hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, v); + } + return 0; +} + +static int hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int temp; + u32 i; + + /* Clear TX FIFO */ + if (!hdmi_cec_clear_tx_fifo(adap)) { + pr_err("cec-%s: could not clear TX FIFO for transmit\n", + adap->name); + return -EIO; + } + + /* Clear TX interrupts */ + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, + HDMI_CEC_TX_FIFO_INT_MASK); + + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, + HDMI_CEC_RETRANSMIT_CNT_INT_MASK); + + /* Set the retry count */ + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, attempts - 1, 6, 4); + + /* Set the initiator addresses */ + hdmi_write_reg(core->base, HDMI_CEC_TX_INIT, cec_msg_initiator(msg)); + + /* Set destination id */ + temp = cec_msg_destination(msg); + if (msg->len == 1) + temp |= 0x80; + hdmi_write_reg(core->base, HDMI_CEC_TX_DEST, temp); + if (msg->len == 1) + return 0; + + /* Setup command and arguments for the command */ + hdmi_write_reg(core->base, HDMI_CEC_TX_COMMAND, msg->msg[1]); + + for (i = 0; i < msg->len - 2; i++) + hdmi_write_reg(core->base, HDMI_CEC_TX_OPERAND + i * 4, + msg->msg[2 + i]); + + /* Operand count */ + hdmi_write_reg(core->base, HDMI_CEC_TRANSMIT_DATA, + (msg->len - 2) | 0x10); + return 0; +} + +static const struct cec_adap_ops hdmi_cec_adap_ops = { + .adap_enable = hdmi_cec_adap_enable, + .adap_log_addr = hdmi_cec_adap_log_addr, + .adap_transmit = hdmi_cec_adap_transmit, +}; + +void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa) +{ + cec_s_phys_addr(core->adap, pa, false); +} + +int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core, + struct hdmi_wp_data *wp) +{ + const u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | + CEC_CAP_PASSTHROUGH | CEC_CAP_RC; + unsigned int ret; + + core->adap = cec_allocate_adapter(&hdmi_cec_adap_ops, core, + "omap4", caps, CEC_MAX_LOG_ADDRS); + ret = PTR_ERR_OR_ZERO(core->adap); + if (ret < 0) + return ret; + core->wp = wp; + + /* + * Initialize CEC clock divider: CEC needs 2MHz clock hence + * set the devider to 24 to get 48/24=2MHz clock + */ + REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0); + + ret = cec_register_adapter(core->adap, &pdev->dev); + if (ret < 0) { + cec_delete_adapter(core->adap); + return ret; + } + return 0; +} + +void hdmi4_cec_uninit(struct hdmi_core_data *core) +{ + cec_unregister_adapter(core->adap); +} diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h new file mode 100644 index 000000000000..0292337c97cc --- /dev/null +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h @@ -0,0 +1,55 @@ +/* + * HDMI header definition for OMAP4 HDMI CEC IP + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _HDMI4_CEC_H_ +#define _HDMI4_CEC_H_ + +struct hdmi_core_data; +struct hdmi_wp_data; +struct platform_device; + +/* HDMI CEC funcs */ +#ifdef CONFIG_OMAP4_DSS_HDMI_CEC +void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa); +void hdmi4_cec_irq(struct hdmi_core_data *core); +int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core, + struct hdmi_wp_data *wp); +void hdmi4_cec_uninit(struct hdmi_core_data *core); +#else +static inline void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa) +{ +} + +static inline void hdmi4_cec_irq(struct hdmi_core_data *core) +{ +} + +static inline int hdmi4_cec_init(struct platform_device *pdev, + struct hdmi_core_data *core, + struct hdmi_wp_data *wp) +{ + return 0; +} + +static inline void hdmi4_cec_uninit(struct hdmi_core_data *core) +{ +} +#endif + +#endif
From: Hans Verkuil hans.verkuil@cisco.com
Hook up the HDMI CEC support in the hdmi4 driver.
It add the CEC irq handler, the CEC (un)init calls and tells the CEC implementation when the physical address changes.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/dss/Kconfig | 8 ++++++++ drivers/gpu/drm/omapdrm/dss/Makefile | 1 + drivers/gpu/drm/omapdrm/dss/hdmi4.c | 23 ++++++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/Kconfig b/drivers/gpu/drm/omapdrm/dss/Kconfig index 8b87d5cf45fc..f24ebf7f61dd 100644 --- a/drivers/gpu/drm/omapdrm/dss/Kconfig +++ b/drivers/gpu/drm/omapdrm/dss/Kconfig @@ -65,6 +65,14 @@ config OMAP4_DSS_HDMI help HDMI support for OMAP4 based SoCs.
+config OMAP4_DSS_HDMI_CEC + bool "Enable HDMI CEC support for OMAP4" + depends on OMAP4_DSS_HDMI + select CEC_CORE + default y + ---help--- + When selected the HDMI transmitter will support the CEC feature. + config OMAP5_DSS_HDMI bool "HDMI support for OMAP5" default n diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile index 688195e448c5..6a3a116512f3 100644 --- a/drivers/gpu/drm/omapdrm/dss/Makefile +++ b/drivers/gpu/drm/omapdrm/dss/Makefile @@ -14,5 +14,6 @@ omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \ hdmi_phy.o omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o +omapdss-$(CONFIG_OMAP4_DSS_HDMI_CEC) += hdmi4_cec.o omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 166aa4df7688..e535010218e6 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -36,9 +36,11 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <sound/omap-hdmi-audio.h> +#include <media/cec.h>
#include "omapdss.h" #include "hdmi4_core.h" +#include "hdmi4_cec.h" #include "dss.h" #include "dss_features.h" #include "hdmi.h" @@ -97,6 +99,13 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data) } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); } + if (irqstatus & HDMI_IRQ_CORE) { + u32 intr4 = hdmi_read_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4); + + hdmi_write_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4, intr4); + if (intr4 & 8) + hdmi4_cec_irq(&hdmi->core); + }
return IRQ_HANDLED; } @@ -393,6 +402,8 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
DSSDBG("Enter hdmi_display_disable\n");
+ hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); + mutex_lock(&hdmi.lock);
spin_lock_irqsave(&hdmi.audio_playing_lock, flags); @@ -493,7 +504,11 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, }
r = read_edid(edid, len); - + if (r >= 256) + hdmi4_cec_set_phys_addr(&hdmi.core, + cec_get_edid_phys_addr(edid, r, NULL)); + else + hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); if (need_enable) hdmi4_core_disable(dssdev);
@@ -727,6 +742,10 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) if (r) goto err;
+ r = hdmi4_cec_init(pdev, &hdmi.core, &hdmi.wp); + if (r) + goto err; + irq = platform_get_irq(pdev, 0); if (irq < 0) { DSSERR("platform_get_irq failed\n"); @@ -771,6 +790,8 @@ static void hdmi4_unbind(struct device *dev, struct device *master, void *data)
hdmi_uninit_output(pdev);
+ hdmi4_cec_uninit(&hdmi.core); + hdmi_pll_uninit(&hdmi.pll);
pm_runtime_disable(&pdev->dev);
From: Hans Verkuil hans.verkuil@cisco.com
The CEC framework needs to know when the hotplug detect signal disappears, since that means the CEC physical address has to be invalidated (i.e. set to f.f.f.f).
Add a lost_hotplug op that is called when the HPD signal goes away.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 8 ++++++-- drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 6 +++++- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 8 ++++++-- drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 + 4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index d9d25df6fc1b..4600d3841c25 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -165,11 +165,15 @@ static bool hdmic_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; + bool connected;
if (gpio_is_valid(ddata->hpd_gpio)) - return gpio_get_value_cansleep(ddata->hpd_gpio); + connected = gpio_get_value_cansleep(ddata->hpd_gpio); else - return in->ops.hdmi->detect(in); + connected = in->ops.hdmi->detect(in); + if (!connected && in->ops.hdmi->lost_hotplug) + in->ops.hdmi->lost_hotplug(in); + return connected; }
static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index 293b8fd07cfc..20058800aab3 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -159,8 +159,12 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + bool connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
- return gpiod_get_value_cansleep(ddata->hpd_gpio); + if (!connected) + in->ops.hdmi->lost_hotplug(in); + return connected; }
static int tpd_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e535010218e6..0eeba0d1a2f5 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -402,8 +402,6 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
DSSDBG("Enter hdmi_display_disable\n");
- hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); - mutex_lock(&hdmi.lock);
spin_lock_irqsave(&hdmi.audio_playing_lock, flags); @@ -515,6 +513,11 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, return r; }
+static void hdmi_lost_hotplug(struct omap_dss_device *dssdev) +{ + hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); +} + static int hdmi_set_infoframe(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi) { @@ -541,6 +544,7 @@ static const struct omapdss_hdmi_ops hdmi_ops = { .get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid, + .lost_hotplug = hdmi_lost_hotplug, .set_infoframe = hdmi_set_infoframe, .set_hdmi_mode = hdmi_set_hdmi_mode, }; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b9b0bb27069a..482a385894d7 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -402,6 +402,7 @@ struct omapdss_hdmi_ops { struct videomode *vm);
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); + void (*lost_hotplug)(struct omap_dss_device *dssdev); bool (*detect)(struct omap_dss_device *dssdev);
int (*register_hpd_cb)(struct omap_dss_device *dssdev,
The CEC framework needs to know when the hotplug detect signal disappears, since that means the CEC physical address has to be invalidated (i.e. set to f.f.f.f).
Add a lost_hotplug op that is called when the HPD signal goes away.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- Change since v2: check that the lost_hotplug callback is set before calling it in encoder-tpd12s015.c. --- drivers/gpu/drm/omapdrm/displays/connector-hdmi.c | 8 ++++++-- drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 6 +++++- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 8 ++++++-- drivers/gpu/drm/omapdrm/dss/omapdss.h | 1 + 4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index d9d25df6fc1b..4600d3841c25 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -165,11 +165,15 @@ static bool hdmic_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; + bool connected;
if (gpio_is_valid(ddata->hpd_gpio)) - return gpio_get_value_cansleep(ddata->hpd_gpio); + connected = gpio_get_value_cansleep(ddata->hpd_gpio); else - return in->ops.hdmi->detect(in); + connected = in->ops.hdmi->detect(in); + if (!connected && in->ops.hdmi->lost_hotplug) + in->ops.hdmi->lost_hotplug(in); + return connected; }
static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index 293b8fd07cfc..e3d98d78fc40 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -159,8 +159,12 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + bool connected = gpiod_get_value_cansleep(ddata->hpd_gpio);
- return gpiod_get_value_cansleep(ddata->hpd_gpio); + if (!connected && in->ops.hdmi->lost_hotplug) + in->ops.hdmi->lost_hotplug(in); + return connected; }
static int tpd_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e535010218e6..0eeba0d1a2f5 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -402,8 +402,6 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
DSSDBG("Enter hdmi_display_disable\n");
- hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); - mutex_lock(&hdmi.lock);
spin_lock_irqsave(&hdmi.audio_playing_lock, flags); @@ -515,6 +513,11 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, return r; }
+static void hdmi_lost_hotplug(struct omap_dss_device *dssdev) +{ + hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); +} + static int hdmi_set_infoframe(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi) { @@ -541,6 +544,7 @@ static const struct omapdss_hdmi_ops hdmi_ops = { .get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid, + .lost_hotplug = hdmi_lost_hotplug, .set_infoframe = hdmi_set_infoframe, .set_hdmi_mode = hdmi_set_hdmi_mode, }; diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index b9b0bb27069a..482a385894d7 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -402,6 +402,7 @@ struct omapdss_hdmi_ops { struct videomode *vm);
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); + void (*lost_hotplug)(struct omap_dss_device *dssdev); bool (*detect)(struct omap_dss_device *dssdev);
int (*register_hpd_cb)(struct omap_dss_device *dssdev,
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 02/08/17 11:53, Hans Verkuil wrote:
From: Hans Verkuil hans.verkuil@cisco.com
This patch series adds CEC support for the omap4. It is based on the 4.13-rc2 kernel with this patch series applied:
http://www.spinics.net/lists/dri-devel/msg143440.html
It is virtually identical to the first patch series posted in April:
http://www.spinics.net/lists/dri-devel/msg138950.html
The only two changes are in the Kconfig due to CEC Kconfig changes in 4.13 (it now selects CEC_CORE instead of depending on CEC_CORE) and a final patch was added adding a lost_hotplug op since for proper CEC support I have to know when the hotplug signal goes away.
Tested with my Pandaboard.
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
So I think something is left enabled, most likely in the HDMI driver. I haven't debugged this yet.
The first time I loaded the modules I also got "operation stopped when reading edid", but I haven't seen that since. Possibly not related to this series.
Are there some simple ways to test the CEC? My buildroot fs has cec-compliance, cec-ctl and cec-follower commands. Are you familiar with those? Can they be used?
Tomi
On 11/08/17 12:57, Tomi Valkeinen wrote:
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 02/08/17 11:53, Hans Verkuil wrote:
From: Hans Verkuil hans.verkuil@cisco.com
This patch series adds CEC support for the omap4. It is based on the 4.13-rc2 kernel with this patch series applied:
http://www.spinics.net/lists/dri-devel/msg143440.html
It is virtually identical to the first patch series posted in April:
http://www.spinics.net/lists/dri-devel/msg138950.html
The only two changes are in the Kconfig due to CEC Kconfig changes in 4.13 (it now selects CEC_CORE instead of depending on CEC_CORE) and a final patch was added adding a lost_hotplug op since for proper CEC support I have to know when the hotplug signal goes away.
Tested with my Pandaboard.
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
So I think something is left enabled, most likely in the HDMI driver. I haven't debugged this yet.
The first time I loaded the modules I also got "operation stopped when reading edid", but I haven't seen that since. Possibly not related to this series.
Are there some simple ways to test the CEC? My buildroot fs has cec-compliance, cec-ctl and cec-follower commands. Are you familiar with those? Can they be used?
I'm very familiar with them since I wrote them :-)
The latest version of those utilities are maintained here:
https://git.linuxtv.org/v4l-utils.git/
But the ones from buildroot should be fine.
To use:
cec-ctl --playback # configure the CEC adapter as a playback device cec-ctl -S # Detect and show all CEC devices
Note: all cec utilities use /dev/cec0 as the default device node. Use the -d option to specify another device node.
So assuming you have the panda connected to a CEC-capable TV you should see the TV in that list.
You can use cec-compliance to check the CEC compliance of devices:
cec-ctl --playback cec-follower # emulate a CEC playback device follower functionality
In another shell run:
cec-compliance -r0 # Test remote CEC device with logical address 0 (== TV)
Regards,
Hans
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
Hi Hans,
On 02/08/17 11:53, Hans Verkuil wrote:
From: Hans Verkuil hans.verkuil@cisco.com
This patch series adds CEC support for the omap4. It is based on the 4.13-rc2 kernel with this patch series applied:
http://www.spinics.net/lists/dri-devel/msg143440.html
It is virtually identical to the first patch series posted in April:
http://www.spinics.net/lists/dri-devel/msg138950.html
The only two changes are in the Kconfig due to CEC Kconfig changes in 4.13 (it now selects CEC_CORE instead of depending on CEC_CORE) and a final patch was added adding a lost_hotplug op since for proper CEC support I have to know when the hotplug signal goes away.
Tested with my Pandaboard.
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
So I think something is left enabled, most likely in the HDMI driver. I haven't debugged this yet.
The first time I loaded the modules I also got "operation stopped when reading edid", but I haven't seen that since. Possibly not related to this series.
Sorry that I have had very little time to debug this. I rebased the cec code on top of the latest omapdrm patches, and tested on AM5 EVM (which is more or less equivalent to OMAP5 on the HDMI front). I get the following crash when I turn on my monitor, which causes a HPD irq.
I'll continue looking at this as soon as I again find time, but I thought I'll share what I have at the moment. I've pushed the branch to:
git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git 4.14/omapdrm-cec
Tomi
[ 34.640159] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 34.648449] pgd = c0004000 [ 34.651249] [00000000] *pgd=00000000 [ 34.654921] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM [ 34.660879] Modules linked in: omapdrm drm_kms_helper drm connector_dvi panel_dsi_cm panel_dpi connector_analog_tv connector_hdmi encode r_tpd12s015 encoder_tfp410 omapdss omapdss_base snd_soc_omap_hdmi_audio cec cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 34.685482] CPU: 0 PID: 264 Comm: irq/248-tpd12s0 Not tainted 4.13.0-rc5-00626-gbf51300abae9 #99 [ 34.694314] Hardware name: Generic DRA74X (Flattened Device Tree) [ 34.700442] task: ed108140 task.stack: ed190000 [ 34.705002] PC is at 0x0 [ 34.707561] LR is at tpd_detect+0x3c/0x44 [encoder_tpd12s015] [ 34.713340] pc : [<00000000>] lr : [<bf200340>] psr: 600c0013 [ 34.719642] sp : ed191ee8 ip : ed191e68 fp : ed191efc [ 34.724897] r10: 00000001 r9 : ee2e0200 r8 : c01b45c8 [ 34.730153] r7 : ed10b064 r6 : 00000000 r5 : bf1d716c r4 : 00000000 [ 34.736716] r3 : 00000000 r2 : 00000000 r1 : ffffffff r0 : bf1d716c [ 34.743283] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none [ 34.750458] Control: 10c5387d Table: ad26406a DAC: 00000051 [ 34.756236] Process irq/248-tpd12s0 (pid: 264, stack limit = 0xed190218) [ 34.762976] Stack: (0xed191ee8 to 0xed192000) [ 34.767363] 1ee0: ed27e610 ed27e6d4 ed191f14 ed191f00 bf200388 bf200310 [ 34.775587] 1f00: ed10b040 ee2e0200 ed191f34 ed191f18 c01b433c bf200354 ed190000 00000001 [ 34.783812] 1f20: 00000000 ed10b064 ed191f74 ed191f38 c01b4660 c01b4324 c01b4318 ed10b040 [ 34.792036] 1f40: 00000000 c01b4418 ed191f74 ed1ebc80 00000000 ed392500 ed190000 ed10b040 [ 34.800261] 1f60: ed1ebcb8 ed24fb08 ed191fac ed191f78 c0163e60 c01b4504 00000000 c01b44f8 [ 34.808486] 1f80: ed191fac ed392500 c0163d30 00000000 00000000 00000000 00000000 00000000 [ 34.816710] 1fa0: 00000000 ed191fb0 c0108af0 c0163d3c 00000000 00000000 00000000 00000000 [ 34.824934] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 34.833157] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 [ 34.841376] Backtrace: [ 34.843861] [<bf200304>] (tpd_detect [encoder_tpd12s015]) from [<bf200388>] (tpd_hpd_isr+0x40/0x68 [encoder_tpd12s015]) [ 34.854701] r5:ed27e6d4 r4:ed27e610 [ 34.858310] [<bf200348>] (tpd_hpd_isr [encoder_tpd12s015]) from [<c01b433c>] (irq_thread_fn+0x24/0x5c) [ 34.867667] r5:ee2e0200 r4:ed10b040 [ 34.871270] [<c01b4318>] (irq_thread_fn) from [<c01b4660>] (irq_thread+0x168/0x254) [ 34.878970] r7:ed10b064 r6:00000000 r5:00000001 r4:ed190000 [ 34.884670] [<c01b44f8>] (irq_thread) from [<c0163e60>] (kthread+0x130/0x174) [ 34.891847] r10:ed24fb08 r9:ed1ebcb8 r8:ed10b040 r7:ed190000 r6:ed392500 r5:00000000 [ 34.899719] r4:ed1ebc80 [ 34.902280] [<c0163d30>] (kthread) from [<c0108af0>] (ret_from_fork+0x14/0x24) [ 34.909544] r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c0163d30 [ 34.917415] r4:ed392500 [ 34.919969] Code: bad PC value [ 34.923157] ---[ end trace 81cba660da396e25 ]--- [ 34.927828] genirq: exiting task "irq/248-tpd12s0" (264) is an active IRQ thread (irq 248)
On 08/17/17 15:03, Tomi Valkeinen wrote:
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
Hi Hans,
On 02/08/17 11:53, Hans Verkuil wrote:
From: Hans Verkuil hans.verkuil@cisco.com
This patch series adds CEC support for the omap4. It is based on the 4.13-rc2 kernel with this patch series applied:
http://www.spinics.net/lists/dri-devel/msg143440.html
It is virtually identical to the first patch series posted in April:
http://www.spinics.net/lists/dri-devel/msg138950.html
The only two changes are in the Kconfig due to CEC Kconfig changes in 4.13 (it now selects CEC_CORE instead of depending on CEC_CORE) and a final patch was added adding a lost_hotplug op since for proper CEC support I have to know when the hotplug signal goes away.
Tested with my Pandaboard.
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
So I think something is left enabled, most likely in the HDMI driver. I haven't debugged this yet.
The first time I loaded the modules I also got "operation stopped when reading edid", but I haven't seen that since. Possibly not related to this series.
Sorry that I have had very little time to debug this. I rebased the cec code on top of the latest omapdrm patches, and tested on AM5 EVM (which is more or less equivalent to OMAP5 on the HDMI front). I get the following crash when I turn on my monitor, which causes a HPD irq.
I see the issue: in drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c, tpd_detect() this line:
if (!connected)
should be:
if (!connected && in->ops.hdmi->lost_hotplug)
I did that correctly in connector-hdmi.c, but not in encoder-tpd12s015.c. And since omap5 doesn't fill in lost_hotplug this crashes.
I'll make a v3 of that patch.
Regards,
Hans
I'll continue looking at this as soon as I again find time, but I thought I'll share what I have at the moment. I've pushed the branch to:
git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git 4.14/omapdrm-cec
Tomi
[ 34.640159] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 34.648449] pgd = c0004000 [ 34.651249] [00000000] *pgd=00000000 [ 34.654921] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM [ 34.660879] Modules linked in: omapdrm drm_kms_helper drm connector_dvi panel_dsi_cm panel_dpi connector_analog_tv connector_hdmi encode r_tpd12s015 encoder_tfp410 omapdss omapdss_base snd_soc_omap_hdmi_audio cec cfbfillrect cfbimgblt cfbcopyarea [last unloaded: omapdss_base] [ 34.685482] CPU: 0 PID: 264 Comm: irq/248-tpd12s0 Not tainted 4.13.0-rc5-00626-gbf51300abae9 #99 [ 34.694314] Hardware name: Generic DRA74X (Flattened Device Tree) [ 34.700442] task: ed108140 task.stack: ed190000 [ 34.705002] PC is at 0x0 [ 34.707561] LR is at tpd_detect+0x3c/0x44 [encoder_tpd12s015] [ 34.713340] pc : [<00000000>] lr : [<bf200340>] psr: 600c0013 [ 34.719642] sp : ed191ee8 ip : ed191e68 fp : ed191efc [ 34.724897] r10: 00000001 r9 : ee2e0200 r8 : c01b45c8 [ 34.730153] r7 : ed10b064 r6 : 00000000 r5 : bf1d716c r4 : 00000000 [ 34.736716] r3 : 00000000 r2 : 00000000 r1 : ffffffff r0 : bf1d716c [ 34.743283] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none [ 34.750458] Control: 10c5387d Table: ad26406a DAC: 00000051 [ 34.756236] Process irq/248-tpd12s0 (pid: 264, stack limit = 0xed190218) [ 34.762976] Stack: (0xed191ee8 to 0xed192000) [ 34.767363] 1ee0: ed27e610 ed27e6d4 ed191f14 ed191f00 bf200388 bf200310 [ 34.775587] 1f00: ed10b040 ee2e0200 ed191f34 ed191f18 c01b433c bf200354 ed190000 00000001 [ 34.783812] 1f20: 00000000 ed10b064 ed191f74 ed191f38 c01b4660 c01b4324 c01b4318 ed10b040 [ 34.792036] 1f40: 00000000 c01b4418 ed191f74 ed1ebc80 00000000 ed392500 ed190000 ed10b040 [ 34.800261] 1f60: ed1ebcb8 ed24fb08 ed191fac ed191f78 c0163e60 c01b4504 00000000 c01b44f8 [ 34.808486] 1f80: ed191fac ed392500 c0163d30 00000000 00000000 00000000 00000000 00000000 [ 34.816710] 1fa0: 00000000 ed191fb0 c0108af0 c0163d3c 00000000 00000000 00000000 00000000 [ 34.824934] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 34.833157] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 [ 34.841376] Backtrace: [ 34.843861] [<bf200304>] (tpd_detect [encoder_tpd12s015]) from [<bf200388>] (tpd_hpd_isr+0x40/0x68 [encoder_tpd12s015]) [ 34.854701] r5:ed27e6d4 r4:ed27e610 [ 34.858310] [<bf200348>] (tpd_hpd_isr [encoder_tpd12s015]) from [<c01b433c>] (irq_thread_fn+0x24/0x5c) [ 34.867667] r5:ee2e0200 r4:ed10b040 [ 34.871270] [<c01b4318>] (irq_thread_fn) from [<c01b4660>] (irq_thread+0x168/0x254) [ 34.878970] r7:ed10b064 r6:00000000 r5:00000001 r4:ed190000 [ 34.884670] [<c01b44f8>] (irq_thread) from [<c0163e60>] (kthread+0x130/0x174) [ 34.891847] r10:ed24fb08 r9:ed1ebcb8 r8:ed10b040 r7:ed190000 r6:ed392500 r5:00000000 [ 34.899719] r4:ed1ebc80 [ 34.902280] [<c0163d30>] (kthread) from [<c0108af0>] (ret_from_fork+0x14/0x24) [ 34.909544] r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c0163d30 [ 34.917415] r4:ed392500 [ 34.919969] Code: bad PC value [ 34.923157] ---[ end trace 81cba660da396e25 ]--- [ 34.927828] genirq: exiting task "irq/248-tpd12s0" (264) is an active IRQ thread (irq 248)
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
This one is caused by hdmi_cec_adap_enable() never getting called with enable=false when unloading the modules. Should that be called explicitly in hdmi4_cec_uninit, or is the CEC framework supposed to call it?
Tomi
On 08/18/17 11:02, Tomi Valkeinen wrote:
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
This one is caused by hdmi_cec_adap_enable() never getting called with enable=false when unloading the modules. Should that be called explicitly in hdmi4_cec_uninit, or is the CEC framework supposed to call it?
Nicely found!
The cec_delete_adapter() function calls __cec_s_phys_addr(CEC_PHYS_ADDR_INVALID) which would normally call adap_enable(false), except when the device node was already unregistered, in which case it just returns immediately.
The patch below should fix this. Let me know if it works, and I'll post a proper patch and get that in for 4.14 (and possible backported as well, I'll have to look at that).
Regards,
Hans
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com --- diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index bf45977b2823..61dffe165565 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -1390,7 +1390,9 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) */ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) { - if (phys_addr == adap->phys_addr || adap->devnode.unregistered) + if (phys_addr == adap->phys_addr) + return; + if (phys_addr != CEC_PHYS_ADDR_INVALID && adap->devnode.unregistered) return;
dprintk(1, "new physical address %x.%x.%x.%x\n",
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
This one is caused by hdmi_cec_adap_enable() never getting called with enable=false when unloading the modules. Should that be called explicitly in hdmi4_cec_uninit, or is the CEC framework supposed to call it?
Nicely found!
The cec_delete_adapter() function calls __cec_s_phys_addr(CEC_PHYS_ADDR_INVALID) which would normally call adap_enable(false), except when the device node was already unregistered, in which case it just returns immediately.
The patch below should fix this. Let me know if it works, and I'll post a proper patch and get that in for 4.14 (and possible backported as well, I'll have to look at that).
Thanks, this fixes the issue.
I again saw "HDMICORE: omapdss HDMICORE error: operation stopped when reading edid" when I loaded the modules. My panda also froze just now when unloading the display modules, and it doesn't react to sysrq.
After testing a bit without the CEC patches, I saw the above error, so I don't think it's related to your patches.
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
Tomi
Hi Tomi,
On 08/22/2017 11:44 AM, Tomi Valkeinen wrote:
Hi Hans,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 11/08/17 13:57, Tomi Valkeinen wrote:
I'm doing some testing with this series on my panda. One issue I see is that when I unload the display modules, I get:
[ 75.180206] platform 58006000.encoder: enabled after unload, idling [ 75.187896] platform 58001000.dispc: enabled after unload, idling [ 75.198242] platform 58000000.dss: enabled after unload, idling
This one is caused by hdmi_cec_adap_enable() never getting called with enable=false when unloading the modules. Should that be called explicitly in hdmi4_cec_uninit, or is the CEC framework supposed to call it?
Nicely found!
The cec_delete_adapter() function calls __cec_s_phys_addr(CEC_PHYS_ADDR_INVALID) which would normally call adap_enable(false), except when the device node was already unregistered, in which case it just returns immediately.
The patch below should fix this. Let me know if it works, and I'll post a proper patch and get that in for 4.14 (and possible backported as well, I'll have to look at that).
Thanks, this fixes the issue.
I again saw "HDMICORE: omapdss HDMICORE error: operation stopped when reading edid" when I loaded the modules. My panda also froze just now when unloading the display modules, and it doesn't react to sysrq.
After testing a bit without the CEC patches, I saw the above error, so I don't think it's related to your patches.
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
What is the status? Do you need anything from me? I'd like to get this in for 4.15.
Regards,
Hans
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 12/10/17 09:50, Hans Verkuil wrote:
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
What is the status? Do you need anything from me? I'd like to get this in for 4.15.
Thanks for reminding. I think I would've forgotten...
I sent the pull request, so all should be fine.
If possible, please test the pull request, preferably with drm-next merged (git://people.freedesktop.org/~airlied/linux drm-next), as I don't have a CEC capable display.
Tomi
On 10/12/17 10:03, Tomi Valkeinen wrote:
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 12/10/17 09:50, Hans Verkuil wrote:
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
What is the status? Do you need anything from me? I'd like to get this in for 4.15.
Thanks for reminding. I think I would've forgotten...
I sent the pull request, so all should be fine.
If possible, please test the pull request, preferably with drm-next merged (git://people.freedesktop.org/~airlied/linux drm-next), as I don't have a CEC capable display.
I'll try to do that tomorrow or Monday.
I have one other question for you: does keeping ls_oe_gpio high all the time affect this old bug fix:
https://github.com/myfluxi/xxICSKernel/commit/21189f03d3ec3a74d9949907c82841...
I don't think so, but I'm not 100% sure. As far as I can see the PHY power sequence (OFF, TXON, LDOON) does not change and that seems to be the crucial fix according to the commit above.
I would hate being responsible for lots of burnt-out pandaboards :-)
There is an alternative solution: when there is no HPD then it is also possible to pull the ls_oe_gpio high only when transmitting a CEC message.
That would obviously require some code changes.
Sorry for raising this issue so late, but this just came up today in internal discussions.
Regards,
Hans
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 12/10/17 12:42, Hans Verkuil wrote:
On 10/12/17 10:03, Tomi Valkeinen wrote:
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 12/10/17 09:50, Hans Verkuil wrote:
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
What is the status? Do you need anything from me? I'd like to get this in for 4.15.
Thanks for reminding. I think I would've forgotten...
I sent the pull request, so all should be fine.
If possible, please test the pull request, preferably with drm-next merged (git://people.freedesktop.org/~airlied/linux drm-next), as I don't have a CEC capable display.
I'll try to do that tomorrow or Monday.
I have one other question for you: does keeping ls_oe_gpio high all the time affect this old bug fix:
https://github.com/myfluxi/xxICSKernel/commit/21189f03d3ec3a74d9949907c82841...
No, the issue is about the HDMI PHY. The i2c lines are not related. LS_OE only affects the i2c.
I don't think so, but I'm not 100% sure. As far as I can see the PHY power sequence (OFF, TXON, LDOON) does not change and that seems to be the crucial fix according to the commit above.
I would hate being responsible for lots of burnt-out pandaboards :-)
There is an alternative solution: when there is no HPD then it is also possible to pull the ls_oe_gpio high only when transmitting a CEC message.
That would obviously require some code changes.
Sorry for raising this issue so late, but this just came up today in internal discussions.
Well, it would be nice to not have LS_OE enabled all the time. But I'm not sure how much that really matters. I'm sure it uses some power, but is that even measurable, I have no idea.
Tomi
On 10/12/2017 10:03 AM, Tomi Valkeinen wrote:
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On 12/10/17 09:50, Hans Verkuil wrote:
I can't test with a TV, so no CEC for me... But otherwise I think the series works ok now, and looks ok. So I'll apply, but it's a bit late for the next merge window, so I'll aim for 4.15 with this.
What is the status? Do you need anything from me? I'd like to get this in for 4.15.
Thanks for reminding. I think I would've forgotten...
I sent the pull request, so all should be fine.
If possible, please test the pull request, preferably with drm-next merged (git://people.freedesktop.org/~airlied/linux drm-next), as I don't have a CEC capable display.
Tested with drm-next. Works fine!
Great to finally see this merged!
Regards,
Hans
dri-devel@lists.freedesktop.org