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