]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/omap/omap16xxcam.c
6f85bd25f01e74aa6ec355de0f2ba272f72cdb4a
[linux-2.6-omap-h63xx.git] / drivers / media / video / omap / omap16xxcam.c
1 /*
2  * drivers/media/video/omap/omap16xxcam.c
3  *
4  * Copyright (C) 2004 Texas Instruments, Inc. 
5  * 
6  * Video-for-Linux (Version 2) camera capture driver for
7  * the OMAP H2 and H3 camera controller.
8  *
9  * leverage some code from CEE distribution 
10  * Copyright (C) 2003-2004 MontaVista Software, Inc.
11  * 
12  * This package is free software; you can redistribute it and/or modify 
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation. 
15  * 
16  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 
19  */
20  
21 #include <linux/config.h>
22 #include <linux/vmalloc.h>
23 #include <linux/slab.h>
24 #include <linux/proc_fs.h>
25 #include <linux/ctype.h>
26 #include <linux/delay.h>
27 #include <linux/device.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/interrupt.h>
30
31 #include <asm/arch/irqs.h>
32 #include <asm/arch/dma.h>
33 #include <asm/arch/hardware.h>
34 #include <asm/io.h>
35 #include <asm/scatterlist.h>
36 #include <asm/mach-types.h>
37 #include <asm/hardware/clock.h>
38
39 #include "omap16xxcam.h"
40 #include "camera_hw_if.h"
41 #include "camera_core.h"
42   
43 #define CONF_CAMERAIF_RESET_R 5
44 #define EN_PER    0
45
46 /* NUM_CAMDMA_CHANNELS is the number of logical channels used for
47  * DMA data transfer.
48  */
49 #define NUM_CAMDMA_CHANNELS 2
50
51 typedef struct {
52         unsigned int ctrlclock;     /* 00 */
53         unsigned int it_status;     /* 04 */
54         unsigned int mode;          /* 08 */
55         unsigned int status;        /* 0C */
56         unsigned int camdata;       /* 10 */
57         unsigned int gpio;          /* 14 */
58         unsigned int peak_counter;  /* 18 */
59 } camera_regs_t;
60
61 struct camdma_state {
62         dma_callback_t callback;
63         void *arg1;
64         void *arg2;
65 };
66
67 struct omap16xxcam {
68         camera_regs_t *camera_regs;
69         unsigned long iobase_phys;
70
71         /* frequncy (in Hz) of camera interface functional clock (ocp_clk) */
72         unsigned long ocp_clk; 
73
74         /* dma related stuff */
75         spinlock_t dma_lock;
76         int free_dmach;
77         int next_dmach;
78         struct camdma_state camdma[NUM_CAMDMA_CHANNELS];
79         int dma_channel_number1;
80         int dma_channel_number2;
81
82         wait_queue_head_t vsync_wait;
83         
84         int new;
85 };
86 static struct omap16xxcam hardware_data;
87    
88 static int omap16xxcam_set_xclk(int, void *);
89 static void omap16xx_cam_dma_link_callback(int, unsigned short, void *);
90
91 /* Clears the camera data FIFO by setting RAZ_FIFO bit in MODE configuration
92    register. */
93 static void
94 omap16xx_cam_clear_fifo(struct omap16xxcam *data)
95 {
96         data->camera_regs->mode |= RAZ_FIFO;
97         udelay(10);
98         data->camera_regs->mode &= ~RAZ_FIFO;
99 }
100   
101 static void
102 omap16xx_cam_reset(struct omap16xxcam *data, int yes)
103 {
104         if (machine_is_omap_h3())
105                 data->camera_regs->gpio = yes ? 0 : 1;
106         else
107                 data->camera_regs->gpio = yes ? 1 : 0;
108 }
109
110 static void 
111 omap16xx_cam_init(void)
112 {
113         /*
114          * FIXME - Use mux API's instead of directly writing in to MUX registers
115          */
116         omap_writel(omap_readl(FUNC_MUX_CTRL_4) & ~(0x1ff << 21), FUNC_MUX_CTRL_4);
117         omap_writel(0, FUNC_MUX_CTRL_5);
118         omap_writel(omap_readl(PULL_DWN_CTRL_0) & ~(0x1FFF << 17), PULL_DWN_CTRL_0);
119         omap_writel(omap_readl(PU_PD_SEL_0) & ~(0x1FFF << 17), PU_PD_SEL_0);
120
121         omap_writel(0xeaef, COMP_MODE_CTRL_0);
122         omap_writel(omap_readl(OMAP1610_RESET_CONTROL) & ~(1 << CONF_CAMERAIF_RESET_R),
123                         OMAP1610_RESET_CONTROL);
124         omap_writel(omap_readl(OMAP1610_RESET_CONTROL) | (1 << CONF_CAMERAIF_RESET_R),
125                         OMAP1610_RESET_CONTROL);
126     
127         /* Enable peripheral reset */
128         omap_writew(omap_readw(ARM_RSTCT2) | (1 << EN_PER), ARM_RSTCT2); 
129
130         /* enable peripheral clock */
131         if (machine_is_omap_h3())
132                 clk_enable(clk_get(0, "tc2_ck"));
133         else {
134                 clk_enable(clk_get(0, "armper_ck"));
135                 clk_enable(clk_get(0, "armxor_ck"));
136         }               
137 }
138
139 static void
140 omap16xx_cam_waitfor_syncedge(struct omap16xxcam *data, u32 edge_mask)
141 {
142         data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT) | edge_mask;
143         do {
144                 interruptible_sleep_on(&data->vsync_wait);
145         } while (signal_pending(current));
146 }
147
148 static void
149 omap16xx_cam_configure_dma(struct omap16xxcam *data)
150 {
151
152         data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT)
153                          | EN_DMA | EN_FIFO_FULL;
154         data->camera_regs->ctrlclock |= LCLK_EN; 
155 }
156
157 /* acquire h/w resources DMA */
158 static int
159 omap16xx_cam_link_open(struct omap16xxcam *data)
160 {
161         int ret;
162
163         /* Acquire first dma channel */
164         if ((ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, 
165                                 "camera dma 1", omap16xx_cam_dma_link_callback,
166                                 (void *)data, &data->dma_channel_number1))) {
167                 return ret;
168         }
169         /* Acquire second dma channel */
170         if ((ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, 
171                                 "camera dma 2", omap16xx_cam_dma_link_callback,
172                                 (void *)data, &data->dma_channel_number2))) {
173                 printk ("No DMA available for camera\n");
174                 return ret;
175         }
176         data->next_dmach = data->dma_channel_number1;
177         OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number1) =
178                 data->dma_channel_number2;
179         OMAP_DMA_CLNK_CTRL_REG(data->dma_channel_number2) =
180                 data->dma_channel_number1;
181
182         return 0;
183 }
184
185 /* free h/w resources, stop i/f */
186 static int
187 omap16xx_cam_link_close(struct omap16xxcam *data)
188 {
189         /* free dma channels */
190         omap_stop_dma(data->dma_channel_number1);
191         omap_stop_dma(data->dma_channel_number2);
192
193         omap_free_dma (data->dma_channel_number1);
194         omap_free_dma (data->dma_channel_number2);
195
196         return 0;
197 }
198
199 /* dma callback routine. */
200 static void
201 omap16xx_cam_dma_link_callback(int lch, unsigned short ch_status, void *data)
202 {
203         int count;
204         void *arg1, *arg2;
205         struct sgdma_state *sgdma = sgdma;
206         struct omap16xxcam *cam = (struct omap16xxcam *)data;
207         dma_callback_t callback;
208
209         spin_lock(&cam->dma_lock);
210         if (cam->free_dmach == 2)
211         {
212                 printk("callback all CHANNELS WERE IDLE \n");
213                 spin_unlock(&cam->dma_lock);
214                 return;
215         }
216         if (cam->free_dmach == 0) {
217                 lch = cam->next_dmach;
218         } else {
219                 lch = cam->next_dmach == cam->dma_channel_number1 ? 
220                         cam->dma_channel_number2 : cam->dma_channel_number1;
221         }
222
223         while (cam->free_dmach < 2)
224         {
225                 if (OMAP_DMA_CCR_REG(lch) & (1 << 7))
226                         break;  
227
228                 count = (lch == cam->dma_channel_number2) ? 1 : 0;
229
230                 callback = cam->camdma[count].callback;
231                 arg1 = cam->camdma[count].arg1;
232                 arg2 = cam->camdma[count].arg2;
233                 cam->free_dmach++;
234
235                 spin_unlock(&cam->dma_lock);            
236                 callback(arg1, arg2);
237                 spin_lock(&cam->dma_lock);
238
239                 lch = (lch == cam->dma_channel_number2) ? cam->dma_channel_number1 :
240                                                         cam->dma_channel_number2;
241         }
242         spin_unlock(&cam->dma_lock);
243         
244 }
245
246 static irqreturn_t
247 omap16xx_cam_isr(int irq, void *client_data, struct pt_regs *regs)
248 {
249         struct omap16xxcam *data = (struct omap16xxcam *)client_data;
250         unsigned int itstat = data->camera_regs->it_status;
251
252         /* VSYNC UP interrupt, start filling FIFO and enabling DMA */
253         if (itstat & V_UP) {            
254                 data->camera_regs->mode &= ~EN_V_UP;
255                 omap16xx_cam_clear_fifo(data);  
256                 omap16xx_cam_configure_dma(data);
257                 omap_start_dma(data->next_dmach);
258                 wake_up_interruptible(&data->vsync_wait);
259         }
260
261         if (itstat & V_DOWN) {
262                 data->camera_regs->mode &= ~EN_V_DOWN;
263                 wake_up_interruptible(&data->vsync_wait);
264         }
265
266         if (itstat & H_UP)
267                 printk("H_UP\n");
268         
269         if (itstat & H_DOWN)
270                 printk("H_DOWN\n");
271         
272         if (itstat & FIFO_FULL) {
273                 omap16xx_cam_clear_fifo(data);  
274                 printk("FIFO_FULL\n");
275         }
276         
277         if (itstat & DATA_XFER)
278                 printk("DATA_TRANS\n");
279         
280         return IRQ_HANDLED;
281 }
282  
283 /* ------------- below are interface functions ----------------- */
284 /* ------------- these functions are named omap16xxcam_<name> -- */
285 static int
286 omap16xxcam_init_dma(void *priv)
287 {
288         int ch;
289         struct omap16xxcam *data = (struct omap16xxcam *) priv;
290
291         data->free_dmach = 2;
292         for (ch = 0; ch < 2; ++ch) {
293                 data->camdma[ch].callback = NULL;
294                 data->camdma[ch].arg1 = NULL;
295                 data->camdma[ch].arg2 = NULL;
296         }
297
298         return 0;
299 }
300
301 /* start the dma of chains */
302 static int 
303 omap16xxcam_start_dma(struct sgdma_state *sgdma,
304                 dma_callback_t callback, void *arg1, void *arg2, void *priv)
305 {
306         struct omap16xxcam *data = (struct omap16xxcam *) priv;
307         struct scatterlist *sglist;
308         unsigned long irqflags;
309         int dmach;
310         int prev_dmach;
311         int count;
312
313         spin_lock_irqsave(&data->dma_lock, irqflags);
314         sglist = (struct scatterlist *)(sgdma->sglist + sgdma->next_sglist);
315
316         if (!data->free_dmach) {
317                 spin_unlock_irqrestore(&data->dma_lock, irqflags);
318                 return -EBUSY;
319         } 
320         dmach = data->next_dmach;
321         count = (dmach == data->dma_channel_number2) ? 1:0;
322         data->camdma[count].callback = callback;
323         data->camdma[count].arg1 = arg1;
324         data->camdma[count].arg2 = arg2;
325         
326         if (machine_is_omap_h3())
327                 omap_set_dma_src_params(dmach, OMAP_DMA_PORT_OCP_T1,
328                             OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
329                             0, 0);
330         else
331                 omap_set_dma_src_params(dmach, OMAP_DMA_PORT_TIPB,
332                             OMAP_DMA_AMODE_CONSTANT, CAM_CAMDATA_REG,
333                             0, 0);
334
335         omap_set_dma_dest_params(dmach, OMAP_DMA_PORT_EMIFF,
336                              OMAP_DMA_AMODE_POST_INC, sg_dma_address(sglist),
337                              0, 0);
338
339         omap_set_dma_transfer_params(dmach, OMAP_DMA_DATA_TYPE_S32,
340                         FIFO_TRIGGER_LVL, 
341                         sg_dma_len(sglist)/(4 * FIFO_TRIGGER_LVL), 
342                         OMAP_DMA_SYNC_FRAME,
343                         0, 0);
344
345         OMAP_DMA_CLNK_CTRL_REG(dmach) &= ~( 1<< 15);
346
347         prev_dmach = (dmach == data->dma_channel_number2) ? 
348                 data->dma_channel_number1 : data->dma_channel_number2;
349         
350         if (data->new) {
351                 data->new = 0;
352                 omap16xx_cam_waitfor_syncedge(data, EN_V_UP);
353         } else {
354                 if (OMAP_DMA_CCR_REG(prev_dmach) & (1 << 7))
355                         OMAP_DMA_CLNK_CTRL_REG(prev_dmach) |= (1 << 15);
356                 else {
357                         /* no transfer is in progress */
358                         omap_start_dma(dmach);
359                 }       
360         }
361         
362         data->next_dmach = prev_dmach; 
363         data->free_dmach--;
364         spin_unlock_irqrestore(&data->dma_lock, irqflags);
365         return 0;
366 }
367 int static
368 omap16xxcam_finish_dma(void *priv)
369 {
370         struct omap16xxcam *data = (struct omap16xxcam *) priv;
371
372         while (data->free_dmach < 2)
373                 mdelay(1);
374
375         return 0;
376 }
377
378
379 /* Enables the camera. Takes camera out of reset. Enables the clocks. */ 
380 static int
381 omap16xxcam_enable(void *priv)
382 {
383         struct omap16xxcam *data = (struct omap16xxcam *) priv;
384
385         omap16xx_cam_reset(data, 1);
386         
387         /* give clock to camera_module */
388         data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT);
389         data->camera_regs->ctrlclock = MCLK_EN | CAMEXCLK_EN;
390
391         omap16xx_cam_clear_fifo(data);
392
393         /* wait for camera to settle down */
394         mdelay(5);
395
396         return 0;
397 }
398  
399 /* Disables all the camera clocks. Put the camera interface in reset. */
400 static int
401 omap16xxcam_disable(void *priv)
402 {       
403         struct omap16xxcam *data = (struct omap16xxcam *) priv;
404
405         omap16xx_cam_clear_fifo(data);
406
407         data->camera_regs->ctrlclock = 0x00000000;     
408         data->camera_regs->mode = 0x00000000;
409         
410         omap16xx_cam_reset(data, 0);
411
412         return 0;
413 }
414
415 /* Abort the data transfer */
416 static int
417 omap16xxcam_abort(void *priv)
418 {
419         return omap16xxcam_disable(priv);
420 }
421
422 static int
423 omap16xxcam_set_xclk(int xclk, void *priv)
424 {       
425         struct omap16xxcam *data = (struct omap16xxcam *) priv;
426         int xclk_val;
427         int divisor = 1;
428         divisor = data->ocp_clk/xclk;
429         if ( divisor * xclk < data->ocp_clk)
430                 ++divisor; 
431
432         switch (divisor) {
433                 case 1:
434                 case 2:
435                         xclk_val = FOSCMOD_TC2_CK2;
436                         break;
437                 case 3:
438                         xclk_val = FOSCMOD_TC2_CK3;
439                         break;
440                 case 4:
441                 case 5:
442                 case 6:
443                 case 7:
444                         xclk_val = FOSCMOD_TC2_CK4;
445                         break;
446                 case 8:
447                 case 9:
448                         xclk_val = FOSCMOD_TC2_CK8;
449                         break;
450                 case 10:
451                 case 11:
452                         xclk_val = FOSCMOD_TC2_CK10;
453                         break;
454                 case 12:
455                 case 13:
456                 case 14:
457                 case 15:
458                         xclk_val = FOSCMOD_TC2_CK12;
459                         break;
460                 case 16:
461                         xclk_val = FOSCMOD_TC2_CK16;
462                         break;
463                 default:
464                         xclk_val = FOSCMOD_TC2_CK16;
465         }
466         
467         /* follow the protocol to change the XCLK clock */
468         data->camera_regs->ctrlclock &= ~CAMEXCLK_EN;
469         data->camera_regs->ctrlclock |= xclk_val;
470         data->camera_regs->ctrlclock |= CAMEXCLK_EN;
471
472         return (data->ocp_clk/divisor);
473 }
474
475 static int
476 omap16xxcam_open(void *priv)
477 {
478         struct omap16xxcam *data = (struct omap16xxcam *) priv;
479         int ret;
480
481         if ((ret = request_irq(INT_CAMERA, omap16xx_cam_isr, SA_INTERRUPT, 
482                                         "camera", data))) {
483                 printk("FAILED to aquire irq\n");
484                 return ret;
485         }
486
487         data->new = 1;
488         omap16xxcam_enable(data);
489         omap16xxcam_init_dma(data);
490
491         return omap16xx_cam_link_open(data);
492 }
493
494 static int
495 omap16xxcam_close(void *priv)
496 {
497         struct omap16xxcam *data = (struct omap16xxcam *) priv;
498
499         omap16xxcam_disable(priv);
500          
501         free_irq(INT_CAMERA, data);
502         
503         return omap16xx_cam_link_close(data);
504 }
505
506 static int
507 omap16xxcam_cleanup(void *priv)
508 {
509         struct omap16xxcam *data = (struct omap16xxcam *) priv;
510
511         omap16xxcam_disable(data);
512         if (machine_is_omap_h3()) {
513                 if (data->camera_regs) {        
514                         iounmap((void *)data->camera_regs);
515                         data->camera_regs= NULL;
516                 }
517         }
518
519         if (data->iobase_phys) {
520                 release_mem_region(data->iobase_phys, CAMERA_IOSIZE);
521                 data->iobase_phys = 0;
522         }
523
524         return 0;
525 }
526
527 /* Initialise the OMAP camera interface */
528 static void *
529 omap16xxcam_init(void)
530 {
531         unsigned long cam_iobase;
532
533         if (!request_region(CAMERA_BASE, CAMERA_IOSIZE, "OAMP16xx Camera")) {
534                 printk ("OMAP16XX Parallel Camera Interface is already in use\n");
535                 return NULL;
536         }
537
538         if (machine_is_omap_h3()) {
539                 cam_iobase = (unsigned long) ioremap (CAMERA_BASE, CAMERA_IOSIZE);
540                 if (!cam_iobase) {
541                         printk("CANNOT MAP CAMERA REGISTER\n");
542                         return NULL;
543                 }
544         }
545         else
546                 cam_iobase = io_p2v(CAMERA_BASE);
547
548         /* Set the base address of the camera registers */
549         hardware_data.camera_regs = (camera_regs_t *)cam_iobase;
550         hardware_data.iobase_phys = (unsigned long) CAMERA_BASE;
551         /* get the input clock value to camera interface and store it */
552         if (machine_is_omap_h3())
553                 hardware_data.ocp_clk = clk_get_rate(clk_get(0, "tc_ck"));
554         else
555                 hardware_data.ocp_clk = clk_get_rate(clk_get(0, "mpuper_ck"));
556
557         /* Init the camera IF */
558         omap16xx_cam_init();
559         /* enable it. This is needed for sensor detection */
560         omap16xxcam_enable((void*)&hardware_data);
561         /* Init dma data */
562         spin_lock_init(&hardware_data.dma_lock);
563
564         init_waitqueue_head(&hardware_data.vsync_wait);
565         return (void*)&hardware_data;
566 }
567
568 struct camera_hardware camera_hardware_if = {
569         version         : 0x01, 
570         name            : "OMAP16xx Camera Parallel", 
571         init            : omap16xxcam_init,
572         cleanup         : omap16xxcam_cleanup,
573         open            : omap16xxcam_open, 
574         close           : omap16xxcam_close,
575         enable          : omap16xxcam_enable, 
576         disable         : omap16xxcam_disable,
577         abort           : omap16xxcam_abort,
578         set_xclk        : omap16xxcam_set_xclk,
579         init_dma        : omap16xxcam_init_dma,
580         start_dma       : omap16xxcam_start_dma,
581         finish_dma      : omap16xxcam_finish_dma,
582 };
583