1 From 25a91bba1bcc8d9f120e8b85b0ec53a18ccec244 Mon Sep 17 00:00:00 2001
2 From: Hugo Villeneuve <hugo@hugovil.com>
3 Date: Thu, 5 Mar 2009 16:04:23 -0500
4 Subject: [PATCH 11/12] Add lyrvpss example driver for the SFFSDR board
6 Currently there is only a VPFE driver in lyrvpss, and it is called luyrvpfe.
7 It works with a FPGA bitstream that generates a ramp and sends it over the
8 VPFE interface. The lyrvpfe driver receives an interrupt each time the HSYNC
9 line is pulsed (even if the VDINT0 interrupt line is used), and stores and
10 checks the data to make sure that it is valid. The driver will request a new
11 frame from the FPGA each time there is a read from /proc/lyrvpfe. For example,
12 to receive a new frame, issue the following:
16 This will send a request to the FPGA (using the GPIO line) to send a new frame,
17 wait one second then display the contents of the PING and PONG reception buffers.
19 Signed-off-by: Hugo Villeneuve <hugo@hugovil.com>
21 .../arm/mach-davinci/include/mach/sffsdr-lyrvpfe.h | 32 +
22 drivers/char/Kconfig | 2 +
23 drivers/char/Makefile | 2 +
24 drivers/char/lyrvpss/Kconfig | 42 ++
25 drivers/char/lyrvpss/Makefile | 8 +
26 drivers/char/lyrvpss/vpfe.c | 753 ++++++++++++++++++++
27 6 files changed, 839 insertions(+), 0 deletions(-)
28 create mode 100644 arch/arm/mach-davinci/include/mach/sffsdr-lyrvpfe.h
29 create mode 100644 drivers/char/lyrvpss/Kconfig
30 create mode 100644 drivers/char/lyrvpss/Makefile
31 create mode 100644 drivers/char/lyrvpss/vpfe.c
33 diff --git a/arch/arm/mach-davinci/include/mach/sffsdr-lyrvpfe.h b/arch/arm/mach-davinci/include/mach/sffsdr-lyrvpfe.h
35 index 0000000..fb47851
37 +++ b/arch/arm/mach-davinci/include/mach/sffsdr-lyrvpfe.h
42 + * This program is free software; you can redistribute it and/or modify it
43 + * under the terms of the GNU General Public License as published by the
44 + * Free Software Foundation; either version 2 of the License, or (at your
45 + * option) any later version.
47 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
48 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
49 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
50 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
54 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 + * You should have received a copy of the GNU General Public License along
59 + * with this program; if not, write to the Free Software Foundation, Inc.,
60 + * 675 Mass Ave, Cambridge, MA 02139, USA.
66 +struct lyrvpfe_platform_data {
67 + unsigned ready_gpio;
70 +#endif /* __LYRVPFE_H */
71 diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
72 index 43d6ba8..b98a8e2 100644
73 --- a/drivers/char/Kconfig
74 +++ b/drivers/char/Kconfig
75 @@ -1073,5 +1073,7 @@ config DEVPORT
77 source "drivers/s390/char/Kconfig"
79 +source "drivers/char/lyrvpss/Kconfig"
83 diff --git a/drivers/char/Makefile b/drivers/char/Makefile
84 index 438f713..8800b3f 100644
85 --- a/drivers/char/Makefile
86 +++ b/drivers/char/Makefile
87 @@ -109,6 +109,8 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
88 obj-$(CONFIG_JS_RTC) += js-rtc.o
91 +obj-$(CONFIG_LYRTECH_VPSS) += lyrvpss/
93 # Files generated that shall be removed upon make clean
94 clean-files := consolemap_deftbl.c defkeymap.c
96 diff --git a/drivers/char/lyrvpss/Kconfig b/drivers/char/lyrvpss/Kconfig
98 index 0000000..80b1487
100 +++ b/drivers/char/lyrvpss/Kconfig
103 +# Lyrtech VPSS drivers
106 +menuconfig LYRTECH_VPSS
107 + bool 'Lyrtech SFFSDR VPSS drivers'
108 + depends on ARCH_DAVINCI && MACH_SFFSDR
110 + This enables support for Lyrtech SFFSDR VPSS drivers.
117 + tristate "Lyrtech VPFE Driver Support"
119 + This option enables support for the Lyrtech VPFE driver
120 + for FPGA to DaVinci data transfers.
122 + To compile this driver as a module, choose M here: the
123 + module will be called lyrvpfe.
128 + tristate "Lyrtech VPBE Driver Support"
130 + This option enables support for the Lyrtech VPBE driver
131 + for DaVinci to FPGA data transfers.
133 + To compile this driver as a module, choose M here: the
134 + module will be called lyrvpbe.
138 +config LYRVPSS_DEBUG
139 + boolean "Debug support for LYRVPSSS drivers"
141 + Say "yes" to enable verbose debug messaging.
143 +endif # LYRTECH_VPSS
144 diff --git a/drivers/char/lyrvpss/Makefile b/drivers/char/lyrvpss/Makefile
146 index 0000000..ac36807
148 +++ b/drivers/char/lyrvpss/Makefile
151 +# Makefile for the Lyrtech SFFSDR VPSS driver
154 +obj-$(CONFIG_LYRTECH_VPFE) += lyrvpfe.o
155 +obj-$(CONFIG_LYRTECH_VPBE) += lyrvpbe.o
156 +lyrvpfe-objs := vpfe.o
157 +lyrvpbe-objs := vpbe.o
158 diff --git a/drivers/char/lyrvpss/vpfe.c b/drivers/char/lyrvpss/vpfe.c
160 index 0000000..45e2853
162 +++ b/drivers/char/lyrvpss/vpfe.c
167 + * Copyright (C) 2008 Lyrtech <www.lyrtech.com>
169 + * This program is free software; you can redistribute it and/or modify
170 + * it under the terms of the GNU General Public License as published by
171 + * the Free Software Foundation; either version 2 of the License, or
172 + * (at your option) any later version.
174 + * This program is distributed in the hope that it will be useful,
175 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
176 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
177 + * GNU General Public License for more details.
179 + * You should have received a copy of the GNU General Public License
180 + * along with this program; if not, write to the Free Software
181 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
184 +#include <linux/kernel.h>
185 +#include <linux/module.h>
186 +#include <linux/init.h>
187 +#include <linux/device.h>
188 +#include <linux/platform_device.h>
189 +#include <linux/string.h>
190 +#include <linux/delay.h>
191 +#include <linux/firmware.h>
192 +#include <linux/interrupt.h>
193 +#include <linux/jiffies.h>
194 +#include <linux/err.h>
195 +#include <linux/fs.h>
196 +#include <linux/io.h>
197 +#include <linux/irq.h>
199 +#ifdef CONFIG_PROC_FS
200 +#include <linux/proc_fs.h>
201 +#include <linux/seq_file.h>
202 +#include <asm/uaccess.h>
203 +#endif /* CONFIG_PROC_FS */
205 +#include <asm/gpio.h>
207 +#include <mach/sffsdr-fpga.h>
208 +#include <mach/sffsdr-lyrvpfe.h>
209 +#include <mach/mux.h>
210 +#include <mach/irqs.h>
212 +#define MODULE_NAME "lyrvpfe"
214 +#ifdef CONFIG_LYRVPSS_DEBUG
215 +#define DBGMSG(fmt, args...) \
216 + printk(KERN_INFO "%s: "fmt"\n" , MODULE_NAME, ## args)
218 +#define DBGMSG(fmt, args...)
221 +#define FAILMSG(fmt, args...) \
222 + printk(KERN_ERR "%s: "fmt"\n" , MODULE_NAME, ## args)
224 +#define DAVINCI_CCDC_REGS_OFFSET 0x400
226 +/* This word is written at index 0 to mark a buffer as invalid. */
227 +#define INVALIDATE_BUFFER_CODE 0x11222211
229 +/* Default values for our driver. */
230 +#define LYRVPFE_LINES_PER_FRAME 2
231 +#define LYRVPFE_WORDS_PER_LINE 8 /* Minimum is 8 words */
233 +/* SFFSDR VPSS limits */
234 +#define LYRVPFE_MAX_WORDS_PER_LINE 1024
235 +#define LYRVPFE_MAX_LINES_PER_FRAME 10
236 +#define LYRVPFE_MAX_BUFFER_SIZE 65536
238 +#define BUFFER_PING 0
239 +#define BUFFER_PONG 1
271 +#define CCDC_REGS_COUNT 38
273 +#define CCDC_WEN_BIT (1 << 17)
274 +#define CCDC_VDHDEN_BIT (1 << 16)
275 +#define CCDC_VDPOL_NEG (1 << 2)
277 +/* Structure containing driver informations. */
278 +struct lyrvpfe_private {
280 + LYRVPFE_INIT_START,
281 + LYRVPFE_INIT_HAVE_REGS,
282 + LYRVPFE_INIT_HAVE_IRQ,
283 + LYRVPFE_INIT_HAVE_GPIO,
285 + LYRVPFE_INIT_HAVE_PING_BUFFER,
286 + LYRVPFE_INIT_HAVE_PONG_BUFFER,
287 + LYRVPFE_INIT_HAVE_PROC
290 + unsigned ready_gpio;
293 + volatile struct ccdc_regs *ccdc_regs;
295 + u32 lines_per_frame;
296 + u32 words_per_line;
299 + int wrid; /* 0 (ping) or 1 (pong) */
300 + u32 *data_buffers[2];
304 +static struct lyrvpfe_private lyrvpfe;
306 +/* Informs the FPGA that the DaVinci can receive a new frame. */
307 +static void lyrvpfe_set_ready(void)
311 + /* Read current pin state */
312 + value = gpio_get_value(lyrvpfe.ready_gpio);
314 + /* Toggle state. */
318 + gpio_set_value(lyrvpfe.ready_gpio, value);
321 +#ifdef CONFIG_PROC_FS
323 +#define LYRVPFE_PROC_NAME "lyrvpfe"
325 +static void *lyrvpfe_start(struct seq_file *m, loff_t *pos)
327 + return *pos < 1 ? (void *)1 : NULL;
330 +static void *lyrvpfe_next(struct seq_file *m, void *v, loff_t *pos)
336 +static void lyrvpfe_stop(struct seq_file *m, void *v)
340 +static void lyrvpfe_display_regs(char *msg, u32 *regs, int size,
341 + struct seq_file *m)
345 + seq_printf(m, "%s:", msg);
346 + for (k = 0; k < size; k++) {
348 + seq_printf(m, "\n");
350 + seq_printf(m, " [$%02X] $%08X", k * 4, regs[k]);
352 + seq_printf(m, "\n");
355 +static int lyrvpfe_show(struct seq_file *m, void *v)
358 + unsigned long jtarget, jcurrent;
360 + /* Toggle pin to receive next frame */
361 + lyrvpfe_set_ready();
363 + jtarget = jiffies + (1 * HZ);
365 + /* Wait 1 second for data to arrive. */
367 + jcurrent = jiffies;
369 + } while (time_before(jcurrent, jtarget));
371 + regs = (u32 *) lyrvpfe.ccdc_regs;
372 + lyrvpfe_display_regs("CCDC registers", regs, CCDC_REGS_COUNT, m);
374 + seq_printf(m, "FPGA registers:\n");
376 + seq_printf(m, " [$%04X] $%04X [$%04X] $%04X" \
377 + " [$%04X] $%04X [$%04X] $%04X\n",
378 + SFFSDR_FPGA_REVISION,
379 + sffsdr_fpga_regread(SFFSDR_FPGA_REVISION),
380 + SFFSDR_FPGA_VPSS_CONTROL,
381 + sffsdr_fpga_regread(SFFSDR_FPGA_VPSS_CONTROL),
382 + SFFSDR_FPGA_VPSS_TO_DSP_FIFO,
383 + sffsdr_fpga_regread(SFFSDR_FPGA_VPSS_TO_DSP_FIFO),
384 + SFFSDR_FPGA_VPSS_LINES_PER_FRAME,
385 + sffsdr_fpga_regread(SFFSDR_FPGA_VPSS_LINES_PER_FRAME));
387 + regs = lyrvpfe.data_buffers[BUFFER_PING];
388 + lyrvpfe_display_regs("PING buffer", regs, 64, m);
390 + regs = lyrvpfe.data_buffers[BUFFER_PONG];
391 + lyrvpfe_display_regs("PONG buffer", regs, 64, m);
396 +static const struct seq_operations lyrvpfe_op = {
397 + .start = lyrvpfe_start,
398 + .next = lyrvpfe_next,
399 + .stop = lyrvpfe_stop,
400 + .show = lyrvpfe_show
403 +static int lyrvpfe_open(struct inode *inode, struct file *file)
405 + struct seq_file *m;
408 + DBGMSG("lyrvpfe_open");
410 + ret = seq_open(file, &lyrvpfe_op);
414 + m = file->private_data;
419 +static const struct file_operations proc_lyrvpfe_operations = {
420 + .open = lyrvpfe_open,
422 + .llseek = seq_lseek,
423 + .release = seq_release,
424 + .owner = THIS_MODULE,
427 +static int lyrvpfe_proc_init(void)
429 + struct proc_dir_entry *entry;
431 + entry = create_proc_entry(LYRVPFE_PROC_NAME, 0, NULL);
433 + FAILMSG("Error creating proc entry");
437 + entry->proc_fops = &proc_lyrvpfe_operations;
438 + entry->data = &lyrvpfe;
443 +#endif /* CONFIG_PROC_FS */
445 +static int lyrvpfe_validate_buffer(u32 *buffer)
448 + u8 *cksum_data = (u8 *) buffer;
450 + /* Compute XOR of bytes 4 and 5 */
451 + xnor = ~(cksum_data[4] ^ cksum_data[5]);
452 + xor = cksum_data[4] ^ cksum_data[5];
454 + if ((xor != cksum_data[1]) || (xnor != cksum_data[0]))
460 +static inline void lyrvpfe_invalidate_buffer(u32 *buffer)
465 + for (line = 0; line < lyrvpfe.lines_per_frame; line++) {
466 + /* Get offset of next line. */
467 + offset = (line * lyrvpfe.ccdc_regs->hsize_off) / 4;
469 + /* Mark buffer as invalid. */
470 + buffer[offset] = INVALIDATE_BUFFER_CODE;
475 + * Lyrtech SFFSDR custom VPFE format:
477 + * Length is in u32 units
479 + * Format for each line:
482 + * |offset| 31..24 | 23..16 | 15..08 | 07..00 |
483 + * ============================================
484 + * 0 | dummy dummy dummy dummy
485 + * 1 | dummy dummy dummy dummy
486 + * 2 | length length cksum cksum
487 + * 3 | data0 data0 data0 data0
488 + * 4 | data1 data1 data1 data1
491 +static int vpfe_check_buffer(u32 *buffer)
499 + for (line = 0; line < lyrvpfe.lines_per_frame; line++) {
500 + /* Get offset of next line. */
501 + offset = (line * lyrvpfe.ccdc_regs->hsize_off) / 4;
503 + if (buffer[offset] == INVALIDATE_BUFFER_CODE) {
504 + /* No error. Means that HD pulses generated the VDINT0
505 + * interruption, but VD was not asserted. */
509 + /* First two words contain empty/dummy data. */
513 + if (lyrvpfe.wrid == BUFFER_PING)
514 + DBGMSG("VDINT: PING buffer");
516 + DBGMSG("VDINT: PONG buffer");
519 + ret = lyrvpfe_validate_buffer(&buffer[offset]);
521 + /* This may mean a checksum error, or that
522 + * the FPGA sent fewer lines than the maximum
524 + FAILMSG(" Checksum error line %d", line);
528 + length = buffer[offset] >> 16;
530 + /* Points to first data word. */
533 + for (k = 0; k < length; k++) {
534 + if (buffer[offset + k] != (lyrvpfe.ramp_index + k)) {
535 + FAILMSG(" Ramp error at index %d, line %d",
536 + lyrvpfe.ramp_index, line);
537 + FAILMSG(" read: $%08X",
538 + buffer[offset + k]);
539 + FAILMSG(" expected: $%08X",
540 + lyrvpfe.ramp_index + k);
542 + lyrvpfe_invalidate_buffer(buffer);
547 + lyrvpfe.ramp_index += length;
553 +static void lyrvpfe_set_ccdc_buffer(u32 *virt_address)
555 + lyrvpfe.ccdc_regs->sdr_addr = (u32) virt_to_phys(virt_address);
559 + * The CCDC VDINT0 and VDINT1 HD counters begin counting HD pulses from the
560 + * rising edge of the external VD. The Lyrtech FPGA VPFE design only drives VD
561 + * when the ARM request data by toggling the SET_VPFE_READY GPIO. Unfortunately,
562 + * the FPGA never disable the HD line, and the ISR will be called all the time
563 + * with invalid data when VD is not driven. This is why we need to invalidate a
564 + * buffer once it has been read.
566 +static irqreturn_t lyrvpfe_isr(int irq, void *dev_id)
569 + int buffer_read_id;
571 + /* Buffer index for reading data */
572 + buffer_read_id = lyrvpfe.wrid;
574 + ret = vpfe_check_buffer(lyrvpfe.data_buffers[buffer_read_id]);
576 + /* This could mean a real error or simply that we received a
577 + * dummy HD interrupt. */
578 + lyrvpfe_invalidate_buffer(lyrvpfe.data_buffers[buffer_read_id]);
580 + /* Valid data was received. We can now switch the pong-pong
583 + /* Switch ping-pong buffers for writing. */
585 + lyrvpfe_set_ccdc_buffer(lyrvpfe.data_buffers[lyrvpfe.wrid]);
587 + /* Make sure to invalidate the new buffer */
588 + lyrvpfe_invalidate_buffer(lyrvpfe.data_buffers[lyrvpfe.wrid]);
591 + return IRQ_HANDLED;
595 + * Configures the VPFE interface to receive data from the FPGA.
597 + * lines_per_frame: Lines per frame (within the VSYNC period).
598 + * words_per_line: 32-bits data words per line (within the HSYNC period).
600 +static int lyrvpfe_init_vpfe(u16 lines_per_frame, u16 words_per_line)
602 + int bytes_per_buffer;
604 + lyrvpfe.ramp_index = 0;
605 + lyrvpfe.wrid = BUFFER_PING;
607 + if (words_per_line > LYRVPFE_MAX_WORDS_PER_LINE) {
608 + FAILMSG("VPFE init: invalid words_per_line (%d)",
613 + if (lines_per_frame > LYRVPFE_MAX_LINES_PER_FRAME) {
614 + FAILMSG("VPFE init: invalid lines_per_frame (%d)",
619 + bytes_per_buffer = (words_per_line + 3) * 4 * lines_per_frame;
620 + if (bytes_per_buffer > LYRVPFE_MAX_BUFFER_SIZE) {
621 + FAILMSG("VPFE init: wrong bytes_per_buffer (%d)",
626 + DBGMSG(" words_per_line = $%04X", words_per_line);
627 + DBGMSG(" lines_per_frame = $%04X", lines_per_frame);
629 + /* Setup FPGA parameters */
630 + sffsdr_fpga_regwrite(SFFSDR_FPGA_VPSS_TO_DSP_FIFO,
631 + (words_per_line & 0x3ff) |
632 + (lines_per_frame << 10));
634 + /* 2 additional for blanking and 1 for header (length and checksum). */
635 + words_per_line = words_per_line + 3;
637 + lyrvpfe.words_per_line = words_per_line;
638 + lyrvpfe.lines_per_frame = lines_per_frame;
640 + /************************************************/
641 + /* Setup Fix VPFE parameter */
642 + /************************************************/
643 + /* Setup VPFE Hardware */
644 + lyrvpfe.ccdc_regs->syn_mode = CCDC_WEN_BIT | CCDC_VDHDEN_BIT |
647 + /* Start at Line 0 */
648 + lyrvpfe.ccdc_regs->vert_start = 0;
650 + /* Disable culling */
651 + lyrvpfe.ccdc_regs->culling = 0xFFFF00FF;
653 + lyrvpfe.ccdc_regs->sdofst = 0;
654 + lyrvpfe.ccdc_regs->clamp = 0;
655 + lyrvpfe.ccdc_regs->dcsub = 0;
656 + lyrvpfe.ccdc_regs->colptn = 0;
657 + lyrvpfe.ccdc_regs->blkcmp = 0;
658 + lyrvpfe.ccdc_regs->fpc = 0;
659 + lyrvpfe.ccdc_regs->vdint = 0;
660 + lyrvpfe.ccdc_regs->alaw = 0;
661 + lyrvpfe.ccdc_regs->rec656if = 0;
663 + /* Disable shadowing as recommended in silicon errata. Very important,
664 + * if not set, a lot of problems may occur. */
665 + /* VDLC: Not latched on VSYNC. */
666 + lyrvpfe.ccdc_regs->ccdcfg = (1 << 15);
668 + /************************************************/
669 + /* Setup variable VPFE parameter */
670 + /************************************************/
671 + /* Max. length of a line */
672 + lyrvpfe.ccdc_regs->horz_info = words_per_line * 4;
674 + /* Max. number of lines per frame - 1 */
675 + lyrvpfe.ccdc_regs->vert_lines = lines_per_frame - 1;
677 + /* Offset of a line in memory (in bytes).
678 + * Must be on 32 bytes boundary */
679 + lyrvpfe.line_size = ((words_per_line * sizeof(u32)) + 31) & ~31;
680 + lyrvpfe.ccdc_regs->hsize_off = lyrvpfe.line_size;
683 + lyrvpfe.ccdc_regs->pcr = 0x1;
688 +static void lyrvpfe_disable_vpfe(void)
691 + lyrvpfe.ccdc_regs->pcr = 0;
694 +static void lyrvpfe_dev_cleanup(void)
696 + DBGMSG("lyrvpfe_dev_cleanup()");
698 + switch (lyrvpfe.init_state) {
699 + case LYRVPFE_INIT_HAVE_PROC:
700 +#ifdef CONFIG_PROC_FS
701 + remove_proc_entry(LYRVPFE_PROC_NAME, NULL);
703 + case LYRVPFE_INIT_HAVE_IRQ:
704 + free_irq(lyrvpfe.irq, &lyrvpfe);
705 + case LYRVPFE_INIT_HAVE_PONG_BUFFER:
706 + kfree(lyrvpfe.data_buffers[BUFFER_PONG]);
707 + case LYRVPFE_INIT_HAVE_PING_BUFFER:
708 + kfree(lyrvpfe.data_buffers[BUFFER_PING]);
709 + case LYRVPFE_INIT_VPFE:
710 + lyrvpfe_disable_vpfe();
711 + case LYRVPFE_INIT_HAVE_GPIO:
712 + gpio_free(lyrvpfe.ready_gpio);
713 + case LYRVPFE_INIT_HAVE_REGS:
714 + iounmap(lyrvpfe.regs);
715 + case LYRVPFE_INIT_START:
720 +struct bus_type lyrvpfe_bus_type = {
723 +EXPORT_SYMBOL(lyrvpfe_bus_type);
725 +static int lyrvpfe_probe(struct platform_device *pdev)
727 + struct lyrvpfe_platform_data *pdata;
728 + struct resource *regs_res;
729 + struct resource *irq_res;
733 + DBGMSG("lyrvpfe_probe()");
735 + /* We Should enable the VPFE with the PSC controller and PINMUX0. */
737 + lyrvpfe.id = pdev->id;
738 + lyrvpfe.dev.bus = &lyrvpfe_bus_type;
739 + lyrvpfe.dev.parent = &pdev->dev;
740 + snprintf(lyrvpfe.dev.bus_id, BUS_ID_SIZE, "lyrvpfe%d", lyrvpfe.id);
741 + lyrvpfe.dev.bus_id[BUS_ID_SIZE - 1] = 0;
742 + lyrvpfe.init_state = LYRVPFE_INIT_START;
744 + regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
746 + FAILMSG("Error getting REGS ressource");
751 + lyrvpfe.regs = ioremap(regs_res->start,
752 + regs_res->end - regs_res->start);
753 + if (!lyrvpfe.regs) {
754 + FAILMSG("Can't remap CCDC registers");
758 + lyrvpfe.ccdc_regs = (struct ccdc_regs *)
759 + (lyrvpfe.regs + DAVINCI_CCDC_REGS_OFFSET);
761 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_REGS;
763 + pdata = pdev->dev.platform_data;
765 + FAILMSG("Error getting platform data");
769 + lyrvpfe.dev.platform_data = pdata;
771 + /* Configure VPFE SET READY GPIO. */
772 + lyrvpfe.ready_gpio = pdata->ready_gpio;
774 + result = gpio_request(lyrvpfe.ready_gpio, "vpfe_ready");
776 + /* Must start at 1, if not gives errors. */
777 + result = gpio_direction_output(lyrvpfe.ready_gpio, 1);
782 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_GPIO;
784 + result = lyrvpfe_init_vpfe(LYRVPFE_LINES_PER_FRAME,
785 + LYRVPFE_WORDS_PER_LINE);
787 + FAILMSG("lyrvpfe_init_vpfe() failed (%d)", result);
790 + lyrvpfe.init_state = LYRVPFE_INIT_VPFE;
792 + /* Adding 256 to compensate for 256 bytes alignment */
793 + lyrvpfe.bufsize = lyrvpfe.line_size * lyrvpfe.lines_per_frame + 256;
795 + buf = kmalloc(lyrvpfe.bufsize /*LYRVPFE_BUFFER_SIZE*/, GFP_KERNEL);
800 + /* Buffer must be 32 bytes aligned for the hardware but must be
801 + * 256 bytes aligned to cope with cache line size. */
802 + lyrvpfe.data_buffers[BUFFER_PING] =
803 + (u32 *) (((u32) buf + 255) & 0xFFFFFF00);
804 + lyrvpfe.data_buffers[BUFFER_PING][0] = 0x11111111;
805 + lyrvpfe.data_buffers[BUFFER_PING][1] = 0x22222222;
806 + lyrvpfe_invalidate_buffer(lyrvpfe.data_buffers[BUFFER_PING]);
807 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_PING_BUFFER;
809 + buf = kmalloc(lyrvpfe.bufsize /*LYRVPFE_BUFFER_SIZE*/, GFP_KERNEL);
814 + /* Buffer must be 32 bytes aligned for the hardware but must be
815 + * 256 bytes aligned to cope with cache line size. */
816 + lyrvpfe.data_buffers[BUFFER_PONG] =
817 + (u32 *) (((u32) buf + 255) & 0xFFFFFF00);
818 + lyrvpfe.data_buffers[BUFFER_PONG][0] = 0x33333333;
819 + lyrvpfe.data_buffers[BUFFER_PONG][1] = 0x44444444;
820 + lyrvpfe_invalidate_buffer(lyrvpfe.data_buffers[BUFFER_PONG]);
821 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_PONG_BUFFER;
823 + lyrvpfe_set_ccdc_buffer(lyrvpfe.data_buffers[lyrvpfe.wrid]);
825 + /* setup interrupt handling */
826 + irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
828 + FAILMSG("Error getting IRQ ressource");
833 + lyrvpfe.irq = irq_res->start;
834 + result = request_irq(lyrvpfe.irq, lyrvpfe_isr,
835 + IRQF_SHARED /*IRQF_DISABLED*/,
836 + MODULE_NAME, &lyrvpfe);
838 + FAILMSG("Error requesting IRQ ressource");
839 + result = -ENODEV; /* To check */
843 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_IRQ;
845 +#ifdef CONFIG_PROC_FS
846 + result = lyrvpfe_proc_init();
848 + FAILMSG("Error creating proc entry");
853 + lyrvpfe.init_state = LYRVPFE_INIT_HAVE_PROC;
858 + lyrvpfe_dev_cleanup();
862 +static int __devexit lyrvpfe_remove(struct platform_device *pdev)
864 + DBGMSG("lyrvpfe_remove()");
866 + lyrvpfe_dev_cleanup();
870 +static struct platform_driver lyrvpfe_pdriver = {
872 + .name = MODULE_NAME,
873 + .owner = THIS_MODULE,
875 + .remove = lyrvpfe_remove,
878 +static int __init lyrvpfe_init(void)
882 + DBGMSG("lyrvpfe_init()");
884 + res = bus_register(&lyrvpfe_bus_type);
886 + FAILMSG("bus_register() failed");
890 + res = platform_driver_probe(&lyrvpfe_pdriver, lyrvpfe_probe);
892 + FAILMSG("platform_driver_probe() failed");
893 + goto fail_platform;
899 + bus_unregister(&lyrvpfe_bus_type);
903 +module_init(lyrvpfe_init);
905 +static void __exit lyrvpfe_exit(void)
907 + DBGMSG("lyrvpfe_exit()");
909 + platform_driver_unregister(&lyrvpfe_pdriver);
910 + bus_unregister(&lyrvpfe_bus_type);
912 +module_exit(lyrvpfe_exit);
914 +MODULE_AUTHOR("Hugo Villeneuve <hvilleneuve@lyrtech.com>");
915 +MODULE_DESCRIPTION("Lyrtech SFFSDR VPFE driver");
916 +MODULE_LICENSE("GPL");