Merge tag 'drm-misc-next-2023-09-27' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / drivers / staging / greybus / audio_manager_module.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Greybus operations
4  *
5  * Copyright 2015-2016 Google Inc.
6  */
7
8 #include <linux/slab.h>
9
10 #include "audio_manager.h"
11 #include "audio_manager_private.h"
12
13 #define to_gb_audio_module_attr(x)      \
14                 container_of(x, struct gb_audio_manager_module_attribute, attr)
15
16 static inline struct gb_audio_manager_module *to_gb_audio_module(struct kobject *kobj)
17 {
18         return container_of(kobj, struct gb_audio_manager_module, kobj);
19 }
20
21 struct gb_audio_manager_module_attribute {
22         struct attribute attr;
23         ssize_t (*show)(struct gb_audio_manager_module *module,
24                         struct gb_audio_manager_module_attribute *attr,
25                         char *buf);
26         ssize_t (*store)(struct gb_audio_manager_module *module,
27                          struct gb_audio_manager_module_attribute *attr,
28                          const char *buf, size_t count);
29 };
30
31 static ssize_t gb_audio_module_attr_show(struct kobject *kobj,
32                                          struct attribute *attr, char *buf)
33 {
34         struct gb_audio_manager_module_attribute *attribute;
35         struct gb_audio_manager_module *module;
36
37         attribute = to_gb_audio_module_attr(attr);
38         module = to_gb_audio_module(kobj);
39
40         if (!attribute->show)
41                 return -EIO;
42
43         return attribute->show(module, attribute, buf);
44 }
45
46 static ssize_t gb_audio_module_attr_store(struct kobject *kobj,
47                                           struct attribute *attr,
48                                           const char *buf, size_t len)
49 {
50         struct gb_audio_manager_module_attribute *attribute;
51         struct gb_audio_manager_module *module;
52
53         attribute = to_gb_audio_module_attr(attr);
54         module = to_gb_audio_module(kobj);
55
56         if (!attribute->store)
57                 return -EIO;
58
59         return attribute->store(module, attribute, buf, len);
60 }
61
62 static const struct sysfs_ops gb_audio_module_sysfs_ops = {
63         .show = gb_audio_module_attr_show,
64         .store = gb_audio_module_attr_store,
65 };
66
67 static void gb_audio_module_release(struct kobject *kobj)
68 {
69         struct gb_audio_manager_module *module = to_gb_audio_module(kobj);
70
71         pr_info("Destroying audio module #%d\n", module->id);
72         /* TODO -> delete from list */
73         kfree(module);
74 }
75
76 static ssize_t gb_audio_module_name_show(struct gb_audio_manager_module *module,
77                                          struct gb_audio_manager_module_attribute *attr, char *buf)
78 {
79         return sprintf(buf, "%s", module->desc.name);
80 }
81
82 static struct gb_audio_manager_module_attribute gb_audio_module_name_attribute =
83         __ATTR(name, 0664, gb_audio_module_name_show, NULL);
84
85 static ssize_t gb_audio_module_vid_show(struct gb_audio_manager_module *module,
86                                         struct gb_audio_manager_module_attribute *attr, char *buf)
87 {
88         return sprintf(buf, "%d", module->desc.vid);
89 }
90
91 static struct gb_audio_manager_module_attribute gb_audio_module_vid_attribute =
92         __ATTR(vid, 0664, gb_audio_module_vid_show, NULL);
93
94 static ssize_t gb_audio_module_pid_show(struct gb_audio_manager_module *module,
95                                         struct gb_audio_manager_module_attribute *attr, char *buf)
96 {
97         return sprintf(buf, "%d", module->desc.pid);
98 }
99
100 static struct gb_audio_manager_module_attribute gb_audio_module_pid_attribute =
101         __ATTR(pid, 0664, gb_audio_module_pid_show, NULL);
102
103 static ssize_t gb_audio_module_intf_id_show(struct gb_audio_manager_module *module,
104                                             struct gb_audio_manager_module_attribute *attr,
105                                             char *buf)
106 {
107         return sprintf(buf, "%d", module->desc.intf_id);
108 }
109
110 static struct gb_audio_manager_module_attribute
111                                         gb_audio_module_intf_id_attribute =
112         __ATTR(intf_id, 0664, gb_audio_module_intf_id_show, NULL);
113
114 static ssize_t gb_audio_module_ip_devices_show(struct gb_audio_manager_module *module,
115                                                struct gb_audio_manager_module_attribute *attr,
116                                                char *buf)
117 {
118         return sprintf(buf, "0x%X", module->desc.ip_devices);
119 }
120
121 static struct gb_audio_manager_module_attribute
122                                         gb_audio_module_ip_devices_attribute =
123         __ATTR(ip_devices, 0664, gb_audio_module_ip_devices_show, NULL);
124
125 static ssize_t gb_audio_module_op_devices_show(struct gb_audio_manager_module *module,
126                                                struct gb_audio_manager_module_attribute *attr,
127                                                char *buf)
128 {
129         return sprintf(buf, "0x%X", module->desc.op_devices);
130 }
131
132 static struct gb_audio_manager_module_attribute
133                                         gb_audio_module_op_devices_attribute =
134         __ATTR(op_devices, 0664, gb_audio_module_op_devices_show, NULL);
135
136 static struct attribute *gb_audio_module_default_attrs[] = {
137         &gb_audio_module_name_attribute.attr,
138         &gb_audio_module_vid_attribute.attr,
139         &gb_audio_module_pid_attribute.attr,
140         &gb_audio_module_intf_id_attribute.attr,
141         &gb_audio_module_ip_devices_attribute.attr,
142         &gb_audio_module_op_devices_attribute.attr,
143         NULL,   /* need to NULL terminate the list of attributes */
144 };
145 ATTRIBUTE_GROUPS(gb_audio_module_default);
146
147 static struct kobj_type gb_audio_module_type = {
148         .sysfs_ops = &gb_audio_module_sysfs_ops,
149         .release = gb_audio_module_release,
150         .default_groups = gb_audio_module_default_groups,
151 };
152
153 static void send_add_uevent(struct gb_audio_manager_module *module)
154 {
155         char name_string[128];
156         char vid_string[64];
157         char pid_string[64];
158         char intf_id_string[64];
159         char ip_devices_string[64];
160         char op_devices_string[64];
161
162         char *envp[] = {
163                 name_string,
164                 vid_string,
165                 pid_string,
166                 intf_id_string,
167                 ip_devices_string,
168                 op_devices_string,
169                 NULL
170         };
171
172         snprintf(name_string, 128, "NAME=%s", module->desc.name);
173         snprintf(vid_string, 64, "VID=%d", module->desc.vid);
174         snprintf(pid_string, 64, "PID=%d", module->desc.pid);
175         snprintf(intf_id_string, 64, "INTF_ID=%d", module->desc.intf_id);
176         snprintf(ip_devices_string, 64, "I/P DEVICES=0x%X",
177                  module->desc.ip_devices);
178         snprintf(op_devices_string, 64, "O/P DEVICES=0x%X",
179                  module->desc.op_devices);
180
181         kobject_uevent_env(&module->kobj, KOBJ_ADD, envp);
182 }
183
184 int gb_audio_manager_module_create(struct gb_audio_manager_module **module,
185                                    struct kset *manager_kset,
186                                    int id, struct gb_audio_manager_module_descriptor *desc)
187 {
188         int err;
189         struct gb_audio_manager_module *m;
190
191         m = kzalloc(sizeof(*m), GFP_ATOMIC);
192         if (!m)
193                 return -ENOMEM;
194
195         /* Initialize the node */
196         INIT_LIST_HEAD(&m->list);
197
198         /* Set the module id */
199         m->id = id;
200
201         /* Copy the provided descriptor */
202         memcpy(&m->desc, desc, sizeof(*desc));
203
204         /* set the kset */
205         m->kobj.kset = manager_kset;
206
207         /*
208          * Initialize and add the kobject to the kernel.  All the default files
209          * will be created here.  As we have already specified a kset for this
210          * kobject, we don't have to set a parent for the kobject, the kobject
211          * will be placed beneath that kset automatically.
212          */
213         err = kobject_init_and_add(&m->kobj, &gb_audio_module_type, NULL, "%d",
214                                    id);
215         if (err) {
216                 pr_err("failed initializing kobject for audio module #%d\n", id);
217                 kobject_put(&m->kobj);
218                 return err;
219         }
220
221         /*
222          * Notify the object was created
223          */
224         send_add_uevent(m);
225
226         *module = m;
227         pr_info("Created audio module #%d\n", id);
228         return 0;
229 }
230
231 void gb_audio_manager_module_dump(struct gb_audio_manager_module *module)
232 {
233         pr_info("audio module #%d name=%s vid=%d pid=%d intf_id=%d i/p devices=0x%X o/p devices=0x%X\n",
234                 module->id,
235                 module->desc.name,
236                 module->desc.vid,
237                 module->desc.pid,
238                 module->desc.intf_id,
239                 module->desc.ip_devices,
240                 module->desc.op_devices);
241 }