percpu: Replace smp_read_barrier_depends() with lockless_dereference()
[sfrench/cifs-2.6.git] / drivers / staging / media / omap24xx / omap24xxcam-dma.c
1 /*
2  * drivers/media/platform/omap24xxcam-dma.c
3  *
4  * Copyright (C) 2004 MontaVista Software, Inc.
5  * Copyright (C) 2004 Texas Instruments.
6  * Copyright (C) 2007 Nokia Corporation.
7  *
8  * Contact: Sakari Ailus <sakari.ailus@nokia.com>
9  *
10  * Based on code from Andy Lowe <source@mvista.com> and
11  *                    David Cohen <david.cohen@indt.org.br>.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * version 2 as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA
26  */
27
28 #include <linux/kernel.h>
29 #include <linux/io.h>
30 #include <linux/scatterlist.h>
31
32 #include "omap24xxcam.h"
33
34 /*
35  *
36  * DMA hardware.
37  *
38  */
39
40 /* Ack all interrupt on CSR and IRQSTATUS_L0 */
41 static void omap24xxcam_dmahw_ack_all(void __iomem *base)
42 {
43         u32 csr;
44         int i;
45
46         for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) {
47                 csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i));
48                 /* ack interrupt in CSR */
49                 omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr);
50         }
51         omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf);
52 }
53
54 /* Ack dmach on CSR and IRQSTATUS_L0 */
55 static u32 omap24xxcam_dmahw_ack_ch(void __iomem *base, int dmach)
56 {
57         u32 csr;
58
59         csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach));
60         /* ack interrupt in CSR */
61         omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr);
62         /* ack interrupt in IRQSTATUS */
63         omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach));
64
65         return csr;
66 }
67
68 static int omap24xxcam_dmahw_running(void __iomem *base, int dmach)
69 {
70         return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE;
71 }
72
73 static void omap24xxcam_dmahw_transfer_setup(void __iomem *base, int dmach,
74                                              dma_addr_t start, u32 len)
75 {
76         omap24xxcam_reg_out(base, CAMDMA_CCR(dmach),
77                             CAMDMA_CCR_SEL_SRC_DST_SYNC
78                             | CAMDMA_CCR_BS
79                             | CAMDMA_CCR_DST_AMODE_POST_INC
80                             | CAMDMA_CCR_SRC_AMODE_POST_INC
81                             | CAMDMA_CCR_FS
82                             | CAMDMA_CCR_WR_ACTIVE
83                             | CAMDMA_CCR_RD_ACTIVE
84                             | CAMDMA_CCR_SYNCHRO_CAMERA);
85         omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(dmach), 0);
86         omap24xxcam_reg_out(base, CAMDMA_CEN(dmach), len);
87         omap24xxcam_reg_out(base, CAMDMA_CFN(dmach), 1);
88         omap24xxcam_reg_out(base, CAMDMA_CSDP(dmach),
89                             CAMDMA_CSDP_WRITE_MODE_POSTED
90                             | CAMDMA_CSDP_DST_BURST_EN_32
91                             | CAMDMA_CSDP_DST_PACKED
92                             | CAMDMA_CSDP_SRC_BURST_EN_32
93                             | CAMDMA_CSDP_SRC_PACKED
94                             | CAMDMA_CSDP_DATA_TYPE_8BITS);
95         omap24xxcam_reg_out(base, CAMDMA_CSSA(dmach), 0);
96         omap24xxcam_reg_out(base, CAMDMA_CDSA(dmach), start);
97         omap24xxcam_reg_out(base, CAMDMA_CSEI(dmach), 0);
98         omap24xxcam_reg_out(base, CAMDMA_CSFI(dmach), DMA_THRESHOLD);
99         omap24xxcam_reg_out(base, CAMDMA_CDEI(dmach), 0);
100         omap24xxcam_reg_out(base, CAMDMA_CDFI(dmach), 0);
101         omap24xxcam_reg_out(base, CAMDMA_CSR(dmach),
102                             CAMDMA_CSR_MISALIGNED_ERR
103                             | CAMDMA_CSR_SECURE_ERR
104                             | CAMDMA_CSR_TRANS_ERR
105                             | CAMDMA_CSR_BLOCK
106                             | CAMDMA_CSR_DROP);
107         omap24xxcam_reg_out(base, CAMDMA_CICR(dmach),
108                             CAMDMA_CICR_MISALIGNED_ERR_IE
109                             | CAMDMA_CICR_SECURE_ERR_IE
110                             | CAMDMA_CICR_TRANS_ERR_IE
111                             | CAMDMA_CICR_BLOCK_IE
112                             | CAMDMA_CICR_DROP_IE);
113 }
114
115 static void omap24xxcam_dmahw_transfer_start(void __iomem *base, int dmach)
116 {
117         omap24xxcam_reg_out(base, CAMDMA_CCR(dmach),
118                             CAMDMA_CCR_SEL_SRC_DST_SYNC
119                             | CAMDMA_CCR_BS
120                             | CAMDMA_CCR_DST_AMODE_POST_INC
121                             | CAMDMA_CCR_SRC_AMODE_POST_INC
122                             | CAMDMA_CCR_ENABLE
123                             | CAMDMA_CCR_FS
124                             | CAMDMA_CCR_SYNCHRO_CAMERA);
125 }
126
127 static void omap24xxcam_dmahw_transfer_chain(void __iomem *base, int dmach,
128                                              int free_dmach)
129 {
130         int prev_dmach, ch;
131
132         if (dmach == 0)
133                 prev_dmach = NUM_CAMDMA_CHANNELS - 1;
134         else
135                 prev_dmach = dmach - 1;
136         omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach),
137                             CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach);
138         /* Did we chain the DMA transfer before the previous one
139          * finished?
140          */
141         ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS;
142         while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch))
143                  & CAMDMA_CCR_ENABLE)) {
144                 if (ch == dmach) {
145                         /* The previous transfer has ended and this one
146                          * hasn't started, so we must not have chained
147                          * to the previous one in time.  We'll have to
148                          * start it now.
149                          */
150                         omap24xxcam_dmahw_transfer_start(base, dmach);
151                         break;
152                 }
153                 ch = (ch + 1) % NUM_CAMDMA_CHANNELS;
154         }
155 }
156
157 /* Abort all chained DMA transfers. After all transfers have been
158  * aborted and the DMA controller is idle, the completion routines for
159  * any aborted transfers will be called in sequence. The DMA
160  * controller may not be idle after this routine completes, because
161  * the completion routines might start new transfers.
162  */
163 static void omap24xxcam_dmahw_abort_ch(void __iomem *base, int dmach)
164 {
165         /* mask all interrupts from this channel */
166         omap24xxcam_reg_out(base, CAMDMA_CICR(dmach), 0);
167         /* unlink this channel */
168         omap24xxcam_reg_merge(base, CAMDMA_CLNK_CTRL(dmach), 0,
169                               CAMDMA_CLNK_CTRL_ENABLE_LNK);
170         /* disable this channel */
171         omap24xxcam_reg_merge(base, CAMDMA_CCR(dmach), 0, CAMDMA_CCR_ENABLE);
172 }
173
174 static void omap24xxcam_dmahw_init(void __iomem *base)
175 {
176         omap24xxcam_reg_out(base, CAMDMA_OCP_SYSCONFIG,
177                             CAMDMA_OCP_SYSCONFIG_MIDLEMODE_FSTANDBY
178                             | CAMDMA_OCP_SYSCONFIG_SIDLEMODE_FIDLE
179                             | CAMDMA_OCP_SYSCONFIG_AUTOIDLE);
180
181         omap24xxcam_reg_merge(base, CAMDMA_GCR, 0x10,
182                               CAMDMA_GCR_MAX_CHANNEL_FIFO_DEPTH);
183
184         omap24xxcam_reg_out(base, CAMDMA_IRQENABLE_L0, 0xf);
185 }
186
187 /*
188  *
189  * Individual DMA channel handling.
190  *
191  */
192
193 /* Start a DMA transfer from the camera to memory.
194  * Returns zero if the transfer was successfully started, or non-zero if all
195  * DMA channels are already in use or starting is currently inhibited.
196  */
197 static int omap24xxcam_dma_start(struct omap24xxcam_dma *dma, dma_addr_t start,
198                                  u32 len, dma_callback_t callback, void *arg)
199 {
200         unsigned long flags;
201         int dmach;
202
203         spin_lock_irqsave(&dma->lock, flags);
204
205         if (!dma->free_dmach || atomic_read(&dma->dma_stop)) {
206                 spin_unlock_irqrestore(&dma->lock, flags);
207                 return -EBUSY;
208         }
209
210         dmach = dma->next_dmach;
211
212         dma->ch_state[dmach].callback = callback;
213         dma->ch_state[dmach].arg = arg;
214
215         omap24xxcam_dmahw_transfer_setup(dma->base, dmach, start, len);
216
217         /* We're ready to start the DMA transfer. */
218
219         if (dma->free_dmach < NUM_CAMDMA_CHANNELS) {
220                 /* A transfer is already in progress, so try to chain to it. */
221                 omap24xxcam_dmahw_transfer_chain(dma->base, dmach,
222                                                  dma->free_dmach);
223         } else {
224                 /* No transfer is in progress, so we'll just start this one
225                  * now.
226                  */
227                 omap24xxcam_dmahw_transfer_start(dma->base, dmach);
228         }
229
230         dma->next_dmach = (dma->next_dmach + 1) % NUM_CAMDMA_CHANNELS;
231         dma->free_dmach--;
232
233         spin_unlock_irqrestore(&dma->lock, flags);
234
235         return 0;
236 }
237
238 /* Abort all chained DMA transfers. After all transfers have been
239  * aborted and the DMA controller is idle, the completion routines for
240  * any aborted transfers will be called in sequence. The DMA
241  * controller may not be idle after this routine completes, because
242  * the completion routines might start new transfers.
243  */
244 static void omap24xxcam_dma_abort(struct omap24xxcam_dma *dma, u32 csr)
245 {
246         unsigned long flags;
247         int dmach, i, free_dmach;
248         dma_callback_t callback;
249         void *arg;
250
251         spin_lock_irqsave(&dma->lock, flags);
252
253         /* stop any DMA transfers in progress */
254         dmach = (dma->next_dmach + dma->free_dmach) % NUM_CAMDMA_CHANNELS;
255         for (i = 0; i < NUM_CAMDMA_CHANNELS; i++) {
256                 omap24xxcam_dmahw_abort_ch(dma->base, dmach);
257                 dmach = (dmach + 1) % NUM_CAMDMA_CHANNELS;
258         }
259
260         /* We have to be careful here because the callback routine
261          * might start a new DMA transfer, and we only want to abort
262          * transfers that were started before this routine was called.
263          */
264         free_dmach = dma->free_dmach;
265         while ((dma->free_dmach < NUM_CAMDMA_CHANNELS) &&
266                (free_dmach < NUM_CAMDMA_CHANNELS)) {
267                 dmach = (dma->next_dmach + dma->free_dmach)
268                         % NUM_CAMDMA_CHANNELS;
269                 callback = dma->ch_state[dmach].callback;
270                 arg = dma->ch_state[dmach].arg;
271                 dma->free_dmach++;
272                 free_dmach++;
273                 if (callback) {
274                         /* leave interrupts disabled during callback */
275                         spin_unlock(&dma->lock);
276                         (*callback) (dma, csr, arg);
277                         spin_lock(&dma->lock);
278                 }
279         }
280
281         spin_unlock_irqrestore(&dma->lock, flags);
282 }
283
284 /* Abort all chained DMA transfers. After all transfers have been
285  * aborted and the DMA controller is idle, the completion routines for
286  * any aborted transfers will be called in sequence. If the completion
287  * routines attempt to start a new DMA transfer it will fail, so the
288  * DMA controller will be idle after this routine completes.
289  */
290 static void omap24xxcam_dma_stop(struct omap24xxcam_dma *dma, u32 csr)
291 {
292         atomic_inc(&dma->dma_stop);
293         omap24xxcam_dma_abort(dma, csr);
294         atomic_dec(&dma->dma_stop);
295 }
296
297 /* Camera DMA interrupt service routine. */
298 void omap24xxcam_dma_isr(struct omap24xxcam_dma *dma)
299 {
300         int dmach;
301         dma_callback_t callback;
302         void *arg;
303         u32 csr;
304         const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
305                 | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
306                 | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;
307
308         spin_lock(&dma->lock);
309
310         if (dma->free_dmach == NUM_CAMDMA_CHANNELS) {
311                 /* A camera DMA interrupt occurred while all channels
312                  * are idle, so we'll acknowledge the interrupt in the
313                  * IRQSTATUS register and exit.
314                  */
315                 omap24xxcam_dmahw_ack_all(dma->base);
316                 spin_unlock(&dma->lock);
317                 return;
318         }
319
320         while (dma->free_dmach < NUM_CAMDMA_CHANNELS) {
321                 dmach = (dma->next_dmach + dma->free_dmach)
322                         % NUM_CAMDMA_CHANNELS;
323                 if (omap24xxcam_dmahw_running(dma->base, dmach)) {
324                         /* This buffer hasn't finished yet, so we're done. */
325                         break;
326                 }
327                 csr = omap24xxcam_dmahw_ack_ch(dma->base, dmach);
328                 if (csr & csr_error) {
329                         /* A DMA error occurred, so stop all DMA
330                          * transfers in progress.
331                          */
332                         spin_unlock(&dma->lock);
333                         omap24xxcam_dma_stop(dma, csr);
334                         return;
335                 }
336                 callback = dma->ch_state[dmach].callback;
337                 arg = dma->ch_state[dmach].arg;
338                 dma->free_dmach++;
339                 if (callback) {
340                         spin_unlock(&dma->lock);
341                         (*callback) (dma, csr, arg);
342                         spin_lock(&dma->lock);
343                 }
344         }
345
346         spin_unlock(&dma->lock);
347
348         omap24xxcam_sgdma_process(
349                 container_of(dma, struct omap24xxcam_sgdma, dma));
350 }
351
352 void omap24xxcam_dma_hwinit(struct omap24xxcam_dma *dma)
353 {
354         unsigned long flags;
355
356         spin_lock_irqsave(&dma->lock, flags);
357
358         omap24xxcam_dmahw_init(dma->base);
359
360         spin_unlock_irqrestore(&dma->lock, flags);
361 }
362
363 static void omap24xxcam_dma_init(struct omap24xxcam_dma *dma,
364                                  void __iomem *base)
365 {
366         int ch;
367
368         /* group all channels on DMA IRQ0 and unmask irq */
369         spin_lock_init(&dma->lock);
370         dma->base = base;
371         dma->free_dmach = NUM_CAMDMA_CHANNELS;
372         dma->next_dmach = 0;
373         for (ch = 0; ch < NUM_CAMDMA_CHANNELS; ch++) {
374                 dma->ch_state[ch].callback = NULL;
375                 dma->ch_state[ch].arg = NULL;
376         }
377 }
378
379 /*
380  *
381  * Scatter-gather DMA.
382  *
383  * High-level DMA construct for transferring whole picture frames to
384  * memory that is discontinuous.
385  *
386  */
387
388 /* DMA completion routine for the scatter-gather DMA fragments. */
389 static void omap24xxcam_sgdma_callback(struct omap24xxcam_dma *dma, u32 csr,
390                                        void *arg)
391 {
392         struct omap24xxcam_sgdma *sgdma =
393                 container_of(dma, struct omap24xxcam_sgdma, dma);
394         int sgslot = (int)arg;
395         struct sgdma_state *sg_state;
396         const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
397                 | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
398                 | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;
399
400         spin_lock(&sgdma->lock);
401
402         /* We got an interrupt, we can remove the timer */
403         del_timer(&sgdma->reset_timer);
404
405         sg_state = sgdma->sg_state + sgslot;
406         if (!sg_state->queued_sglist) {
407                 spin_unlock(&sgdma->lock);
408                 printk(KERN_ERR "%s: sgdma completed when none queued!\n",
409                        __func__);
410                 return;
411         }
412
413         sg_state->csr |= csr;
414         if (!--sg_state->queued_sglist) {
415                 /* Queue for this sglist is empty, so check to see if we're
416                  * done.
417                  */
418                 if ((sg_state->next_sglist == sg_state->sglen)
419                     || (sg_state->csr & csr_error)) {
420                         sgdma_callback_t callback = sg_state->callback;
421                         void *arg = sg_state->arg;
422                         u32 sg_csr = sg_state->csr;
423                         /* All done with this sglist */
424                         sgdma->free_sgdma++;
425                         if (callback) {
426                                 spin_unlock(&sgdma->lock);
427                                 (*callback) (sgdma, sg_csr, arg);
428                                 return;
429                         }
430                 }
431         }
432
433         spin_unlock(&sgdma->lock);
434 }
435
436 /* Start queued scatter-gather DMA transfers. */
437 void omap24xxcam_sgdma_process(struct omap24xxcam_sgdma *sgdma)
438 {
439         unsigned long flags;
440         int queued_sgdma, sgslot;
441         struct sgdma_state *sg_state;
442         const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR
443                 | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR
444                 | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP;
445
446         spin_lock_irqsave(&sgdma->lock, flags);
447
448         queued_sgdma = NUM_SG_DMA - sgdma->free_sgdma;
449         sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA;
450         while (queued_sgdma > 0) {
451                 sg_state = sgdma->sg_state + sgslot;
452                 while ((sg_state->next_sglist < sg_state->sglen) &&
453                        !(sg_state->csr & csr_error)) {
454                         const struct scatterlist *sglist;
455                         unsigned int len;
456
457                         sglist = sg_state->sglist + sg_state->next_sglist;
458                         /* try to start the next DMA transfer */
459                         if (sg_state->next_sglist + 1 == sg_state->sglen) {
460                                 /*
461                                  *  On the last sg, we handle the case where
462                                  *  cam->img.pix.sizeimage % PAGE_ALIGN != 0
463                                  */
464                                 len = sg_state->len - sg_state->bytes_read;
465                         } else {
466                                 len = sg_dma_len(sglist);
467                         }
468
469                         if (omap24xxcam_dma_start(&sgdma->dma,
470                                                   sg_dma_address(sglist),
471                                                   len,
472                                                   omap24xxcam_sgdma_callback,
473                                                   (void *)sgslot)) {
474                                 /* DMA start failed */
475                                 spin_unlock_irqrestore(&sgdma->lock, flags);
476                                 return;
477                         }
478                         /* DMA start was successful */
479                         sg_state->next_sglist++;
480                         sg_state->bytes_read += len;
481                         sg_state->queued_sglist++;
482
483                         /* We start the reset timer */
484                         mod_timer(&sgdma->reset_timer, jiffies + HZ);
485                 }
486                 queued_sgdma--;
487                 sgslot = (sgslot + 1) % NUM_SG_DMA;
488         }
489
490         spin_unlock_irqrestore(&sgdma->lock, flags);
491 }
492
493 /*
494  * Queue a scatter-gather DMA transfer from the camera to memory.
495  * Returns zero if the transfer was successfully queued, or non-zero
496  * if all of the scatter-gather slots are already in use.
497  */
498 int omap24xxcam_sgdma_queue(struct omap24xxcam_sgdma *sgdma,
499                             const struct scatterlist *sglist, int sglen,
500                             int len, sgdma_callback_t callback, void *arg)
501 {
502         unsigned long flags;
503         struct sgdma_state *sg_state;
504
505         if ((sglen < 0) || ((sglen > 0) && !sglist))
506                 return -EINVAL;
507
508         spin_lock_irqsave(&sgdma->lock, flags);
509
510         if (!sgdma->free_sgdma) {
511                 spin_unlock_irqrestore(&sgdma->lock, flags);
512                 return -EBUSY;
513         }
514
515         sg_state = sgdma->sg_state + sgdma->next_sgdma;
516
517         sg_state->sglist = sglist;
518         sg_state->sglen = sglen;
519         sg_state->next_sglist = 0;
520         sg_state->bytes_read = 0;
521         sg_state->len = len;
522         sg_state->queued_sglist = 0;
523         sg_state->csr = 0;
524         sg_state->callback = callback;
525         sg_state->arg = arg;
526
527         sgdma->next_sgdma = (sgdma->next_sgdma + 1) % NUM_SG_DMA;
528         sgdma->free_sgdma--;
529
530         spin_unlock_irqrestore(&sgdma->lock, flags);
531
532         omap24xxcam_sgdma_process(sgdma);
533
534         return 0;
535 }
536
537 /* Sync scatter-gather DMA by aborting any DMA transfers currently in progress.
538  * Any queued scatter-gather DMA transactions that have not yet been started
539  * will remain queued.  The DMA controller will be idle after this routine
540  * completes.  When the scatter-gather queue is restarted, the next
541  * scatter-gather DMA transfer will begin at the start of a new transaction.
542  */
543 void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma)
544 {
545         unsigned long flags;
546         int sgslot;
547         struct sgdma_state *sg_state;
548         u32 csr = CAMDMA_CSR_TRANS_ERR;
549
550         /* stop any DMA transfers in progress */
551         omap24xxcam_dma_stop(&sgdma->dma, csr);
552
553         spin_lock_irqsave(&sgdma->lock, flags);
554
555         if (sgdma->free_sgdma < NUM_SG_DMA) {
556                 sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA;
557                 sg_state = sgdma->sg_state + sgslot;
558                 if (sg_state->next_sglist != 0) {
559                         /* This DMA transfer was in progress, so abort it. */
560                         sgdma_callback_t callback = sg_state->callback;
561                         void *arg = sg_state->arg;
562
563                         sgdma->free_sgdma++;
564                         if (callback) {
565                                 /* leave interrupts masked */
566                                 spin_unlock(&sgdma->lock);
567                                 (*callback) (sgdma, csr, arg);
568                                 spin_lock(&sgdma->lock);
569                         }
570                 }
571         }
572
573         spin_unlock_irqrestore(&sgdma->lock, flags);
574 }
575
576 void omap24xxcam_sgdma_init(struct omap24xxcam_sgdma *sgdma,
577                             void __iomem *base,
578                             void (*reset_callback)(unsigned long data),
579                             unsigned long reset_callback_data)
580 {
581         int sg;
582
583         spin_lock_init(&sgdma->lock);
584         sgdma->free_sgdma = NUM_SG_DMA;
585         sgdma->next_sgdma = 0;
586         for (sg = 0; sg < NUM_SG_DMA; sg++) {
587                 sgdma->sg_state[sg].sglen = 0;
588                 sgdma->sg_state[sg].next_sglist = 0;
589                 sgdma->sg_state[sg].bytes_read = 0;
590                 sgdma->sg_state[sg].queued_sglist = 0;
591                 sgdma->sg_state[sg].csr = 0;
592                 sgdma->sg_state[sg].callback = NULL;
593                 sgdma->sg_state[sg].arg = NULL;
594         }
595
596         omap24xxcam_dma_init(&sgdma->dma, base);
597         setup_timer(&sgdma->reset_timer, reset_callback, reset_callback_data);
598 }