From patchwork Mon May 18 20:35:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bard Liao X-Patchwork-Id: 11557245 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3AD1113B4 for ; Tue, 19 May 2020 08:32:30 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C5C9220709 for ; Tue, 19 May 2020 08:32:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="ORndY2m6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C5C9220709 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org 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 273F91708; Tue, 19 May 2020 10:31:42 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 273F91708 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1589877148; bh=jGGXjKbdj0A2fNAby+0rcsd8HTQSKFYgkU5Wb4zh/F8=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=ORndY2m6S0anXXW6EnYxBtEP1hKr4FtR94l4Jt3r5By6eBN47kwQRwmZCEYEeGwSw tVCdC0v5x5iyk2/6KxzxDvLYLmN6B9fJ+2jD5ImNwZIIIVwaOqBzni8D/GyhlZTiPn iaRgMr1r3WzemZCffhXYmEOx+npz6u5qYLQFgFcM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id DD356F801A3; Tue, 19 May 2020 10:30: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 C047FF8025E; Tue, 19 May 2020 10:30:50 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: * X-Spam-Status: No, score=1.1 required=5.0 tests=DATE_IN_PAST_06_12, SPF_HELO_NONE,SPF_NONE,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 44CAAF800C9 for ; Tue, 19 May 2020 10:30:44 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 44CAAF800C9 IronPort-SDR: JiKc/NX029WMHoFbYX4qnTJxH0FpromM9KTflZTWwXh4ABvYC8Gh/Csz39NzZwQgI3yV1u1r0r Te5oHkrSP+fQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 May 2020 01:30:40 -0700 IronPort-SDR: gaXqNWvjg8kCkmUz7jDm7ZIZiK+jr2wYSiQvRU+fSCgdHqkOJW0WITrnSitAbdoy+lsjEyhPlz o2pgjWk2kojw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,409,1583222400"; d="scan'208";a="264233991" Received: from bard-ubuntu.sh.intel.com ([10.239.13.33]) by orsmga003.jf.intel.com with ESMTP; 19 May 2020 01:30:36 -0700 From: Bard Liao To: alsa-devel@alsa-project.org, vkoul@kernel.org Subject: [PATCH 1/3] soundwire: disco: s/ch/channels/ Date: Tue, 19 May 2020 04:35:49 +0800 Message-Id: <20200518203551.2053-2-yung-chuan.liao@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> References: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> Cc: pierre-louis.bossart@linux.intel.com, vinod.koul@linaro.org, tiwai@suse.de, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, ranjani.sridharan@linux.intel.com, hui.wang@canonical.com, broonie@kernel.org, srinivas.kandagatla@linaro.org, jank@cadence.com, mengdong.lin@intel.com, slawomir.blauciak@intel.com, sanyog.r.kale@intel.com, rander.wang@linux.intel.com, bard.liao@intel.com 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Pierre-Louis Bossart Use more meaningful member names in preparation for sysfs support. No functionality change. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao --- drivers/soundwire/mipi_disco.c | 11 ++++++----- include/linux/soundwire/sdw.h | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 844e6b22974f..4ae62b452b8c 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -231,16 +231,17 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list"); if (nval > 0) { - dpn[i].num_ch = nval; - dpn[i].ch = devm_kcalloc(&slave->dev, dpn[i].num_ch, - sizeof(*dpn[i].ch), + dpn[i].num_channels = nval; + dpn[i].channels = devm_kcalloc(&slave->dev, + dpn[i].num_channels, + sizeof(*dpn[i].channels), GFP_KERNEL); - if (!dpn[i].ch) + if (!dpn[i].channels) return -ENOMEM; fwnode_property_read_u32_array(node, "mipi-sdw-channel-number-list", - dpn[i].ch, dpn[i].num_ch); + dpn[i].channels, dpn[i].num_channels); } nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list"); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 7658d9698dd5..9c27a32df9bb 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -291,8 +291,8 @@ struct sdw_dpn_audio_mode { * implementation-defined interrupts * @max_ch: Maximum channels supported * @min_ch: Minimum channels supported - * @num_ch: Number of discrete channels supported - * @ch: Discrete channels supported + * @num_channels: Number of discrete channels supported + * @channels: Discrete channels supported * @num_ch_combinations: Number of channel combinations supported * @ch_combinations: Channel combinations supported * @modes: SDW mode supported @@ -316,8 +316,8 @@ struct sdw_dpn_prop { u32 imp_def_interrupts; u32 max_ch; u32 min_ch; - u32 num_ch; - u32 *ch; + u32 num_channels; + u32 *channels; u32 num_ch_combinations; u32 *ch_combinations; u32 modes; From patchwork Mon May 18 20:35:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bard Liao X-Patchwork-Id: 11557247 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DA610138A for ; Tue, 19 May 2020 08:33:20 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 710E620709 for ; Tue, 19 May 2020 08:33:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="OrRTL7tc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 710E620709 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org 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 C1A00171A; Tue, 19 May 2020 10:32:32 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C1A00171A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1589877198; bh=VRqEGs4D+HnKJHQ4NWyc13cZsh58uhMYvgGh+NxUsiE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=OrRTL7tckM8syGkSeEwHhDYrN+jMzZeUG5aotH0L1SjsWZwju/g/QxjU0dWPbrltV ofocN2L1gvSiazmmkOHVjaS8QzFYWfW4lrsN26BKFQepOamsz401IBt+WJUxfqKikr qhf3OZ7gaCCFxBzb+TL8W8xfruD06hc8owRhfsOk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 678C3F80291; Tue, 19 May 2020 10:30:55 +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 86239F80256; Tue, 19 May 2020 10:30:52 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: * X-Spam-Status: No, score=1.1 required=5.0 tests=DATE_IN_PAST_06_12, SPF_HELO_NONE,SPF_NONE,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 E790EF80161 for ; Tue, 19 May 2020 10:30:45 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz E790EF80161 IronPort-SDR: EJc/OVcSiUzP9hyE4yIx4CiX3pkn8plduWVW7HCun7QWw83n9tWWO80VoaF9YlZ9BhMV9FVE3q Bt+RG1SgpPEA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 May 2020 01:30:45 -0700 IronPort-SDR: V5XC9tv8exP3gG6P7AtGtNEHOBH6QMa/lM81dPQnQQsHOKFyzf8vBwrwsrFs7Gm7mxMe7AeXdz oqkGXyk3fpJA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,409,1583222400"; d="scan'208";a="264234012" Received: from bard-ubuntu.sh.intel.com ([10.239.13.33]) by orsmga003.jf.intel.com with ESMTP; 19 May 2020 01:30:40 -0700 From: Bard Liao To: alsa-devel@alsa-project.org, vkoul@kernel.org Subject: [PATCH 2/3] soundwire: master: add sysfs support Date: Tue, 19 May 2020 04:35:50 +0800 Message-Id: <20200518203551.2053-3-yung-chuan.liao@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> References: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> Cc: pierre-louis.bossart@linux.intel.com, vinod.koul@linaro.org, tiwai@suse.de, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, ranjani.sridharan@linux.intel.com, hui.wang@canonical.com, broonie@kernel.org, srinivas.kandagatla@linaro.org, jank@cadence.com, mengdong.lin@intel.com, slawomir.blauciak@intel.com, sanyog.r.kale@intel.com, rander.wang@linux.intel.com, bard.liao@intel.com 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Pierre-Louis Bossart Add the master properties as attributes. The description is directly derived from the MIPI DisCo specification. Credits: this patch is based on an earlier internal contribution by Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao --- .../ABI/testing/sysfs-bus-soundwire-master | 23 +++++ drivers/soundwire/master.c | 84 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-soundwire-master diff --git a/Documentation/ABI/testing/sysfs-bus-soundwire-master b/Documentation/ABI/testing/sysfs-bus-soundwire-master new file mode 100644 index 000000000000..46ef038d8722 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-soundwire-master @@ -0,0 +1,23 @@ +What: /sys/bus/soundwire/devices/sdw-master-N/revision + /sys/bus/soundwire/devices/sdw-master-N/clk_stop_modes + /sys/bus/soundwire/devices/sdw-master-N/clk_freq + /sys/bus/soundwire/devices/sdw-master-N/clk_gears + /sys/bus/soundwire/devices/sdw-master-N/default_col + /sys/bus/soundwire/devices/sdw-master-N/default_frame_rate + /sys/bus/soundwire/devices/sdw-master-N/default_row + /sys/bus/soundwire/devices/sdw-master-N/dynamic_shape + /sys/bus/soundwire/devices/sdw-master-N/err_threshold + /sys/bus/soundwire/devices/sdw-master-N/max_clk_freq + +Date: April 2020 + +Contact: Pierre-Louis Bossart + Bard Liao + Vinod Koul + +Description: SoundWire Master-N DisCo properties. + These properties are defined by MIPI DisCo Specification + for SoundWire. They define various properties of the Master + and are used by the bus to configure the Master. clk_stop_modes + is a bitmask for simplifications and combines the + clock-stop-mode0 and clock-stop-mode1 properties. diff --git a/drivers/soundwire/master.c b/drivers/soundwire/master.c index 5411791e6aff..5f0b2189defe 100644 --- a/drivers/soundwire/master.c +++ b/drivers/soundwire/master.c @@ -8,6 +8,89 @@ #include #include "bus.h" +/* + * The sysfs for properties reflects the MIPI description as given + * in the MIPI DisCo spec + * + * Base file is: + * sdw-master-N + * |---- revision + * |---- clk_stop_modes + * |---- max_clk_freq + * |---- clk_freq + * |---- clk_gears + * |---- default_row + * |---- default_col + * |---- dynamic_shape + * |---- err_threshold + */ + +#define sdw_master_attr(field, format_string) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sdw_master_device *md = dev_to_sdw_master_device(dev); \ + return sprintf(buf, format_string, md->bus->prop.field); \ +} \ +static DEVICE_ATTR_RO(field) + +sdw_master_attr(revision, "0x%x\n"); +sdw_master_attr(clk_stop_modes, "0x%x\n"); +sdw_master_attr(max_clk_freq, "%d\n"); +sdw_master_attr(default_row, "%d\n"); +sdw_master_attr(default_col, "%d\n"); +sdw_master_attr(default_frame_rate, "%d\n"); +sdw_master_attr(dynamic_frame, "%d\n"); +sdw_master_attr(err_threshold, "%d\n"); + +static ssize_t clock_frequencies_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sdw_master_device *md = dev_to_sdw_master_device(dev); + ssize_t size = 0; + int i; + + for (i = 0; i < md->bus->prop.num_clk_freq; i++) + size += sprintf(buf + size, "%8d ", + md->bus->prop.clk_freq[i]); + size += sprintf(buf + size, "\n"); + + return size; +} +static DEVICE_ATTR_RO(clock_frequencies); + +static ssize_t clock_gears_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sdw_master_device *md = dev_to_sdw_master_device(dev); + ssize_t size = 0; + int i; + + for (i = 0; i < md->bus->prop.num_clk_gears; i++) + size += sprintf(buf + size, "%8d ", + md->bus->prop.clk_gears[i]); + size += sprintf(buf + size, "\n"); + + return size; +} +static DEVICE_ATTR_RO(clock_gears); + +static struct attribute *master_node_attrs[] = { + &dev_attr_revision.attr, + &dev_attr_clk_stop_modes.attr, + &dev_attr_max_clk_freq.attr, + &dev_attr_default_row.attr, + &dev_attr_default_col.attr, + &dev_attr_default_frame_rate.attr, + &dev_attr_dynamic_frame.attr, + &dev_attr_err_threshold.attr, + &dev_attr_clock_frequencies.attr, + &dev_attr_clock_gears.attr, + NULL, +}; +ATTRIBUTE_GROUPS(master_node); + static void sdw_master_device_release(struct device *dev) { struct sdw_master_device *md = dev_to_sdw_master_device(dev); @@ -48,6 +131,7 @@ int sdw_master_device_add(struct sdw_bus *bus, struct device *parent, md->dev.bus = &sdw_bus_type; md->dev.type = &sdw_master_type; md->dev.parent = parent; + md->dev.groups = master_node_groups; md->dev.of_node = parent->of_node; md->dev.fwnode = fwnode; md->dev.dma_mask = parent->dma_mask; From patchwork Mon May 18 20:35:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bard Liao X-Patchwork-Id: 11557249 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E7A4C138A for ; Tue, 19 May 2020 08:34:04 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7DEFD20709 for ; Tue, 19 May 2020 08:34:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="Ys4ZVSg6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7DEFD20709 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org 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 C41C316F9; Tue, 19 May 2020 10:33:16 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz C41C316F9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1589877242; bh=aGn/r+OWx7FJch4RSQUj1h35bxX0Q2ggbb8f/xhQ4Ag=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Ys4ZVSg6+npto/nO7LwSbvPSUnSPL6bFKHOokEGDhmG7+9Gj/VYNX2LowEe4atg6b kF+TbqiJFxLSrCQn0zoDS6HxeL7f8RUmMPZ8UQ275EC4n6GvAQgeZBke6cBt0wUs3/ +nmiI5dmvVQtPcxCEfEFieQQL/UgbFRpa5LOgV9w= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id E7DF7F802A1; Tue, 19 May 2020 10:31:00 +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 233E5F802A2; Tue, 19 May 2020 10:30:59 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: * X-Spam-Status: No, score=1.1 required=5.0 tests=DATE_IN_PAST_06_12, SPF_HELO_NONE,SPF_NONE,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 2D57DF800C9 for ; Tue, 19 May 2020 10:30:51 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 2D57DF800C9 IronPort-SDR: /yMXz5sNqtV/4vIQhQyhnuumTfwNAn9QCgBlJg1SrBO3C6ulf/p+eVWaiMGEPfANOmFA17FbrN h7km8exlr1Aw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 May 2020 01:30:50 -0700 IronPort-SDR: h4lHrinJ9Ag9SykPBqrv+PUDQgZjHpbaJ+UVePZpyDjNG0Ko0Mn7ewhJMLEVocg0DuBeAYn6UQ WelHWAYnipEw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,409,1583222400"; d="scan'208";a="264234026" Received: from bard-ubuntu.sh.intel.com ([10.239.13.33]) by orsmga003.jf.intel.com with ESMTP; 19 May 2020 01:30:45 -0700 From: Bard Liao To: alsa-devel@alsa-project.org, vkoul@kernel.org Subject: [PATCH 3/3] soundwire: add Slave sysfs support Date: Tue, 19 May 2020 04:35:51 +0800 Message-Id: <20200518203551.2053-4-yung-chuan.liao@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> References: <20200518203551.2053-1-yung-chuan.liao@linux.intel.com> Cc: pierre-louis.bossart@linux.intel.com, vinod.koul@linaro.org, tiwai@suse.de, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, ranjani.sridharan@linux.intel.com, hui.wang@canonical.com, broonie@kernel.org, srinivas.kandagatla@linaro.org, jank@cadence.com, mengdong.lin@intel.com, slawomir.blauciak@intel.com, sanyog.r.kale@intel.com, rander.wang@linux.intel.com, bard.liao@intel.com 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Pierre-Louis Bossart Expose MIPI DisCo Slave properties in sysfs. For Slave properties and Data Port 0, the attributes are managed with simple devm_ support. A Slave Device may have more than one Data Port (DPN), and each Data Port can be sink or source. The attributes are created dynamically using pre-canned macros, but still use devm_ with a name attribute group to avoid creating kobjects - as requested by GregKH. In the _show function, we use container_of() to retrieve port number and direction required to extract the information. Audio modes are not supported for now. Depending on the discussions the SoundWire Device Class, we may add it later as is or follow the new specification. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao Reviewed-by: Greg Kroah-Hartman --- .../ABI/testing/sysfs-bus-soundwire-slave | 91 ++++++ drivers/soundwire/Makefile | 3 +- drivers/soundwire/bus.c | 1 + drivers/soundwire/bus.h | 1 + drivers/soundwire/bus_type.c | 9 +- drivers/soundwire/sysfs_local.h | 14 + drivers/soundwire/sysfs_slave.c | 215 +++++++++++++ drivers/soundwire/sysfs_slave_dpn.c | 300 ++++++++++++++++++ 8 files changed, 631 insertions(+), 3 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-soundwire-slave create mode 100644 drivers/soundwire/sysfs_local.h create mode 100644 drivers/soundwire/sysfs_slave.c create mode 100644 drivers/soundwire/sysfs_slave_dpn.c diff --git a/Documentation/ABI/testing/sysfs-bus-soundwire-slave b/Documentation/ABI/testing/sysfs-bus-soundwire-slave new file mode 100644 index 000000000000..db4c9511d1aa --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-soundwire-slave @@ -0,0 +1,91 @@ +What: /sys/bus/soundwire/devices/sdw:.../dev-properties/mipi_revision + /sys/bus/soundwire/devices/sdw:.../dev-properties/wake_capable + /sys/bus/soundwire/devices/sdw:.../dev-properties/test_mode_capable + /sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_mode1 + /sys/bus/soundwire/devices/sdw:.../dev-properties/simple_clk_stop_capable + /sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_timeout + /sys/bus/soundwire/devices/sdw:.../dev-properties/ch_prep_timeout + /sys/bus/soundwire/devices/sdw:.../dev-properties/reset_behave + /sys/bus/soundwire/devices/sdw:.../dev-properties/high_PHY_capable + /sys/bus/soundwire/devices/sdw:.../dev-properties/paging_support + /sys/bus/soundwire/devices/sdw:.../dev-properties/bank_delay_support + /sys/bus/soundwire/devices/sdw:.../dev-properties/p15_behave + /sys/bus/soundwire/devices/sdw:.../dev-properties/master_count + /sys/bus/soundwire/devices/sdw:.../dev-properties/source_ports + /sys/bus/soundwire/devices/sdw:.../dev-properties/sink_ports + +Date: May 2020 + +Contact: Pierre-Louis Bossart + Bard Liao + Vinod Koul + +Description: SoundWire Slave DisCo properties. + These properties are defined by MIPI DisCo Specification + for SoundWire. They define various properties of the + SoundWire Slave and are used by the bus to configure + the Slave + + +What: /sys/bus/soundwire/devices/sdw:.../dp0/max_word + /sys/bus/soundwire/devices/sdw:.../dp0/min_word + /sys/bus/soundwire/devices/sdw:.../dp0/words + /sys/bus/soundwire/devices/sdw:.../dp0/BRA_flow_controlled + /sys/bus/soundwire/devices/sdw:.../dp0/simple_ch_prep_sm + /sys/bus/soundwire/devices/sdw:.../dp0/imp_def_interrupts + +Date: May 2020 + +Contact: Pierre-Louis Bossart + Bard Liao + Vinod Koul + +Description: SoundWire Slave Data Port-0 DisCo properties. + These properties are defined by MIPI DisCo Specification + for the SoundWire. They define various properties of the + Data port 0 are used by the bus to configure the Data Port 0. + + +What: /sys/bus/soundwire/devices/sdw:.../dpN_src/max_word + /sys/bus/soundwire/devices/sdw:.../dpN_src/min_word + /sys/bus/soundwire/devices/sdw:.../dpN_src/words + /sys/bus/soundwire/devices/sdw:.../dpN_src/type + /sys/bus/soundwire/devices/sdw:.../dpN_src/max_grouping + /sys/bus/soundwire/devices/sdw:.../dpN_src/simple_ch_prep_sm + /sys/bus/soundwire/devices/sdw:.../dpN_src/ch_prep_timeout + /sys/bus/soundwire/devices/sdw:.../dpN_src/imp_def_interrupts + /sys/bus/soundwire/devices/sdw:.../dpN_src/min_ch + /sys/bus/soundwire/devices/sdw:.../dpN_src/max_ch + /sys/bus/soundwire/devices/sdw:.../dpN_src/channels + /sys/bus/soundwire/devices/sdw:.../dpN_src/ch_combinations + /sys/bus/soundwire/devices/sdw:.../dpN_src/max_async_buffer + /sys/bus/soundwire/devices/sdw:.../dpN_src/block_pack_mode + /sys/bus/soundwire/devices/sdw:.../dpN_src/port_encoding + + /sys/bus/soundwire/devices/sdw:.../dpN_sink/max_word + /sys/bus/soundwire/devices/sdw:.../dpN_sink/min_word + /sys/bus/soundwire/devices/sdw:.../dpN_sink/words + /sys/bus/soundwire/devices/sdw:.../dpN_sink/type + /sys/bus/soundwire/devices/sdw:.../dpN_sink/max_grouping + /sys/bus/soundwire/devices/sdw:.../dpN_sink/simple_ch_prep_sm + /sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_prep_timeout + /sys/bus/soundwire/devices/sdw:.../dpN_sink/imp_def_interrupts + /sys/bus/soundwire/devices/sdw:.../dpN_sink/min_ch + /sys/bus/soundwire/devices/sdw:.../dpN_sink/max_ch + /sys/bus/soundwire/devices/sdw:.../dpN_sink/channels + /sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_combinations + /sys/bus/soundwire/devices/sdw:.../dpN_sink/max_async_buffer + /sys/bus/soundwire/devices/sdw:.../dpN_sink/block_pack_mode + /sys/bus/soundwire/devices/sdw:.../dpN_sink/port_encoding + +Date: May 2020 + +Contact: Pierre-Louis Bossart + Bard Liao + Vinod Koul + +Description: SoundWire Slave Data Source/Sink Port-N DisCo properties. + These properties are defined by MIPI DisCo Specification + for SoundWire. They define various properties of the + Source/Sink Data port N and are used by the bus to configure + the Data Port N. diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile index 7319918e0aec..9b0aeee94876 100644 --- a/drivers/soundwire/Makefile +++ b/drivers/soundwire/Makefile @@ -4,7 +4,8 @@ # #Bus Objs -soundwire-bus-objs := bus_type.o bus.o master.o slave.o mipi_disco.o stream.o +soundwire-bus-objs := bus_type.o bus.o master.o slave.o mipi_disco.o stream.o \ + sysfs_slave.o sysfs_slave_dpn.o obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o ifdef CONFIG_DEBUG_FS diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 11cfe435e4a8..24ba77226376 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -8,6 +8,7 @@ #include #include #include "bus.h" +#include "sysfs_local.h" static DEFINE_IDA(sdw_ida); diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h index 93ab0234a491..82484f741168 100644 --- a/drivers/soundwire/bus.h +++ b/drivers/soundwire/bus.h @@ -175,5 +175,6 @@ sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val) #define SDW_UNATTACH_REQUEST_MASTER_RESET BIT(0) void sdw_clear_slave_status(struct sdw_bus *bus, u32 request); +int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size); #endif /* __SDW_BUS_H */ diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 2c1a19caba51..de9a671802b8 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -7,6 +7,7 @@ #include #include #include "bus.h" +#include "sysfs_local.h" /** * sdw_get_device_id - find the matching SoundWire device id @@ -46,8 +47,7 @@ static int sdw_bus_match(struct device *dev, struct device_driver *ddrv) return ret; } -static int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, - size_t size) +int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size) { /* modalias is sdw:mp */ @@ -105,6 +105,11 @@ static int sdw_drv_probe(struct device *dev) if (slave->ops && slave->ops->read_prop) slave->ops->read_prop(slave); + /* init the sysfs as we have properties now */ + ret = sdw_slave_sysfs_init(slave); + if (ret < 0) + dev_warn(dev, "Slave sysfs init failed:%d\n", ret); + /* * Check for valid clk_stop_timeout, use DisCo worst case value of * 300ms diff --git a/drivers/soundwire/sysfs_local.h b/drivers/soundwire/sysfs_local.h new file mode 100644 index 000000000000..ff60adee3c41 --- /dev/null +++ b/drivers/soundwire/sysfs_local.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2015-2020 Intel Corporation. */ + +#ifndef __SDW_SYSFS_LOCAL_H +#define __SDW_SYSFS_LOCAL_H + +/* + * SDW sysfs APIs - + */ + +int sdw_slave_sysfs_init(struct sdw_slave *slave); +int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave); + +#endif /* __SDW_SYSFS_LOCAL_H */ diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c new file mode 100644 index 000000000000..ae6d241eca50 --- /dev/null +++ b/drivers/soundwire/sysfs_slave.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2015-2020 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include "bus.h" +#include "sysfs_local.h" + +/* + * Slave sysfs + */ + +/* + * The sysfs for Slave reflects the MIPI description as given + * in the MIPI DisCo spec + * + * Base file is device + * |---- modalias + * |---- dev-properties + * |---- mipi_revision + * |---- wake_capable + * |---- test_mode_capable + * |---- clk_stop_mode1 + * |---- simple_clk_stop_capable + * |---- clk_stop_timeout + * |---- ch_prep_timeout + * |---- reset_behave + * |---- high_PHY_capable + * |---- paging_support + * |---- bank_delay_support + * |---- p15_behave + * |---- master_count + * |---- source_ports + * |---- sink_ports + * |---- dp0 + * |---- max_word + * |---- min_word + * |---- words + * |---- BRA_flow_controlled + * |---- simple_ch_prep_sm + * |---- imp_def_interrupts + * |---- dpN_ + * |---- max_word + * |---- min_word + * |---- words + * |---- type + * |---- max_grouping + * |---- simple_ch_prep_sm + * |---- ch_prep_timeout + * |---- imp_def_interrupts + * |---- min_ch + * |---- max_ch + * |---- channels + * |---- ch_combinations + * |---- max_async_buffer + * |---- block_pack_mode + * |---- port_encoding + * + */ + +#define sdw_slave_attr(field, format_string) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sdw_slave *slave = dev_to_sdw_dev(dev); \ + return sprintf(buf, format_string, slave->prop.field); \ +} \ +static DEVICE_ATTR_RO(field) + +sdw_slave_attr(mipi_revision, "0x%x\n"); +sdw_slave_attr(wake_capable, "%d\n"); +sdw_slave_attr(test_mode_capable, "%d\n"); +sdw_slave_attr(clk_stop_mode1, "%d\n"); +sdw_slave_attr(simple_clk_stop_capable, "%d\n"); +sdw_slave_attr(clk_stop_timeout, "%d\n"); +sdw_slave_attr(ch_prep_timeout, "%d\n"); +sdw_slave_attr(reset_behave, "%d\n"); +sdw_slave_attr(high_PHY_capable, "%d\n"); +sdw_slave_attr(paging_support, "%d\n"); +sdw_slave_attr(bank_delay_support, "%d\n"); +sdw_slave_attr(p15_behave, "%d\n"); +sdw_slave_attr(master_count, "%d\n"); +sdw_slave_attr(source_ports, "0x%x\n"); +sdw_slave_attr(sink_ports, "0x%x\n"); + +static ssize_t modalias_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + + return sdw_slave_modalias(slave, buf, 256); +} +static DEVICE_ATTR_RO(modalias); + +static struct attribute *slave_attrs[] = { + &dev_attr_modalias.attr, + NULL, +}; +ATTRIBUTE_GROUPS(slave); + +static struct attribute *slave_dev_attrs[] = { + &dev_attr_mipi_revision.attr, + &dev_attr_wake_capable.attr, + &dev_attr_test_mode_capable.attr, + &dev_attr_clk_stop_mode1.attr, + &dev_attr_simple_clk_stop_capable.attr, + &dev_attr_clk_stop_timeout.attr, + &dev_attr_ch_prep_timeout.attr, + &dev_attr_reset_behave.attr, + &dev_attr_high_PHY_capable.attr, + &dev_attr_paging_support.attr, + &dev_attr_bank_delay_support.attr, + &dev_attr_p15_behave.attr, + &dev_attr_master_count.attr, + &dev_attr_source_ports.attr, + &dev_attr_sink_ports.attr, + NULL, +}; + +/* + * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory + * for device-level properties + */ +static struct attribute_group sdw_slave_dev_attr_group = { + .attrs = slave_dev_attrs, + .name = "dev-properties", +}; + +/* + * DP0 sysfs + */ + +#define sdw_dp0_attr(field, format_string) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sdw_slave *slave = dev_to_sdw_dev(dev); \ + return sprintf(buf, format_string, slave->prop.dp0_prop->field);\ +} \ +static DEVICE_ATTR_RO(field) + +sdw_dp0_attr(max_word, "%d\n"); +sdw_dp0_attr(min_word, "%d\n"); +sdw_dp0_attr(BRA_flow_controlled, "%d\n"); +sdw_dp0_attr(simple_ch_prep_sm, "%d\n"); +sdw_dp0_attr(imp_def_interrupts, "0x%x\n"); + +static ssize_t words_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + ssize_t size = 0; + int i; + + for (i = 0; i < slave->prop.dp0_prop->num_words; i++) + size += sprintf(buf + size, "%d ", + slave->prop.dp0_prop->words[i]); + size += sprintf(buf + size, "\n"); + + return size; +} +static DEVICE_ATTR_RO(words); + +static struct attribute *dp0_attrs[] = { + &dev_attr_max_word.attr, + &dev_attr_min_word.attr, + &dev_attr_words.attr, + &dev_attr_BRA_flow_controlled.attr, + &dev_attr_simple_ch_prep_sm.attr, + &dev_attr_imp_def_interrupts.attr, + NULL, +}; + +/* + * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory + * for dp0-level properties + */ +static const struct attribute_group dp0_group = { + .attrs = dp0_attrs, + .name = "dp0", +}; + +int sdw_slave_sysfs_init(struct sdw_slave *slave) +{ + int ret; + + ret = devm_device_add_groups(&slave->dev, slave_groups); + if (ret < 0) + return ret; + + ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group); + if (ret < 0) + return ret; + + if (slave->prop.dp0_prop) { + ret = devm_device_add_group(&slave->dev, &dp0_group); + if (ret < 0) + return ret; + } + + if (slave->prop.source_ports || slave->prop.sink_ports) { + ret = sdw_slave_sysfs_dpn_init(slave); + if (ret < 0) + return ret; + } + + return 0; +} + diff --git a/drivers/soundwire/sysfs_slave_dpn.c b/drivers/soundwire/sysfs_slave_dpn.c new file mode 100644 index 000000000000..c175a7d08815 --- /dev/null +++ b/drivers/soundwire/sysfs_slave_dpn.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2015-2020 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include "bus.h" +#include "sysfs_local.h" + +struct dpn_attribute { + struct device_attribute dev_attr; + int N; + int dir; + const char *format_string; +}; + +/* + * Since we can't use ARRAY_SIZE, hard-code number of dpN attributes. + * This needs to be updated when adding new attributes - an error will be + * flagged on a mismatch. + */ +#define SDW_DPN_ATTRIBUTES 15 + +#define sdw_dpn_attribute_alloc(field) \ +static int field##_attribute_alloc(struct device *dev, \ + struct attribute **res, \ + int N, int dir, \ + const char *format_string) \ +{ \ + struct dpn_attribute *dpn_attr; \ + \ + dpn_attr = devm_kzalloc(dev, sizeof(*dpn_attr), GFP_KERNEL); \ + if (!dpn_attr) \ + return -ENOMEM; \ + dpn_attr->N = N; \ + dpn_attr->dir = dir; \ + dpn_attr->format_string = format_string; \ + dpn_attr->dev_attr.attr.name = __stringify(field); \ + dpn_attr->dev_attr.attr.mode = 0444; \ + dpn_attr->dev_attr.show = field##_show; \ + \ + *res = &dpn_attr->dev_attr.attr; \ + \ + return 0; \ +} + +#define sdw_dpn_attr(field) \ + \ +static ssize_t field##_dpn_show(struct sdw_slave *slave, \ + int N, \ + int dir, \ + const char *format_string, \ + char *buf) \ +{ \ + struct sdw_dpn_prop *dpn; \ + unsigned long mask; \ + int bit; \ + int i; \ + \ + if (dir) { \ + dpn = slave->prop.src_dpn_prop; \ + mask = slave->prop.source_ports; \ + } else { \ + dpn = slave->prop.sink_dpn_prop; \ + mask = slave->prop.sink_ports; \ + } \ + \ + i = 0; \ + for_each_set_bit(bit, &mask, 32) { \ + if (bit == N) { \ + return sprintf(buf, format_string, \ + dpn[i].field); \ + } \ + i++; \ + } \ + return -EINVAL; \ +} \ + \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sdw_slave *slave = dev_to_sdw_dev(dev); \ + struct dpn_attribute *dpn_attr = \ + container_of(attr, struct dpn_attribute, dev_attr); \ + \ + return field##_dpn_show(slave, \ + dpn_attr->N, dpn_attr->dir, \ + dpn_attr->format_string, \ + buf); \ +} \ +sdw_dpn_attribute_alloc(field) + +sdw_dpn_attr(imp_def_interrupts); +sdw_dpn_attr(max_word); +sdw_dpn_attr(min_word); +sdw_dpn_attr(type); +sdw_dpn_attr(max_grouping); +sdw_dpn_attr(simple_ch_prep_sm); +sdw_dpn_attr(ch_prep_timeout); +sdw_dpn_attr(max_ch); +sdw_dpn_attr(min_ch); +sdw_dpn_attr(max_async_buffer); +sdw_dpn_attr(block_pack_mode); +sdw_dpn_attr(port_encoding); + +#define sdw_dpn_array_attr(field) \ + \ +static ssize_t field##_dpn_show(struct sdw_slave *slave, \ + int N, \ + int dir, \ + const char *format_string, \ + char *buf) \ +{ \ + struct sdw_dpn_prop *dpn; \ + unsigned long mask; \ + ssize_t size = 0; \ + int bit; \ + int i; \ + int j; \ + \ + if (dir) { \ + dpn = slave->prop.src_dpn_prop; \ + mask = slave->prop.source_ports; \ + } else { \ + dpn = slave->prop.sink_dpn_prop; \ + mask = slave->prop.sink_ports; \ + } \ + \ + i = 0; \ + for_each_set_bit(bit, &mask, 32) { \ + if (bit == N) { \ + for (j = 0; j < dpn[i].num_##field; j++) \ + size += sprintf(buf + size, \ + format_string, \ + dpn[i].field[j]); \ + size += sprintf(buf + size, "\n"); \ + return size; \ + } \ + i++; \ + } \ + return -EINVAL; \ +} \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sdw_slave *slave = dev_to_sdw_dev(dev); \ + struct dpn_attribute *dpn_attr = \ + container_of(attr, struct dpn_attribute, dev_attr); \ + \ + return field##_dpn_show(slave, \ + dpn_attr->N, dpn_attr->dir, \ + dpn_attr->format_string, \ + buf); \ +} \ +sdw_dpn_attribute_alloc(field) + +sdw_dpn_array_attr(words); +sdw_dpn_array_attr(ch_combinations); +sdw_dpn_array_attr(channels); + +static int add_all_attributes(struct device *dev, int N, int dir) +{ + struct attribute **dpn_attrs; + struct attribute_group *dpn_group; + int i = 0; + int ret; + + /* allocate attributes, last one is NULL */ + dpn_attrs = devm_kcalloc(dev, SDW_DPN_ATTRIBUTES + 1, + sizeof(struct attribute *), + GFP_KERNEL); + if (!dpn_attrs) + return -ENOMEM; + + ret = max_word_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = min_word_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = words_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = type_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = max_grouping_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = simple_ch_prep_sm_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = ch_prep_timeout_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = imp_def_interrupts_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "0x%x\n"); + if (ret < 0) + return ret; + + ret = min_ch_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = max_ch_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = channels_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = ch_combinations_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = max_async_buffer_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = block_pack_mode_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + ret = port_encoding_attribute_alloc(dev, &dpn_attrs[i++], + N, dir, "%d\n"); + if (ret < 0) + return ret; + + /* paranioa check for editing mistakes */ + if (i != SDW_DPN_ATTRIBUTES) { + dev_err(dev, "mismatch in attributes, allocated %d got %d\n", + SDW_DPN_ATTRIBUTES, i); + return -EINVAL; + } + + dpn_group = devm_kzalloc(dev, sizeof(*dpn_group), GFP_KERNEL); + if (!dpn_group) + return -ENOMEM; + + dpn_group->attrs = dpn_attrs; + dpn_group->name = devm_kasprintf(dev, GFP_KERNEL, "dp%d_%s", + N, dir ? "src" : "sink"); + if (!dpn_group->name) + return -ENOMEM; + + ret = devm_device_add_group(dev, dpn_group); + if (ret < 0) + return ret; + + return 0; +} + +int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave) +{ + unsigned long mask; + int ret; + int i; + + mask = slave->prop.source_ports; + for_each_set_bit(i, &mask, 32) { + ret = add_all_attributes(&slave->dev, i, 1); + if (ret < 0) + return ret; + } + + mask = slave->prop.sink_ports; + for_each_set_bit(i, &mask, 32) { + ret = add_all_attributes(&slave->dev, i, 0); + if (ret < 0) + return ret; + } + + return 0; +}