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