Following (copying !) what Hans have done in this serie of patches http://www.spinics.net/lists/linux-media/msg109141.html I have implemented hdmi notifier in hdmi controled and stih-cec drivers.
Those patches should be applied on top of Hans patches for exynos.
I have tested hdmi notifier by pluging/unpluging HDMI cable and check the value of the physical address with "cec-ctl --tuner". "cec-compliance -A" is also functional.
Hans, I haven't move stih-cec out of staging because I don't have the exact branch to test it, can you do the move for stih-cec after applying those patches ?
Regards, Benjamin
Benjamin Gaignard (2): sti: hdmi: add HDMI notifier support stih-cec: add hdmi-notifier support
.../devicetree/bindings/media/stih-cec.txt | 2 ++ arch/arm/boot/dts/stih407-family.dtsi | 12 --------- arch/arm/boot/dts/stih410.dtsi | 15 ++++++++++- drivers/gpu/drm/sti/Kconfig | 1 + drivers/gpu/drm/sti/sti_hdmi.c | 15 +++++++++++ drivers/gpu/drm/sti/sti_hdmi.h | 2 ++ drivers/staging/media/st-cec/Kconfig | 1 + drivers/staging/media/st-cec/stih-cec.c | 29 +++++++++++++++++++++- 8 files changed, 63 insertions(+), 14 deletions(-)
Implement the HDMI notifier support to allow CEC drivers to be informed when there is a new EDID and when a connect or disconnect happens.
Signed-off-by: Benjamin Gaignard benjamin.gaignard@linaro.org --- drivers/gpu/drm/sti/Kconfig | 1 + drivers/gpu/drm/sti/sti_hdmi.c | 15 +++++++++++++++ drivers/gpu/drm/sti/sti_hdmi.h | 2 ++ 3 files changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig index acd7286..59ceffc 100644 --- a/drivers/gpu/drm/sti/Kconfig +++ b/drivers/gpu/drm/sti/Kconfig @@ -8,5 +8,6 @@ config DRM_STI select DRM_PANEL select FW_LOADER select SND_SOC_HDMI_CODEC if SND_SOC + select HDMI_NOTIFIERS help Choose this option to enable DRM on STM stiH4xx chipset diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 376b076..6667371 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -786,6 +786,8 @@ static void sti_hdmi_disable(struct drm_bridge *bridge) clk_disable_unprepare(hdmi->clk_pix);
hdmi->enabled = false; + + hdmi_event_disconnect(hdmi->notifier); }
static void sti_hdmi_pre_enable(struct drm_bridge *bridge) @@ -892,6 +894,10 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector) if (!edid) goto fail;
+ hdmi_event_connect(hdmi->notifier); + hdmi_event_new_edid(hdmi->notifier, edid, + EDID_LENGTH * (edid->extensions + 1)); + count = drm_add_edid_modes(connector, edid); drm_mode_connector_update_edid_property(connector, edid); drm_edid_to_eld(connector, edid); @@ -949,10 +955,12 @@ struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
if (hdmi->hpd) { DRM_DEBUG_DRIVER("hdmi cable connected\n"); + hdmi_event_connect(hdmi->notifier); return connector_status_connected; }
DRM_DEBUG_DRIVER("hdmi cable disconnected\n"); + hdmi_event_disconnect(hdmi->notifier); return connector_status_disconnected; }
@@ -1464,6 +1472,10 @@ static int sti_hdmi_probe(struct platform_device *pdev) goto release_adapter; }
+ hdmi->notifier = hdmi_notifier_get(&pdev->dev); + if (!hdmi->notifier) + goto release_adapter; + hdmi->reset = devm_reset_control_get(dev, "hdmi"); /* Take hdmi out of reset */ if (!IS_ERR(hdmi->reset)) @@ -1483,11 +1495,14 @@ static int sti_hdmi_remove(struct platform_device *pdev) { struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
+ hdmi_event_disconnect(hdmi->notifier); + i2c_put_adapter(hdmi->ddc_adapt); if (hdmi->audio_pdev) platform_device_unregister(hdmi->audio_pdev); component_del(&pdev->dev, &sti_hdmi_ops);
+ hdmi_notifier_put(hdmi->notifier); return 0; }
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index 119bc35..70aac98 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h @@ -8,6 +8,7 @@ #define _STI_HDMI_H_
#include <linux/hdmi.h> +#include <linux/hdmi-notifier.h> #include <linux/platform_device.h>
#include <drm/drmP.h> @@ -102,6 +103,7 @@ struct sti_hdmi { struct platform_device *audio_pdev; struct hdmi_audio_params audio; struct drm_connector *drm_connector; + struct hdmi_notifier *notifier; };
u32 hdmi_read(struct sti_hdmi *hdmi, int offset);
By using the HDMI notifier framework there is no longer any reason to manually set the physical address. This was the one blocking issue that prevented this driver from going out of staging, so do this move as well.
Update the bindings documenting the new hdmi phandle and update stih410.dtsi and stih407-family.dtsi accordingly.
Signed-off-by: Benjamin Gaignard benjamin.gaignard@linaro.org --- .../devicetree/bindings/media/stih-cec.txt | 2 ++ arch/arm/boot/dts/stih407-family.dtsi | 12 --------- arch/arm/boot/dts/stih410.dtsi | 15 ++++++++++- drivers/staging/media/st-cec/Kconfig | 1 + drivers/staging/media/st-cec/stih-cec.c | 29 +++++++++++++++++++++- 5 files changed, 45 insertions(+), 14 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/stih-cec.txt b/Documentation/devicetree/bindings/media/stih-cec.txt index 71c4b2f..7d82121 100644 --- a/Documentation/devicetree/bindings/media/stih-cec.txt +++ b/Documentation/devicetree/bindings/media/stih-cec.txt @@ -9,6 +9,7 @@ Required properties: - pinctrl-names: Contains only one value - "default" - pinctrl-0: Specifies the pin control groups used for CEC hardware. - resets: Reference to a reset controller + - st,hdmi-handle: Phandle to the HMDI controller
Example for STIH407:
@@ -22,4 +23,5 @@ sti-cec@094a087c { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_cec0_default>; resets = <&softreset STIH407_LPM_SOFTRESET>; + st,hdmi-handle = <&hdmi>; }; diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 8f79b41..ef7c79a 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -756,18 +756,6 @@ <&clk_s_c0_flexgen CLK_ETH_PHY>; };
- cec: sti-cec@094a087c { - compatible = "st,stih-cec"; - reg = <0x94a087c 0x64>; - clocks = <&clk_sysin>; - clock-names = "cec-clk"; - interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>; - interrupt-names = "cec-irq"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cec0_default>; - resets = <&softreset STIH407_LPM_SOFTRESET>; - }; - rng10: rng@08a89000 { compatible = "st,rng"; reg = <0x08a89000 0x1000>; diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index a3ef734..c98d86e 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -193,7 +193,7 @@ <&clk_s_d2_quadfs 0>; };
- sti-hdmi@8d04000 { + hdmi: sti-hdmi@8d04000 { compatible = "st,stih407-hdmi"; reg = <0x8d04000 0x1000>; reg-names = "hdmi-reg"; @@ -259,5 +259,18 @@ clocks = <&clk_sysin>; interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>; }; + + sti-cec@094a087c { + compatible = "st,stih-cec"; + reg = <0x94a087c 0x64>; + clocks = <&clk_sysin>; + clock-names = "cec-clk"; + interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>; + interrupt-names = "cec-irq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cec0_default>; + resets = <&softreset STIH407_LPM_SOFTRESET>; + st,hdmi-handle = <&hdmi>; + }; }; }; diff --git a/drivers/staging/media/st-cec/Kconfig b/drivers/staging/media/st-cec/Kconfig index 784d2c6..3072387 100644 --- a/drivers/staging/media/st-cec/Kconfig +++ b/drivers/staging/media/st-cec/Kconfig @@ -1,6 +1,7 @@ config VIDEO_STI_HDMI_CEC tristate "STMicroelectronics STiH4xx HDMI CEC driver" depends on VIDEO_DEV && MEDIA_CEC && (ARCH_STI || COMPILE_TEST) + select HDMI_NOTIFIERS ---help--- This is a driver for STIH4xx HDMI CEC interface. It uses the generic CEC framework interface. diff --git a/drivers/staging/media/st-cec/stih-cec.c b/drivers/staging/media/st-cec/stih-cec.c index 2143448..ce94097 100644 --- a/drivers/staging/media/st-cec/stih-cec.c +++ b/drivers/staging/media/st-cec/stih-cec.c @@ -10,11 +10,13 @@ * (at your option) any later version. */ #include <linux/clk.h> +#include <linux/hdmi-notifier.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/version.h>
@@ -130,6 +132,7 @@ struct stih_cec { void __iomem *regs; int irq; u32 irq_status; + struct hdmi_notifier *notifier; };
static int stih_cec_adap_enable(struct cec_adapter *adap, bool enable) @@ -304,12 +307,29 @@ static int stih_cec_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; struct stih_cec *cec; + struct device_node *np; + struct platform_device *hdmi_dev; int ret;
cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL); if (!cec) return -ENOMEM;
+ np = of_parse_phandle(pdev->dev.of_node, "st,hdmi-handle", 0); + + if (!np) { + dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n"); + return -ENODEV; + } + + hdmi_dev = of_find_device_by_node(np); + if (!hdmi_dev) + return -EPROBE_DEFER; + + cec->notifier = hdmi_notifier_get(&hdmi_dev->dev); + if (!cec->notifier) + return -ENOMEM; + cec->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -336,7 +356,7 @@ static int stih_cec_probe(struct platform_device *pdev) cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec, CEC_NAME, CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | - CEC_CAP_PHYS_ADDR | CEC_CAP_TRANSMIT, + CEC_CAP_TRANSMIT, 1, &pdev->dev); ret = PTR_ERR_OR_ZERO(cec->adap); if (ret) @@ -348,12 +368,19 @@ static int stih_cec_probe(struct platform_device *pdev) return ret; }
+ cec_register_hdmi_notifier(cec->adap, cec->notifier); + platform_set_drvdata(pdev, cec); return 0; }
static int stih_cec_remove(struct platform_device *pdev) { + struct stih_cec *cec = platform_get_drvdata(pdev); + + cec_unregister_adapter(cec->adap); + hdmi_notifier_put(cec->notifier); + return 0; }
linaro-kernel@lists.linaro.org