Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp7028560pxv; Fri, 30 Jul 2021 08:21:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzMjxrTnaIVK27WnAZqB5sHRD7vwBpbIavQYGoc9YNtesAQ5ukgMli0697E371Cn1Zqu8kr X-Received: by 2002:a50:954c:: with SMTP id v12mr3536833eda.313.1627658482835; Fri, 30 Jul 2021 08:21:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627658482; cv=none; d=google.com; s=arc-20160816; b=gzbAKqgVWo/aeKau6cRBdjI3emjp2W029EzOWijwPw75OOEdr+i+jxlN8HkXIdK0Ko hXykj2W+EvP2fSC5ZGIiwF/kExXlOy1P8iqWZ8WVSlmBZ4bvARQexTzsqAL3VbZl4xqA karv8BPK0nu9UFhCbwAReo47TqOqpU0lLA7C2iubp8Z1+PCbrafQ5tOOqi3Oc1ijSywJ cWDJD0Mjt4+qXC9C1fUxgGza0pz+ClXtAzd9GtKXWeibwM7OkRbCTpW3ySnUNt89edi0 QNvmeFk0VTkSZton4LcT0REouZSBmfpjNA6rbJKme+AJXarFT7LXlNaW4FLqQLm/gam5 zE3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=x+8N5rtoDpowqZ1EFeAifI9PMkD9XbHHnj9C9dge1/4=; b=DglqUHhTyULoW9Ft3p76jwjxCC//jhya1/aN9bP5Zzt7U/P8URn2tM+9E0xOitr88g GYAGBht7gAK0UpHrcsQ8RmrNVtN9i3zp+Zkt4y5h1WprCEyhrT3O6QeWBFOgrZdzWIyd OS2xE+lTJI/94dmV+fO0tMtjYt6BIEhMpTdybeyP4a9l8QEKmKGjPG1zL+beIom3W/F/ GQ/jnbEQm5ErWE4D3/ucXsfZaHgeogFRDtpboL++x7rM4HkBquy7nPwIkRSiauzR9E8q bNGQh9/zkQBONh91QeT44wSSrT/T5YG/r0k7re/ZRMb1+cSuZgkIRl6K5aNd/x6WuXMe qxJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="Ix/ajP3H"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l15si1777659eji.174.2021.07.30.08.20.58; Fri, 30 Jul 2021 08:21:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b="Ix/ajP3H"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239654AbhG3PTe (ORCPT + 99 others); Fri, 30 Jul 2021 11:19:34 -0400 Received: from mx0a-001ae601.pphosted.com ([67.231.149.25]:64268 "EHLO mx0b-001ae601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S239500AbhG3PTb (ORCPT ); Fri, 30 Jul 2021 11:19:31 -0400 Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 16UEL0dg003614; Fri, 30 Jul 2021 10:19:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=x+8N5rtoDpowqZ1EFeAifI9PMkD9XbHHnj9C9dge1/4=; b=Ix/ajP3HYUi714LESobw6J4JU0bklJD4API6XtkV+9Jh0S8Sp/Dbpj1io5xyq8pESvP2 tXo7TmznSu4pT0CNnjGOb4fH/Y3Ykv3XiO6aFcRHUXgZgm8n9gesF90W8N6MUiA2Lz8r hejvHQG6h66i8DpS1NP0tsHTksUPSvxy+KLo0m6M3C4IpncDGB/x/mmJvJULAn7SUFI9 lllYMIxqhdBw85TnczAnwWSkfhfLin+3+Bb1X2hpWAPpifVZMZf0DmR5Cb9C+2xXWjnf uVBYnQPEaTw3tcYYIDCi8RwOu14JLoYsUlYb2J6ytxi8S7Ar1iM8OE+eTGoE9U0l/PhJ 7w== Received: from ediex01.ad.cirrus.com ([87.246.76.36]) by mx0a-001ae601.pphosted.com with ESMTP id 3a41wd181n-7 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Fri, 30 Jul 2021 10:19:18 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2242.4; Fri, 30 Jul 2021 16:19:09 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2242.4 via Frontend Transport; Fri, 30 Jul 2021 16:19:09 +0100 Received: from vitaly-Inspiron-5415.ad.cirrus.com (unknown [198.90.238.32]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 8D10246E; Fri, 30 Jul 2021 15:19:09 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai CC: , , , Lucas Tanure , Stefan Binding Subject: [PATCH v3 13/27] ALSA: hda/cs8409: Dont disable I2C clock between consecutive accesses Date: Fri, 30 Jul 2021 16:18:30 +0100 Message-ID: <20210730151844.7873-14-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210730151844.7873-1-vitalyr@opensource.cirrus.com> References: <20210730151844.7873-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: c1JEct2FLvZptsQHDHbNQn4lAWAHNWgZ X-Proofpoint-ORIG-GUID: c1JEct2FLvZptsQHDHbNQn4lAWAHNWgZ X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 impostorscore=0 spamscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 lowpriorityscore=0 malwarescore=0 phishscore=0 bulkscore=0 suspectscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2107140000 definitions=main-2107300102 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lucas Tanure Only disable I2C clock 25 ms after not being used. The current implementation enables and disables the I2C clock for each I2C transaction. Each enable/disable call requires two verb transactions. This means each I2C transaction requires a total of four verb transactions to enable and disable the clock. However, if there are multiple consecutive I2C transactions, it is not necessary to enable and disable the clock each time, instead it is more efficient to enable the clock for the first transaction, and disable it after the final transaction, which would improve performance. This is achieved by using a timeout which disables the clock if no request to enable the clock has occurred for 25 ms. Signed-off-by: Lucas Tanure Signed-off-by: Vitaly Rodionov Signed-off-by: Stefan Binding --- Changes in v2: - Improved delayed work start/cancel implementation, and re-worked commit message adding more explanation why this was required. Changes in v3: - Cancel the disable timer, but do not wait for any running disable functions to finish. If the disable timer runs out before cancel, the delayed work thread will be blocked, waiting for the mutex to become unlocked. This mutex will be locked for the duration of any i2c transaction, so the disable function will run to completion immediately afterwards in the scenario. The next enable call will re-enable the clock, regardless. sound/pci/hda/patch_cs8409.c | 64 ++++++++++++++++++++++++++---------- sound/pci/hda/patch_cs8409.h | 4 +++ 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c index 08205c19698c..1c75aa262ebc 100644 --- a/sound/pci/hda/patch_cs8409.c +++ b/sound/pci/hda/patch_cs8409.c @@ -53,7 +53,9 @@ static struct cs8409_spec *cs8409_alloc_spec(struct hda_codec *codec) if (!spec) return NULL; codec->spec = spec; + spec->codec = codec; codec->power_save_node = 1; + INIT_DELAYED_WORK(&spec->i2c_clk_work, cs8409_disable_i2c_clock); snd_hda_gen_spec_init(&spec->gen); return spec; @@ -72,21 +74,45 @@ static inline void cs8409_vendor_coef_set(struct hda_codec *codec, unsigned int snd_hda_codec_write(codec, CS8409_PIN_VENDOR_WIDGET, 0, AC_VERB_SET_PROC_COEF, coef); } -/** +/* + * cs8409_disable_i2c_clock - Worker that disable the I2C Clock after 25ms without use + */ +static void cs8409_disable_i2c_clock(struct work_struct *work) +{ + struct cs8409_spec *spec = container_of(work, struct cs8409_spec, i2c_clk_work.work); + + mutex_lock(&spec->cs8409_i2c_mux); + if (spec->i2c_clck_enabled) { + cs8409_vendor_coef_set(spec->codec, 0x0, + cs8409_vendor_coef_get(spec->codec, 0x0) & 0xfffffff7); + spec->i2c_clck_enabled = 0; + } + mutex_unlock(&spec->cs8409_i2c_mux); +} + +/* * cs8409_enable_i2c_clock - Enable I2C clocks * @codec: the codec instance - * @enable: Enable or disable I2C clocks - * * Enable or Disable I2C clocks. + * This must be called when the i2c mutex is locked. */ -static void cs8409_enable_i2c_clock(struct hda_codec *codec, unsigned int enable) +static void cs8409_enable_i2c_clock(struct hda_codec *codec) { - unsigned int retval; - unsigned int newval; + struct cs8409_spec *spec = codec->spec; + + /* Cancel the disable timer, but do not wait for any running disable functions to finish. + * If the disable timer runs out before cancel, the delayed work thread will be blocked, + * waiting for the mutex to become unlocked. This mutex will be locked for the duration of + * any i2c transaction, so the disable function will run to completion immediately + * afterwards in the scenario. The next enable call will re-enable the clock, regardless. + */ + cancel_delayed_work(&spec->i2c_clk_work); - retval = cs8409_vendor_coef_get(codec, 0x0); - newval = (enable) ? (retval | 0x8) : (retval & 0xfffffff7); - cs8409_vendor_coef_set(codec, 0x0, newval); + if (!spec->i2c_clck_enabled) { + cs8409_vendor_coef_set(codec, 0x0, cs8409_vendor_coef_get(codec, 0x0) | 0x8); + spec->i2c_clck_enabled = 1; + } + queue_delayed_work(system_power_efficient_wq, &spec->i2c_clk_work, msecs_to_jiffies(25)); } /** @@ -134,7 +160,7 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un if (spec->cs42l42_suspended) return -EPERM; - cs8409_enable_i2c_clock(codec, 1); + cs8409_enable_i2c_clock(codec); cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, i2c_address); if (paged) { @@ -157,8 +183,6 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un /* Register in bits 15-8 and the data in 7-0 */ read_data = cs8409_vendor_coef_get(codec, CS8409_I2C_QREAD); - cs8409_enable_i2c_clock(codec, 0); - return read_data & 0x0ff; } @@ -182,7 +206,7 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u if (spec->cs42l42_suspended) return -EPERM; - cs8409_enable_i2c_clock(codec, 1); + cs8409_enable_i2c_clock(codec); cs8409_vendor_coef_set(codec, CS8409_I2C_ADDR, i2c_address); if (paged) { @@ -203,8 +227,6 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u return -EIO; } - cs8409_enable_i2c_clock(codec, 0); - return 0; } @@ -551,6 +573,14 @@ static int cs8409_suspend(struct hda_codec *codec) } #endif +static void cs8409_free(struct hda_codec *codec) +{ + struct cs8409_spec *spec = codec->spec; + + cancel_delayed_work_sync(&spec->i2c_clk_work); + snd_hda_gen_free(codec); +} + /* Vendor specific HW configuration * PLL, ASP, I2C, SPI, GPIOs, DMIC etc... */ @@ -633,7 +663,7 @@ static const struct hda_codec_ops cs8409_cs42l42_patch_ops = { .build_controls = cs8409_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cs8409_cs42l42_init, - .free = snd_hda_gen_free, + .free = cs8409_free, .unsol_event = cs8409_jack_unsol_event, #ifdef CONFIG_PM .suspend = cs8409_suspend, @@ -785,7 +815,7 @@ static int patch_cs8409(struct hda_codec *codec) err = cs8409_parse_auto_config(codec); if (err < 0) { - snd_hda_gen_free(codec); + cs8409_free(codec); return err; } diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h index bf0e8a4cc4cc..542582c213d2 100644 --- a/sound/pci/hda/patch_cs8409.h +++ b/sound/pci/hda/patch_cs8409.h @@ -11,6 +11,7 @@ #include #include +#include #include #include "hda_local.h" #include "hda_auto_parser.h" @@ -267,6 +268,7 @@ struct cs8409_cir_param { struct cs8409_spec { struct hda_gen_spec gen; + struct hda_codec *codec; unsigned int gpio_mask; unsigned int gpio_dir; @@ -278,6 +280,8 @@ struct cs8409_spec { s8 vol[CS42L42_VOLUMES]; struct mutex cs8409_i2c_mux; + unsigned int i2c_clck_enabled; + struct delayed_work i2c_clk_work; /* verb exec op override */ int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, -- 2.25.1