Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt...
[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_s *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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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 inline 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     {
197       frame_index = dt3155_fbuffer[ m ]->ready_que[ index ];
198       printk(" %d ", frame_index );
199     }
200
201   printk("\n E:");
202   for ( index = 0; index < dt3155_fbuffer[ m ]->empty_len; index++ )
203     {
204       frame_index = dt3155_fbuffer[ m ]->empty_buffers[ index ];
205       printk(" %d ", frame_index );
206     }
207
208   frame_index = dt3155_fbuffer[ m ]->active_buf;
209   printk("\n A: %d", frame_index);
210
211   frame_index = dt3155_fbuffer[ m ]->locked_buf;
212   printk("\n L: %d \n", frame_index );
213
214 }
215
216 /*****************************************************
217  * adjust_4MB
218  *
219  *  If a buffer intersects the 4MB boundary, push
220  *  the start address up to the beginning of the
221  *  next 4MB chunk (assuming bufsize < 4MB).
222  *****************************************************/
223 u32 adjust_4MB (u32 buf_addr, u32 bufsize) {
224   if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
225     return (buf_addr+bufsize) & UPPER_10_BITS;
226   else
227     return buf_addr;
228 }
229
230
231 /*****************************************************
232  * allocate_buffers
233  *
234  *  Try to allocate enough memory for all requested
235  *  buffers.  If there is not enough free space
236  *  try for less memory.
237  *****************************************************/
238 void allocate_buffers (u32 *buf_addr, u32* total_size_kbs,
239                        u32 bufsize)
240 {
241   /* Compute the minimum amount of memory guaranteed to hold all
242      MAXBUFFERS such that no buffer crosses the 4MB boundary.
243      Store this value in the variable "full_size" */
244
245   u32 allocator_max;
246   u32 bufs_per_chunk = (FOUR_MB / bufsize);
247   u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
248   u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
249
250   u32 full_size = bufsize      /* possibly unusable part of 1st chunk */
251     + filled_chunks * FOUR_MB   /* max # of completely filled 4mb chunks */
252     + leftover_bufs * bufsize;  /* these buffs will be in a partly filled
253                                    chunk at beginning or end */
254
255   u32 full_size_kbs = 1 + (full_size-1) / 1024;
256   u32 min_size_kbs = 2*ndevices*bufsize / 1024;
257   u32 size_kbs;
258
259   /* Now, try to allocate full_size.  If this fails, keep trying for
260      less & less memory until it succeeds. */
261 #ifndef STANDALONE_ALLOCATOR
262   /* initialize the allocator            */
263   allocator_init(&allocator_max);
264 #endif
265   size_kbs = full_size_kbs;
266   *buf_addr = 0;
267   printk("DT3155: We would like to get: %d KB\n", full_size_kbs);
268   printk("DT3155: ...but need at least: %d KB\n", min_size_kbs);
269   printk("DT3155: ...the allocator has: %d KB\n", allocator_max);
270   size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
271   if (size_kbs > min_size_kbs) {
272     if ((*buf_addr = allocator_allocate_dma (size_kbs, GFP_KERNEL)) != 0) {
273       printk("DT3155:  Managed to allocate: %d KB\n", size_kbs);
274       *total_size_kbs = size_kbs;
275       return;
276     }
277   }
278   /* If we got here, the allocation failed */
279   printk ("DT3155: Allocator failed!\n");
280   *buf_addr = 0;
281   *total_size_kbs = 0;
282   return;
283
284 }
285
286
287 /*****************************************************
288  * dt3155_setup_buffers
289  *
290  *  setup_buffers just puts the buffering system into
291  *  a consistent state before the start of interrupts
292  *
293  * JML : it looks like all the buffers need to be
294  * continuous. So I'm going to try and allocate one
295  * continuous buffer.
296  *
297  * GCS : Fix DMA problems when buffer spans
298  * 4MB boundary.  Also, add error checking.  This
299  * function will return -ENOMEM when not enough memory.
300  *****************************************************/
301 u32 dt3155_setup_buffers(u32 *allocatorAddr)
302
303 {
304   u32 index;
305   u32 rambuff_addr; /* start of allocation */
306   u32 rambuff_size; /* total size allocated to driver */
307   u32 rambuff_acm;  /* accumlator, keep track of how much
308                           is left after being split up*/
309   u32 rambuff_end;  /* end of rambuff */
310   u32 numbufs;      /* number of useful buffers allocated (per device) */
311   u32 bufsize      = DT3155_MAX_ROWS * DT3155_MAX_COLS;
312   int m;               /* minor # of device, looped for all devs */
313
314   /* zero the fbuffer status and address structure */
315   for ( m = 0; m < ndevices; m++)
316     {
317       dt3155_fbuffer[ m ] = &(dt3155_status[ m ].fbuffer);
318
319       /* Make sure the buffering variables are consistent */
320       {
321         u8 *ptr = (u8 *) dt3155_fbuffer[ m ];
322         for( index = 0; index < sizeof(struct dt3155_fbuffer_s); index++)
323           *(ptr++)=0;
324       }
325     }
326
327   /* allocate a large contiguous chunk of RAM */
328   allocate_buffers (&rambuff_addr, &rambuff_size, bufsize);
329   printk("DT3155: mem info\n");
330   printk("  - rambuf_addr = 0x%x \n", rambuff_addr);
331   printk("  - length (kb) = %u \n", rambuff_size);
332   if( rambuff_addr == 0 )
333     {
334       printk( KERN_INFO
335               "DT3155: Error setup_buffers() allocator dma failed \n" );
336       return -ENOMEM;
337     }
338   *allocatorAddr = rambuff_addr;
339   rambuff_end = rambuff_addr + 1024 * rambuff_size;
340
341   /* after allocation, we need to count how many useful buffers there
342      are so we can give an equal number to each device */
343   rambuff_acm = rambuff_addr;
344   for ( index = 0; index < MAXBUFFERS; index++) {
345     rambuff_acm = adjust_4MB (rambuff_acm, bufsize);/*avoid spanning 4MB bdry*/
346     if (rambuff_acm + bufsize > rambuff_end)
347       break;
348     rambuff_acm += bufsize;
349   }
350   /* Following line is OK, will waste buffers if index
351    * not evenly divisible by ndevices -NJC*/
352   numbufs = index / ndevices;
353   printk("  - numbufs = %u\n", numbufs);
354   if (numbufs < 2) {
355     printk( KERN_INFO
356             "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n" );
357     return -ENOMEM;
358   }
359
360   /* now that we have board memory we spit it up */
361   /* between the boards and the buffers          */
362   rambuff_acm = rambuff_addr;
363   for ( m = 0; m < ndevices; m ++)
364     {
365       rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
366
367       /* Save the start of this boards buffer space (for mmap).  */
368       dt3155_status[ m ].mem_addr = rambuff_acm;
369
370       for (index = 0; index < numbufs; index++)
371         {
372           rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
373           if (rambuff_acm + bufsize > rambuff_end) {
374             /* Should never happen */
375             printk ("DT3155 PROGRAM ERROR (GCS)\n"
376                     "Error distributing allocated buffers\n");
377             return -ENOMEM;
378           }
379
380           dt3155_fbuffer[ m ]->frame_info[ index ].addr = rambuff_acm;
381           push_empty( index, m );
382           /* printk("  - Buffer : %lx\n",
383            * dt3155_fbuffer[ m ]->frame_info[ index ].addr );
384            */
385           dt3155_fbuffer[ m ]->nbuffers += 1;
386           rambuff_acm += bufsize;
387         }
388
389       /* Make sure there is an active buffer there. */
390       dt3155_fbuffer[ m ]->active_buf    = pop_empty( m );
391       dt3155_fbuffer[ m ]->even_happened = 0;
392       dt3155_fbuffer[ m ]->even_stopped  = 0;
393
394       /* make sure there is no locked_buf JML 2/28/00 */
395       dt3155_fbuffer[ m ]->locked_buf = -1;
396
397       dt3155_status[ m ].mem_size =
398         rambuff_acm - dt3155_status[ m ].mem_addr;
399
400       /* setup the ready queue */
401       dt3155_fbuffer[ m ]->ready_head = 0;
402       dt3155_fbuffer[ m ]->ready_len = 0;
403       printk("Available buffers for device %d: %d\n",
404              m, dt3155_fbuffer[ m ]->nbuffers);
405     }
406
407   return 1;
408 }
409
410 /*****************************************************
411  * internal_release_locked_buffer
412  *
413  * The internal function for releasing a locked buffer.
414  * It assumes interrupts are turned off.
415  *
416  * m is minor number of device
417  *****************************************************/
418 static inline void internal_release_locked_buffer( int m )
419 {
420   /* Pointer into global structure for handling buffers */
421   if ( dt3155_fbuffer[ m ]->locked_buf >= 0 )
422     {
423       push_empty( dt3155_fbuffer[ m ]->locked_buf, m );
424       dt3155_fbuffer[ m ]->locked_buf = -1;
425     }
426 }
427
428
429 /*****************************************************
430  * dt3155_release_locked_buffer()
431  * m is minor # of device
432  *
433  * The user function of the above.
434  *
435  *****************************************************/
436 inline void dt3155_release_locked_buffer( int m )
437 {
438         unsigned long int flags;
439         local_save_flags(flags);
440         local_irq_disable();
441         internal_release_locked_buffer(m);
442         local_irq_restore(flags);
443 }
444
445
446 /*****************************************************
447  * dt3155_flush()
448  * m is minor # of device
449  *
450  *****************************************************/
451 inline int dt3155_flush( int m )
452 {
453   int index;
454   unsigned long int flags;
455   local_save_flags(flags);
456   local_irq_disable();
457
458   internal_release_locked_buffer( m );
459   dt3155_fbuffer[ m ]->empty_len = 0;
460
461   for ( index = 0; index < dt3155_fbuffer[ m ]->nbuffers; index++ )
462     push_empty( index,  m );
463
464   /* Make sure there is an active buffer there. */
465   dt3155_fbuffer[ m ]->active_buf = pop_empty( m );
466
467   dt3155_fbuffer[ m ]->even_happened = 0;
468   dt3155_fbuffer[ m ]->even_stopped  = 0;
469
470   /* setup the ready queue  */
471   dt3155_fbuffer[ m ]->ready_head = 0;
472   dt3155_fbuffer[ m ]->ready_len = 0;
473
474   local_irq_restore(flags);
475
476   return 0;
477 }
478
479 /*****************************************************
480  * dt3155_get_ready_buffer()
481  * m is minor # of device
482  *
483  * get_ready_buffer will grab the next chunk of data
484  * if it is already there, otherwise it returns 0.
485  * If the user has a buffer locked it will unlock
486  * that buffer before returning the new one.
487  *****************************************************/
488 inline int dt3155_get_ready_buffer( int m )
489 {
490   int frame_index;
491   unsigned long int flags;
492   local_save_flags(flags);
493   local_irq_disable();
494
495 #ifdef DEBUG_QUES_A
496   printques( m );
497 #endif
498
499   internal_release_locked_buffer( m );
500
501   if (is_ready_buf_empty( m ))
502     frame_index = -1;
503   else
504     {
505       frame_index = pop_ready( m );
506       dt3155_fbuffer[ m ]->locked_buf = frame_index;
507     }
508
509 #ifdef DEBUG_QUES_B
510   printques( m );
511 #endif
512
513   local_irq_restore(flags);
514
515   return frame_index;
516 }