Skip to content

Commit 1697493

Browse files
committed
soundwire: add Slave sysfs support
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 <pierre-louis.bossart@linux.intel.com>
1 parent ce6dcce commit 1697493

File tree

8 files changed

+631
-3
lines changed

8 files changed

+631
-3
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
What: /sys/bus/soundwire/devices/sdw:.../dev-properties/mipi_revision
2+
/sys/bus/soundwire/devices/sdw:.../dev-properties/wake_capable
3+
/sys/bus/soundwire/devices/sdw:.../dev-properties/test_mode_capable
4+
/sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_mode1
5+
/sys/bus/soundwire/devices/sdw:.../dev-properties/simple_clk_stop_capable
6+
/sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_timeout
7+
/sys/bus/soundwire/devices/sdw:.../dev-properties/ch_prep_timeout
8+
/sys/bus/soundwire/devices/sdw:.../dev-properties/reset_behave
9+
/sys/bus/soundwire/devices/sdw:.../dev-properties/high_PHY_capable
10+
/sys/bus/soundwire/devices/sdw:.../dev-properties/paging_support
11+
/sys/bus/soundwire/devices/sdw:.../dev-properties/bank_delay_support
12+
/sys/bus/soundwire/devices/sdw:.../dev-properties/p15_behave
13+
/sys/bus/soundwire/devices/sdw:.../dev-properties/master_count
14+
/sys/bus/soundwire/devices/sdw:.../dev-properties/source_ports
15+
/sys/bus/soundwire/devices/sdw:.../dev-properties/sink_ports
16+
17+
Date: May 2020
18+
19+
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
20+
Bard Liao <yung-chuan.liao@linux.intel.com>
21+
Vinod Koul <vkoul@kernel.org>
22+
23+
Description: SoundWire Slave DisCo properties.
24+
These properties are defined by MIPI DisCo Specification
25+
for SoundWire. They define various properties of the
26+
SoundWire Slave and are used by the bus to configure
27+
the Slave
28+
29+
30+
What: /sys/bus/soundwire/devices/sdw:.../dp0/max_word
31+
/sys/bus/soundwire/devices/sdw:.../dp0/min_word
32+
/sys/bus/soundwire/devices/sdw:.../dp0/words
33+
/sys/bus/soundwire/devices/sdw:.../dp0/BRA_flow_controlled
34+
/sys/bus/soundwire/devices/sdw:.../dp0/simple_ch_prep_sm
35+
/sys/bus/soundwire/devices/sdw:.../dp0/imp_def_interrupts
36+
37+
Date: May 2020
38+
39+
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
40+
Bard Liao <yung-chuan.liao@linux.intel.com>
41+
Vinod Koul <vkoul@kernel.org>
42+
43+
Description: SoundWire Slave Data Port-0 DisCo properties.
44+
These properties are defined by MIPI DisCo Specification
45+
for the SoundWire. They define various properties of the
46+
Data port 0 are used by the bus to configure the Data Port 0.
47+
48+
49+
What: /sys/bus/soundwire/devices/sdw:.../dpN_src/max_word
50+
/sys/bus/soundwire/devices/sdw:.../dpN_src/min_word
51+
/sys/bus/soundwire/devices/sdw:.../dpN_src/words
52+
/sys/bus/soundwire/devices/sdw:.../dpN_src/type
53+
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_grouping
54+
/sys/bus/soundwire/devices/sdw:.../dpN_src/simple_ch_prep_sm
55+
/sys/bus/soundwire/devices/sdw:.../dpN_src/ch_prep_timeout
56+
/sys/bus/soundwire/devices/sdw:.../dpN_src/imp_def_interrupts
57+
/sys/bus/soundwire/devices/sdw:.../dpN_src/min_ch
58+
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_ch
59+
/sys/bus/soundwire/devices/sdw:.../dpN_src/channels
60+
/sys/bus/soundwire/devices/sdw:.../dpN_src/ch_combinations
61+
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_async_buffer
62+
/sys/bus/soundwire/devices/sdw:.../dpN_src/block_pack_mode
63+
/sys/bus/soundwire/devices/sdw:.../dpN_src/port_encoding
64+
65+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_word
66+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/min_word
67+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/words
68+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/type
69+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_grouping
70+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/simple_ch_prep_sm
71+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_prep_timeout
72+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/imp_def_interrupts
73+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/min_ch
74+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_ch
75+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/channels
76+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_combinations
77+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_async_buffer
78+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/block_pack_mode
79+
/sys/bus/soundwire/devices/sdw:.../dpN_sink/port_encoding
80+
81+
Date: May 2020
82+
83+
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
84+
Bard Liao <yung-chuan.liao@linux.intel.com>
85+
Vinod Koul <vkoul@kernel.org>
86+
87+
Description: SoundWire Slave Data Source/Sink Port-N DisCo properties.
88+
These properties are defined by MIPI DisCo Specification
89+
for SoundWire. They define various properties of the
90+
Source/Sink Data port N and are used by the bus to configure
91+
the Data Port N.

drivers/soundwire/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#
55

66
#Bus Objs
7-
soundwire-bus-objs := bus_type.o bus.o master.o slave.o mipi_disco.o stream.o
7+
soundwire-bus-objs := bus_type.o bus.o master.o slave.o mipi_disco.o stream.o \
8+
sysfs_slave.o sysfs_slave_dpn.o
89
obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
910

1011
soundwire-generic-allocation-objs := generic_bandwidth_allocation.o

drivers/soundwire/bus.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/soundwire/sdw_registers.h>
99
#include <linux/soundwire/sdw.h>
1010
#include "bus.h"
11+
#include "sysfs_local.h"
1112

1213
/**
1314
* sdw_add_bus_master() - add a bus Master instance

drivers/soundwire/bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,5 +216,6 @@ static inline int sdw_update(struct sdw_slave *slave, u32 addr, u8 mask, u8 val)
216216
void sdw_clear_slave_status(struct sdw_bus *bus, u32 request);
217217

218218
int sdw_slave_uevent(struct device *dev, struct kobj_uevent_env *env);
219+
int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size);
219220

220221
#endif /* __SDW_BUS_H */

drivers/soundwire/bus_type.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/soundwire/sdw.h>
88
#include <linux/soundwire/sdw_type.h>
99
#include "bus.h"
10+
#include "sysfs_local.h"
1011

1112
/**
1213
* 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)
4647
return ret;
4748
}
4849

49-
static int sdw_slave_modalias(const struct sdw_slave *slave, char *buf,
50-
size_t size)
50+
int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size)
5151
{
5252
/* modalias is sdw:m<mfg_id>p<part_id> */
5353

@@ -105,6 +105,11 @@ static int sdw_drv_probe(struct device *dev)
105105
if (slave->ops && slave->ops->read_prop)
106106
slave->ops->read_prop(slave);
107107

108+
/* init the sysfs as we have properties now */
109+
ret = sdw_slave_sysfs_init(slave);
110+
if (ret < 0)
111+
dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
112+
108113
/*
109114
* Check for valid clk_stop_timeout, use DisCo worst case value of
110115
* 300ms

drivers/soundwire/sysfs_local.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/* Copyright(c) 2015-2020 Intel Corporation. */
3+
4+
#ifndef __SDW_SYSFS_LOCAL_H
5+
#define __SDW_SYSFS_LOCAL_H
6+
7+
/*
8+
* SDW sysfs APIs -
9+
*/
10+
11+
int sdw_slave_sysfs_init(struct sdw_slave *slave);
12+
int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave);
13+
14+
#endif /* __SDW_SYSFS_LOCAL_H */

drivers/soundwire/sysfs_slave.c

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
// Copyright(c) 2015-2020 Intel Corporation.
3+
4+
#include <linux/device.h>
5+
#include <linux/mod_devicetable.h>
6+
#include <linux/slab.h>
7+
#include <linux/sysfs.h>
8+
#include <linux/soundwire/sdw.h>
9+
#include <linux/soundwire/sdw_type.h>
10+
#include "bus.h"
11+
#include "sysfs_local.h"
12+
13+
/*
14+
* Slave sysfs
15+
*/
16+
17+
/*
18+
* The sysfs for Slave reflects the MIPI description as given
19+
* in the MIPI DisCo spec
20+
*
21+
* Base file is device
22+
* |---- modalias
23+
* |---- dev-properties
24+
* |---- mipi_revision
25+
* |---- wake_capable
26+
* |---- test_mode_capable
27+
* |---- clk_stop_mode1
28+
* |---- simple_clk_stop_capable
29+
* |---- clk_stop_timeout
30+
* |---- ch_prep_timeout
31+
* |---- reset_behave
32+
* |---- high_PHY_capable
33+
* |---- paging_support
34+
* |---- bank_delay_support
35+
* |---- p15_behave
36+
* |---- master_count
37+
* |---- source_ports
38+
* |---- sink_ports
39+
* |---- dp0
40+
* |---- max_word
41+
* |---- min_word
42+
* |---- words
43+
* |---- BRA_flow_controlled
44+
* |---- simple_ch_prep_sm
45+
* |---- imp_def_interrupts
46+
* |---- dpN_<sink/src>
47+
* |---- max_word
48+
* |---- min_word
49+
* |---- words
50+
* |---- type
51+
* |---- max_grouping
52+
* |---- simple_ch_prep_sm
53+
* |---- ch_prep_timeout
54+
* |---- imp_def_interrupts
55+
* |---- min_ch
56+
* |---- max_ch
57+
* |---- channels
58+
* |---- ch_combinations
59+
* |---- max_async_buffer
60+
* |---- block_pack_mode
61+
* |---- port_encoding
62+
*
63+
*/
64+
65+
#define sdw_slave_attr(field, format_string) \
66+
static ssize_t field##_show(struct device *dev, \
67+
struct device_attribute *attr, \
68+
char *buf) \
69+
{ \
70+
struct sdw_slave *slave = dev_to_sdw_dev(dev); \
71+
return sprintf(buf, format_string, slave->prop.field); \
72+
} \
73+
static DEVICE_ATTR_RO(field)
74+
75+
sdw_slave_attr(mipi_revision, "0x%x\n");
76+
sdw_slave_attr(wake_capable, "%d\n");
77+
sdw_slave_attr(test_mode_capable, "%d\n");
78+
sdw_slave_attr(clk_stop_mode1, "%d\n");
79+
sdw_slave_attr(simple_clk_stop_capable, "%d\n");
80+
sdw_slave_attr(clk_stop_timeout, "%d\n");
81+
sdw_slave_attr(ch_prep_timeout, "%d\n");
82+
sdw_slave_attr(reset_behave, "%d\n");
83+
sdw_slave_attr(high_PHY_capable, "%d\n");
84+
sdw_slave_attr(paging_support, "%d\n");
85+
sdw_slave_attr(bank_delay_support, "%d\n");
86+
sdw_slave_attr(p15_behave, "%d\n");
87+
sdw_slave_attr(master_count, "%d\n");
88+
sdw_slave_attr(source_ports, "0x%x\n");
89+
sdw_slave_attr(sink_ports, "0x%x\n");
90+
91+
static ssize_t modalias_show(struct device *dev,
92+
struct device_attribute *attr, char *buf)
93+
{
94+
struct sdw_slave *slave = dev_to_sdw_dev(dev);
95+
96+
return sdw_slave_modalias(slave, buf, 256);
97+
}
98+
static DEVICE_ATTR_RO(modalias);
99+
100+
static struct attribute *slave_attrs[] = {
101+
&dev_attr_modalias.attr,
102+
NULL,
103+
};
104+
ATTRIBUTE_GROUPS(slave);
105+
106+
static struct attribute *slave_dev_attrs[] = {
107+
&dev_attr_mipi_revision.attr,
108+
&dev_attr_wake_capable.attr,
109+
&dev_attr_test_mode_capable.attr,
110+
&dev_attr_clk_stop_mode1.attr,
111+
&dev_attr_simple_clk_stop_capable.attr,
112+
&dev_attr_clk_stop_timeout.attr,
113+
&dev_attr_ch_prep_timeout.attr,
114+
&dev_attr_reset_behave.attr,
115+
&dev_attr_high_PHY_capable.attr,
116+
&dev_attr_paging_support.attr,
117+
&dev_attr_bank_delay_support.attr,
118+
&dev_attr_p15_behave.attr,
119+
&dev_attr_master_count.attr,
120+
&dev_attr_source_ports.attr,
121+
&dev_attr_sink_ports.attr,
122+
NULL,
123+
};
124+
125+
/*
126+
* we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
127+
* for device-level properties
128+
*/
129+
static struct attribute_group sdw_slave_dev_attr_group = {
130+
.attrs = slave_dev_attrs,
131+
.name = "dev-properties",
132+
};
133+
134+
/*
135+
* DP0 sysfs
136+
*/
137+
138+
#define sdw_dp0_attr(field, format_string) \
139+
static ssize_t field##_show(struct device *dev, \
140+
struct device_attribute *attr, \
141+
char *buf) \
142+
{ \
143+
struct sdw_slave *slave = dev_to_sdw_dev(dev); \
144+
return sprintf(buf, format_string, slave->prop.dp0_prop->field);\
145+
} \
146+
static DEVICE_ATTR_RO(field)
147+
148+
sdw_dp0_attr(max_word, "%d\n");
149+
sdw_dp0_attr(min_word, "%d\n");
150+
sdw_dp0_attr(BRA_flow_controlled, "%d\n");
151+
sdw_dp0_attr(simple_ch_prep_sm, "%d\n");
152+
sdw_dp0_attr(imp_def_interrupts, "0x%x\n");
153+
154+
static ssize_t words_show(struct device *dev,
155+
struct device_attribute *attr, char *buf)
156+
{
157+
struct sdw_slave *slave = dev_to_sdw_dev(dev);
158+
ssize_t size = 0;
159+
int i;
160+
161+
for (i = 0; i < slave->prop.dp0_prop->num_words; i++)
162+
size += sprintf(buf + size, "%d ",
163+
slave->prop.dp0_prop->words[i]);
164+
size += sprintf(buf + size, "\n");
165+
166+
return size;
167+
}
168+
static DEVICE_ATTR_RO(words);
169+
170+
static struct attribute *dp0_attrs[] = {
171+
&dev_attr_max_word.attr,
172+
&dev_attr_min_word.attr,
173+
&dev_attr_words.attr,
174+
&dev_attr_BRA_flow_controlled.attr,
175+
&dev_attr_simple_ch_prep_sm.attr,
176+
&dev_attr_imp_def_interrupts.attr,
177+
NULL,
178+
};
179+
180+
/*
181+
* we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory
182+
* for dp0-level properties
183+
*/
184+
static const struct attribute_group dp0_group = {
185+
.attrs = dp0_attrs,
186+
.name = "dp0",
187+
};
188+
189+
int sdw_slave_sysfs_init(struct sdw_slave *slave)
190+
{
191+
int ret;
192+
193+
ret = devm_device_add_groups(&slave->dev, slave_groups);
194+
if (ret < 0)
195+
return ret;
196+
197+
ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group);
198+
if (ret < 0)
199+
return ret;
200+
201+
if (slave->prop.dp0_prop) {
202+
ret = devm_device_add_group(&slave->dev, &dp0_group);
203+
if (ret < 0)
204+
return ret;
205+
}
206+
207+
if (slave->prop.source_ports || slave->prop.sink_ports) {
208+
ret = sdw_slave_sysfs_dpn_init(slave);
209+
if (ret < 0)
210+
return ret;
211+
}
212+
213+
return 0;
214+
}
215+

0 commit comments

Comments
 (0)