]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/omap/omap16xxcam.c
ARM: OMAP: Remove io_p2v, use ioremap and XXX_IO_ADDRESS
[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 <mach/irqs.h>
32 #include <mach/dma.h>
33 #include <mach/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         /* Frequency (in Hz) of camera interface functional clock (ocp_clk) */
71         unsigned long ocp_clk;
72
73         struct clk *func_clk;
74
75         /* DMA related stuff */
76         spinlock_t dma_lock;
77         int free_dmach;
78         int next_dmach;
79         struct camdma_state camdma[NUM_CAMDMA_CHANNELS];
80         int dma_channel_number1;
81         int dma_channel_number2;
82
83         wait_queue_head_t vsync_wait;
84
85         int new;
86 };
87 static struct omap16xxcam hardware_data;
88
89 static int omap16xxcam_set_xclk(int, void *);
90 static void omap16xx_cam_dma_link_callback(int, unsigned short, void *);
91
92 /* Clears the camera data FIFO by setting RAZ_FIFO bit in MODE configuration
93  * register.
94  */
95 static void omap16xx_cam_clear_fifo(struct omap16xxcam *data)
96 {
97         data->camera_regs->mode |= RAZ_FIFO;
98         udelay(10);
99         data->camera_regs->mode &= ~RAZ_FIFO;
100 }
101
102 static void 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 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),
116                     FUNC_MUX_CTRL_4);
117         omap_writel(0, FUNC_MUX_CTRL_5);
118         omap_writel(omap_readl(PULL_DWN_CTRL_0) & ~(0x1FFF << 17),
119                     PULL_DWN_CTRL_0);
120         omap_writel(omap_readl(PU_PD_SEL_0) & ~(0x1FFF << 17), PU_PD_SEL_0);
121
122         omap_writel(0xeaef, COMP_MODE_CTRL_0);
123         omap_writel(omap_readl(OMAP1610_RESET_CONTROL) &
124                     ~(1 << CONF_CAMERAIF_RESET_R), OMAP1610_RESET_CONTROL);
125         omap_writel(omap_readl(OMAP1610_RESET_CONTROL) |
126                     (1 << CONF_CAMERAIF_RESET_R), OMAP1610_RESET_CONTROL);
127
128         /* Enable peripheral reset */
129         omap_writew(omap_readw(ARM_RSTCT2) | (1 << EN_PER), ARM_RSTCT2);
130
131         /* Enable peripheral clock */
132         clk_enable(hardware_data.func_clk);
133 }
134
135 static void omap16xx_cam_waitfor_syncedge(struct omap16xxcam *data,
136                                           u32 edge_mask)
137 {
138         data->camera_regs->mode =
139             (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 omap16xx_cam_configure_dma(struct omap16xxcam *data)
146 {
147
148         data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT)
149             | EN_DMA | EN_FIFO_FULL;
150         data->camera_regs->ctrlclock |= LCLK_EN;
151 }
152
153 /* Acquire h/w resources DMA */
154 static int omap16xx_cam_link_open(struct omap16xxcam *data)
155 {
156         int ret;
157
158         /* Acquire first DMA channel */
159         ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX,
160                                "camera dma 1",
161                                omap16xx_cam_dma_link_callback,
162                                (void *)data, &data->dma_channel_number1);
163         if (ret)
164                 return ret;
165
166         /* Acquire second DMA channel */
167         ret = omap_request_dma(OMAP_DMA_CAMERA_IF_RX,
168                                "camera dma 2",
169                                omap16xx_cam_dma_link_callback,
170                                (void *)data, &data->dma_channel_number2);
171         if (ret) {
172                 printk(KERN_ERR "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 omap16xx_cam_link_close(struct omap16xxcam *data)
186 {
187         /* Free DMA channels */
188         omap_stop_dma(data->dma_channel_number1);
189         omap_stop_dma(data->dma_channel_number2);
190
191         omap_free_dma(data->dma_channel_number1);
192         omap_free_dma(data->dma_channel_number2);
193
194         return 0;
195 }
196
197 /* DMA callback routine. */
198 static void omap16xx_cam_dma_link_callback(int lch, unsigned short ch_status,
199                                            void *data)
200 {
201         int count;
202         void *arg1, *arg2;
203         struct sgdma_state *sgdma = sgdma;
204         struct omap16xxcam *cam = (struct omap16xxcam *)data;
205         dma_callback_t callback;
206
207         spin_lock(&cam->dma_lock);
208         if (cam->free_dmach == 2) {
209                 printk(KERN_ERR "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                 if (OMAP_DMA_CCR_REG(lch) & (1 << 7))
222                         break;
223
224                 count = (lch == cam->dma_channel_number2) ? 1 : 0;
225
226                 callback = cam->camdma[count].callback;
227                 arg1 = cam->camdma[count].arg1;
228                 arg2 = cam->camdma[count].arg2;
229                 cam->free_dmach++;
230
231                 spin_unlock(&cam->dma_lock);
232                 callback(arg1, arg2);
233                 spin_lock(&cam->dma_lock);
234
235                 lch =
236                     (lch ==
237                      cam->dma_channel_number2) ? cam->
238                     dma_channel_number1 : cam->dma_channel_number2;
239         }
240         spin_unlock(&cam->dma_lock);
241
242 }
243
244 static irqreturn_t 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(KERN_INFO "H_UP\n");
265
266         if (itstat & H_DOWN)
267                 printk(KERN_INFO "H_DOWN\n");
268
269         if (itstat & FIFO_FULL) {
270                 omap16xx_cam_clear_fifo(data);
271                 printk(KERN_INFO "FIFO_FULL\n");
272         }
273
274         if (itstat & DATA_XFER)
275                 printk(KERN_INFO "DATA_TRANS\n");
276
277         return IRQ_HANDLED;
278 }
279
280 /* ------------- Below are interface functions -----------------
281  * ------------- These functions are named omap16xxcam_<name> --
282  */
283 static int 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 omap16xxcam_start_dma(struct sgdma_state *sgdma,
300                                  dma_callback_t callback, void *arg1,
301                                  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,
326                                         CAM_CAMDATA_REG, 0, 0);
327         else
328                 omap_set_dma_src_params(dmach, OMAP_DMA_PORT_TIPB,
329                                         OMAP_DMA_AMODE_CONSTANT,
330                                         CAM_CAMDATA_REG, 0, 0);
331
332         omap_set_dma_dest_params(dmach, OMAP_DMA_PORT_EMIFF,
333                                  OMAP_DMA_AMODE_POST_INC,
334                                  sg_dma_address(sglist), 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 *
339                                                            FIFO_TRIGGER_LVL),
340                                      OMAP_DMA_SYNC_FRAME, 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
365 int static 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 /* Enables the camera. Takes camera out of reset. Enables the clocks. */
376 static int omap16xxcam_enable(void *priv)
377 {
378         struct omap16xxcam *data = (struct omap16xxcam *)priv;
379
380         omap16xx_cam_reset(data, 1);
381
382         /* Give clock to camera_module */
383         data->camera_regs->mode = (FIFO_TRIGGER_LVL << THRESHOLD_BIT);
384         data->camera_regs->ctrlclock = MCLK_EN | CAMEXCLK_EN;
385
386         omap16xx_cam_clear_fifo(data);
387
388         /* Wait for camera to settle down */
389         mdelay(5);
390
391         return 0;
392 }
393
394 /* Disables all the camera clocks. Put the camera interface in reset. */
395 static int omap16xxcam_disable(void *priv)
396 {
397         struct omap16xxcam *data = (struct omap16xxcam *)priv;
398
399         omap16xx_cam_clear_fifo(data);
400
401         data->camera_regs->ctrlclock = 0x00000000;
402         data->camera_regs->mode = 0x00000000;
403
404         omap16xx_cam_reset(data, 0);
405
406         return 0;
407 }
408
409 /* Abort the data transfer */
410 static int omap16xxcam_abort(void *priv)
411 {
412         return omap16xxcam_disable(priv);
413 }
414
415 static int omap16xxcam_set_xclk(int xclk, void *priv)
416 {
417         struct omap16xxcam *data = (struct omap16xxcam *)priv;
418         int xclk_val;
419         int divisor = 1;
420         divisor = data->ocp_clk / xclk;
421         if (divisor * xclk < data->ocp_clk)
422                 ++divisor;
423
424         switch (divisor) {
425         case 1:
426         case 2:
427                 xclk_val = FOSCMOD_TC2_CK2;
428                 break;
429         case 3:
430                 xclk_val = FOSCMOD_TC2_CK3;
431                 break;
432         case 4:
433         case 5:
434         case 6:
435         case 7:
436                 xclk_val = FOSCMOD_TC2_CK4;
437                 break;
438         case 8:
439         case 9:
440                 xclk_val = FOSCMOD_TC2_CK8;
441                 break;
442         case 10:
443         case 11:
444                 xclk_val = FOSCMOD_TC2_CK10;
445                 break;
446         case 12:
447         case 13:
448         case 14:
449         case 15:
450                 xclk_val = FOSCMOD_TC2_CK12;
451                 break;
452         case 16:
453                 xclk_val = FOSCMOD_TC2_CK16;
454                 break;
455         default:
456                 xclk_val = FOSCMOD_TC2_CK16;
457         }
458
459         /* Follow the protocol to change the XCLK clock */
460         data->camera_regs->ctrlclock &= ~CAMEXCLK_EN;
461         data->camera_regs->ctrlclock |= xclk_val;
462         data->camera_regs->ctrlclock |= CAMEXCLK_EN;
463
464         return (data->ocp_clk / divisor);
465 }
466
467 static int omap16xxcam_open(void *priv)
468 {
469         struct omap16xxcam *data = (struct omap16xxcam *)priv;
470         int ret;
471
472         ret = request_irq(INT_CAMERA, omap16xx_cam_isr, IRQF_DISABLED,
473                           "camera", data);
474         if (ret) {
475                 printk(KERN_ERR "FAILED to acquire IRQ\n");
476                 return ret;
477         }
478
479         data->new = 1;
480         omap16xxcam_enable(data);
481         omap16xxcam_init_dma(data);
482
483         return omap16xx_cam_link_open(data);
484 }
485
486 static int omap16xxcam_close(void *priv)
487 {
488         struct omap16xxcam *data = (struct omap16xxcam *)priv;
489
490         omap16xxcam_disable(priv);
491
492         free_irq(INT_CAMERA, data);
493
494         return omap16xx_cam_link_close(data);
495 }
496
497 static int omap16xxcam_cleanup(void *priv)
498 {
499         struct omap16xxcam *data = (struct omap16xxcam *)priv;
500
501         if (!data->camera_regs)
502                 return -EINVAL;
503
504         omap16xxcam_disable(data);
505         if (cpu_is_omap1710())
506                 iounmap((void *)data->camera_regs);
507         data->camera_regs = NULL;
508
509         if (data->iobase_phys) {
510                 release_mem_region(data->iobase_phys, CAMERA_IOSIZE);
511                 data->iobase_phys = 0;
512         }
513
514         if (hardware_data.func_clk) {
515                 clk_disable(hardware_data.func_clk);
516                 clk_put(hardware_data.func_clk);
517                 hardware_data.func_clk = NULL;
518         }
519
520         return 0;
521 }
522
523 /* Initialize the OMAP camera interface */
524 static void *omap16xxcam_init(void)
525 {
526         unsigned long cam_iobase;
527
528         if (!request_mem_region(CAMERA_BASE, CAMERA_IOSIZE,
529                                 camera_hardware_if.name)) {
530                 pr_debug("%s is already in use\n", camera_hardware_if.name);
531                 return NULL;
532         }
533
534         if (cpu_is_omap1710()) {
535                 cam_iobase = (unsigned long)ioremap(CAMERA_BASE, CAMERA_IOSIZE);
536                 if (!cam_iobase) {
537                         printk(KERN_ERR "CANNOT MAP CAMERA REGISTER\n");
538                         return NULL;
539                 }
540         } else
541                 cam_iobase = OMAP1_IO_ADDRESS(CAMERA_BASE);
542
543         /* Set the base address of the camera registers */
544         hardware_data.camera_regs = (camera_regs_t *) cam_iobase;
545         hardware_data.iobase_phys = (unsigned long)CAMERA_BASE;
546
547         /* Get the input clock value to camera interface and store it */
548         if (cpu_is_omap1710())
549                 hardware_data.func_clk = clk_get(0, "tc2_ck");
550         else
551                 hardware_data.func_clk = clk_get(0, "armper_ck");
552         hardware_data.ocp_clk = clk_get_rate(hardware_data.func_clk);
553
554         /* Initialize the camera IF */
555         omap16xx_cam_init();
556         /* Enable it. This is needed for sensor detection */
557         omap16xxcam_enable((void *)&hardware_data);
558         /* Initialize DMA data */
559         spin_lock_init(&hardware_data.dma_lock);
560
561         init_waitqueue_head(&hardware_data.vsync_wait);
562         return (void *)&hardware_data;
563 }
564
565 struct camera_hardware camera_hardware_if = {
566         .version        = 0x01,
567         .name           = "OMAP16xx Parallel Camera",
568         .init           = omap16xxcam_init,
569         .cleanup        = omap16xxcam_cleanup,
570         .open           = omap16xxcam_open,
571         .close          = omap16xxcam_close,
572         .enable         = omap16xxcam_enable,
573         .disable        = omap16xxcam_disable,
574         .abort          = omap16xxcam_abort,
575         .set_xclk       = omap16xxcam_set_xclk,
576         .init_dma       = omap16xxcam_init_dma,
577         .start_dma      = omap16xxcam_start_dma,
578         .finish_dma     = omap16xxcam_finish_dma,
579 };