Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[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,
484d3be1 4 Jason Lapenta, Scott Smedley, Greg Sharp
aa337ef1
SS
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
484d3be1 25 (the actual isr is in dt3155_drv.c)
aa337ef1
SS
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
484d3be1
GI
33 module; Merged John Roll's mods to make work with
34 multiple boards.
aa337ef1 35 10-Jul-2002 GCS Complete rewrite of setup_buffers to disallow
484d3be1 36 buffers which span a 4MB boundary.
aa337ef1
SS
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).
484d3be1
GI
41 Also, allocator_init() now returns allocator_max
42 so cleaned up allocate_buffers() accordingly.
aa337ef1
SS
43 08-Aug-2005 SS port to 2.6 kernel.
44
45*/
46
47#include <asm/system.h>
5a0e3ad6 48#include <linux/gfp.h>
aa337ef1
SS
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 */
e802b4b7 63struct dt3155_fbuffer *dt3155_fbuffer[MAXBOARDS] = {NULL
aa337ef1
SS
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 ***************************/
e8afd402 80bool are_empty_buffers(int m)
aa337ef1 81{
484d3be1 82 return dt3155_fbuffer[m]->empty_len;
aa337ef1
SS
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 **************************/
e8afd402 95void push_empty(int index, int m)
aa337ef1 96{
484d3be1 97 dt3155_fbuffer[m]->empty_buffers[dt3155_fbuffer[m]->empty_len] = index;
aa337ef1
SS
98 dt3155_fbuffer[m]->empty_len++;
99}
100
101/**************************
484d3be1 102 * pop_empty(m)
aa337ef1
SS
103 * m is minor # of device
104 **************************/
e8afd402 105int pop_empty(int m)
aa337ef1
SS
106{
107 dt3155_fbuffer[m]->empty_len--;
484d3be1 108 return dt3155_fbuffer[m]->empty_buffers[dt3155_fbuffer[m]->empty_len];
aa337ef1
SS
109}
110
111/*************************
484d3be1 112 * is_ready_buf_empty(m)
aa337ef1
SS
113 * m is minor # of device
114 *************************/
e8afd402 115bool is_ready_buf_empty(int m)
aa337ef1 116{
484d3be1 117 return ((dt3155_fbuffer[m]->ready_len) == 0);
aa337ef1
SS
118}
119
120/*************************
484d3be1 121 * is_ready_buf_full(m)
aa337ef1
SS
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 *************************/
e8afd402 127bool is_ready_buf_full(int m)
aa337ef1 128{
484d3be1 129 return dt3155_fbuffer[m]->ready_len == dt3155_fbuffer[m]->nbuffers;
aa337ef1
SS
130}
131
132/*****************************************************
484d3be1 133 * push_ready(m, buffer)
aa337ef1
SS
134 * m is minor # of device
135 *
136 *****************************************************/
e8afd402 137void push_ready(int m, int index)
aa337ef1
SS
138{
139 int head = dt3155_fbuffer[m]->ready_head;
140
484d3be1
GI
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++;
aa337ef1
SS
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 *****************************************************/
e8afd402 154static int get_tail(int m)
aa337ef1 155{
484d3be1
GI
156 return (dt3155_fbuffer[m]->ready_head -
157 dt3155_fbuffer[m]->ready_len +
158 dt3155_fbuffer[m]->nbuffers)%
159 (dt3155_fbuffer[m]->nbuffers);
aa337ef1
SS
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 *****************************************************/
e8afd402 171int pop_ready(int m)
aa337ef1
SS
172{
173 int tail;
174 tail = get_tail(m);
484d3be1
GI
175 dt3155_fbuffer[m]->ready_len--;
176 return dt3155_fbuffer[m]->ready_que[tail];
aa337ef1
SS
177}
178
179
180/*****************************************************
181 * printques
182 * m is minor # of device
183 *****************************************************/
e8afd402 184void printques(int m)
aa337ef1 185{
484d3be1 186 int head = dt3155_fbuffer[m]->ready_head;
aa337ef1 187 int tail;
484d3be1 188 int num = dt3155_fbuffer[m]->nbuffers;
aa337ef1
SS
189 int frame_index;
190 int index;
191
192 tail = get_tail(m);
193
194 printk("\n R:");
484d3be1
GI
195 for (index = tail; index != head; index++, index = index % (num)) {
196 frame_index = dt3155_fbuffer[m]->ready_que[index];
197 printk(" %d ", frame_index);
aa337ef1
SS
198 }
199
200 printk("\n E:");
484d3be1
GI
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);
aa337ef1
SS
204 }
205
484d3be1 206 frame_index = dt3155_fbuffer[m]->active_buf;
aa337ef1
SS
207 printk("\n A: %d", frame_index);
208
484d3be1
GI
209 frame_index = dt3155_fbuffer[m]->locked_buf;
210 printk("\n L: %d\n", frame_index);
aa337ef1
SS
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 *****************************************************/
484d3be1
GI
221u32 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;
aa337ef1
SS
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 *****************************************************/
484d3be1 237void allocate_buffers(u32 *buf_addr, u32* total_size_kbs,
3a8954e8 238 u32 bufsize)
aa337ef1
SS
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
3a8954e8
HS
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;
aa337ef1 248
3a8954e8 249 u32 full_size = bufsize /* possibly unusable part of 1st chunk */
aa337ef1
SS
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
3a8954e8
HS
254 u32 full_size_kbs = 1 + (full_size-1) / 1024;
255 u32 min_size_kbs = 2*ndevices*bufsize / 1024;
256 u32 size_kbs;
aa337ef1
SS
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;
3a8954e8
HS
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);
aa337ef1 269 size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
484d3be1
GI
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 }
aa337ef1 276 }
aa337ef1 277 /* If we got here, the allocation failed */
484d3be1 278 printk("DT3155: Allocator failed!\n");
aa337ef1
SS
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 *****************************************************/
3a8954e8 300u32 dt3155_setup_buffers(u32 *allocatorAddr)
aa337ef1
SS
301
302{
3a8954e8
HS
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
aa337ef1 307 is left after being split up*/
3a8954e8
HS
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;
aa337ef1
SS
311 int m; /* minor # of device, looped for all devs */
312
313 /* zero the fbuffer status and address structure */
484d3be1
GI
314 for (m = 0; m < ndevices; m++) {
315 dt3155_fbuffer[m] = &(dt3155_status[m].fbuffer);
aa337ef1
SS
316
317 /* Make sure the buffering variables are consistent */
318 {
484d3be1 319 u8 *ptr = (u8 *) dt3155_fbuffer[m];
e802b4b7 320 for (index = 0; index < sizeof(struct dt3155_fbuffer); index++)
484d3be1 321 *(ptr++) = 0;
aa337ef1
SS
322 }
323 }
324
325 /* allocate a large contiguous chunk of RAM */
484d3be1 326 allocate_buffers(&rambuff_addr, &rambuff_size, bufsize);
3a8954e8 327 printk("DT3155: mem info\n");
484d3be1
GI
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;
aa337ef1
SS
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;
484d3be1
GI
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 }
aa337ef1
SS
347 /* Following line is OK, will waste buffers if index
348 * not evenly divisible by ndevices -NJC*/
349 numbufs = index / ndevices;
3a8954e8 350 printk(" - numbufs = %u\n", numbufs);
484d3be1
GI
351 if (numbufs < 2) {
352 printk(KERN_INFO
353 "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n");
354 return -ENOMEM;
355 }
aa337ef1
SS
356
357 /* now that we have board memory we spit it up */
358 /* between the boards and the buffers */
484d3be1
GI
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;
aa337ef1
SS
382 }
383
484d3be1
GI
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;
aa337ef1 388
484d3be1
GI
389 /* make sure there is no locked_buf JML 2/28/00 */
390 dt3155_fbuffer[m]->locked_buf = -1;
aa337ef1 391
484d3be1
GI
392 dt3155_status[m].mem_size =
393 rambuff_acm - dt3155_status[m].mem_addr;
aa337ef1 394
484d3be1
GI
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);
aa337ef1
SS
400 }
401
484d3be1 402 return 1;
aa337ef1
SS
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 *****************************************************/
e8afd402 413static void internal_release_locked_buffer(int m)
aa337ef1
SS
414{
415 /* Pointer into global structure for handling buffers */
484d3be1
GI
416 if (dt3155_fbuffer[m]->locked_buf >= 0) {
417 push_empty(dt3155_fbuffer[m]->locked_buf, m);
418 dt3155_fbuffer[m]->locked_buf = -1;
aa337ef1
SS
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 *****************************************************/
e8afd402 430void dt3155_release_locked_buffer(int m)
aa337ef1 431{
aa337ef1
SS
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);
aa337ef1
SS
437}
438
439
440/*****************************************************
441 * dt3155_flush()
442 * m is minor # of device
443 *
444 *****************************************************/
e8afd402 445int dt3155_flush(int m)
aa337ef1
SS
446{
447 int index;
2141ec62
SH
448 unsigned long int flags;
449 local_save_flags(flags);
450 local_irq_disable();
aa337ef1 451
484d3be1
GI
452 internal_release_locked_buffer(m);
453 dt3155_fbuffer[m]->empty_len = 0;
aa337ef1 454
484d3be1
GI
455 for (index = 0; index < dt3155_fbuffer[m]->nbuffers; index++)
456 push_empty(index, m);
aa337ef1
SS
457
458 /* Make sure there is an active buffer there. */
484d3be1 459 dt3155_fbuffer[m]->active_buf = pop_empty(m);
aa337ef1 460
484d3be1
GI
461 dt3155_fbuffer[m]->even_happened = 0;
462 dt3155_fbuffer[m]->even_stopped = 0;
aa337ef1
SS
463
464 /* setup the ready queue */
484d3be1
GI
465 dt3155_fbuffer[m]->ready_head = 0;
466 dt3155_fbuffer[m]->ready_len = 0;
aa337ef1 467
aa337ef1 468 local_irq_restore(flags);
aa337ef1
SS
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 *****************************************************/
e8afd402 482int dt3155_get_ready_buffer(int m)
aa337ef1
SS
483{
484 int frame_index;
2141ec62
SH
485 unsigned long int flags;
486 local_save_flags(flags);
487 local_irq_disable();
aa337ef1
SS
488
489#ifdef DEBUG_QUES_A
484d3be1 490 printques(m);
aa337ef1
SS
491#endif
492
484d3be1 493 internal_release_locked_buffer(m);
aa337ef1 494
484d3be1
GI
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;
aa337ef1
SS
500 }
501
502#ifdef DEBUG_QUES_B
484d3be1 503 printques(m);
aa337ef1
SS
504#endif
505
aa337ef1 506 local_irq_restore(flags);
aa337ef1
SS
507
508 return frame_index;
509}