From patchwork Wed Nov 11 08:39:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: libin.yang@linux.intel.com X-Patchwork-Id: 7594511 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 312B89F2F7 for ; Wed, 11 Nov 2015 08:41:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4AB3E203B8 for ; Wed, 11 Nov 2015 08:41:08 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id E7C6C203A1 for ; Wed, 11 Nov 2015 08:41:06 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id AC5652657DD; Wed, 11 Nov 2015 09:41:05 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 04B1C2605BD; Wed, 11 Nov 2015 09:40:58 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id D2BF52605EE; Wed, 11 Nov 2015 09:40:56 +0100 (CET) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by alsa0.perex.cz (Postfix) with ESMTP id 7EEB82605B1 for ; Wed, 11 Nov 2015 09:40:49 +0100 (CET) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 11 Nov 2015 00:40:48 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.20,274,1444719600"; d="scan'208";a="848305311" Received: from younglee-grantley.sh.intel.com ([10.239.159.137]) by fmsmga002.fm.intel.com with ESMTP; 11 Nov 2015 00:40:43 -0800 From: libin.yang@linux.intel.com To: alsa-devel@alsa-project.org, tiwai@suse.de Date: Wed, 11 Nov 2015 16:39:09 +0800 Message-Id: <1447231149-88326-1-git-send-email-libin.yang@linux.intel.com> X-Mailer: git-send-email 1.9.1 Cc: libin.yang@intel.com, Libin Yang , mengdong.lin@linux.intel.com Subject: [alsa-devel] [PATCH] ALSA - hda: hdmi flag to stop playback when monitor is disconnected X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 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-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Libin Yang Add a flag that user can decide to stop HDMI/DP playback when the corresponding monitor is disconnected and refuse to open PCM if there is no monitor connected. Background: When a monitor is disconnected and a new monitor is connected, the parameters of the 2 monitors may be different. Audio driver need handle this situation. Besides, stopping playback when monitor is disconnected will help to save the power. Signed-off-by: Libin Yang --- sound/pci/hda/patch_hdmi.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f503a88..4f5023a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -47,6 +47,11 @@ static bool static_hdmi_pcm; module_param(static_hdmi_pcm, bool, 0644); MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); +static bool hdmi_pcm_stop_on_disconnect; +module_param(hdmi_pcm_stop_on_disconnect, bool, 0644); +MODULE_PARM_DESC(hdmi_pcm_stop_on_disconnect, + "Stop PCM when monitor is disconnected"); + #define is_haswell(codec) ((codec)->core.vendor_id == 0x80862807) #define is_broadwell(codec) ((codec)->core.vendor_id == 0x80862808) #define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809) @@ -72,6 +77,7 @@ struct hdmi_spec_per_cvt { struct hdmi_spec_per_pin { hda_nid_t pin_nid; + int pin_idx; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; int mux_idx; @@ -1456,6 +1462,9 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_pin = get_pin(spec, pin_idx); eld = &per_pin->sink_eld; + if (hdmi_pcm_stop_on_disconnect && !eld->eld_valid) + return -ENODEV; + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); if (err < 0) return err; @@ -1529,6 +1538,28 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } +static void hdmi_pcm_stop(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + struct hda_codec *codec = per_pin->codec; + struct snd_pcm_substream *substream; + int pin_idx = per_pin->pin_idx; + + if (!hdmi_pcm_stop_on_disconnect) + return; + + substream = get_pcm_rec(spec, pin_idx)->pcm->streams[0].substream; + + snd_pcm_stream_lock_irq(substream); + if (substream && substream->runtime && + snd_pcm_running(substream)) { + codec_info(codec, + "HDMI: monitor disconnected, try to stop playback\n"); + snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); + } + snd_pcm_stream_unlock_irq(substream); +} + static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_jack_tbl *jack; @@ -1586,6 +1617,8 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) } } + if (!eld->eld_valid) + hdmi_pcm_stop(spec, per_pin); if (pin_eld->eld_valid != eld->eld_valid) eld_changed = true; @@ -1680,6 +1713,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) return -ENOMEM; per_pin->pin_nid = pin_nid; + per_pin->pin_idx = pin_idx; per_pin->non_pcm = false; err = hdmi_read_pin_conn(codec, pin_idx);