Staging: rtl8192su, rtl8192u: use min_t() in store_debug_level()
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / dt3155 / dt3155_isr.c
CommitLineData
aa337ef1
SS
1/*
2
3Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
4 Jason Lapenta, Scott Smedley, Greg Sharp
5
6This file is part of the DT3155 Device Driver.
7
8The DT3155 Device Driver is free software; you can redistribute it
9and/or modify it under the terms of the GNU General Public License as
10published by the Free Software Foundation; either version 2 of the
11License, or (at your option) any later version.
12
13The DT3155 Device Driver is distributed in the hope that it will be
14useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with the DT3155 Device Driver; if not, write to the Free
20Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21MA 02111-1307 USA
22
23 File: dt3155_isr.c
24Purpose: 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/slab.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 */
63struct 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 ***************************/
80inline 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 **************************/
95inline 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 **************************/
105inline 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 *************************/
115inline 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 *************************/
127inline 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 *****************************************************/
137inline 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 *****************************************************/
154static 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 *****************************************************/
171inline 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 *****************************************************/
184inline 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 *****************************************************/
223u_long adjust_4MB (u_long buf_addr, u_long 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 *****************************************************/
238void allocate_buffers (u_long *buf_addr, u_long* total_size_kbs,
239 u_long 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 u_long allocator_max;
246 u_long bufs_per_chunk = (FOUR_MB / bufsize);
247 u_long filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
248 u_long leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
249
250 u_long 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 u_long full_size_kbs = 1 + (full_size-1) / 1024;
256 u_long min_size_kbs = 2*ndevices*bufsize / 1024;
257 u_long 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", (u_int)(full_size_kbs));
268 printk ("DT3155: ...but need at least: %d KB\n", (u_int)(min_size_kbs));
269 printk ("DT3155: ...the allocator has: %d KB\n", (u_int)(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", (u_int)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 *****************************************************/
301u_long dt3155_setup_buffers(u_long *allocatorAddr)
302
303{
304 u_long index;
305 u_long rambuff_addr; /* start of allocation */
306 u_long rambuff_size; /* total size allocated to driver */
307 u_long rambuff_acm; /* accumlator, keep track of how much
308 is left after being split up*/
309 u_long rambuff_end; /* end of rambuff */
310 u_long numbufs; /* number of useful buffers allocated (per device) */
311 u_long 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 u_char *ptr = (u_char *) 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", (u_int)rambuff_addr );
331 printk( " - length (kb) = %u \n", (u_int)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", (u_int) 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 *****************************************************/
418static 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 *****************************************************/
436inline void dt3155_release_locked_buffer( int m )
437{
438#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
439 unsigned long int flags;
440 local_save_flags(flags);
441 local_irq_disable();
442 internal_release_locked_buffer(m);
443 local_irq_restore(flags);
444#else
445 int flags;
446
447 save_flags( flags );
448 cli();
449 internal_release_locked_buffer( m );
450 restore_flags( flags );
451#endif
452}
453
454
455/*****************************************************
456 * dt3155_flush()
457 * m is minor # of device
458 *
459 *****************************************************/
460inline int dt3155_flush( int m )
461{
462 int index;
463#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
464 unsigned long int flags;
465 local_save_flags(flags);
466 local_irq_disable();
467#else
468 int flags;
469 save_flags( flags );
470 cli();
471#endif
472
473 internal_release_locked_buffer( m );
474 dt3155_fbuffer[ m ]->empty_len = 0;
475
476 for ( index = 0; index < dt3155_fbuffer[ m ]->nbuffers; index++ )
477 push_empty( index, m );
478
479 /* Make sure there is an active buffer there. */
480 dt3155_fbuffer[ m ]->active_buf = pop_empty( m );
481
482 dt3155_fbuffer[ m ]->even_happened = 0;
483 dt3155_fbuffer[ m ]->even_stopped = 0;
484
485 /* setup the ready queue */
486 dt3155_fbuffer[ m ]->ready_head = 0;
487 dt3155_fbuffer[ m ]->ready_len = 0;
488
489#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
490 local_irq_restore(flags);
491#else
492 restore_flags( flags );
493#endif
494
495 return 0;
496}
497
498/*****************************************************
499 * dt3155_get_ready_buffer()
500 * m is minor # of device
501 *
502 * get_ready_buffer will grab the next chunk of data
503 * if it is already there, otherwise it returns 0.
504 * If the user has a buffer locked it will unlock
505 * that buffer before returning the new one.
506 *****************************************************/
507inline int dt3155_get_ready_buffer( int m )
508{
509 int frame_index;
510#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
511 unsigned long int flags;
512 local_save_flags(flags);
513 local_irq_disable();
514#else
515 int flags;
516 save_flags( flags );
517 cli();
518#endif
519
520#ifdef DEBUG_QUES_A
521 printques( m );
522#endif
523
524 internal_release_locked_buffer( m );
525
526 if (is_ready_buf_empty( m ))
527 frame_index = -1;
528 else
529 {
530 frame_index = pop_ready( m );
531 dt3155_fbuffer[ m ]->locked_buf = frame_index;
532 }
533
534#ifdef DEBUG_QUES_B
535 printques( m );
536#endif
537
538#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
539 local_irq_restore(flags);
540#else
541 restore_flags( flags );
542#endif
543
544 return frame_index;
545}