~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/zoran/videocodec.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * VIDEO MOTION CODECs internal API for video devices
 
3
 *
 
4
 * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
 
5
 * bound to a master device.
 
6
 *
 
7
 * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
 
8
 *
 
9
 * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $
 
10
 *
 
11
 * ------------------------------------------------------------------------
 
12
 *
 
13
 * This program is free software; you can redistribute it and/or modify
 
14
 * it under the terms of the GNU General Public License as published by
 
15
 * the Free Software Foundation; either version 2 of the License, or
 
16
 * (at your option) any later version.
 
17
 *
 
18
 * This program is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this program; if not, write to the Free Software
 
25
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
26
 *
 
27
 * ------------------------------------------------------------------------
 
28
 */
 
29
 
 
30
#define VIDEOCODEC_VERSION "v0.2"
 
31
 
 
32
#include <linux/kernel.h>
 
33
#include <linux/module.h>
 
34
#include <linux/init.h>
 
35
#include <linux/types.h>
 
36
#include <linux/slab.h>
 
37
 
 
38
// kernel config is here (procfs flag)
 
39
 
 
40
#ifdef CONFIG_PROC_FS
 
41
#include <linux/proc_fs.h>
 
42
#include <linux/seq_file.h>
 
43
#include <asm/uaccess.h>
 
44
#endif
 
45
 
 
46
#include "videocodec.h"
 
47
 
 
48
static int debug;
 
49
module_param(debug, int, 0);
 
50
MODULE_PARM_DESC(debug, "Debug level (0-4)");
 
51
 
 
52
#define dprintk(num, format, args...) \
 
53
        do { \
 
54
                if (debug >= num) \
 
55
                        printk(format, ##args); \
 
56
        } while (0)
 
57
 
 
58
struct attached_list {
 
59
        struct videocodec *codec;
 
60
        struct attached_list *next;
 
61
};
 
62
 
 
63
struct codec_list {
 
64
        const struct videocodec *codec;
 
65
        int attached;
 
66
        struct attached_list *list;
 
67
        struct codec_list *next;
 
68
};
 
69
 
 
70
static struct codec_list *codeclist_top = NULL;
 
71
 
 
72
/* ================================================= */
 
73
/* function prototypes of the master/slave interface */
 
74
/* ================================================= */
 
75
 
 
76
struct videocodec *
 
77
videocodec_attach (struct videocodec_master *master)
 
78
{
 
79
        struct codec_list *h = codeclist_top;
 
80
        struct attached_list *a, *ptr;
 
81
        struct videocodec *codec;
 
82
        int res;
 
83
 
 
84
        if (!master) {
 
85
                dprintk(1, KERN_ERR "videocodec_attach: no data\n");
 
86
                return NULL;
 
87
        }
 
88
 
 
89
        dprintk(2,
 
90
                "videocodec_attach: '%s', flags %lx, magic %lx\n",
 
91
                master->name, master->flags, master->magic);
 
92
 
 
93
        if (!h) {
 
94
                dprintk(1,
 
95
                        KERN_ERR
 
96
                        "videocodec_attach: no device available\n");
 
97
                return NULL;
 
98
        }
 
99
 
 
100
        while (h) {
 
101
                // attach only if the slave has at least the flags
 
102
                // expected by the master
 
103
                if ((master->flags & h->codec->flags) == master->flags) {
 
104
                        dprintk(4, "videocodec_attach: try '%s'\n",
 
105
                                h->codec->name);
 
106
 
 
107
                        if (!try_module_get(h->codec->owner))
 
108
                                return NULL;
 
109
 
 
110
                        codec = kmemdup(h->codec, sizeof(struct videocodec),
 
111
                                        GFP_KERNEL);
 
112
                        if (!codec) {
 
113
                                dprintk(1,
 
114
                                        KERN_ERR
 
115
                                        "videocodec_attach: no mem\n");
 
116
                                goto out_module_put;
 
117
                        }
 
118
 
 
119
                        snprintf(codec->name, sizeof(codec->name),
 
120
                                 "%s[%d]", codec->name, h->attached);
 
121
                        codec->master_data = master;
 
122
                        res = codec->setup(codec);
 
123
                        if (res == 0) {
 
124
                                dprintk(3, "videocodec_attach '%s'\n",
 
125
                                        codec->name);
 
126
                                ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
 
127
                                if (!ptr) {
 
128
                                        dprintk(1,
 
129
                                                KERN_ERR
 
130
                                                "videocodec_attach: no memory\n");
 
131
                                        goto out_kfree;
 
132
                                }
 
133
                                ptr->codec = codec;
 
134
 
 
135
                                a = h->list;
 
136
                                if (!a) {
 
137
                                        h->list = ptr;
 
138
                                        dprintk(4,
 
139
                                                "videocodec: first element\n");
 
140
                                } else {
 
141
                                        while (a->next)
 
142
                                                a = a->next;    // find end
 
143
                                        a->next = ptr;
 
144
                                        dprintk(4,
 
145
                                                "videocodec: in after '%s'\n",
 
146
                                                h->codec->name);
 
147
                                }
 
148
 
 
149
                                h->attached += 1;
 
150
                                return codec;
 
151
                        } else {
 
152
                                kfree(codec);
 
153
                        }
 
154
                }
 
155
                h = h->next;
 
156
        }
 
157
 
 
158
        dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
 
159
        return NULL;
 
160
 
 
161
 out_module_put:
 
162
        module_put(h->codec->owner);
 
163
 out_kfree:
 
164
        kfree(codec);
 
165
        return NULL;
 
166
}
 
167
 
 
168
int
 
169
videocodec_detach (struct videocodec *codec)
 
170
{
 
171
        struct codec_list *h = codeclist_top;
 
172
        struct attached_list *a, *prev;
 
173
        int res;
 
174
 
 
175
        if (!codec) {
 
176
                dprintk(1, KERN_ERR "videocodec_detach: no data\n");
 
177
                return -EINVAL;
 
178
        }
 
179
 
 
180
        dprintk(2,
 
181
                "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n",
 
182
                codec->name, codec->type, codec->flags, codec->magic);
 
183
 
 
184
        if (!h) {
 
185
                dprintk(1,
 
186
                        KERN_ERR "videocodec_detach: no device left...\n");
 
187
                return -ENXIO;
 
188
        }
 
189
 
 
190
        while (h) {
 
191
                a = h->list;
 
192
                prev = NULL;
 
193
                while (a) {
 
194
                        if (codec == a->codec) {
 
195
                                res = a->codec->unset(a->codec);
 
196
                                if (res >= 0) {
 
197
                                        dprintk(3,
 
198
                                                "videocodec_detach: '%s'\n",
 
199
                                                a->codec->name);
 
200
                                        a->codec->master_data = NULL;
 
201
                                } else {
 
202
                                        dprintk(1,
 
203
                                                KERN_ERR
 
204
                                                "videocodec_detach: '%s'\n",
 
205
                                                a->codec->name);
 
206
                                        a->codec->master_data = NULL;
 
207
                                }
 
208
                                if (prev == NULL) {
 
209
                                        h->list = a->next;
 
210
                                        dprintk(4,
 
211
                                                "videocodec: delete first\n");
 
212
                                } else {
 
213
                                        prev->next = a->next;
 
214
                                        dprintk(4,
 
215
                                                "videocodec: delete middle\n");
 
216
                                }
 
217
                                module_put(a->codec->owner);
 
218
                                kfree(a->codec);
 
219
                                kfree(a);
 
220
                                h->attached -= 1;
 
221
                                return 0;
 
222
                        }
 
223
                        prev = a;
 
224
                        a = a->next;
 
225
                }
 
226
                h = h->next;
 
227
        }
 
228
 
 
229
        dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n");
 
230
        return -EINVAL;
 
231
}
 
232
 
 
233
int
 
234
videocodec_register (const struct videocodec *codec)
 
235
{
 
236
        struct codec_list *ptr, *h = codeclist_top;
 
237
 
 
238
        if (!codec) {
 
239
                dprintk(1, KERN_ERR "videocodec_register: no data!\n");
 
240
                return -EINVAL;
 
241
        }
 
242
 
 
243
        dprintk(2,
 
244
                "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
 
245
                codec->name, codec->type, codec->flags, codec->magic);
 
246
 
 
247
        ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
 
248
        if (!ptr) {
 
249
                dprintk(1, KERN_ERR "videocodec_register: no memory\n");
 
250
                return -ENOMEM;
 
251
        }
 
252
        ptr->codec = codec;
 
253
 
 
254
        if (!h) {
 
255
                codeclist_top = ptr;
 
256
                dprintk(4, "videocodec: hooked in as first element\n");
 
257
        } else {
 
258
                while (h->next)
 
259
                        h = h->next;    // find the end
 
260
                h->next = ptr;
 
261
                dprintk(4, "videocodec: hooked in after '%s'\n",
 
262
                        h->codec->name);
 
263
        }
 
264
 
 
265
        return 0;
 
266
}
 
267
 
 
268
int
 
269
videocodec_unregister (const struct videocodec *codec)
 
270
{
 
271
        struct codec_list *prev = NULL, *h = codeclist_top;
 
272
 
 
273
        if (!codec) {
 
274
                dprintk(1, KERN_ERR "videocodec_unregister: no data!\n");
 
275
                return -EINVAL;
 
276
        }
 
277
 
 
278
        dprintk(2,
 
279
                "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
 
280
                codec->name, codec->type, codec->flags, codec->magic);
 
281
 
 
282
        if (!h) {
 
283
                dprintk(1,
 
284
                        KERN_ERR
 
285
                        "videocodec_unregister: no device left...\n");
 
286
                return -ENXIO;
 
287
        }
 
288
 
 
289
        while (h) {
 
290
                if (codec == h->codec) {
 
291
                        if (h->attached) {
 
292
                                dprintk(1,
 
293
                                        KERN_ERR
 
294
                                        "videocodec: '%s' is used\n",
 
295
                                        h->codec->name);
 
296
                                return -EBUSY;
 
297
                        }
 
298
                        dprintk(3, "videocodec: unregister '%s' is ok.\n",
 
299
                                h->codec->name);
 
300
                        if (prev == NULL) {
 
301
                                codeclist_top = h->next;
 
302
                                dprintk(4,
 
303
                                        "videocodec: delete first element\n");
 
304
                        } else {
 
305
                                prev->next = h->next;
 
306
                                dprintk(4,
 
307
                                        "videocodec: delete middle element\n");
 
308
                        }
 
309
                        kfree(h);
 
310
                        return 0;
 
311
                }
 
312
                prev = h;
 
313
                h = h->next;
 
314
        }
 
315
 
 
316
        dprintk(1,
 
317
                KERN_ERR
 
318
                "videocodec_unregister: given codec not found!\n");
 
319
        return -EINVAL;
 
320
}
 
321
 
 
322
#ifdef CONFIG_PROC_FS
 
323
static int proc_videocodecs_show(struct seq_file *m, void *v)
 
324
{
 
325
        struct codec_list *h = codeclist_top;
 
326
        struct attached_list *a;
 
327
 
 
328
        seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
 
329
        seq_printf(m, "(connected as)\n");
 
330
 
 
331
        h = codeclist_top;
 
332
        while (h) {
 
333
                seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n",
 
334
                              h->codec->name, h->codec->type,
 
335
                              h->codec->flags, h->codec->magic);
 
336
                a = h->list;
 
337
                while (a) {
 
338
                        seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n",
 
339
                                      a->codec->master_data->name,
 
340
                                      a->codec->master_data->type,
 
341
                                      a->codec->master_data->flags,
 
342
                                      a->codec->master_data->magic,
 
343
                                      a->codec->name);
 
344
                        a = a->next;
 
345
                }
 
346
                h = h->next;
 
347
        }
 
348
 
 
349
        return 0;
 
350
}
 
351
 
 
352
static int proc_videocodecs_open(struct inode *inode, struct file *file)
 
353
{
 
354
        return single_open(file, proc_videocodecs_show, NULL);
 
355
}
 
356
 
 
357
static const struct file_operations videocodecs_proc_fops = {
 
358
        .owner          = THIS_MODULE,
 
359
        .open           = proc_videocodecs_open,
 
360
        .read           = seq_read,
 
361
        .llseek         = seq_lseek,
 
362
        .release        = single_release,
 
363
};
 
364
#endif
 
365
 
 
366
/* ===================== */
 
367
/* hook in driver module */
 
368
/* ===================== */
 
369
static int __init
 
370
videocodec_init (void)
 
371
{
 
372
#ifdef CONFIG_PROC_FS
 
373
        static struct proc_dir_entry *videocodec_proc_entry;
 
374
#endif
 
375
 
 
376
        printk(KERN_INFO "Linux video codec intermediate layer: %s\n",
 
377
               VIDEOCODEC_VERSION);
 
378
 
 
379
#ifdef CONFIG_PROC_FS
 
380
        videocodec_proc_entry = proc_create("videocodecs", 0, NULL, &videocodecs_proc_fops);
 
381
        if (!videocodec_proc_entry) {
 
382
                dprintk(1, KERN_ERR "videocodec: can't init procfs.\n");
 
383
        }
 
384
#endif
 
385
        return 0;
 
386
}
 
387
 
 
388
static void __exit
 
389
videocodec_exit (void)
 
390
{
 
391
#ifdef CONFIG_PROC_FS
 
392
        remove_proc_entry("videocodecs", NULL);
 
393
#endif
 
394
}
 
395
 
 
396
EXPORT_SYMBOL(videocodec_attach);
 
397
EXPORT_SYMBOL(videocodec_detach);
 
398
EXPORT_SYMBOL(videocodec_register);
 
399
EXPORT_SYMBOL(videocodec_unregister);
 
400
 
 
401
module_init(videocodec_init);
 
402
module_exit(videocodec_exit);
 
403
 
 
404
MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
 
405
MODULE_DESCRIPTION("Intermediate API module for video codecs "
 
406
                   VIDEOCODEC_VERSION);
 
407
MODULE_LICENSE("GPL");