0001
0002
0003
0004 #include <linux/device.h>
0005 #include <linux/mod_devicetable.h>
0006 #include <linux/slab.h>
0007 #include <linux/sysfs.h>
0008 #include <linux/soundwire/sdw.h>
0009 #include <linux/soundwire/sdw_type.h>
0010 #include "bus.h"
0011 #include "sysfs_local.h"
0012
0013 struct dpn_attribute {
0014 struct device_attribute dev_attr;
0015 int N;
0016 int dir;
0017 const char *format_string;
0018 };
0019
0020
0021
0022
0023
0024
0025 #define SDW_DPN_ATTRIBUTES 15
0026
0027 #define sdw_dpn_attribute_alloc(field) \
0028 static int field##_attribute_alloc(struct device *dev, \
0029 struct attribute **res, \
0030 int N, int dir, \
0031 const char *format_string) \
0032 { \
0033 struct dpn_attribute *dpn_attr; \
0034 \
0035 dpn_attr = devm_kzalloc(dev, sizeof(*dpn_attr), GFP_KERNEL); \
0036 if (!dpn_attr) \
0037 return -ENOMEM; \
0038 dpn_attr->N = N; \
0039 dpn_attr->dir = dir; \
0040 sysfs_attr_init(&dpn_attr->dev_attr.attr); \
0041 dpn_attr->format_string = format_string; \
0042 dpn_attr->dev_attr.attr.name = __stringify(field); \
0043 dpn_attr->dev_attr.attr.mode = 0444; \
0044 dpn_attr->dev_attr.show = field##_show; \
0045 \
0046 *res = &dpn_attr->dev_attr.attr; \
0047 \
0048 return 0; \
0049 }
0050
0051 #define sdw_dpn_attr(field) \
0052 \
0053 static ssize_t field##_dpn_show(struct sdw_slave *slave, \
0054 int N, \
0055 int dir, \
0056 const char *format_string, \
0057 char *buf) \
0058 { \
0059 struct sdw_dpn_prop *dpn; \
0060 unsigned long mask; \
0061 int bit; \
0062 int i; \
0063 \
0064 if (dir) { \
0065 dpn = slave->prop.src_dpn_prop; \
0066 mask = slave->prop.source_ports; \
0067 } else { \
0068 dpn = slave->prop.sink_dpn_prop; \
0069 mask = slave->prop.sink_ports; \
0070 } \
0071 \
0072 i = 0; \
0073 for_each_set_bit(bit, &mask, 32) { \
0074 if (bit == N) { \
0075 return sprintf(buf, format_string, \
0076 dpn[i].field); \
0077 } \
0078 i++; \
0079 } \
0080 return -EINVAL; \
0081 } \
0082 \
0083 static ssize_t field##_show(struct device *dev, \
0084 struct device_attribute *attr, \
0085 char *buf) \
0086 { \
0087 struct sdw_slave *slave = dev_to_sdw_dev(dev); \
0088 struct dpn_attribute *dpn_attr = \
0089 container_of(attr, struct dpn_attribute, dev_attr); \
0090 \
0091 return field##_dpn_show(slave, \
0092 dpn_attr->N, dpn_attr->dir, \
0093 dpn_attr->format_string, \
0094 buf); \
0095 } \
0096 sdw_dpn_attribute_alloc(field)
0097
0098 sdw_dpn_attr(imp_def_interrupts);
0099 sdw_dpn_attr(max_word);
0100 sdw_dpn_attr(min_word);
0101 sdw_dpn_attr(type);
0102 sdw_dpn_attr(max_grouping);
0103 sdw_dpn_attr(simple_ch_prep_sm);
0104 sdw_dpn_attr(ch_prep_timeout);
0105 sdw_dpn_attr(max_ch);
0106 sdw_dpn_attr(min_ch);
0107 sdw_dpn_attr(max_async_buffer);
0108 sdw_dpn_attr(block_pack_mode);
0109 sdw_dpn_attr(port_encoding);
0110
0111 #define sdw_dpn_array_attr(field) \
0112 \
0113 static ssize_t field##_dpn_show(struct sdw_slave *slave, \
0114 int N, \
0115 int dir, \
0116 const char *format_string, \
0117 char *buf) \
0118 { \
0119 struct sdw_dpn_prop *dpn; \
0120 unsigned long mask; \
0121 ssize_t size = 0; \
0122 int bit; \
0123 int i; \
0124 int j; \
0125 \
0126 if (dir) { \
0127 dpn = slave->prop.src_dpn_prop; \
0128 mask = slave->prop.source_ports; \
0129 } else { \
0130 dpn = slave->prop.sink_dpn_prop; \
0131 mask = slave->prop.sink_ports; \
0132 } \
0133 \
0134 i = 0; \
0135 for_each_set_bit(bit, &mask, 32) { \
0136 if (bit == N) { \
0137 for (j = 0; j < dpn[i].num_##field; j++) \
0138 size += sprintf(buf + size, \
0139 format_string, \
0140 dpn[i].field[j]); \
0141 size += sprintf(buf + size, "\n"); \
0142 return size; \
0143 } \
0144 i++; \
0145 } \
0146 return -EINVAL; \
0147 } \
0148 static ssize_t field##_show(struct device *dev, \
0149 struct device_attribute *attr, \
0150 char *buf) \
0151 { \
0152 struct sdw_slave *slave = dev_to_sdw_dev(dev); \
0153 struct dpn_attribute *dpn_attr = \
0154 container_of(attr, struct dpn_attribute, dev_attr); \
0155 \
0156 return field##_dpn_show(slave, \
0157 dpn_attr->N, dpn_attr->dir, \
0158 dpn_attr->format_string, \
0159 buf); \
0160 } \
0161 sdw_dpn_attribute_alloc(field)
0162
0163 sdw_dpn_array_attr(words);
0164 sdw_dpn_array_attr(ch_combinations);
0165 sdw_dpn_array_attr(channels);
0166
0167 static int add_all_attributes(struct device *dev, int N, int dir)
0168 {
0169 struct attribute **dpn_attrs;
0170 struct attribute_group *dpn_group;
0171 int i = 0;
0172 int ret;
0173
0174
0175 dpn_attrs = devm_kcalloc(dev, SDW_DPN_ATTRIBUTES + 1,
0176 sizeof(struct attribute *),
0177 GFP_KERNEL);
0178 if (!dpn_attrs)
0179 return -ENOMEM;
0180
0181 ret = max_word_attribute_alloc(dev, &dpn_attrs[i++],
0182 N, dir, "%d\n");
0183 if (ret < 0)
0184 return ret;
0185
0186 ret = min_word_attribute_alloc(dev, &dpn_attrs[i++],
0187 N, dir, "%d\n");
0188 if (ret < 0)
0189 return ret;
0190
0191 ret = words_attribute_alloc(dev, &dpn_attrs[i++],
0192 N, dir, "%d\n");
0193 if (ret < 0)
0194 return ret;
0195
0196 ret = type_attribute_alloc(dev, &dpn_attrs[i++],
0197 N, dir, "%d\n");
0198 if (ret < 0)
0199 return ret;
0200
0201 ret = max_grouping_attribute_alloc(dev, &dpn_attrs[i++],
0202 N, dir, "%d\n");
0203 if (ret < 0)
0204 return ret;
0205
0206 ret = simple_ch_prep_sm_attribute_alloc(dev, &dpn_attrs[i++],
0207 N, dir, "%d\n");
0208 if (ret < 0)
0209 return ret;
0210
0211 ret = ch_prep_timeout_attribute_alloc(dev, &dpn_attrs[i++],
0212 N, dir, "%d\n");
0213 if (ret < 0)
0214 return ret;
0215
0216 ret = imp_def_interrupts_attribute_alloc(dev, &dpn_attrs[i++],
0217 N, dir, "0x%x\n");
0218 if (ret < 0)
0219 return ret;
0220
0221 ret = min_ch_attribute_alloc(dev, &dpn_attrs[i++],
0222 N, dir, "%d\n");
0223 if (ret < 0)
0224 return ret;
0225
0226 ret = max_ch_attribute_alloc(dev, &dpn_attrs[i++],
0227 N, dir, "%d\n");
0228 if (ret < 0)
0229 return ret;
0230
0231 ret = channels_attribute_alloc(dev, &dpn_attrs[i++],
0232 N, dir, "%d\n");
0233 if (ret < 0)
0234 return ret;
0235
0236 ret = ch_combinations_attribute_alloc(dev, &dpn_attrs[i++],
0237 N, dir, "%d\n");
0238 if (ret < 0)
0239 return ret;
0240
0241 ret = max_async_buffer_attribute_alloc(dev, &dpn_attrs[i++],
0242 N, dir, "%d\n");
0243 if (ret < 0)
0244 return ret;
0245
0246 ret = block_pack_mode_attribute_alloc(dev, &dpn_attrs[i++],
0247 N, dir, "%d\n");
0248 if (ret < 0)
0249 return ret;
0250
0251 ret = port_encoding_attribute_alloc(dev, &dpn_attrs[i++],
0252 N, dir, "%d\n");
0253 if (ret < 0)
0254 return ret;
0255
0256
0257 if (i != SDW_DPN_ATTRIBUTES) {
0258 dev_err(dev, "mismatch in attributes, allocated %d got %d\n",
0259 SDW_DPN_ATTRIBUTES, i);
0260 return -EINVAL;
0261 }
0262
0263 dpn_group = devm_kzalloc(dev, sizeof(*dpn_group), GFP_KERNEL);
0264 if (!dpn_group)
0265 return -ENOMEM;
0266
0267 dpn_group->attrs = dpn_attrs;
0268 dpn_group->name = devm_kasprintf(dev, GFP_KERNEL, "dp%d_%s",
0269 N, dir ? "src" : "sink");
0270 if (!dpn_group->name)
0271 return -ENOMEM;
0272
0273 ret = devm_device_add_group(dev, dpn_group);
0274 if (ret < 0)
0275 return ret;
0276
0277 return 0;
0278 }
0279
0280 int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave)
0281 {
0282 unsigned long mask;
0283 int ret;
0284 int i;
0285
0286 mask = slave->prop.source_ports;
0287 for_each_set_bit(i, &mask, 32) {
0288 ret = add_all_attributes(&slave->dev, i, 1);
0289 if (ret < 0)
0290 return ret;
0291 }
0292
0293 mask = slave->prop.sink_ports;
0294 for_each_set_bit(i, &mask, 32) {
0295 ret = add_all_attributes(&slave->dev, i, 0);
0296 if (ret < 0)
0297 return ret;
0298 }
0299
0300 return 0;
0301 }