1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * VIDEO MOTION CODECs internal API for video devices
5 * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
6 * bound to a master device.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/slab.h>
17 #include "videocodec.h"
19 struct attached_list {
20 struct videocodec *codec;
21 struct attached_list *next;
25 const struct videocodec *codec;
27 struct attached_list *list;
28 struct codec_list *next;
31 static struct codec_list *codeclist_top;
33 /* ================================================= */
34 /* function prototypes of the master/slave interface */
35 /* ================================================= */
37 struct videocodec *videocodec_attach(struct videocodec_master *master)
39 struct codec_list *h = codeclist_top;
41 struct attached_list *a, *ptr;
42 struct videocodec *codec;
46 pr_err("%s: no data\n", __func__);
50 zr = videocodec_master_to_zoran(master);
52 zrdev_dbg(zr, "%s: '%s', flags %lx, magic %lx\n", __func__,
53 master->name, master->flags, master->magic);
56 zrdev_err(zr, "%s: no device available\n", __func__);
61 // attach only if the slave has at least the flags
62 // expected by the master
63 if ((master->flags & h->codec->flags) == master->flags) {
64 zrdev_dbg(zr, "%s: try '%s'\n", __func__, h->codec->name);
66 codec = kmemdup(h->codec, sizeof(struct videocodec), GFP_KERNEL);
70 res = strlen(codec->name);
71 snprintf(codec->name + res, sizeof(codec->name) - res, "[%d]", h->attached);
72 codec->master_data = master;
73 res = codec->setup(codec);
75 zrdev_dbg(zr, "%s: '%s'\n", __func__, codec->name);
76 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
84 zrdev_dbg(zr, "videocodec: first element\n");
87 a = a->next; // find end
89 zrdev_dbg(zr, "videocodec: in after '%s'\n",
101 zrdev_err(zr, "%s: no codec found!\n", __func__);
109 int videocodec_detach(struct videocodec *codec)
111 struct codec_list *h = codeclist_top;
113 struct attached_list *a, *prev;
117 pr_err("%s: no data\n", __func__);
121 zr = videocodec_to_zoran(codec);
123 zrdev_dbg(zr, "%s: '%s', type: %x, flags %lx, magic %lx\n", __func__,
124 codec->name, codec->type, codec->flags, codec->magic);
127 zrdev_err(zr, "%s: no device left...\n", __func__);
135 if (codec == a->codec) {
136 res = a->codec->unset(a->codec);
138 zrdev_dbg(zr, "%s: '%s'\n", __func__,
140 a->codec->master_data = NULL;
142 zrdev_err(zr, "%s: '%s'\n", __func__, a->codec->name);
143 a->codec->master_data = NULL;
147 zrdev_dbg(zr, "videocodec: delete first\n");
149 prev->next = a->next;
150 zrdev_dbg(zr, "videocodec: delete middle\n");
163 zrdev_err(zr, "%s: given codec not found!\n", __func__);
167 int videocodec_register(const struct videocodec *codec)
169 struct codec_list *ptr, *h = codeclist_top;
173 pr_err("%s: no data!\n", __func__);
177 zr = videocodec_to_zoran((struct videocodec *)codec);
180 "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
181 codec->name, codec->type, codec->flags, codec->magic);
183 ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
190 zrdev_dbg(zr, "videocodec: hooked in as first element\n");
193 h = h->next; // find the end
195 zrdev_dbg(zr, "videocodec: hooked in after '%s'\n",
202 int videocodec_unregister(const struct videocodec *codec)
204 struct codec_list *prev = NULL, *h = codeclist_top;
208 pr_err("%s: no data!\n", __func__);
212 zr = videocodec_to_zoran((struct videocodec *)codec);
215 "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
216 codec->name, codec->type, codec->flags, codec->magic);
219 zrdev_err(zr, "%s: no device left...\n", __func__);
224 if (codec == h->codec) {
226 zrdev_err(zr, "videocodec: '%s' is used\n",
230 zrdev_dbg(zr, "videocodec: unregister '%s' is ok.\n",
233 codeclist_top = h->next;
235 "videocodec: delete first element\n");
237 prev->next = h->next;
239 "videocodec: delete middle element\n");
248 zrdev_err(zr, "%s: given codec not found!\n", __func__);
252 int videocodec_debugfs_show(struct seq_file *m)
254 struct codec_list *h = codeclist_top;
255 struct attached_list *a;
257 seq_puts(m, "<S>lave or attached <M>aster name type flags magic ");
258 seq_puts(m, "(connected as)\n");
261 seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
262 h->codec->name, h->codec->type,
263 h->codec->flags, h->codec->magic);
266 seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
267 a->codec->master_data->name,
268 a->codec->master_data->type,
269 a->codec->master_data->flags,
270 a->codec->master_data->magic,