]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/meta-ti-glsdk.git/blob - recipes-kernel/linux/linux-ti33x-psp-3.2/beaglebone/0073-beaglebone-add-support-for-QuickLogic-Camera-interfa.patch
linux-ti33x-psp 3.2: enable more tracing features for beaglebone
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / beaglebone / 0073-beaglebone-add-support-for-QuickLogic-Camera-interfa.patch
1 From cf35e6b861c3c7d4d9c9db1557ba27b5578e8aa2 Mon Sep 17 00:00:00 2001
2 From: Dan Aizenstros <daizenstros@quicklogic.com>
3 Date: Fri, 29 Jun 2012 13:57:49 -0400
4 Subject: [PATCH] beaglebone: add support for QuickLogic Camera interface on
5  camera cape
7 Signed-off-by: Dan Aizenstros <daizenstros@quicklogic.com>
8 ---
9  arch/arm/mach-omap2/board-am335xevm.c         |  205 ++++-
10  arch/arm/mach-omap2/devices.c                 |    2 +-
11  arch/arm/plat-omap/include/plat/dma-33xx.h    |    1 +
12  drivers/media/video/Kconfig                   |    7 +
13  drivers/media/video/Makefile                  |    2 +
14  drivers/media/video/cssp_camera/Makefile      |    3 +
15  drivers/media/video/cssp_camera/cssp_camera.c | 1119 +++++++++++++++++++++++++
16  drivers/media/video/cssp_camera/cssp_camera.h |  148 ++++
17  8 files changed, 1478 insertions(+), 9 deletions(-)
18  create mode 100644 drivers/media/video/cssp_camera/Makefile
19  create mode 100644 drivers/media/video/cssp_camera/cssp_camera.c
20  create mode 100644 drivers/media/video/cssp_camera/cssp_camera.h
22 diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
23 index dc78b4a..1680612 100644
24 --- a/arch/arm/mach-omap2/board-am335xevm.c
25 +++ b/arch/arm/mach-omap2/board-am335xevm.c
26 @@ -66,6 +66,10 @@
27  #include <plat/mmc.h>
28  #include <plat/emif.h>
29  #include <plat/nand.h>
30 +#include <plat/dma-33xx.h>
31 +
32 +#include <media/soc_camera.h>
33 +#include <media/mt9t112.h>
34  
35  #include "board-flash.h"
36  #include "cpuidle33xx.h"
37 @@ -804,6 +808,42 @@ static struct pinmux_config i2c1_pin_mux[] = {
38         {NULL, 0},
39  };
40  
41 +/* Pin mux for GPMC bus */
42 +static struct pinmux_config gpmc_pin_mux[] = {
43 +       {"gpmc_ad0.gpmc_ad0",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
44 +       {"gpmc_ad1.gpmc_ad1",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
45 +       {"gpmc_ad2.gpmc_ad2",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
46 +       {"gpmc_ad3.gpmc_ad3",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
47 +       {"gpmc_ad4.gpmc_ad4",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
48 +       {"gpmc_ad5.gpmc_ad5",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
49 +       {"gpmc_ad6.gpmc_ad6",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
50 +       {"gpmc_ad7.gpmc_ad7",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
51 +       {"gpmc_ad8.gpmc_ad8",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
52 +       {"gpmc_ad9.gpmc_ad9",     OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
53 +       {"gpmc_ad10.gpmc_ad10",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
54 +       {"gpmc_ad11.gpmc_ad11",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
55 +       {"gpmc_ad12.gpmc_ad12",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
56 +       {"gpmc_ad13.gpmc_ad13",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
57 +       {"gpmc_ad14.gpmc_ad14",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
58 +       {"gpmc_ad15.gpmc_ad15",   OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
59 +       {"gpmc_wait0.gpmc_wait0", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
60 +       {"gpmc_wpn.gpmc_wpn",     OMAP_MUX_MODE7 | AM33XX_PIN_INPUT_PULLUP},
61 +       {"gpmc_csn1.gpmc_csn1",   OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
62 +       {"gpmc_advn_ale.gpmc_advn_ale",  OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
63 +       {"gpmc_oen_ren.gpmc_oen_ren",    OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
64 +       {"gpmc_wen.gpmc_wen",     OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
65 +       {"gpmc_ben0_cle.gpmc_ben0_cle",  OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
66 +       {"gpmc_clk.gpmc_clk",    OMAP_MUX_MODE0 | AM33XX_PIN_INPUT},
67 +       {"ecap0_in_pwm0_out.xdma_event_intr2", OMAP_MUX_MODE6 | AM33XX_PIN_INPUT}, // DMAREQ
68 +       {NULL, 0},
69 +};
70 +
71 +static struct pinmux_config camera_cape_pin_mux[] = {
72 +       {"spi0_d1.gpio0_4",    OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT },            // QL CSSP and Camera Sensor Reset
73 +       {"spi0_cs0.gpio0_5",   OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT_PULLUP },     // 1V8 and 2V8 Power Enable
74 +       {NULL, 0},
75 +};
76 +
77  static struct pinmux_config i2c2_pin_mux[] = {
78         {"uart1_ctsn.i2c2_sda",    OMAP_MUX_MODE3 | AM33XX_SLEWCTRL_SLOW |
79                                         AM33XX_PIN_INPUT_PULLUP},
80 @@ -1803,6 +1843,156 @@ static void dvileds_init(int evm_id, int profile )
81                 pr_err("failed to register BeagleBone DVI cape LEDS\n");
82  }
83  
84 +static struct resource cssp_camera_resources[] = {
85 +       {
86 +               .name = "gpmc_phys_mem_slot",
87 +               .flags = IORESOURCE_MEM,
88 +       },
89 +};
90 +
91 +static struct mt9t112_camera_info mt9t111_cam_info = {
92 +       /* divider calculated for 32Mhz CAM_MCLK */
93 +       .divider = {
94 +               .m = 24, .n = 1,
95 +               .p1 = 0, .p2 = 7, .p3 = 0, .p4 = 11, .p5 = 15, .p6 = 7, .p7 = 0,
96 +       },
97 +};
98 +
99 +static struct soc_camera_link mt9t111_camera_link =  {
100 +       .priv = &mt9t111_cam_info,
101 +       .i2c_adapter_id = 3,
102 +};
104 +static struct i2c_board_info i2c_camera = {
105 +       I2C_BOARD_INFO("mt9t112", 0x3c),
106 +       .platform_data = &mt9t111_camera_link,
107 +};
109 +struct cssp_cam_platform_data {
110 +       struct i2c_board_info *cam_i2c_board_info;
111 +       const char *cam_clk_name;
112 +       int dma_ch;
113 +       int cssp_reset_pin;
114 +};
116 +static struct cssp_cam_platform_data cssp_cam_platform_data = {
117 +       .cam_i2c_board_info = &i2c_camera,
118 +       .cam_clk_name = "clkout2_ck",
119 +       .dma_ch = AM33XX_DMA_XDMA_EVENT_INTR2,
120 +       .cssp_reset_pin = GPIO_TO_PIN(0, 4),
121 +};
123 +static struct platform_device cssp_camera = {
124 +       .name  = "cssp-camera",
125 +       .id    = -1,
126 +       .dev   = {
127 +               .platform_data = &cssp_cam_platform_data,
128 +       },
129 +       .num_resources = sizeof(cssp_camera_resources) / sizeof(cssp_camera_resources[0]),
130 +       .resource = cssp_camera_resources,
131 +};
133 +static struct gpmc_timings cssp_timings = {
134 +       /* Minimum clock period for synchronous mode (in picoseconds) */
135 +       .sync_clk = 10000,
137 +       .cs_on = 0,
138 +       .cs_rd_off = 23 * 10,           /* Read deassertion time */
139 +       .cs_wr_off = 23 * 10,           /* Write deassertion time */
141 +       /* ADV signal timings corresponding to GPMC_CONFIG3 */
142 +       .adv_on = 0,                    /* Assertion time */
143 +       .adv_rd_off = 2 * 10,           /* Read deassertion time */
144 +       .adv_wr_off = 2 * 10,           /* Write deassertion time */
146 +       /* WE signals timings corresponding to GPMC_CONFIG4 */
147 +       .we_on = 3 * 10,                /* WE assertion time */
148 +       .we_off = 23 * 10,              /* WE deassertion time */
150 +       /* OE signals timings corresponding to GPMC_CONFIG4 */
151 +       .oe_on = 3 * 10,                /* OE assertion time */
152 +       .oe_off = 23 * 10,              /* OE deassertion time */
154 +       /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
155 +       .page_burst_access = 1 * 10,    /* Multiple access word delay */
156 +       .access = 7 * 10,               /* Start-cycle to first data valid delay */
157 +       .rd_cycle = 23 * 10,            /* Total read cycle time */
158 +       .wr_cycle = 23 * 10,            /* Total write cycle time */
160 +       /* The following are only on OMAP3430 */
161 +       .wr_access = 7 * 10,            /* WRACCESSTIME */
162 +       .wr_data_mux_bus = 3 * 10,      /* WRDATAONADMUXBUS */
163 +};
165 +static int gpmc_cssp_init(void)
166 +{
167 +       int cs = 1; /* Chip Select on GPMC bus */
168 +       int val;
169 +       long unsigned int cssp_gpmc_mem_base_phys;
171 +       if (gpmc_cs_request(cs, SZ_16M, &cssp_gpmc_mem_base_phys) < 0) {
172 +                       printk(KERN_ERR "[cssp_cam platform init]: gpmc_cs_request failed\n");
173 +                       return -1;
174 +       }
176 +       cssp_camera_resources[0].start = cssp_gpmc_mem_base_phys;
177 +       cssp_camera_resources[0].end = cssp_gpmc_mem_base_phys + 0x1ffff;
179 +       if (gpmc_cs_configure(cs, GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NOR) < 0) {
180 +                       printk(KERN_ERR "[cssp_cam platform init]: gpmc_cs_configure failed\n");
181 +                       return -1;
182 +       }
184 +       val = GPMC_CONFIG1_READMULTIPLE_SUPP;
185 +       val |= GPMC_CONFIG1_READTYPE_SYNC;
186 +       val |= GPMC_CONFIG1_WRITETYPE_SYNC;
187 +       val |= GPMC_CONFIG1_CLKACTIVATIONTIME(1);
188 +       val |= GPMC_CONFIG1_PAGE_LEN(2);
189 +       val |= GPMC_CONFIG1_DEVICESIZE_16;
190 +       val |= GPMC_CONFIG1_DEVICETYPE_NOR;
191 +       val |= GPMC_CONFIG1_MUXADDDATA;
192 +       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, val);
194 +       if (gpmc_cs_set_timings(cs, &cssp_timings) < 0) {
195 +               printk(KERN_ERR "Failed gpmc_cs_set_timings for QuickLogic CAMIF device\n");
196 +               goto free;
197 +       }
199 +       val = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
200 +       val &= 0xe0f0f030;
201 +       val |= 0x07030481;
202 +       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, val);
204 +       printk(KERN_INFO "gpmc_cssp_init for QuickLogic CAMIF device succeeded\n");
206 +       return 0;
208 +free:
209 +       gpmc_cs_free(cs);
211 +       printk(KERN_ERR "Could not initialize QuickLogic CAMIF device\n");
213 +       return -1;
214 +}
216 +static void cssp_gpmc_init(void)
217 +{
218 +       struct gpmc_devices_info gpmc_device[2] = {
219 +                       { NULL, GPMC_DEVICE_NOR },
220 +               };
222 +       setup_pin_mux(camera_cape_pin_mux);
223 +       setup_pin_mux(gpmc_pin_mux);
225 +       omap_init_gpmc(gpmc_device, sizeof(gpmc_device));
226 +       gpmc_cssp_init();
228 +       platform_device_register(&cssp_camera);
230 +       printk(KERN_INFO "[cssp_cam platform init]: cssp_gpmc_init: DONE\n");
231 +}
234  static void lcd3leds_init(int evm_id, int profile )
235  {
236         int err;
237 @@ -2851,6 +3041,7 @@ static void beaglebone_cape_setup(struct memory_accessor *mem_acc, void *context
238         if (!strncmp("BB-BONE-CAM-01", cape_config.partnumber, 14)) {
239                 pr_info("BeagleBone cape: recognized Camera cape\n");
240                 beaglebone_w1gpio_free = 0;
241 +               cssp_gpmc_init();
242         }
243  
244         goto out2;
245 @@ -3762,15 +3953,13 @@ static struct pinmux_config clkout2_pin_mux[] = {
246  
247  static void __init clkout2_enable(void)
248  {
249 -       struct clk *ck_32;
251 -       ck_32 = clk_get(NULL, "clkout2_ck");
252 -       if (IS_ERR(ck_32)) {
253 -               pr_err("Cannot clk_get ck_32\n");
254 -               return;
255 -       }
256 +       void __iomem *base;
257 +       unsigned int val;
258  
259 -       clk_enable(ck_32);
260 +       base = ioremap(0x44E00700, SZ_4K);
261 +       val = (5 << 3) | (3 << 0); //32 MHz
262 +       writel(val, base);
263 +       iounmap(base);
264  
265         setup_pin_mux(clkout2_pin_mux);
266  }
267 diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
268 index 41c9b0f..3ef045e 100644
269 --- a/arch/arm/mach-omap2/devices.c
270 +++ b/arch/arm/mach-omap2/devices.c
271 @@ -968,7 +968,7 @@ static struct event_to_channel_map am33xx_xbar_event_mapping[] = {
272         {27, -1},
273         {28, -1},
274         {29, -1},
275 -       {30, -1},
276 +       {30, 20},       /* XDMA_EVENT_INTR2 */
277         {31, -1},
278         {-1, -1}
279  };
280 diff --git a/arch/arm/plat-omap/include/plat/dma-33xx.h b/arch/arm/plat-omap/include/plat/dma-33xx.h
281 index bebdaa7..ded00aa 100644
282 --- a/arch/arm/plat-omap/include/plat/dma-33xx.h
283 +++ b/arch/arm/plat-omap/include/plat/dma-33xx.h
284 @@ -83,5 +83,6 @@
285  #define AM33XX_DMA_PWMSS2_EPW                          63
286  #define AM33XX_DMA_MMCHS2_W                            64      /* xBar */
287  #define AM33XX_DMA_MMCHS2_R                            65      /* xBar */
288 +#define AM33XX_DMA_XDMA_EVENT_INTR2                    93      /* xBar */
289  
290  #endif
291 diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
292 index b303a3f..a31723f 100644
293 --- a/drivers/media/video/Kconfig
294 +++ b/drivers/media/video/Kconfig
295 @@ -1002,6 +1002,13 @@ config VIDEO_S5P_MIPI_CSIS
296  
297  source "drivers/media/video/s5p-tv/Kconfig"
298  
299 +config VIDEO_QL_CAMIF
300 +       tristate "QuickLogic Camera Interface support (EXPERIMENTAL)"
301 +       depends on VIDEO_DEV && SOC_CAMERA && SOC_OMAPAM33XX && EXPERIMENTAL
302 +       select VIDEOBUF2_DMA_CONTIG
303 +       ---help---
304 +         This is a v4l2 driver for the QuickLogic CAMIF controller.
306  #
307  # USB Multimedia device configuration
308  #
309 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
310 index 117f9c4..af7af692 100644
311 --- a/drivers/media/video/Makefile
312 +++ b/drivers/media/video/Makefile
313 @@ -195,6 +195,8 @@ obj-y       += davinci/
314  
315  obj-$(CONFIG_ARCH_OMAP)        += omap/
316  
317 +obj-$(CONFIG_VIDEO_QL_CAMIF)   += cssp_camera/
319  ccflags-y += -Idrivers/media/dvb/dvb-core
320  ccflags-y += -Idrivers/media/dvb/frontends
321  ccflags-y += -Idrivers/media/common/tuners
322 diff --git a/drivers/media/video/cssp_camera/Makefile b/drivers/media/video/cssp_camera/Makefile
323 new file mode 100644
324 index 0000000..d85a84e
325 --- /dev/null
326 +++ b/drivers/media/video/cssp_camera/Makefile
327 @@ -0,0 +1,3 @@
328 +# cssp_camera
330 +obj-$(CONFIG_VIDEO_QL_CAMIF) += cssp_camera.o
331 diff --git a/drivers/media/video/cssp_camera/cssp_camera.c b/drivers/media/video/cssp_camera/cssp_camera.c
332 new file mode 100644
333 index 0000000..39aa003
334 --- /dev/null
335 +++ b/drivers/media/video/cssp_camera/cssp_camera.c
336 @@ -0,0 +1,1119 @@
337 +/*
338 + * cssp-camera driver
339 + *
340 + * Based on Vivi driver
341 + *
342 + * Copyright (C) 2012 QuickLogic Corp.
343 + *
344 + * Developed for QuickLogic by:
345 + * Damian Eppel <damian.eppel@teleca.com>
346 + * Przemek Szewczyk <przemek.szewczyk@teleca.com>
347 + * Dan Aizenstros <daizenstros@quicklogic.com>
348 + *
349 + * This program is free software; you can redistribute it and/or modify
350 + * it under the terms of the GNU General Public License version 2 as
351 + * published by the Free Software Foundation.
352 + *
353 + */
356 +#include <linux/init.h>
357 +#include <linux/module.h>
358 +#include <linux/gpio.h>
359 +#include <linux/i2c.h>
360 +#include <linux/delay.h>
361 +#include <linux/spinlock.h>
362 +#include <linux/dma-mapping.h>
363 +#include <linux/interrupt.h>
364 +#include <mach/edma.h>
365 +#include <linux/clk.h>
366 +// V4L2 Interface *********************
367 +#include <media/soc_camera.h>
368 +#include <media/v4l2-mediabus.h>
369 +#include <media/videobuf2-dma-contig.h>
370 +#include <media/v4l2-ioctl.h>
371 +#include <media/v4l2-event.h>
372 +//*************************************
373 +#include "cssp_camera.h"
376 +/*
377 + * ---------------------------------------------------------------------------
378 + *  QuickLoigc Camera Interface registers
379 + * ---------------------------------------------------------------------------
380 + */
382 +#define REG_MODE               0x00000
383 +#define REG_DATA               0x10000
385 +/* MODE bit shifts */
386 +#define FMT_2X8_EN             BIT(15) /* Enable 2 byte format on CAMIF bus (0 - 10 bit, 1 - 16 bit 2x8) */
387 +#define PCLK_POL               BIT(14) /* PCLK polarity (0 - rising edge, 1 - falling edge */
388 +#define HS_EN                  BIT(13) /* High speed bus (0 =< 50 MHz, 1 > 50 MHz) */
389 +#define ENABLE                 BIT(12)
392 +static struct cssp_cam_fmt formats[] = {
393 +       {
394 +               .name   = "4:2:2, packed, YUYV",
395 +               .fourcc = V4L2_PIX_FMT_YUYV,
396 +               .depth  = 16,
397 +               .code   = V4L2_MBUS_FMT_YUYV8_2X8,
398 +       },
399 +       {
400 +               .name   = "4:2:2, packed, UYVY",
401 +               .fourcc = V4L2_PIX_FMT_UYVY,
402 +               .depth  = 16,
403 +               .code   = V4L2_MBUS_FMT_UYVY8_2X8,
404 +       },
405 +       {
406 +               .name   = "4:2:2, packed, VYUY",
407 +               .fourcc = V4L2_PIX_FMT_VYUY,
408 +               .depth  = 16,
409 +               .code   = V4L2_MBUS_FMT_VYUY8_2X8,
410 +       },
411 +       {
412 +               .name   = "4:2:2, packed, YVYU",
413 +               .fourcc = V4L2_PIX_FMT_YVYU,
414 +               .depth  = 16,
415 +               .code   = V4L2_MBUS_FMT_YVYU8_2X8,
416 +       },
417 +       {
418 +               .name   = "RGB565 (LE)",
419 +               .fourcc = V4L2_PIX_FMT_RGB565,
420 +               .depth  = 16,
421 +               .code   = V4L2_MBUS_FMT_RGB565_2X8_LE,
422 +       },
423 +       {
424 +               .name   = "RGB555 (LE)",
425 +               .fourcc = V4L2_PIX_FMT_RGB555,
426 +               .depth  = 16,
427 +               .code   = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
428 +       },
429 +};
432 +/***************************************************************************/
435 +static int configure_gpio(int nr, int val, const char *name)
436 +{
437 +       unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
438 +       int ret;
439 +       if (!gpio_is_valid(nr))
440 +               return 0;
441 +       ret = gpio_request_one(nr, flags, name);
442 +       if (!ret)
443 +               gpio_export(nr, 0);
444 +       return ret;
445 +}
447 +static int reset_cssp(struct cssp_cam_dev *cam)
448 +{
449 +       struct platform_device *pdev = cam->pdev;
450 +       int err;
452 +       cam->reset_pin = ((struct cssp_cam_platform_data *)pdev->dev.platform_data)->gpio_reset_pin;
454 +       err = configure_gpio(cam->reset_pin, 0, "cssp_reset");
455 +       if (err) {
456 +               printk(KERN_ERR "[%s]: failed to configure cssp reset pin\n", pdev->name);
457 +               return -1;
458 +       }
460 +       mdelay(1);
462 +       gpio_direction_output(cam->reset_pin, 1);
464 +       return err;
465 +}
467 +static int trigger_dma_transfer_to_buf(struct cssp_cam_dev *dev, struct vb2_buffer *vb)
468 +{
469 +       dma_addr_t dma_buf = vb2_dma_contig_plane_dma_addr(vb, 0);
471 +       if (!dma_buf) {
472 +               /* Is this possible? Release the vb2_buffer with an error here, */
473 +               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
474 +               dev->current_vb = NULL;
475 +               return -ENOMEM;
476 +       }
478 +       dev->dma_tr_params.dst = dma_buf;
480 +       // Enable DMA
481 +       edma_write_slot(dev->dma_ch, &dev->dma_tr_params);
483 +       // Enable data capture
484 +       dev->mode |= ENABLE;
485 +       writew(dev->mode, dev->reg_base_virt + REG_MODE);
486 +       readw(dev->reg_base_virt + REG_MODE);
488 +       dev->current_vb = vb;
490 +       return 0;
491 +}
493 +static void dequeue_buffer_for_dma(struct cssp_cam_dev *dev)
494 +{
495 +       struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
496 +       unsigned long flags = 0;
498 +       spin_lock_irqsave(&dev->slock, flags);
499 +       if (!list_empty(&dma_q->active)) {
500 +               struct cssp_cam_buffer *buf;
502 +               buf = list_entry(dma_q->active.next, struct cssp_cam_buffer, list);
503 +               list_del(&buf->list);
504 +               spin_unlock_irqrestore(&dev->slock, flags);
506 +               buf->fmt = dev->fmt;
508 +               trigger_dma_transfer_to_buf(dev, &buf->vb);
509 +       } else {
510 +               spin_unlock_irqrestore(&dev->slock, flags);
511 +       }
512 +}
514 +static void dma_callback(unsigned lch, u16 ch_status, void *data)
515 +{
516 +       struct cssp_cam_dev *dev = (struct cssp_cam_dev *)data;
518 +       // Disable data capture
519 +       dev->mode &= ~ENABLE;
520 +       writew(dev->mode, dev->reg_base_virt + REG_MODE);
521 +       readw(dev->reg_base_virt + REG_MODE);
523 +       if (ch_status == DMA_COMPLETE) {
524 +               struct vb2_buffer *vb = dev->current_vb;
525 +               struct timeval ts;
527 +               vb->v4l2_buf.field = dev->field;
528 +               dev->field_count++;
529 +               vb->v4l2_buf.sequence = dev->field_count >> 1;
530 +               do_gettimeofday(&ts);
531 +               vb->v4l2_buf.timestamp = ts;
532 +               vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
533 +               dev->current_vb = NULL;
534 +               dev->frame_cnt++;
536 +               /* check if we have new buffer queued */
537 +               dequeue_buffer_for_dma(dev);
538 +       } else {
539 +               printk(KERN_ERR "[cssp_camera]: EDMA error (ch_status = %d)\n", ch_status);
540 +               /* we got a missed interrupt so just start a new DMA with the existing buffer */
541 +               if (dev->current_vb != NULL)
542 +                       trigger_dma_transfer_to_buf(dev, dev->current_vb);
543 +       }
544 +}
546 +static int configure_edma(struct cssp_cam_dev *cam)
547 +{
548 +       struct platform_device *pdev = cam->pdev;
549 +       int dma_channel;
551 +       dma_channel = ((struct cssp_cam_platform_data *)pdev->dev.platform_data)->dma_ch;
553 +       pdev->dev.dma_mask = &cam->dma_mask;
555 +       pdev->dev.coherent_dma_mask = (u32)~0;
557 +       if (dma_set_mask(&pdev->dev, (u32)~0)) {
558 +               printk(KERN_ERR "[%s]: failed setting mask for DMA\n", pdev->name);
559 +               return -1;
560 +       }
562 +       cam->dma_ch = edma_alloc_channel(dma_channel, dma_callback, cam, EVENTQ_1);
563 +       if (cam->dma_ch < 0) {
564 +               printk(KERN_ERR "[%s]: allocating channel for DMA failed\n", pdev->name);
565 +               return -EBUSY;
566 +       } else {
567 +               printk(KERN_ERR "[%s]: allocating channel for DMA succeeded, chan=%d\n", pdev->name, cam->dma_ch);
568 +       }
570 +       cam->dma_tr_params.opt = TCINTEN | TCC(cam->dma_ch);
571 +       cam->dma_tr_params.src = cam->reg_base_phys + REG_DATA;
572 +       cam->dma_tr_params.a_b_cnt = ACNT(BYTES_PER_DMA_EVT) | BCNT((VGA_WIDTH * BYTES_PER_PIXEL) / BYTES_PER_DMA_EVT);
573 +       cam->dma_tr_params.src_dst_bidx = SRCBIDX(0) | DSTBIDX(BYTES_PER_DMA_EVT);
574 +       cam->dma_tr_params.link_bcntrld = BCNTRLD((VGA_WIDTH * BYTES_PER_PIXEL) / BYTES_PER_DMA_EVT) | LINK(0xffff);
575 +       cam->dma_tr_params.src_dst_cidx = SRCCIDX(0) | DSTCIDX(BYTES_PER_DMA_EVT);
576 +       cam->dma_tr_params.ccnt = CCNT(VGA_HEIGHT);
578 +       return 0;
579 +}
581 +static int configure_cssp(struct cssp_cam_dev *cam)
582 +{
583 +       struct platform_device *pdev = cam->pdev;
584 +       int ret = 0;
585 +       unsigned int val;
586 +       struct resource *res;
588 +       ret = reset_cssp(cam);
589 +       if (ret)
590 +               return ret;
592 +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpmc_phys_mem_slot");
593 +       if (res == NULL) {
594 +               printk(KERN_ERR "[%s]: failed to get gpmc_phys_mem_slot resource\n", pdev->name);
595 +               return -ENODEV;
596 +       }
598 +       /*
599 +        * Request the region.
600 +        */
601 +       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
602 +               return -EBUSY;
603 +       }
605 +       cam->reg_base_phys = res->start;
606 +       cam->reg_size = resource_size(res);
608 +       cam->reg_base_virt = (unsigned int)ioremap(cam->reg_base_phys, cam->reg_size);
609 +       if (cam->reg_base_virt == 0) {
610 +               printk(KERN_ERR "[%s]: ioremap of registers region failed\n", pdev->name);
611 +               release_mem_region(cam->reg_base_phys, cam->reg_size);
612 +               return -ENOMEM;
613 +       }
615 +       printk(KERN_INFO "[%s]: reg_base_virt = 0x%x\n", pdev->name, cam->reg_base_virt);
617 +       val = readw(cam->reg_base_virt + REG_MODE);
618 +       printk(KERN_INFO "[%s]: reading register address=0x0 returns 0x%x\n", pdev->name, val);
620 +       return 0;
621 +}
623 +static int configure_camera_sensor(struct cssp_cam_dev *cam)
624 +{
625 +       struct i2c_board_info *info = cam->camera_board_info;
626 +       struct i2c_client *client;
627 +       struct i2c_adapter *adapter;
628 +       struct v4l2_subdev *subdev;
629 +       struct v4l2_mbus_framefmt f_format = {
630 +                       .width = VGA_WIDTH,
631 +                       .height = VGA_HEIGHT,
632 +                       .code = V4L2_MBUS_FMT_YUYV8_2X8,
633 +                       .colorspace = V4L2_COLORSPACE_JPEG,
634 +       };
636 +       /* Enable the clock just for the time of loading the camera driver and disable after that */
637 +       /* It is going to be be re-enabled later, when camera will be in use */
638 +       clk_enable(cam->camera_clk);
639 +       udelay(5); // let the clock stabilize
641 +       adapter = i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
642 +       if (!adapter) {
643 +               printk(KERN_INFO "[%s]: failed to get adapter...\n", __func__);
644 +               return -ENODEV;
645 +       }
647 +       client = i2c_new_device(adapter, info);
648 +       i2c_put_adapter(adapter);
650 +       if (client == NULL) {
651 +               return -ENODEV;
652 +       }
654 +       printk(KERN_INFO "[%s]: client's name is: %s\n", __func__, client->name);
656 +       subdev = (struct v4l2_subdev *)i2c_get_clientdata(client);
657 +       if (subdev == NULL) {
658 +               i2c_unregister_device(client);
659 +               return -ENODEV;
660 +       }
662 +       cam->subdev = subdev;
664 +       v4l2_subdev_call(subdev, video, s_mbus_fmt, &f_format);
666 +       clk_disable(cam->camera_clk);
668 +       return 0;
669 +}
671 +static int start_camera_sensor(struct cssp_cam_dev *cam)
672 +{
673 +       clk_enable(cam->camera_clk);
674 +       udelay(5); /* let the clock stabilize */
676 +       v4l2_subdev_call(cam->subdev, video, s_stream, 1);
678 +       return 0;
679 +}
681 +static void stop_camera_sensor(struct cssp_cam_dev *cam)
682 +{
683 +       v4l2_subdev_call(cam->subdev, video, s_stream, 0);
685 +       clk_disable(cam->camera_clk);
687 +       return;
688 +}
691 +/************************************************
692 + *                             Video4Linux2
693 + */
695 +static struct cssp_cam_fmt *get_format(struct v4l2_format *f)
696 +{
697 +       struct cssp_cam_fmt *fmt;
698 +       unsigned int k;
700 +       for (k = 0; k < ARRAY_SIZE(formats); k++) {
701 +               fmt = &formats[k];
702 +               if (fmt->fourcc == f->fmt.pix.pixelformat)
703 +                       break;
704 +       }
706 +       if (k == ARRAY_SIZE(formats))
707 +               return NULL;
709 +       return &formats[k];
710 +}
713 +/* ------------------------------------------------------------------
714 +       Videobuf operations
715 +   ------------------------------------------------------------------*/
717 +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
718 +                               unsigned int *nbuffers, unsigned int *nplanes,
719 +                               unsigned int sizes[], void *alloc_ctxs[])
720 +{
721 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
722 +       unsigned long size;
724 +       size = dev->sizeimage;
726 +       if (0 == *nbuffers)
727 +               *nbuffers = 32;
729 +       while (size * *nbuffers > vid_limit * 1024 * 1024)
730 +               (*nbuffers)--;
732 +       *nplanes = 1;
734 +       sizes[0] = size;
736 +       alloc_ctxs[0] = dev->dma_cont_ctx;
738 +       dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__, *nbuffers, size);
740 +       return 0;
741 +}
743 +static int buffer_init(struct vb2_buffer *vb)
744 +{
745 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
747 +       BUG_ON(NULL == dev->fmt);
749 +       /*
750 +        * This callback is called once per buffer, after its allocation.
751 +        *
752 +        * Vivi does not allow changing format during streaming, but it is
753 +        * possible to do so when streaming is paused (i.e. in streamoff state).
754 +        * Buffers however are not freed when going into streamoff and so
755 +        * buffer size verification has to be done in buffer_prepare, on each
756 +        * qbuf.
757 +        * It would be best to move verification code here to buf_init and
758 +        * s_fmt though.
759 +        */
761 +       return 0;
762 +}
764 +static int buffer_prepare(struct vb2_buffer *vb)
765 +{
766 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
767 +       struct cssp_cam_buffer *buf = container_of(vb, struct cssp_cam_buffer, vb);
768 +       unsigned long size;
770 +       dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
772 +       BUG_ON(NULL == dev->fmt);
774 +       /*
775 +        * Theses properties only change when queue is idle, see s_fmt.
776 +        * The below checks should not be performed here, on each
777 +        * buffer_prepare (i.e. on each qbuf). Most of the code in this function
778 +        * should thus be moved to buffer_init and s_fmt.
779 +        */
780 +       if (dev->width  < 48 || dev->width  > MAX_WIDTH ||
781 +           dev->height < 32 || dev->height > MAX_HEIGHT)
782 +               return -EINVAL;
784 +       size = dev->sizeimage;
785 +       if (vb2_plane_size(vb, 0) < size) {
786 +               dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
787 +                               __func__, vb2_plane_size(vb, 0), size);
788 +               return -EINVAL;
789 +       }
791 +       vb2_set_plane_payload(&buf->vb, 0, size);
793 +       buf->fmt = dev->fmt;
795 +       return 0;
796 +}
798 +static int buffer_finish(struct vb2_buffer *vb)
799 +{
800 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
801 +       dprintk(dev, 1, "%s\n", __func__);
802 +       return 0;
803 +}
805 +static void buffer_cleanup(struct vb2_buffer *vb)
806 +{
807 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
808 +       dprintk(dev, 1, "%s\n", __func__);
809 +}
811 +static void buffer_queue(struct vb2_buffer *vb)
812 +{
813 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
814 +       struct cssp_cam_buffer *buf = container_of(vb, struct cssp_cam_buffer, vb);
815 +       struct cssp_cam_dmaqueue *vidq = &dev->vidq;
816 +       unsigned long flags = 0;
818 +       dprintk(dev, 1, "%s\n", __func__);
820 +       if (dev->streaming_started && !dev->current_vb) {
821 +               trigger_dma_transfer_to_buf(dev, &buf->vb);
822 +       } else {
823 +               spin_lock_irqsave(&dev->slock, flags);
824 +               list_add_tail(&buf->list, &vidq->active);
825 +               spin_unlock_irqrestore(&dev->slock, flags);
826 +       }
827 +}
829 +static int start_streaming(struct vb2_queue *vq, unsigned int count)
830 +{
831 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
832 +       int ret;
834 +       dprintk(dev, 1, "%s\n", __func__);
836 +       ret = start_camera_sensor(dev);
837 +       if (ret != 0)
838 +               return ret;
840 +       // Enable DMA
841 +       edma_start(dev->dma_ch);
843 +       dev->streaming_started = 1;
845 +       /* check if we have new buffer queued */
846 +       dequeue_buffer_for_dma(dev);
848 +       return 0;
849 +}
851 +/* abort streaming and wait for last buffer */
852 +static int stop_streaming(struct vb2_queue *vq)
853 +{
854 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
855 +       struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
857 +       dprintk(dev, 1, "%s\n", __func__);
859 +       // Disable DMA
860 +       edma_stop(dev->dma_ch);
862 +       // Disable data capture
863 +       dev->mode &= ~ENABLE;
864 +       writew(dev->mode, dev->reg_base_virt + REG_MODE);
865 +       readw(dev->reg_base_virt + REG_MODE);
867 +       stop_camera_sensor(dev);
869 +       dev->streaming_started = 0;
871 +       /* Release all active buffers */
872 +       while (!list_empty(&dma_q->active)) {
873 +               struct cssp_cam_buffer *buf;
875 +               buf = list_entry(dma_q->active.next, struct cssp_cam_buffer, list);
876 +               list_del(&buf->list);
877 +               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
878 +               dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
879 +       }
881 +       dev->current_vb = NULL;
883 +       return 0;
884 +}
886 +static void cssp_cam_lock(struct vb2_queue *vq)
887 +{
888 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
889 +       mutex_lock(&dev->mutex);
890 +}
892 +static void cssp_cam_unlock(struct vb2_queue *vq)
893 +{
894 +       struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
895 +       mutex_unlock(&dev->mutex);
896 +}
898 +static struct vb2_ops cssp_cam_video_qops = {
899 +       .queue_setup            = queue_setup,
900 +       .buf_init               = buffer_init,
901 +       .buf_prepare            = buffer_prepare,
902 +       .buf_finish             = buffer_finish,
903 +       .buf_cleanup            = buffer_cleanup,
904 +       .buf_queue              = buffer_queue,
905 +       .start_streaming        = start_streaming,
906 +       .stop_streaming         = stop_streaming,
907 +       .wait_prepare           = cssp_cam_unlock,
908 +       .wait_finish            = cssp_cam_lock,
909 +};
912 +/* ------------------------------------------------------------------
913 +       IOCTL vidioc handling
914 +   ------------------------------------------------------------------*/
916 +static int vidioc_querycap(struct file *file, void *priv,
917 +                                       struct v4l2_capability *cap)
918 +{
919 +       struct cssp_cam_dev *dev = video_drvdata(file);
921 +       strcpy(cap->driver, "cssp_camera");
922 +       strcpy(cap->card, "cssp_camera");
923 +       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
924 +       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
925 +                           V4L2_CAP_READWRITE;
926 +       return 0;
927 +}
929 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
930 +                                       struct v4l2_fmtdesc *f)
931 +{
932 +       struct cssp_cam_fmt *fmt;
934 +       if (f->index >= ARRAY_SIZE(formats))
935 +               return -EINVAL;
937 +       fmt = &formats[f->index];
939 +       strlcpy(f->description, fmt->name, sizeof(f->description));
940 +       f->pixelformat = fmt->fourcc;
941 +       return 0;
942 +}
944 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
945 +                                       struct v4l2_format *f)
946 +{
947 +       struct cssp_cam_dev *dev = video_drvdata(file);
949 +       f->fmt.pix.width        = dev->width;
950 +       f->fmt.pix.height       = dev->height;
951 +       f->fmt.pix.field        = dev->field;
952 +       f->fmt.pix.pixelformat  = dev->fmt->fourcc;
953 +       f->fmt.pix.bytesperline = dev->bytesperline;
954 +       f->fmt.pix.sizeimage    = dev->sizeimage;
955 +       f->fmt.pix.colorspace   = dev->colorspace;
957 +       return 0;
958 +}
960 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
961 +                       struct v4l2_format *f)
962 +{
963 +       struct cssp_cam_dev *dev = video_drvdata(file);
964 +       struct cssp_cam_fmt *fmt;
965 +       struct v4l2_mbus_framefmt mbus_fmt;
966 +       struct v4l2_pix_format *pix = &f->fmt.pix;
968 +       fmt = get_format(f);
969 +       if (!fmt) {
970 +               dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
971 +                       f->fmt.pix.pixelformat);
972 +               return -EINVAL;
973 +       }
975 +       v4l2_fill_mbus_format(&mbus_fmt, pix, fmt->code);
976 +       v4l2_subdev_call(dev->subdev, video, try_mbus_fmt, &mbus_fmt);
977 +       v4l2_fill_pix_format(pix, &mbus_fmt);
978 +       pix->bytesperline = (pix->width * fmt->depth) >> 3;
979 +       pix->sizeimage = pix->height * pix->bytesperline;
981 +       return 0;
982 +}
984 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
985 +                                       struct v4l2_format *f)
986 +{
987 +       struct cssp_cam_dev *dev = video_drvdata(file);
988 +       struct vb2_queue *q = &dev->vb_vidq;
989 +       struct v4l2_pix_format *pix = &f->fmt.pix;
990 +       struct v4l2_mbus_framefmt mbus_fmt;
992 +       int ret = vidioc_try_fmt_vid_cap(file, priv, f);
993 +       if (ret < 0)
994 +               return ret;
996 +       if (vb2_is_streaming(q)) {
997 +               dprintk(dev, 1, "%s device busy\n", __func__);
998 +               return -EBUSY;
999 +       }
1001 +       dev->fmt = get_format(f);
1002 +       dev->width = f->fmt.pix.width;
1003 +       dev->height = f->fmt.pix.height;
1004 +       dev->field = f->fmt.pix.field;
1005 +       dev->colorspace = f->fmt.pix.colorspace;
1006 +       dev->bytesperline = f->fmt.pix.bytesperline;
1007 +       dev->sizeimage = f->fmt.pix.sizeimage;
1009 +       /* Set the sensor into the new format */
1010 +       v4l2_fill_mbus_format(&mbus_fmt, pix, dev->fmt->code);
1011 +       v4l2_subdev_call(dev->subdev, video, s_mbus_fmt, &mbus_fmt);
1013 +       /* Set the EDMA for the new resolution */
1014 +       dev->dma_tr_params.a_b_cnt = ACNT(BYTES_PER_DMA_EVT) | BCNT(dev->bytesperline / BYTES_PER_DMA_EVT);
1015 +       dev->dma_tr_params.link_bcntrld = BCNTRLD(dev->bytesperline / BYTES_PER_DMA_EVT) | LINK(0xffff);
1016 +       dev->dma_tr_params.ccnt = CCNT(dev->height);
1018 +       return 0;
1019 +}
1021 +static int vidioc_reqbufs(struct file *file, void *priv,
1022 +                         struct v4l2_requestbuffers *p)
1023 +{
1024 +       struct cssp_cam_dev *dev = video_drvdata(file);
1025 +       return vb2_reqbufs(&dev->vb_vidq, p);
1026 +}
1028 +static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
1029 +{
1030 +       struct cssp_cam_dev *dev = video_drvdata(file);
1031 +       return vb2_querybuf(&dev->vb_vidq, p);
1032 +}
1034 +static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
1035 +{
1036 +       struct cssp_cam_dev *dev = video_drvdata(file);
1037 +       return vb2_qbuf(&dev->vb_vidq, p);
1038 +}
1040 +static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
1041 +{
1042 +       struct cssp_cam_dev *dev = video_drvdata(file);
1043 +       return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
1044 +}
1046 +static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1047 +{
1048 +       struct cssp_cam_dev *dev = video_drvdata(file);
1049 +       return vb2_streamon(&dev->vb_vidq, i);
1050 +}
1052 +static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1053 +{
1054 +       struct cssp_cam_dev *dev = video_drvdata(file);
1055 +       return vb2_streamoff(&dev->vb_vidq, i);
1056 +}
1058 +static int vidioc_log_status(struct file *file, void *priv)
1059 +{
1060 +       struct cssp_cam_dev *dev = video_drvdata(file);
1062 +       v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
1063 +       return 0;
1064 +}
1066 +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
1067 +{
1068 +       return 0;
1069 +}
1071 +/* only one input in this sample driver */
1072 +static int vidioc_enum_input(struct file *file, void *priv,
1073 +                               struct v4l2_input *inp)
1074 +{
1075 +       return -EINVAL;
1077 +       inp->type = V4L2_INPUT_TYPE_CAMERA;
1078 +       inp->std = V4L2_STD_525_60;
1079 +       sprintf(inp->name, "Camera %u", inp->index);
1080 +       return 0;
1081 +}
1083 +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1084 +{
1085 +       struct cssp_cam_dev *dev = video_drvdata(file);
1087 +       *i = dev->input;
1089 +       return 0;
1090 +}
1092 +static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1093 +{
1094 +       struct cssp_cam_dev *dev = video_drvdata(file);
1096 +       return -EINVAL;
1098 +       if (i == dev->input)
1099 +               return 0;
1101 +       dev->input = i;
1103 +       return 0;
1104 +}
1106 +static int vidioc_subscribe_event(struct v4l2_fh *fh,
1107 +                               struct v4l2_event_subscription *sub)
1108 +{
1109 +       switch (sub->type) {
1110 +       case V4L2_EVENT_CTRL:
1111 +               return v4l2_event_subscribe(fh, sub, 0);
1112 +       default:
1113 +               return -EINVAL;
1114 +       }
1115 +}
1117 +static const struct v4l2_ioctl_ops cssp_cam_ioctl_ops = {
1118 +       .vidioc_querycap                = vidioc_querycap,
1119 +       .vidioc_enum_fmt_vid_cap        = vidioc_enum_fmt_vid_cap,
1120 +       .vidioc_g_fmt_vid_cap           = vidioc_g_fmt_vid_cap,
1121 +       .vidioc_try_fmt_vid_cap         = vidioc_try_fmt_vid_cap,
1122 +       .vidioc_s_fmt_vid_cap           = vidioc_s_fmt_vid_cap,
1123 +       .vidioc_reqbufs                 = vidioc_reqbufs,
1124 +       .vidioc_querybuf                = vidioc_querybuf,
1125 +       .vidioc_qbuf                    = vidioc_qbuf,
1126 +       .vidioc_dqbuf                   = vidioc_dqbuf,
1127 +       .vidioc_s_std                   = vidioc_s_std,
1128 +       .vidioc_enum_input              = vidioc_enum_input,
1129 +       .vidioc_g_input                 = vidioc_g_input,
1130 +       .vidioc_s_input                 = vidioc_s_input,
1131 +       .vidioc_streamon                = vidioc_streamon,
1132 +       .vidioc_streamoff               = vidioc_streamoff,
1133 +       .vidioc_log_status              = vidioc_log_status,
1134 +       .vidioc_subscribe_event         = vidioc_subscribe_event,
1135 +       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
1136 +};
1139 +/* ------------------------------------------------------------------
1140 +       File operations
1141 +   ------------------------------------------------------------------*/
1143 +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
1144 +{
1145 +       struct cssp_cam_dev *dev = video_drvdata(file);
1146 +       struct v4l2_fh *fh = file->private_data;
1147 +       struct vb2_queue *q = &dev->vb_vidq;
1148 +       unsigned int res;
1150 +       dprintk(dev, 1, "%s\n", __func__);
1151 +       res = vb2_poll(q, file, wait);
1152 +       if (v4l2_event_pending(fh))
1153 +               res |= POLLPRI;
1154 +       else
1155 +               poll_wait(file, &fh->wait, wait);
1156 +       return res;
1157 +}
1159 +static int video_mmap(struct file *file, struct vm_area_struct *vma)
1160 +{
1161 +       struct cssp_cam_dev *dev = video_drvdata(file);
1162 +       int ret;
1164 +       dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
1166 +       ret = vb2_mmap(&dev->vb_vidq, vma);
1167 +       dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
1168 +               (unsigned long)vma->vm_start,
1169 +               (unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
1170 +               ret);
1171 +       return ret;
1172 +}
1174 +static ssize_t video_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
1175 +{
1176 +       struct cssp_cam_dev *cam_dev = video_drvdata(file);
1178 +       dprintk(cam_dev, 1, "read called\n");
1179 +       return vb2_read(&cam_dev->vb_vidq, buf, size, offset, file->f_flags & O_NONBLOCK);
1180 +}
1182 +static int video_close(struct file *file)
1183 +{
1184 +       struct video_device *vdev = video_devdata(file);
1185 +       struct cssp_cam_dev *cam_dev = video_drvdata(file);
1187 +       dprintk(cam_dev, 1, "close called (dev=%s), file %p\n",
1188 +               video_device_node_name(vdev), file);
1190 +       if (v4l2_fh_is_singular_file(file))
1191 +               vb2_queue_release(&cam_dev->vb_vidq);
1192 +       return v4l2_fh_release(file);
1193 +}
1195 +static const struct v4l2_file_operations cssp_cam_fops = {
1196 +       .owner          = THIS_MODULE,
1197 +       .open           = v4l2_fh_open,
1198 +       .release        = video_close,
1199 +       .read           = video_read,
1200 +       .poll           = video_poll,
1201 +       .unlocked_ioctl = video_ioctl2,
1202 +       .mmap           = video_mmap,
1203 +};
1206 +/* ------------------------------------------------------------------
1207 +       Driver initialization
1208 +   ------------------------------------------------------------------*/
1210 +static struct video_device cssp_cam_template = {
1211 +       .name           = "cssp_camera",
1212 +       .fops           = &cssp_cam_fops,
1213 +       .ioctl_ops      = &cssp_cam_ioctl_ops,
1214 +       .minor          = -1,
1215 +       .release        = video_device_release,
1216 +       .tvnorms        = V4L2_STD_525_60,
1217 +       .current_norm   = V4L2_STD_NTSC_M,
1218 +};
1220 +static int __init  video_probe(struct cssp_cam_dev *cam_dev)
1221 +{
1222 +       struct video_device *vfd;
1223 +       struct v4l2_ctrl_handler *hdl;
1224 +       struct vb2_queue *q;
1225 +       int ret = 0;
1227 +       snprintf(cam_dev->v4l2_dev.name, sizeof(cam_dev->v4l2_dev.name),
1228 +                       "%s-%03d", "cssp_camera", 0);
1229 +       ret = v4l2_device_register(NULL, &cam_dev->v4l2_dev);
1230 +       if (ret)
1231 +               goto free_dev;
1233 +       cam_dev->fmt = &formats[0];
1234 +       cam_dev->width = VGA_WIDTH;
1235 +       cam_dev->height = VGA_HEIGHT;
1236 +       cam_dev->sizeimage = VGA_WIDTH * VGA_HEIGHT * BYTES_PER_PIXEL;
1237 +       hdl = &cam_dev->ctrl_handler;
1238 +       v4l2_ctrl_handler_init(hdl, 0);
1240 +       if (hdl->error) {
1241 +               ret = hdl->error;
1242 +               goto unreg_dev;
1243 +       }
1244 +       cam_dev->v4l2_dev.ctrl_handler = hdl;
1246 +       /* initialize locks */
1247 +       spin_lock_init(&cam_dev->slock);
1249 +       /* initialize queue */
1250 +       q = &cam_dev->vb_vidq;
1251 +       memset(q, 0, sizeof(cam_dev->vb_vidq));
1252 +       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1253 +       q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1254 +       q->drv_priv = cam_dev;
1255 +       q->buf_struct_size = sizeof(struct cssp_cam_buffer);
1256 +       q->ops = &cssp_cam_video_qops;
1257 +       q->mem_ops = &vb2_dma_contig_memops;
1259 +       vb2_queue_init(q);
1261 +       mutex_init(&cam_dev->mutex);
1263 +       /* init video dma queues */
1264 +       INIT_LIST_HEAD(&cam_dev->vidq.active);
1266 +       ret = -ENOMEM;
1267 +       vfd = video_device_alloc();
1268 +       if (!vfd)
1269 +               goto unreg_dev;
1271 +       *vfd = cssp_cam_template;
1272 +       vfd->debug = debug;
1273 +       vfd->v4l2_dev = &cam_dev->v4l2_dev;
1274 +       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
1276 +       /*
1277 +        * Provide a mutex to v4l2 core. It will be used to protect
1278 +        * all fops and v4l2 ioctls.
1279 +        */
1280 +       vfd->lock = &cam_dev->mutex;
1282 +       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
1283 +       if (ret < 0)
1284 +               goto rel_vdev;
1286 +       video_set_drvdata(vfd, cam_dev);
1288 +       if (video_nr != -1)
1289 +               video_nr++;
1291 +       cam_dev->vdev = vfd;
1292 +       v4l2_info(&cam_dev->v4l2_dev, "V4L2 device registered as %s\n",
1293 +       video_device_node_name(vfd));
1295 +       return 0;
1297 +rel_vdev:
1298 +       video_device_release(vfd);
1299 +unreg_dev:
1300 +       v4l2_ctrl_handler_free(hdl);
1301 +       v4l2_device_unregister(&cam_dev->v4l2_dev);
1302 +free_dev:
1303 +       return ret;
1304 +}
1306 +static int video_remove(struct cssp_cam_dev *cam_dev)
1307 +{
1308 +       if (cam_dev->dma_cont_ctx != NULL)
1309 +               vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
1311 +       v4l2_info(&cam_dev->v4l2_dev, "unregistering %s\n",
1312 +                       video_device_node_name(cam_dev->vdev));
1313 +       video_unregister_device(cam_dev->vdev);
1314 +       v4l2_device_unregister(&cam_dev->v4l2_dev);
1315 +       v4l2_ctrl_handler_free(&cam_dev->ctrl_handler);
1317 +       return 0;
1318 +}
1320 +static int __init  cssp_cam_probe(struct platform_device *pdev)
1321 +{
1322 +       struct cssp_cam_dev *cam_dev;
1323 +       int ret = 0;
1324 +       struct cssp_cam_platform_data *cssp_cam_platform_data;
1326 +       cssp_cam_platform_data = (struct cssp_cam_platform_data *) pdev->dev.platform_data;
1327 +       if (cssp_cam_platform_data == NULL) {
1328 +               printk(KERN_ERR "[%s]: missing platform data\n", pdev->name);
1329 +               return -ENODEV;
1330 +       }
1332 +       if (cssp_cam_platform_data->cam_i2c_board_info == NULL) {
1333 +               printk(KERN_ERR "[%s]: missing camera i2c board info\n", pdev->name);
1334 +               return -ENODEV;
1335 +       }
1337 +       cam_dev = kzalloc(sizeof(*cam_dev), GFP_KERNEL);
1338 +       if (!cam_dev)
1339 +               return -ENOMEM;
1341 +       cam_dev->pdev = pdev;
1342 +       platform_set_drvdata(pdev, cam_dev);
1344 +       cam_dev->camera_board_info = cssp_cam_platform_data->cam_i2c_board_info;
1346 +       cam_dev->camera_clk = clk_get(&pdev->dev, cssp_cam_platform_data->cam_clk_name);
1347 +       if (IS_ERR(cam_dev->camera_clk)) {
1348 +               ret = PTR_ERR(cam_dev->camera_clk);
1349 +               printk(KERN_ERR "[%s]: cannot clk_get %s\n", pdev->name, cssp_cam_platform_data->cam_clk_name);
1350 +               goto fail0;
1351 +       }
1353 +       ret = configure_cssp(cam_dev);
1354 +       if (ret)
1355 +               goto fail1;
1357 +       ret = configure_edma(cam_dev);
1358 +       if (ret)
1359 +               goto fail2;
1361 +       cam_dev->mode = FMT_2X8_EN | PCLK_POL | HS_EN;
1363 +       ret = configure_camera_sensor(cam_dev);
1364 +       if (ret) {
1365 +               printk(KERN_ERR "[%s]: camera sensor configuration failed\n", pdev->name);
1366 +               goto fail3;
1367 +       }
1369 +       cam_dev->dma_cont_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1370 +       if (IS_ERR(cam_dev->dma_cont_ctx)) {
1371 +               ret = PTR_ERR(cam_dev->dma_cont_ctx);
1372 +               goto fail3;
1373 +       }
1375 +       ret = video_probe(cam_dev);
1376 +       if (ret)
1377 +               goto fail4;
1379 +       return ret;
1381 +fail4:
1382 +       vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
1384 +fail3:
1385 +       edma_free_channel(cam_dev->dma_ch);
1387 +fail2:
1388 +       gpio_free(cam_dev->reset_pin);
1389 +       iounmap((void *)cam_dev->reg_base_virt);
1390 +       release_mem_region(cam_dev->reg_base_phys, cam_dev->reg_size);
1392 +fail1:
1393 +       clk_put(cam_dev->camera_clk);
1395 +fail0:
1396 +       kfree(cam_dev);
1398 +       return ret;
1399 +}
1401 +static int cssp_cam_remove(struct platform_device *pdev)
1402 +{
1403 +       struct cssp_cam_dev *cam = platform_get_drvdata(pdev);
1405 +       iounmap((void *)cam->reg_base_virt);
1407 +       release_mem_region(cam->reg_base_phys, cam->reg_size);
1409 +       gpio_free(cam->reset_pin);
1411 +       edma_free_channel(cam->dma_ch);
1413 +       video_remove(cam);
1415 +       clk_put(cam->camera_clk);
1417 +       kfree(cam);
1419 +       printk(KERN_INFO "[%s]: removed\n", pdev->name);
1421 +       return 0;
1422 +}
1425 +static struct platform_driver cssp_cam_driver = {
1426 +       .probe          = cssp_cam_probe,
1427 +       .remove         = __devexit_p(cssp_cam_remove),
1428 +       .driver         = {
1429 +               .name   = "cssp-camera",
1430 +               .owner  = THIS_MODULE,
1431 +       },
1432 +};
1435 +static int __init cssp_cam_init(void)
1436 +{
1437 +       return platform_driver_register(&cssp_cam_driver);
1438 +}
1440 +static void __exit cssp_cam_exit(void)
1441 +{
1442 +       platform_driver_unregister(&cssp_cam_driver);
1443 +}
1446 +module_init(cssp_cam_init);
1447 +module_exit(cssp_cam_exit);
1449 +/*
1450 + * Macros sets license, author and description
1451 + */
1452 +MODULE_LICENSE("GPLv2");
1453 +MODULE_AUTHOR("Dan Aizenstros, Damian Eppel, Przemek Szewczyk");
1454 +MODULE_DESCRIPTION("QuickLogic Camera Interface driver");
1456 diff --git a/drivers/media/video/cssp_camera/cssp_camera.h b/drivers/media/video/cssp_camera/cssp_camera.h
1457 new file mode 100644
1458 index 0000000..d018ca1
1459 --- /dev/null
1460 +++ b/drivers/media/video/cssp_camera/cssp_camera.h
1461 @@ -0,0 +1,148 @@
1462 +/*
1463 + * cssp-camera driver
1464 + *
1465 + * Based on Vivi driver
1466 + *
1467 + * Copyright (C) 2012 QuickLogic Corp.
1468 + *
1469 + * Developed for QuickLogic by:
1470 + * Damian Eppel <damian.eppel@teleca.com>
1471 + * Przemek Szewczyk <przemek.szewczyk@teleca.com>
1472 + * Dan Aizenstros <daizenstros@quicklogic.com>
1473 + *
1474 + * This program is free software; you can redistribute it and/or modify
1475 + * it under the terms of the GNU General Public License version 2 as
1476 + * published by the Free Software Foundation.
1477 + *
1478 + */
1480 +#ifndef CSSP_CAMERA_H
1481 +#define CSSP_CAMERA_H
1484 +static unsigned video_nr = -1;
1485 +module_param(video_nr, uint, 0644);
1486 +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
1488 +static unsigned debug;
1489 +module_param(debug, uint, 0644);
1490 +MODULE_PARM_DESC(debug, "activates debug info");
1492 +static unsigned int vid_limit = 1;
1493 +module_param(vid_limit, uint, 0644);
1494 +MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
1496 +#define dprintk(dev, level, fmt, arg...) \
1497 +       v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
1499 +#define VGA_WIDTH 640
1500 +#define VGA_HEIGHT 480
1502 +#define MAX_WIDTH 2048
1503 +#define MAX_HEIGHT 1536
1505 +#define VGA_RES (VGA_WIDTH * VGA_HEIGHT)
1506 +#define BYTES_PER_PIXEL 2
1507 +#define BYTES_PER_DMA_EVT 32
1509 +/* PaRAM.opt: */
1510 +#define TCC(v) (((v) & 0x3f) << 12)
1511 +/* PaRAM.a_b_cnt: */
1512 +#define ACNT(v) ((v) & 0xffff)
1513 +#define BCNT(v) (((v) & 0xffff) << 16)
1514 +/* PaRAM.src_dst_bidx: */
1515 +#define SRCBIDX(v) ((v) & 0xffff)
1516 +#define DSTBIDX(v) (((v) & 0xffff) << 16)
1517 +/* PaRAM.link_bcntrld: */
1518 +#define LINK(v) ((v) & 0xffff)
1519 +#define BCNTRLD(v) (((v) & 0xffff) << 16)
1520 +/* PaRAM.src_dst_cidx: */
1521 +#define SRCCIDX(v) ((v) & 0xffff)
1522 +#define DSTCIDX(v) (((v) & 0xffff) << 16)
1523 +/* PaRAM.ccnt: */
1524 +#define CCNT(v) ((v) & 0xffff)
1527 +struct cssp_cam_platform_data {
1528 +       struct i2c_board_info *cam_i2c_board_info;
1529 +       const char *cam_clk_name;
1530 +       int dma_ch;
1531 +       int gpio_reset_pin;
1532 +};
1535 +/* ------------------------------------------------------------------
1536 +       video Basic structures
1537 +   ------------------------------------------------------------------*/
1539 +struct cssp_cam_fmt {
1540 +       char    *name;
1541 +       u32     fourcc;          /* v4l2 format id */
1542 +       int     depth;
1543 +       enum v4l2_mbus_pixelcode code;
1544 +};
1546 +/* buffer for one video frame */
1547 +struct cssp_cam_buffer {
1548 +       /* common v4l buffer stuff -- must be first */
1549 +       struct vb2_buffer       vb;
1550 +       struct list_head        list;
1551 +       struct cssp_cam_fmt     *fmt;
1552 +};
1554 +struct cssp_cam_dmaqueue {
1555 +       struct list_head        active;
1556 +};
1558 +struct cssp_cam_dev {
1559 +       struct v4l2_device              v4l2_dev;
1560 +       struct v4l2_ctrl_handler        ctrl_handler;
1561 +       struct v4l2_subdev              *subdev;
1563 +       spinlock_t                      slock;
1564 +       struct mutex                    mutex;
1566 +       /* various device info */
1567 +       struct video_device             *vdev;
1568 +       struct platform_device          *pdev;
1570 +       struct cssp_cam_dmaqueue        vidq;
1571 +       void                            *dma_cont_ctx;
1572 +       int                             streaming_started;
1573 +       struct vb2_buffer               *current_vb;
1575 +       /* Input Number */
1576 +       int                             input;
1578 +       /* video capture */
1579 +       struct cssp_cam_fmt             *fmt;
1580 +       u32                             width;
1581 +       u32                             height;
1582 +       u32                             bytesperline;
1583 +       u32                             sizeimage;
1584 +       enum v4l2_colorspace            colorspace;
1585 +       struct vb2_queue                vb_vidq;
1586 +       enum v4l2_field                 field;
1587 +       unsigned int                    field_count;
1590 +       /* Camera Sensor */
1591 +       struct i2c_board_info           *camera_board_info;
1592 +       struct clk                      *camera_clk;
1594 +       unsigned int                    reg_base_virt;
1595 +       unsigned int                    reg_base_phys;
1596 +       resource_size_t                 reg_size;
1597 +       u16                             mode;
1599 +       struct edmacc_param             dma_tr_params;
1600 +       int                             dma_ch;
1601 +       u64                             dma_mask;
1603 +       int                             frame_cnt;
1605 +       int                             reset_pin;
1606 +};
1609 +#endif /* CSSP_CAMERA_H */
1610 -- 
1611 1.7.10