From patchwork Tue Apr 2 08:35:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yang, Libin" X-Patchwork-Id: 10881241 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 097F317E1 for ; Tue, 2 Apr 2019 08:52:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E325128595 for ; Tue, 2 Apr 2019 08:52:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D6A74286D5; Tue, 2 Apr 2019 08:52:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CF09A28595 for ; Tue, 2 Apr 2019 08:52:45 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 86F2E869; Tue, 2 Apr 2019 10:51:53 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 86F2E869 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1554195163; bh=raeShKytRNrnxnDn/eI62pycsc8/8K2t5bYeLwKW1kc=; h=From:To:Date:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From; b=Oc9T0GBeRD6BwbBjkRwb7wzMRTpkz8+8M6AH9YKl/GhAF+POlYcNZYJJbsmwlCaf4 Z2rGj/RUV+/83hARdPmAKOGiwGYOIWT+aM8MXr2hm6GSKgvKaWpE7pzHx2EZTRbjVN h/hb+ATeLlPuRNC0TgAsZ87vpSocYpZS4ks2Ru3g= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B79D5F89631; Tue, 2 Apr 2019 10:51:52 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7DF8EF80715; Tue, 2 Apr 2019 10:51:50 +0200 (CEST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id CB9B1F80715 for ; Tue, 2 Apr 2019 10:51:45 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz CB9B1F80715 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 02 Apr 2019 01:51:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,300,1549958400"; d="scan'208";a="157960846" Received: from younglee-svr.sh.intel.com ([10.239.159.31]) by fmsmga004.fm.intel.com with ESMTP; 02 Apr 2019 01:51:41 -0700 From: libin.yang@intel.com To: alsa-devel@alsa-project.org, tiwai@suse.de, broonie@kernel.org, pierre-louis.bossart@linux.intel.com Date: Tue, 2 Apr 2019 16:35:32 +0800 Message-Id: <1554194132-2177-1-git-send-email-libin.yang@intel.com> X-Mailer: git-send-email 2.7.4 Cc: libin.yang@intel.com Subject: [alsa-devel] [RFC PATCH V2] ASoC: hdac_hdmi: add device PM dependency X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Libin Yang HDMI audio codec register operation depends on the display audio power domain. The hdmi audio codec dapm event callback must be called after display audio power is turned on. Add hdac_hdmi_device_link_add/del() in HDMI audio codec driver. The customer audio driver, such as cAVS/SST and SOF audio driver, can call the function to set/remove the audio power dependency. Signed-off-by: Libin Yang --- sound/soc/codecs/hdac_hdmi.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/hdac_hdmi.h | 7 ++++ 2 files changed, 93 insertions(+) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 5eeb0fe..7490219 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -133,6 +133,12 @@ struct hdac_hdmi_drv_data { int port_num; }; +/* each supplier - consumer pair has one instance of this structure */ +struct hdac_hdmi_dev_link { + struct list_head head; + struct device_link *link; +}; + struct hdac_hdmi_priv { struct hdac_device *hdev; struct snd_soc_component *component; @@ -141,10 +147,12 @@ struct hdac_hdmi_priv { struct list_head pin_list; struct list_head cvt_list; struct list_head pcm_list; + struct list_head link_list; /* supplier - consumer pairs */ int num_pin; int num_cvt; int num_ports; struct mutex pin_mutex; + struct mutex link_mutex; struct hdac_chmap chmap; struct hdac_hdmi_drv_data *drv_data; struct snd_soc_dai_driver *dai_drv; @@ -1792,6 +1800,72 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, } EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init); +/** + * hdac_hdmi_device_link_add - add a link between consumer and hdev device + * @consumer: Consumer end of the link. + * @component: The hdmi codec component. + * @flags: Link flags. + * + * If there is a consumer of the hdev device, which means a consumer device + * operation depends on the hdev device power status, the consumer device + * driver should call this function. It supports several consumers depending + * on the same hdmi codec hdev device. + * + * Return: pointer of device_link, or NULL if fails to create device_link + */ +struct device_link * +hdac_hdmi_device_link_add(struct device *consumer, + struct snd_soc_component *component, + u32 flags) +{ + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; + struct hdac_hdmi_dev_link *dev_link; + + dev_link = devm_kzalloc(&hdev->dev, sizeof(*dev_link), GFP_KERNEL); + if (!dev_link) + return NULL; + + dev_link->link = device_link_add(consumer, &hdev->dev, flags); + + mutex_lock(&hdmi->link_mutex); + if (dev_link->link) + list_add(&dev_link->head, &hdmi->link_list); + mutex_unlock(&hdmi->link_mutex); + + return dev_link->link; +} +EXPORT_SYMBOL_GPL(hdac_hdmi_device_link_add); + +/** + * hdac_hdmi_device_link_del - del the link between consumer and hdev device + * @consumer: Consumer end of the link. + * @component: The hdmi codec component. + * + * If the consumer doesn't need the dependency any longer, the consumer device + * driver should call this function to release the device_link + */ +void hdac_hdmi_device_link_del(struct device *consumer, + struct snd_soc_component *component) +{ + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_device *hdev = hdmi->hdev; + struct hdac_hdmi_dev_link *dev_link, *tmp; + + mutex_lock(&hdmi->link_mutex); + list_for_each_entry_safe(dev_link, tmp, &hdmi->link_list, head) { + if (dev_link->link->consumer == consumer && + dev_link->link->supplier == &hdev->dev) { + device_link_del(dev_link->link); + list_del(&dev_link->head); + devm_kfree(&hdev->dev, dev_link); + return; + } + } + mutex_unlock(&hdmi->link_mutex); +} +EXPORT_SYMBOL_GPL(hdac_hdmi_device_link_del); + static void hdac_hdmi_present_sense_all_pins(struct hdac_device *hdev, struct hdac_hdmi_priv *hdmi, bool detect_pin_caps) { @@ -2031,7 +2105,9 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) INIT_LIST_HEAD(&hdmi_priv->pin_list); INIT_LIST_HEAD(&hdmi_priv->cvt_list); INIT_LIST_HEAD(&hdmi_priv->pcm_list); + INIT_LIST_HEAD(&hdmi_priv->link_list); mutex_init(&hdmi_priv->pin_mutex); + mutex_init(&hdmi_priv->link_mutex); /* * Turned off in the runtime_suspend during the first explicit @@ -2058,8 +2134,18 @@ static int hdac_hdmi_dev_probe(struct hdac_device *hdev) static int hdac_hdmi_dev_remove(struct hdac_device *hdev) { + struct hdac_hdmi_dev_link *dev_link, *tmp; + struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); + snd_hdac_display_power(hdev->bus, hdev->addr, false); + mutex_unlock(&hdmi->link_mutex); + list_for_each_entry_safe(dev_link, tmp, &hdmi->link_list, head) { + device_link_del(dev_link->link); + list_del(&dev_link->head); + } + mutex_unlock(&hdmi->link_mutex); + return 0; } diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h index 4fa2fc9..e877167 100644 --- a/sound/soc/codecs/hdac_hdmi.h +++ b/sound/soc/codecs/hdac_hdmi.h @@ -7,4 +7,11 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, int hdac_hdmi_jack_port_init(struct snd_soc_component *component, struct snd_soc_dapm_context *dapm); + +struct device_link * +hdac_hdmi_device_link_add(struct device *consumer, + struct snd_soc_component *component, + u32 flags); +void hdac_hdmi_device_link_del(struct device *consumer, + struct snd_soc_component *component); #endif /* __HDAC_HDMI_H__ */