Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp3672954ybi; Tue, 18 Jun 2019 04:50:37 -0700 (PDT) X-Google-Smtp-Source: APXvYqxYHnWxq5dAyjiUnXqx4fYPf/fsEaTeYr+KVA6ia0WvNO9EEBYLQwYMjXRxehnmKEys1X3U X-Received: by 2002:a17:90a:37e9:: with SMTP id v96mr4633793pjb.10.1560858636901; Tue, 18 Jun 2019 04:50:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1560858636; cv=none; d=google.com; s=arc-20160816; b=lcrrTWunLTRQa+mlIJHuaMd8E3dN4oHzMYYvW5n7StQcZSfxXwjYfYUnQSsQozPa2i lEr/ObG0tdbm1LrNG0u650ZwawNU/HCT6EYOmutl4+e9G0YueBu4SXeXIcs7O3xvsGXz FL3tjWzt62EGp2V89X+JyJ7KeDY0YAuHiX+Vj6XOiD7I6Om532UIu+caxe71cXi23D+A nqgHS1I4xG9wS15p8W3Cay6FnqPBwdZaW55dUjqgiT89OCaxckZ3bBI81B+IokmVhNHR tvZMjBMV4w1TKaq+tv8nzIXT0hfWM1B1tQjrP6afM2EOCYrktk4ci2AfUnWtCjXfmVH3 WlLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=Yn4pzIg4hZCmYmYBu0uWlHPLD5CVrUJDOUIsfyyt+Pk=; b=K8PiQ9NPppWDm8amqlv2Y+z3zvd7Ly7pn2juO+fa+4XePrwOCtYYjrpsAT41usFL93 9oKBNcYfCw6EenRybQK5fkTRLeo2QwG6yPzdxET92n0gSyjkbYZFmlbDVh9zhG3NNfxD 1+jkkCnuzveoxB/ngCsuLglsuCivye3j1UR0CCc6K/ThPkD3O0DWBW/T9cg38nrGBrn2 rUc2DqU67GRFBZ5Io7lL/A8sIJrCjLpjA7xUcV9tU0vtTkHujm6w808h6+d7+aflphOQ WWSTQ7b4WiZKkO2pNcvhNDyqY9rMpUEyy/P5P50HM31NsdnykMc4Hq1X7U+0XDgOjFf1 Da2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=QPggYLqa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j36si12942444plb.77.2019.06.18.04.50.21; Tue, 18 Jun 2019 04:50:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=QPggYLqa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729850AbfFRLsg (ORCPT + 99 others); Tue, 18 Jun 2019 07:48:36 -0400 Received: from mail-vk1-f195.google.com ([209.85.221.195]:41775 "EHLO mail-vk1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729813AbfFRLsg (ORCPT ); Tue, 18 Jun 2019 07:48:36 -0400 Received: by mail-vk1-f195.google.com with SMTP id u64so1790450vku.8 for ; Tue, 18 Jun 2019 04:48:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Yn4pzIg4hZCmYmYBu0uWlHPLD5CVrUJDOUIsfyyt+Pk=; b=QPggYLqa02a0llxIMIHsHS9jmySnda7OkAo+IrnQoVsxS5rv1l2S48jJtuXFe4pb8y ZhBc6vx/RFcmC3RjAHpAa6TO2/BuOSj8xYkjGUqytcLU3Ip3Dkdyyf5h6RssyfhfAJy+ 0hE4u8aqVG4PolgVrJndFkt7zGmqL9cJjKigk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Yn4pzIg4hZCmYmYBu0uWlHPLD5CVrUJDOUIsfyyt+Pk=; b=XPaVJczKW93wPRlqwRtw73w1dI9avdAciJbippPPP/Q7fPGAFH+b0Lz1k66Z+hfHTx rJ85tpM0eY7tAgrkXAq+R/HvyyCJJXA3ZF2dsdh/3JiS+Ek1ttFsnTnKK7HF7GOMQL52 XxtEZ/xbgOq5laqzcbxz5e1M16qRnHngYqWPNU8FEC3j3nNYjgqeCnryiS2/tdhk0/nU OysSsPQQtnXo60fzyHMR3TwcqrfH/VGhf+hwsjOiiXSVOUJfH8bBrqX6Xq5jPFrYf6ho L5mDKZKD+efioUMVqiVoOQq14Rjjhi7rkqHmVD1PfGEiFqjUz5M66XIw/h8MwFiuPj+D lSKg== X-Gm-Message-State: APjAAAUyzNUbpG5f9La8OgUbNN2nyLoI7u7621Ss203E5OBKZACI3ZiD U3rCkU3X/iT94GgXYprB9xREUzk7s85DD+5Fx/jZBQ== X-Received: by 2002:a1f:b20d:: with SMTP id b13mr1642610vkf.75.1560858513696; Tue, 18 Jun 2019 04:48:33 -0700 (PDT) MIME-Version: 1.0 References: <20190603043251.226549-1-cychiang@chromium.org> <20190603043251.226549-2-cychiang@chromium.org> <41e7052b-a58c-5a8c-5d94-37237e0c2070@xs4all.nl> <20190603080931.GG21222@phenom.ffwll.local> <20190604072411.GP21222@phenom.ffwll.local> <20190611123455.GD2458@phenom.ffwll.local> In-Reply-To: <20190611123455.GD2458@phenom.ffwll.local> From: Cheng-yi Chiang Date: Tue, 18 Jun 2019 19:48:06 +0800 Message-ID: Subject: Re: [PATCH 1/7] video: add HDMI state notifier support To: Cheng-yi Chiang , Hans Verkuil , linux-kernel , Bartlomiej Zolnierkiewicz , Greg Kroah-Hartman , Philipp Zabel , Mark Brown , Liam Girdwood , Takashi Iwai , Jaroslav Kysela , Russell King , Andrzej Hajda , Laurent Pinchart , David Airlie , Rob Herring , Heiko Stuebner , Doug Anderson , Dylan Reid , tzungbi@chromium.org, linux-media@vger.kernel.org, "moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM..." , dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, Dariusz Marcinkiewicz Cc: Daniel Vetter Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jun 11, 2019 at 8:35 PM Daniel Vetter wrote: > > On Tue, Jun 11, 2019 at 08:10:38PM +0800, Cheng-yi Chiang wrote: > > On Tue, Jun 4, 2019 at 3:24 PM Daniel Vetter wrote: > > > > > > On Tue, Jun 04, 2019 at 10:32:50AM +0800, Cheng-yi Chiang wrote: > > > > On Mon, Jun 3, 2019 at 4:09 PM Daniel Vetter wrote: > > > > > > > > > > On Mon, Jun 03, 2019 at 09:45:49AM +0200, Hans Verkuil wrote: > > > > > > On 6/3/19 6:32 AM, Cheng-Yi Chiang wrote: > > > > > > > From: Hans Verkuil > > > > > > > > > > > > > > Add support for HDMI hotplug and EDID notifiers, which is used to convey > > > > > > > information from HDMI drivers to their CEC and audio counterparts. > > > > > > > > > > > > > > Based on an earlier version from Russell King: > > > > > > > > > > > > > > https://patchwork.kernel.org/patch/9277043/ > > > > > > > > > > > > > > The hdmi_notifier is a reference counted object containing the HDMI state > > > > > > > of an HDMI device. > > > > > > > > > > > > > > When a new notifier is registered the current state will be reported to > > > > > > > that notifier at registration time. > > > > > > > > > > > > > > Based on Hans Verkuil's patch: > > > > > > > > > > > > > > https://patchwork.kernel.org/patch/9472521/ > > > > > > > > > > > > Erm, you are aware that this patch morphed into a CEC-specific notifier > > > > > > found in drivers/media/cec/cec-notifier.c? > > > > > > > > > > > > I don't think it makes sense to have two notifier implementations in the kernel. > > > > > > The original intention was to have the notifier deal with both CEC and ASoC > > > > > > notifications, but there was not enough interest for the ASoC bits at the time > > > > > > and it was dropped. > > > > > > > > > > > > I am planning changes to the cec-notifier API, I hope to work on that this > > > > > > week. I'll CC you when I post those. Those might be a good starting point > > > > > > to convert the cec-notifier to an hdmi-notifier as was originally intended. > > > > > > > > > > > > I've added your colleague Dariusz Marcinkiewicz to the CC list since he's been > > > > > > working on some nice cec-notifier improvements as well. > > > > > > > > > > We also have some interfaces for drm/alsa interactions around hdmi > > > > > already in drm/drm_audio_component.h, but it's not used by anything > > > > > outside of i915. Imo we should extend that, not reinvent a new wheel. > > > > > > > > > Hi Daniel, > > > > Thank you for the pointer. Looking at the ops, it seems that it is > > > > specific to HDA. > > > > I am not familiar with drm and HDA. I am not sure how applicable it > > > > would be to report jack status to ASoC. > > > > There is a use case in sound/soc/codecs/hdac_hdmi.c though so it > > > > should be possible. > > > > > > Currently hda is the only user, but the idea was to make it more generic. > > > Jack status in alsa is what drm calls connector status btw. > > > > > > So if we can take that as a baseline and extend it (probably needs some > > > registration boilerplate and helpers to look up the right endpoint using > > > of/dt for soc systems, we use component.c in i915/hda for this), that > > > would be great I think. > > > > > > > > Another note: notifiers considered evil, imo. Gets the job done for one > > > > > case, as soon as you have multiple devices and need to make sure you get > > > > > the update for the right one it all comes crashing down. Please create an > > > > > api which registers for updates from a specific device only, plus > > > > > something that has real callbacks (like the drm_audio_component.h thing we > > > > > started already). > > > > > > > > To clarify a bit, this hdmi-notifier indeed supports updating from a > > > > specific device only. > > > > hdmi_notifier_get takes a device and return the notifier. > > > > > > Hm I missed that, I thought it's global, so one of my usual notifier > > > concerns addressed. > > > > > > > It seems that a major difference between drm_audio_components and > > > > hdmi-notifier is that > > > > drm_audio_components defines all supported ops in drm_audio_component_audio_ops. > > > > On the other hand, hdmi-notifier passes different events using an enum > > > > like HDMI_CONNECTED and let listener handle different events. > > > > In this regard I agree with you that drm_audio_component is cleaner. > > > > Anyway, I will look into it a bit more and see how it works. > > > > > > Yeah I think if we could combine the approach, i.e. notifier side for > > > registration, some _ops structure for the actual notifications, then > > > there's a solid interface. I just really don't like the opaque void * > > > interface notifier provides, it encourages abuse way too much. > > > > > > Ofc the registration side would then no longer be based on the notifier > > > datastructure, list_head (like cec-notifier.c) of registeres devices with > > > their _ops structure should be enough. > > > -Daniel > > > > Hi Daniel, > > Yes, I agree the above statement that we should have a more solid interface. > > > > Hi Hans, > > I am not sure if I missed the patch. > > Do you have a estimated timeline for new cec-notifier interface you > > are working on? > > It seems that your PoC patch needs Dariusz's patch to work. > > I would like to seek your advice on whether I can proceed without your > > patch and Dariusz's patch. > > > > I looked through the patch from Dariusz > > > > https://lkml.org/lkml/2019/5/21/389 > > > > , and saw that you were thinking whether we should use cec-notifier > > for both HDMI and CEC. > > > > https://lkml.org/lkml/2019/5/24/298 > > > > Could you please let me know your latest thought on whether we should > > reuse cec-notifier? > > Nah, see later in that thread, I think cec and audio seem to be different > use-cases. > Ack > But definitely a good idea to sync with Dariusz, I forgot to pull the two > threads together. Thanks for doing that. > > > I agree with you that I should not proceed with hdmi-notifier. Reasons include: > > 1. Method like cec_notifier_parse_hdmi_phandle can be reused. It is > > error prone to memory leak if it is implemented by user, like the > > patch in hdmi-codec.c in this series did not handle the ref count. > > 2. cec-notifier has a simpler implementation of register / unregister > > because there is no call chain. I am not aware of the need for > > hdmi-notifier to support a chain of callbacks. So I think that call > > chain support can be removed. > > > > If I go ahead and add a new interface to register ops to handle > > connector status report from cec-notifer, based on current > > cec-notifier, do you think that would work ? > > I think it might work if I add another cec_notifier object inside > > dw-hdmi.c, but only for HDMI jack reporting, not for CEC related > > reporting. > > > > And after some investigation, I realize that my requirement is even > > simpler. I don't need hdmi_event_new_edid and hdmi_event_new_eld in my > > use case. > > Yeah, connector status is how we started with the drm/alsa interface in > i915 too, but later on had to extend it. I think eventually we'll need it > all, that's why I suggested to use that as the interface between drm and > alsa side, but augmented with some register/unregister and bind logic. > Hi Daniel, Sorry for the late reply. I spent some time investigating how drm_audio_component works. The coupling of HDA in drm_audio_component framework makes the register/unregister logic looks complicated to me as I don't use HDA in my use case. After some time, I found another patch series which also use component framework to communicate between drm and mei world. https://patchwork.kernel.org/patch/10824527/ And from that patch, I realized that I can follow the similar approach to register a master component on ALSA side, a slave component on DRM side, and use device and subcomponent to match them. I should be able to do this without touching anything specific to HDA. After that, DRM world should be able to use the ops in drm_audio_component_audio_ops to notify ALSA world some event when there is something happen in DRM world. Currently the ops like pin_eld_notify, pin2port are too specific to HDA. I think I can add an ops to drm_audio_component_audio_ops to convey connector status. I will work toward this approach these days. If you have other thought please let me know. Thanks! > > I just need to report the connector status from synopsys/dw-hdmi.c to > > codecs/hdmi-codec.c for codec driver to update the jack status. > > Do you think I can proceed in this direction ? Or do you prefer I wait > > for a while and work on it based on your new patch. > > I think most important part here is that we sync across all the different > people pushing for better drm/alsa integration. What the solution looks > like in the end doesn't matter much imo, as long as we don't end up with 3 > different things :-) Totally agree. Thanks again! > > Cheers, Daniel > > > > > Thanks a lot! > > > > > > > > > > > > > > > Thanks again! > > > > > > > > > -Daniel > > > > > > > > > > > > > > > > > Regards, > > > > > > > > > > > > Hans > > > > > > > > > > > > > > > > > > > > Modified by Cheng-Yi Chiang: > > > > > > > - Add a section in MAINTAINER. > > > > > > > - Changes connected and has_eld to bitfield of unsigned int. > > > > > > > - Other minor fixes to pass checkpatch.pl --strict checks. > > > > > > > > > > > > > > Signed-off-by: Hans Verkuil > > > > > > > Acked-by: Philipp Zabel > > > > > > > Signed-off-by: Cheng-Yi Chiang > > > > > > > --- > > > > > > > The original patch is at > > > > > > > https://lore.kernel.org/linux-arm-kernel/20161213150813.37966-2-hverkuil@xs4all.nl > > > > > > > > > > > > > > MAINTAINERS | 6 ++ > > > > > > > drivers/video/Kconfig | 3 + > > > > > > > drivers/video/Makefile | 1 + > > > > > > > drivers/video/hdmi-notifier.c | 145 ++++++++++++++++++++++++++++++++++ > > > > > > > include/linux/hdmi-notifier.h | 112 ++++++++++++++++++++++++++ > > > > > > > 5 files changed, 267 insertions(+) > > > > > > > create mode 100644 drivers/video/hdmi-notifier.c > > > > > > > create mode 100644 include/linux/hdmi-notifier.h > > > > > > > > > > > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > > > > > > index 5cfbea4ce575..ffb7376f9509 100644 > > > > > > > --- a/MAINTAINERS > > > > > > > +++ b/MAINTAINERS > > > > > > > @@ -16676,6 +16676,12 @@ W: https://linuxtv.org > > > > > > > S: Maintained > > > > > > > F: drivers/media/platform/vicodec/* > > > > > > > > > > > > > > +VIDEO FRAMEWORK > > > > > > > +M: Hans Verkuil > > > > > > > +L: linux-media@vger.kernel.org > > > > > > > +F: drivers/video/hdmi-notifier.* > > > > > > > +S: Maintained > > > > > > > + > > > > > > > VIDEO MULTIPLEXER DRIVER > > > > > > > M: Philipp Zabel > > > > > > > L: linux-media@vger.kernel.org > > > > > > > diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig > > > > > > > index 83d3d271ca15..000ba9bc0ae7 100644 > > > > > > > --- a/drivers/video/Kconfig > > > > > > > +++ b/drivers/video/Kconfig > > > > > > > @@ -34,6 +34,9 @@ config VIDEOMODE_HELPERS > > > > > > > config HDMI > > > > > > > bool > > > > > > > > > > > > > > +config HDMI_NOTIFIERS > > > > > > > + bool > > > > > > > + > > > > > > > endif # HAS_IOMEM > > > > > > > > > > > > > > if VT > > > > > > > diff --git a/drivers/video/Makefile b/drivers/video/Makefile > > > > > > > index df7650adede9..eff4736102ca 100644 > > > > > > > --- a/drivers/video/Makefile > > > > > > > +++ b/drivers/video/Makefile > > > > > > > @@ -1,6 +1,7 @@ > > > > > > > # SPDX-License-Identifier: GPL-2.0 > > > > > > > obj-$(CONFIG_VGASTATE) += vgastate.o > > > > > > > obj-$(CONFIG_HDMI) += hdmi.o > > > > > > > +obj-$(CONFIG_HDMI_NOTIFIERS) += hdmi-notifier.o > > > > > > > > > > > > > > obj-$(CONFIG_VT) += console/ > > > > > > > obj-$(CONFIG_FB_STI) += console/ > > > > > > > diff --git a/drivers/video/hdmi-notifier.c b/drivers/video/hdmi-notifier.c > > > > > > > new file mode 100644 > > > > > > > index 000000000000..d1eedf661648 > > > > > > > --- /dev/null > > > > > > > +++ b/drivers/video/hdmi-notifier.c > > > > > > > @@ -0,0 +1,145 @@ > > > > > > > +// SPDX-License-Identifier: GPL-2.0 > > > > > > > +/* hdmi-notifier.c - notify interested parties of (dis)connect and EDID > > > > > > > + * events > > > > > > > + * > > > > > > > + * Copyright 2016 Russell King > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. > > > > > > > + * All rights reserved. > > > > > > > + */ > > > > > > > + > > > > > > > +#include > > > > > > > +#include > > > > > > > +#include > > > > > > > +#include > > > > > > > +#include > > > > > > > + > > > > > > > +static LIST_HEAD(hdmi_notifiers); > > > > > > > +static DEFINE_MUTEX(hdmi_notifiers_lock); > > > > > > > + > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev) > > > > > > > +{ > > > > > > > + struct hdmi_notifier *n; > > > > > > > + > > > > > > > + mutex_lock(&hdmi_notifiers_lock); > > > > > > > + list_for_each_entry(n, &hdmi_notifiers, head) { > > > > > > > + if (n->dev == dev) { > > > > > > > + mutex_unlock(&hdmi_notifiers_lock); > > > > > > > + kref_get(&n->kref); > > > > > > > + return n; > > > > > > > + } > > > > > > > + } > > > > > > > + n = kzalloc(sizeof(*n), GFP_KERNEL); > > > > > > > + if (!n) > > > > > > > + goto unlock; > > > > > > > + n->dev = dev; > > > > > > > + mutex_init(&n->lock); > > > > > > > + BLOCKING_INIT_NOTIFIER_HEAD(&n->notifiers); > > > > > > > + kref_init(&n->kref); > > > > > > > + list_add_tail(&n->head, &hdmi_notifiers); > > > > > > > +unlock: > > > > > > > + mutex_unlock(&hdmi_notifiers_lock); > > > > > > > + return n; > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_get); > > > > > > > + > > > > > > > +static void hdmi_notifier_release(struct kref *kref) > > > > > > > +{ > > > > > > > + struct hdmi_notifier *n = > > > > > > > + container_of(kref, struct hdmi_notifier, kref); > > > > > > > + > > > > > > > + mutex_lock(&hdmi_notifiers_lock); > > > > > > > + list_del(&n->head); > > > > > > > + mutex_unlock(&hdmi_notifiers_lock); > > > > > > > + kfree(n->edid); > > > > > > > + kfree(n); > > > > > > > +} > > > > > > > + > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n) > > > > > > > +{ > > > > > > > + kref_put(&n->kref, hdmi_notifier_release); > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_put); > > > > > > > + > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb) > > > > > > > +{ > > > > > > > + int ret = blocking_notifier_chain_register(&n->notifiers, nb); > > > > > > > + > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > + kref_get(&n->kref); > > > > > > > + mutex_lock(&n->lock); > > > > > > > + if (n->connected) { > > > > > > > + blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n); > > > > > > > + if (n->edid_size) > > > > > > > + blocking_notifier_call_chain(&n->notifiers, > > > > > > > + HDMI_NEW_EDID, n); > > > > > > > + if (n->has_eld) > > > > > > > + blocking_notifier_call_chain(&n->notifiers, > > > > > > > + HDMI_NEW_ELD, n); > > > > > > > + } > > > > > > > + mutex_unlock(&n->lock); > > > > > > > + return 0; > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_register); > > > > > > > + > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, struct notifier_block *nb) > > > > > > > +{ > > > > > > > + int ret = blocking_notifier_chain_unregister(&n->notifiers, nb); > > > > > > > + > > > > > > > + if (ret == 0) > > > > > > > + hdmi_notifier_put(n); > > > > > > > + return ret; > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_notifier_unregister); > > > > > > > + > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n) > > > > > > > +{ > > > > > > > + mutex_lock(&n->lock); > > > > > > > + n->connected = true; > > > > > > > + blocking_notifier_call_chain(&n->notifiers, HDMI_CONNECTED, n); > > > > > > > + mutex_unlock(&n->lock); > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_connect); > > > > > > > + > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n) > > > > > > > +{ > > > > > > > + mutex_lock(&n->lock); > > > > > > > + n->connected = false; > > > > > > > + n->has_eld = false; > > > > > > > + n->edid_size = 0; > > > > > > > + blocking_notifier_call_chain(&n->notifiers, HDMI_DISCONNECTED, n); > > > > > > > + mutex_unlock(&n->lock); > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_disconnect); > > > > > > > + > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size) > > > > > > > +{ > > > > > > > + mutex_lock(&n->lock); > > > > > > > + if (n->edid_allocated_size < size) { > > > > > > > + void *p = kmalloc(size, GFP_KERNEL); > > > > > > > + > > > > > > > + if (!p) { > > > > > > > + mutex_unlock(&n->lock); > > > > > > > + return -ENOMEM; > > > > > > > + } > > > > > > > + kfree(n->edid); > > > > > > > + n->edid = p; > > > > > > > + n->edid_allocated_size = size; > > > > > > > + } > > > > > > > + memcpy(n->edid, edid, size); > > > > > > > + n->edid_size = size; > > > > > > > + blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_EDID, n); > > > > > > > + mutex_unlock(&n->lock); > > > > > > > + return 0; > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_edid); > > > > > > > + > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]) > > > > > > > +{ > > > > > > > + mutex_lock(&n->lock); > > > > > > > + memcpy(n->eld, eld, sizeof(n->eld)); > > > > > > > + n->has_eld = true; > > > > > > > + blocking_notifier_call_chain(&n->notifiers, HDMI_NEW_ELD, n); > > > > > > > + mutex_unlock(&n->lock); > > > > > > > +} > > > > > > > +EXPORT_SYMBOL_GPL(hdmi_event_new_eld); > > > > > > > diff --git a/include/linux/hdmi-notifier.h b/include/linux/hdmi-notifier.h > > > > > > > new file mode 100644 > > > > > > > index 000000000000..c8f35110e3e3 > > > > > > > --- /dev/null > > > > > > > +++ b/include/linux/hdmi-notifier.h > > > > > > > @@ -0,0 +1,112 @@ > > > > > > > +/* SPDX-License-Identifier: GPL-2.0 > > > > > > > + * hdmi-notifier.h - notify interested parties of (dis)connect and EDID > > > > > > > + * events > > > > > > > + * > > > > > > > + * Copyright 2016 Russell King > > > > > > > + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. > > > > > > > + * All rights reserved. > > > > > > > + */ > > > > > > > + > > > > > > > +#ifndef LINUX_HDMI_NOTIFIER_H > > > > > > > +#define LINUX_HDMI_NOTIFIER_H > > > > > > > + > > > > > > > +#include > > > > > > > +#include > > > > > > > +#include > > > > > > > + > > > > > > > +enum { > > > > > > > + HDMI_CONNECTED, > > > > > > > + HDMI_DISCONNECTED, > > > > > > > + HDMI_NEW_EDID, > > > > > > > + HDMI_NEW_ELD, > > > > > > > +}; > > > > > > > + > > > > > > > +struct device; > > > > > > > + > > > > > > > +struct hdmi_notifier { > > > > > > > + /* Lock to protect callback registration and notification. */ > > > > > > > + struct mutex lock; > > > > > > > + struct list_head head; > > > > > > > + struct kref kref; > > > > > > > + struct blocking_notifier_head notifiers; > > > > > > > + struct device *dev; > > > > > > > + > > > > > > > + /* Current state */ > > > > > > > + unsigned int connected : 1; > > > > > > > + unsigned int has_eld : 1; > > > > > > > + unsigned char eld[128]; > > > > > > > + void *edid; > > > > > > > + size_t edid_size; > > > > > > > + size_t edid_allocated_size; > > > > > > > +}; > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_notifier_get - find or create a new hdmi_notifier for the given device. > > > > > > > + * @dev: device that sends the events. > > > > > > > + * > > > > > > > + * If a notifier for device @dev already exists, then increase the refcount > > > > > > > + * and return that notifier. > > > > > > > + * > > > > > > > + * If it doesn't exist, then allocate a new notifier struct and return a > > > > > > > + * pointer to that new struct. > > > > > > > + * > > > > > > > + * Return NULL if the memory could not be allocated. > > > > > > > + */ > > > > > > > +struct hdmi_notifier *hdmi_notifier_get(struct device *dev); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_notifier_put - decrease refcount and delete when the refcount reaches 0. > > > > > > > + * @n: notifier > > > > > > > + */ > > > > > > > +void hdmi_notifier_put(struct hdmi_notifier *n); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_notifier_register - register the notifier with the notifier_block. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * @nb: the notifier_block > > > > > > > + */ > > > > > > > +int hdmi_notifier_register(struct hdmi_notifier *n, struct notifier_block *nb); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_notifier_unregister - unregister the notifier with the notifier_block. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * @nb: the notifier_block > > > > > > > + */ > > > > > > > +int hdmi_notifier_unregister(struct hdmi_notifier *n, > > > > > > > + struct notifier_block *nb); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_event_connect - send a connect event. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * > > > > > > > + * Send an HDMI_CONNECTED event to any registered parties. > > > > > > > + */ > > > > > > > +void hdmi_event_connect(struct hdmi_notifier *n); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_event_disconnect - send a disconnect event. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * > > > > > > > + * Send an HDMI_DISCONNECTED event to any registered parties. > > > > > > > + */ > > > > > > > +void hdmi_event_disconnect(struct hdmi_notifier *n); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_event_new_edid - send a new EDID event. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * > > > > > > > + * Send an HDMI_NEW_EDID event to any registered parties. > > > > > > > + * This function will make a copy the EDID so it can return -ENOMEM if > > > > > > > + * no memory could be allocated. > > > > > > > + */ > > > > > > > +int hdmi_event_new_edid(struct hdmi_notifier *n, const void *edid, size_t size); > > > > > > > + > > > > > > > +/** > > > > > > > + * hdmi_event_new_eld - send a new ELD event. > > > > > > > + * @n: the HDMI notifier > > > > > > > + * > > > > > > > + * Send an HDMI_NEW_ELD event to any registered parties. > > > > > > > + */ > > > > > > > +void hdmi_event_new_eld(struct hdmi_notifier *n, const u8 eld[128]); > > > > > > > + > > > > > > > +#endif > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > Daniel Vetter > > > > > Software Engineer, Intel Corporation > > > > > http://blog.ffwll.ch > > > > > > -- > > > Daniel Vetter > > > Software Engineer, Intel Corporation > > > http://blog.ffwll.ch > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch