Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mcheha...
[pandora-kernel.git] / drivers / staging / dt3155 / dt3155_isr.c
1 /*
2
3 Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4                                 Jason Lapenta, Scott Smedley, Greg Sharp
5
6 This file is part of the DT3155 Device Driver.
7
8 The DT3155 Device Driver is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The DT3155 Device Driver is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with the DT3155 Device Driver; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 MA 02111-1307 USA
22
23    File: dt3155_isr.c
24 Purpose: Buffer management routines, and other routines for the ISR
25                 (the actual isr is in dt3155_drv.c)
26
27 -- Changes --
28
29   Date       Programmer  Description of changes made
30   -------------------------------------------------------------------
31   03-Jul-2000 JML       n/a
32   02-Apr-2002 SS        Mods to make work with separate allocator
33                         module; Merged John Roll's mods to make work with
34                         multiple boards.
35   10-Jul-2002 GCS       Complete rewrite of setup_buffers to disallow
36                         buffers which span a 4MB boundary.
37   24-Jul-2002 SS        GPL licence.
38   30-Jul-2002 NJC       Added support for buffer loop.
39   31-Jul-2002 NJC       Complete rewrite of buffer management
40   02-Aug-2002 NJC       Including slab.h instead of malloc.h (no warning).
41                         Also, allocator_init() now returns allocator_max
42                         so cleaned up allocate_buffers() accordingly.
43   08-Aug-2005 SS        port to 2.6 kernel.
44
45 */
46
47 #include <asm/system.h>
48 #include <linux/gfp.h>
49 #include <linux/sched.h>
50 #include <linux/types.h>
51
52 #include "dt3155.h"
53 #include "dt3155_drv.h"
54 #include "dt3155_io.h"
55 #include "dt3155_isr.h"
56 #include "allocator.h"
57
58 #define FOUR_MB         (0x0400000)  /* Can't DMA accross a 4MB boundary!*/
59 #define UPPER_10_BITS   (0x3FF<<22)  /* Can't DMA accross a 4MB boundary!*/
60
61
62 /* Pointer into global structure for handling buffers */
63 struct dt3155_fbuffer *dt3155_fbuffer[MAXBOARDS] = {NULL
64 #if MAXBOARDS == 2
65                                                       , NULL
66 #endif
67 };
68
69 /******************************************************************************
70  * Simple array based que struct
71  *
72  * Some handy functions using the buffering structure.
73  *****************************************************************************/
74
75
76 /***************************
77  * are_empty_buffers
78  * m is minor # of device
79  ***************************/
80 bool are_empty_buffers(int m)
81 {
82   return dt3155_fbuffer[m]->empty_len;
83 }
84
85 /**************************
86  * push_empty
87  * m is minor # of device
88  *
89  * This is slightly confusing.  The number empty_len is the literal #
90  * of empty buffers.  After calling, empty_len-1 is the index into the
91  * empty buffer stack.  So, if empty_len == 1, there is one empty buffer,
92  * given by dt3155_fbuffer[m]->empty_buffers[0].
93  * empty_buffers should never fill up, though this is not checked.
94  **************************/
95 void push_empty(int index, int m)
96 {
97   dt3155_fbuffer[m]->empty_buffers[dt3155_fbuffer[m]->empty_len] = index;
98   dt3155_fbuffer[m]->empty_len++;
99 }
100
101 /**************************
102  * pop_empty(m)
103  * m is minor # of device
104  **************************/
105 int pop_empty(int m)
106 {
107   dt3155_fbuffer[m]->empty_len--;
108   return dt3155_fbuffer[m]->empty_buffers[dt3155_fbuffer[m]->empty_len];
109 }
110
111 /*************************
112  * is_ready_buf_empty(m)
113  * m is minor # of device
114  *************************/
115 bool is_ready_buf_empty(int m)
116 {
117   return ((dt3155_fbuffer[m]->ready_len) == 0);
118 }
119
120 /*************************
121  * is_ready_buf_full(m)
122  * m is minor # of device
123  * this should *never* be true if there are any active, locked or empty
124  * buffers, since it corresponds to nbuffers ready buffers!!
125  * 7/31/02: total rewrite. --NJC
126  *************************/
127 bool is_ready_buf_full(int m)
128 {
129   return dt3155_fbuffer[m]->ready_len == dt3155_fbuffer[m]->nbuffers;
130 }
131
132 /*****************************************************
133  * push_ready(m, buffer)
134  * m is minor # of device
135  *
136  *****************************************************/
137 void push_ready(int m, int index)
138 {
139   int head = dt3155_fbuffer[m]->ready_head;
140
141   dt3155_fbuffer[m]->ready_que[head] = index;
142   dt3155_fbuffer[m]->ready_head = ((head + 1) %
143                                       (dt3155_fbuffer[m]->nbuffers));
144   dt3155_fbuffer[m]->ready_len++;
145
146 }
147
148 /*****************************************************
149  * get_tail()
150  * m is minor # of device
151  *
152  * Simply comptutes the tail given the head and the length.
153  *****************************************************/
154 static int get_tail(int m)
155 {
156   return (dt3155_fbuffer[m]->ready_head -
157            dt3155_fbuffer[m]->ready_len +
158            dt3155_fbuffer[m]->nbuffers)%
159           (dt3155_fbuffer[m]->nbuffers);
160 }
161
162
163
164 /*****************************************************
165  * pop_ready()
166  * m is minor # of device
167  *
168  * This assumes that there is a ready buffer ready... should
169  * be checked (e.g. with is_ready_buf_empty()  prior to call.
170  *****************************************************/
171 int pop_ready(int m)
172 {
173   int tail;
174   tail = get_tail(m);
175   dt3155_fbuffer[m]->ready_len--;
176   return dt3155_fbuffer[m]->ready_que[tail];
177 }
178
179
180 /*****************************************************
181  * printques
182  * m is minor # of device
183  *****************************************************/
184 void printques(int m)
185 {
186   int head = dt3155_fbuffer[m]->ready_head;
187   int tail;
188   int num = dt3155_fbuffer[m]->nbuffers;
189   int frame_index;
190   int index;
191
192   tail = get_tail(m);
193
194   printk("\n R:");
195     for (index = tail; index != head; index++, index = index % (num)) {
196         frame_index = dt3155_fbuffer[m]->ready_que[index];
197         printk(" %d ", frame_index);
198     }
199
200   printk("\n E:");
201     for (index = 0; index < dt3155_fbuffer[m]->empty_len; index++) {
202         frame_index = dt3155_fbuffer[m]->empty_buffers[index];
203         printk(" %d ", frame_index);
204     }
205
206   frame_index = dt3155_fbuffer[m]->active_buf;
207   printk("\n A: %d", frame_index);
208
209   frame_index = dt3155_fbuffer[m]->locked_buf;
210   printk("\n L: %d\n", frame_index);
211
212 }
213
214 /*****************************************************
215  * adjust_4MB
216  *
217  *  If a buffer intersects the 4MB boundary, push
218  *  the start address up to the beginning of the
219  *  next 4MB chunk (assuming bufsize < 4MB).
220  *****************************************************/
221 u32 adjust_4MB(u32 buf_addr, u32 bufsize)
222 {
223     if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
224         return (buf_addr+bufsize) & UPPER_10_BITS;
225     else
226         return buf_addr;
227 }
228
229
230 /*****************************************************
231  * allocate_buffers
232  *
233  *  Try to allocate enough memory for all requested
234  *  buffers.  If there is not enough free space
235  *  try for less memory.
236  *****************************************************/
237 void allocate_buffers(u32 *buf_addr, u32* total_size_kbs,
238                        u32 bufsize)
239 {
240   /* Compute the minimum amount of memory guaranteed to hold all
241      MAXBUFFERS such that no buffer crosses the 4MB boundary.
242      Store this value in the variable "full_size" */
243
244   u32 allocator_max;
245   u32 bufs_per_chunk = (FOUR_MB / bufsize);
246   u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
247   u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
248
249   u32 full_size = bufsize      /* possibly unusable part of 1st chunk */
250     + filled_chunks * FOUR_MB   /* max # of completely filled 4mb chunks */
251     + leftover_bufs * bufsize;  /* these buffs will be in a partly filled
252                                    chunk at beginning or end */
253
254   u32 full_size_kbs = 1 + (full_size-1) / 1024;
255   u32 min_size_kbs = 2*ndevices*bufsize / 1024;
256   u32 size_kbs;
257
258   /* Now, try to allocate full_size.  If this fails, keep trying for
259      less & less memory until it succeeds. */
260 #ifndef STANDALONE_ALLOCATOR
261   /* initialize the allocator            */
262   allocator_init(&allocator_max);
263 #endif
264   size_kbs = full_size_kbs;
265   *buf_addr = 0;
266   printk("DT3155: We would like to get: %d KB\n", full_size_kbs);
267   printk("DT3155: ...but need at least: %d KB\n", min_size_kbs);
268   printk("DT3155: ...the allocator has: %d KB\n", allocator_max);
269   size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
270     if (size_kbs > min_size_kbs) {
271         if ((*buf_addr = allocator_allocate_dma(size_kbs, GFP_KERNEL)) != 0) {
272                 printk("DT3155:  Managed to allocate: %d KB\n", size_kbs);
273                 *total_size_kbs = size_kbs;
274                 return;
275         }
276     }
277   /* If we got here, the allocation failed */
278   printk("DT3155: Allocator failed!\n");
279   *buf_addr = 0;
280   *total_size_kbs = 0;
281   return;
282
283 }
284
285
286 /*****************************************************
287  * dt3155_setup_buffers
288  *
289  *  setup_buffers just puts the buffering system into
290  *  a consistent state before the start of interrupts
291  *
292  * JML : it looks like all the buffers need to be
293  * continuous. So I'm going to try and allocate one
294  * continuous buffer.
295  *
296  * GCS : Fix DMA problems when buffer spans
297  * 4MB boundary.  Also, add error checking.  This
298  * function will return -ENOMEM when not enough memory.
299  *****************************************************/
300 u32 dt3155_setup_buffers(u32 *allocatorAddr)
301
302 {
303   u32 index;
304   u32 rambuff_addr; /* start of allocation */
305   u32 rambuff_size; /* total size allocated to driver */
306   u32 rambuff_acm;  /* accumlator, keep track of how much
307                           is left after being split up*/
308   u32 rambuff_end;  /* end of rambuff */
309   u32 numbufs;      /* number of useful buffers allocated (per device) */
310   u32 bufsize      = DT3155_MAX_ROWS * DT3155_MAX_COLS;
311   int m;               /* minor # of device, looped for all devs */
312
313   /* zero the fbuffer status and address structure */
314     for (m = 0; m < ndevices; m++) {
315         dt3155_fbuffer[m] = &(dt3155_status[m].fbuffer);
316
317       /* Make sure the buffering variables are consistent */
318       {
319         u8 *ptr = (u8 *) dt3155_fbuffer[m];
320                 for (index = 0; index < sizeof(struct dt3155_fbuffer); index++)
321                         *(ptr++) = 0;
322       }
323     }
324
325   /* allocate a large contiguous chunk of RAM */
326   allocate_buffers(&rambuff_addr, &rambuff_size, bufsize);
327   printk("DT3155: mem info\n");
328   printk("  - rambuf_addr = 0x%x\n", rambuff_addr);
329   printk("  - length (kb) = %u\n", rambuff_size);
330     if (rambuff_addr == 0) {
331         printk(KERN_INFO
332             "DT3155: Error setup_buffers() allocator dma failed\n");
333         return -ENOMEM;
334     }
335   *allocatorAddr = rambuff_addr;
336   rambuff_end = rambuff_addr + 1024 * rambuff_size;
337
338   /* after allocation, we need to count how many useful buffers there
339      are so we can give an equal number to each device */
340   rambuff_acm = rambuff_addr;
341     for (index = 0; index < MAXBUFFERS; index++) {
342         rambuff_acm = adjust_4MB(rambuff_acm, bufsize);/*avoid spanning 4MB bdry*/
343         if (rambuff_acm + bufsize > rambuff_end)
344                 break;
345         rambuff_acm += bufsize;
346     }
347   /* Following line is OK, will waste buffers if index
348    * not evenly divisible by ndevices -NJC*/
349   numbufs = index / ndevices;
350   printk("  - numbufs = %u\n", numbufs);
351     if (numbufs < 2) {
352         printk(KERN_INFO
353         "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n");
354         return -ENOMEM;
355     }
356
357   /* now that we have board memory we spit it up */
358   /* between the boards and the buffers          */
359     rambuff_acm = rambuff_addr;
360     for (m = 0; m < ndevices; m++) {
361         rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
362
363         /* Save the start of this boards buffer space (for mmap).  */
364         dt3155_status[m].mem_addr = rambuff_acm;
365
366         for (index = 0; index < numbufs; index++) {
367                 rambuff_acm = adjust_4MB(rambuff_acm, bufsize);
368                 if (rambuff_acm + bufsize > rambuff_end) {
369                         /* Should never happen */
370                         printk("DT3155 PROGRAM ERROR (GCS)\n"
371                         "Error distributing allocated buffers\n");
372                         return -ENOMEM;
373                 }
374
375                 dt3155_fbuffer[m]->frame_info[index].addr = rambuff_acm;
376                 push_empty(index, m);
377                 /* printk("  - Buffer : %lx\n",
378                 * dt3155_fbuffer[m]->frame_info[index].addr);
379                 */
380                 dt3155_fbuffer[m]->nbuffers += 1;
381                 rambuff_acm += bufsize;
382         }
383
384         /* Make sure there is an active buffer there. */
385         dt3155_fbuffer[m]->active_buf    = pop_empty(m);
386         dt3155_fbuffer[m]->even_happened = 0;
387         dt3155_fbuffer[m]->even_stopped  = 0;
388
389         /* make sure there is no locked_buf JML 2/28/00 */
390         dt3155_fbuffer[m]->locked_buf = -1;
391
392         dt3155_status[m].mem_size =
393         rambuff_acm - dt3155_status[m].mem_addr;
394
395         /* setup the ready queue */
396         dt3155_fbuffer[m]->ready_head = 0;
397         dt3155_fbuffer[m]->ready_len = 0;
398         printk("Available buffers for device %d: %d\n",
399             m, dt3155_fbuffer[m]->nbuffers);
400     }
401
402     return 1;
403 }
404
405 /*****************************************************
406  * internal_release_locked_buffer
407  *
408  * The internal function for releasing a locked buffer.
409  * It assumes interrupts are turned off.
410  *
411  * m is minor number of device
412  *****************************************************/
413 static void internal_release_locked_buffer(int m)
414 {
415   /* Pointer into global structure for handling buffers */
416     if (dt3155_fbuffer[m]->locked_buf >= 0) {
417         push_empty(dt3155_fbuffer[m]->locked_buf, m);
418         dt3155_fbuffer[m]->locked_buf = -1;
419     }
420 }
421
422
423 /*****************************************************
424  * dt3155_release_locked_buffer()
425  * m is minor # of device
426  *
427  * The user function of the above.
428  *
429  *****************************************************/
430 void dt3155_release_locked_buffer(int m)
431 {
432         unsigned long int flags;
433         local_save_flags(flags);
434         local_irq_disable();
435         internal_release_locked_buffer(m);
436         local_irq_restore(flags);
437 }
438
439
440 /*****************************************************
441  * dt3155_flush()
442  * m is minor # of device
443  *
444  *****************************************************/
445 int dt3155_flush(int m)
446 {
447   int index;
448   unsigned long int flags;
449   local_save_flags(flags);
450   local_irq_disable();
451
452   internal_release_locked_buffer(m);
453   dt3155_fbuffer[m]->empty_len = 0;
454
455     for (index = 0; index < dt3155_fbuffer[m]->nbuffers; index++)
456         push_empty(index,  m);
457
458   /* Make sure there is an active buffer there. */
459   dt3155_fbuffer[m]->active_buf = pop_empty(m);
460
461   dt3155_fbuffer[m]->even_happened = 0;
462   dt3155_fbuffer[m]->even_stopped  = 0;
463
464   /* setup the ready queue  */
465   dt3155_fbuffer[m]->ready_head = 0;
466   dt3155_fbuffer[m]->ready_len = 0;
467
468   local_irq_restore(flags);
469
470   return 0;
471 }
472
473 /*****************************************************
474  * dt3155_get_ready_buffer()
475  * m is minor # of device
476  *
477  * get_ready_buffer will grab the next chunk of data
478  * if it is already there, otherwise it returns 0.
479  * If the user has a buffer locked it will unlock
480  * that buffer before returning the new one.
481  *****************************************************/
482 int dt3155_get_ready_buffer(int m)
483 {
484   int frame_index;
485   unsigned long int flags;
486   local_save_flags(flags);
487   local_irq_disable();
488
489 #ifdef DEBUG_QUES_A
490   printques(m);
491 #endif
492
493   internal_release_locked_buffer(m);
494
495     if (is_ready_buf_empty(m))
496         frame_index = -1;
497     else {
498         frame_index = pop_ready(m);
499         dt3155_fbuffer[m]->locked_buf = frame_index;
500     }
501
502 #ifdef DEBUG_QUES_B
503   printques(m);
504 #endif
505
506   local_irq_restore(flags);
507
508   return frame_index;
509 }