diff --git a/quad/Examples/ASI/Makefile b/quad/Examples/ASI/Makefile deleted file mode 100755 index 4a284e6c7..000000000 --- a/quad/Examples/ASI/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# Makefile for the DVB ASI example programs - -SHELL = /bin/sh -INSTALL = install - -INCLUDEDIR = ../../include -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -CFLAGS = -O2 -Wall -W -I$(INCLUDEDIR) -D_LARGEFILE_SOURCE \ - $(shell getconf LFS_CFLAGS; getconf LFS_LDFLAGS; getconf LFS_LIBS) -TARGETS = asicfg txcfg rxcfg txmon rxmon txtest rxtest \ - calcstuff mknull cknull stampinfo - -.c: - $(CC) $(CFLAGS) -o $@ $@.c - -all: $(TARGETS) - -asicfg: asicfg.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -txcfg: txcfg.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../pci_ids.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -rxcfg: rxcfg.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../pci_ids.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -txmon: txmon.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -rxmon: rxmon.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -txtest: txtest.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -rxtest: rxtest.c $(INCLUDEDIR)/asi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -calcstuff: calcstuff.c $(INCLUDEDIR)/master.h -mknull: mknull.c $(INCLUDEDIR)/master.h -cknull: cknull.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -stampinfo: stampinfo.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o - -clean: - $(RM) *.o *~ core $(TARGETS) - -install: all - $(INSTALL) $(TARGETS) $(bindir) - -uninstall: - $(RM) $(foreach prog,$(TARGETS),$(bindir)/$(prog)) - diff --git a/quad/Examples/ASI/asicfg.c b/quad/Examples/ASI/asicfg.c old mode 100755 new mode 100644 index 9315c70d9..88ef4982b --- a/quad/Examples/ASI/asicfg.c +++ b/quad/Examples/ASI/asicfg.c @@ -116,12 +116,12 @@ main (int argc, char **argv) "\tset the packet timestamping mode\n"); printf (" -V\t\toutput version information " "and exit\n"); - printf (" -x CLKSRC\tset the clock source\n"); + printf (" -x CLKSRC\tset the clock source " + "(transmitters only)\n"); printf ("\nIf no options are specified, " "the current configuration is displayed.\n"); printf ("\nBUFFERS must be two or more.\n"); - printf ("\nCLKSRC is valid only for transmitters and " - "may be:\n" + printf ("\nCLKSRC may be:\n" "\t0 (onboard oscillator)\n" "\t1 (external reference clock)\n" "\t2 (recovered receive clock)\n" @@ -243,8 +243,8 @@ main (int argc, char **argv) snprintf (name, sizeof (name), fmt, type, num, "dev"); memset (data, 0, sizeof (data)); if (util_read (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the device number"); + fprintf (stderr, "%s: error reading %s: ", argv[0], name); + perror (NULL); return -1; } if (strtoul (data, &endptr, 0) != (buf.st_rdev >> 8)) { @@ -283,6 +283,12 @@ main (int argc, char **argv) printf ("\tSet buffer size = %lu bytes.\n", bufsize); } if (write_flags & CLKSRC_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the clock source: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "clock_source"); snprintf (data, sizeof (data), "%lu\n", clksrc); diff --git a/quad/Examples/ASI/calcstuff.c b/quad/Examples/ASI/calcstuff.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/cknull.c b/quad/Examples/ASI/cknull.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/mknull.c b/quad/Examples/ASI/mknull.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/rxcfg.c b/quad/Examples/ASI/rxcfg.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/rxmon.c b/quad/Examples/ASI/rxmon.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/rxtest.c b/quad/Examples/ASI/rxtest.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/stampinfo.c b/quad/Examples/ASI/stampinfo.c old mode 100755 new mode 100644 index abf7fc271..9dc2b5164 --- a/quad/Examples/ASI/stampinfo.c +++ b/quad/Examples/ASI/stampinfo.c @@ -3,7 +3,7 @@ * * Read the timestamps attached to each MPEG-2 transport stream packet. * - * Copyright (C) 2005 Linear Systems Ltd. + * Copyright (C) 2005-2010 Linear Systems Ltd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -42,7 +42,6 @@ #include #include #include -#include #include "master.h" #include "../util.h" @@ -60,9 +59,7 @@ #define TIMESTAMP_SIZE 8 #if __BYTE_ORDER == __BIG_ENDIAN -#define ltohll(x) (((uint64_t)ntohl(x)) << 32 + ntohl((x) >> 32)) -#elif __BYTE_ORDER == __LITTLE_ENDIAN -#define ltohll(x) (x) +#error Big endian architecture not supported #endif static const char progname[] = "stampinfo"; @@ -177,7 +174,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2005 " + printf ("\nCopyright (C) 2005-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -232,7 +229,7 @@ main (int argc, char **argv) i++; ts = append ? getpcr (stamp) : - ltohll (*(uint64_t *)stamp); + *(uint64_t *)stamp; /* Little endian only */ if (verbose) { printf ("%u: hdr=%08X ts=%"PRIu64"\n", i, @@ -270,7 +267,7 @@ main (int argc, char **argv) i++; ts = append ? getpcr (stamp) : - ltohll (*(uint64_t *)stamp); + *(uint64_t *)stamp; /* Little endian only */ diff = ts - oldts; if (verbose) { printf ("%u: hdr=%08X ts=%"PRIu64" diff=%lli\n", diff --git a/quad/Examples/ASI/txcfg.c b/quad/Examples/ASI/txcfg.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/txmon.c b/quad/Examples/ASI/txmon.c old mode 100755 new mode 100644 diff --git a/quad/Examples/ASI/txtest.c b/quad/Examples/ASI/txtest.c old mode 100755 new mode 100644 diff --git a/quad/Examples/Makefile b/quad/Examples/Makefile deleted file mode 100755 index b7eecb9a8..000000000 --- a/quad/Examples/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# Makefile for the Master Linux example programs - -SHELL = /bin/sh -INSTALL = install - -INCLUDEDIR = ../include -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -CFLAGS = -O2 -Wall -W -I$(INCLUDEDIR) -D_LARGEFILE_SOURCE \ - $(shell getconf LFS_CFLAGS; getconf LFS_LDFLAGS; getconf LFS_LIBS) -TARGETS = mastercfg -SUBDIRS = ASI SDI SDIAUDIO SDIVIDEO - -.c: - $(CC) $(CFLAGS) -o $@ $@.c - -all: $(TARGETS) - for n in $(SUBDIRS); do $(MAKE) -C $$n || exit 1; done - -mastercfg: mastercfg.c $(INCLUDEDIR)/master.h util.o - $(CC) $(CFLAGS) -o $@ $@.c util.o - -util.o: util.c pci_ids.h util.h - -clean: - $(RM) *.o *~ core $(TARGETS) - for n in $(SUBDIRS); do $(MAKE) -C $$n clean; done - -install: all - $(INSTALL) $(TARGETS) $(bindir) - for n in $(SUBDIRS); do $(MAKE) -C $$n install || exit 1; done - -uninstall: - $(RM) $(foreach prog,$(TARGETS),$(bindir)/$(prog)) - for n in $(SUBDIRS); do $(MAKE) -C $$n uninstall || exit 1; done - diff --git a/quad/Examples/SDI/Makefile b/quad/Examples/SDI/Makefile deleted file mode 100755 index 707997ba2..000000000 --- a/quad/Examples/SDI/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# Makefile for the SMPTE 259M-C example programs - -SHELL = /bin/sh -INSTALL = install - -INCLUDEDIR = ../../include -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -CFLAGS = -O2 -Wall -W -I$(INCLUDEDIR) -D_LARGEFILE_SOURCE \ - $(shell getconf LFS_CFLAGS; getconf LFS_LDFLAGS; getconf LFS_LIBS) -TARGETS = bt801 capture eg1 mcapture mplayout playout sdicfg sdirxcfg sditxcfg - -.c: - $(CC) $(CFLAGS) -o $@ $@.c - -all: $(TARGETS) - -bt801: bt801.c $(INCLUDEDIR)/master.h -capture: capture.c $(INCLUDEDIR)/sdi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -eg1: eg1.c $(INCLUDEDIR)/master.h -mcapture: mcapture.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -mplayout: mplayout.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -playout: playout.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdicfg: sdicfg.c $(INCLUDEDIR)/sdi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdirxcfg: sdirxcfg.c $(INCLUDEDIR)/sdi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sditxcfg: sditxcfg.c $(INCLUDEDIR)/sdi.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o - -clean: - $(RM) *.o *~ core $(TARGETS) - -install: all - $(INSTALL) $(TARGETS) $(bindir) - -uninstall: - $(RM) $(foreach prog,$(TARGETS),$(bindir)/$(prog)) - diff --git a/quad/Examples/SDI/bitrate.c b/quad/Examples/SDI/bitrate.c deleted file mode 100755 index 18fb74db9..000000000 --- a/quad/Examples/SDI/bitrate.c +++ /dev/null @@ -1,406 +0,0 @@ -/* rxtest.c - * - * Example program for DVB ASI receivers. - * - * Copyright (C) 2000-2005 Linear Systems Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of Linear Systems Ltd. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY LINEAR SYSTEMS LTD. "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL LINEAR SYSTEMS LTD. OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Linear Systems can be contacted at . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sdi.h" -#include "master.h" -#include "../util.h" - -#ifndef _LFS_LARGEFILE -#error Large file support not found -#endif - -#define BUFLEN 256 - -static const char *argv0; -static const char progname[] = "bitrate"; - -int -main (int argc, char **argv) -{ - const char fmt[] = "/sys/class/sdi/sdirx%i/%s"; - int opt; - int fd, val; - int period, seconds, quiet, verbose, num; - unsigned long int bufsize; - int ofd, read_ret, write_ret; - struct stat buf; - unsigned char *data; - unsigned int bytes_written; - struct timeval tv; - struct pollfd pfd; - double bytes, time_sec, lasttime, dt, status_time; - char name[BUFLEN], str[BUFLEN], *endptr; - - argv0 = argv[0]; - - /* Parse the command line */ - period = 0; - seconds = -1; - quiet = 0; - verbose = 0; - while ((opt = getopt (argc, argv, "dDhiIn:p:qs:vV")) != -1) { - switch (opt) { - case 'h': - printf ("Usage: %s [OPTION]... DEVICE_FILE [FILE]\n", - argv0); - printf ("Copy DEVICE_FILE to FILE and monitor for " - "DVB ASI receiver events.\n\n"); - printf (" -d\t\tgain packet synchronization " - "after two sychronization bytes\n"); - printf (" -D\t\tgain packet synchronization " - "after one synchronization byte\n"); - printf (" -h\t\tdisplay this help and exit\n"); - printf (" -i\t\tsynchronize on packets starting with " - "0x47 or 0xB8\n"); - printf (" -I\t\tsynchronize on packets starting with " - "0x47 only\n"); - printf (" -n TIME\tstop receiving after " - "TIME seconds\n"); - printf (" -p PID\tcount packets " - "with the given PID\n"); - printf (" -q\t\tquiet operation\n"); - printf (" -s PERIOD\tdisplay status " - "every PERIOD seconds\n"); - printf (" -v\t\tverbose output\n"); - printf (" -V\t\toutput version information " - "and exit\n"); - printf ("\nReport bugs to .\n"); - return 0; - case 'n': - seconds = strtol (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid timeout: %s\n", - argv0, optarg); - return -1; - } - break; - case 'q': - quiet = 1; - break; - case 's': - period = strtol (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid period: %s\n", - argv0, optarg); - return -1; - } - break; - case 'v': - verbose = 1; - break; - case 'V': - printf ("%s from master-%s (%s)\n", progname, - MASTER_DRIVER_VERSION, - MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2000-2005 " - "Linear Systems Ltd.\n" - "This is free software; " - "see the source for copying conditions. " - "There is NO\n" - "warranty; not even for MERCHANTABILITY " - "or FITNESS FOR A PARTICULAR PURPOSE.\n"); - return 0; - case '?': - goto USAGE; - } - } - - /* Check the number of arguments */ - if ((argc - optind) < 1) { - if (!quiet) { - fprintf (stderr, "%s: missing arguments\n", argv0); - goto USAGE; - } - return -1; - } else if ((argc - optind) > 2) { - if (!quiet) { - fprintf (stderr, "%s: extra operand\n", argv0); - goto USAGE; - } - return -1; - } - - /* Get the sysfs info */ - memset (&buf, 0, sizeof (buf)); - if (stat (argv[optind], &buf) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to get the file status"); - } - return -1; - } - if (!S_ISCHR (buf.st_mode)) { - if (!quiet) { - fprintf (stderr, "%s: not a character device\n", - argv0); - } - return -1; - } - if (!(buf.st_rdev & 0x0080)) { - if (!quiet) { - fprintf (stderr, "%s: not a receiver\n", argv0); - } - return -1; - } - num = buf.st_rdev & 0x007f; - snprintf (name, sizeof (name), fmt, num, "dev"); - memset (str, 0, sizeof (str)); - if (util_read (name, str, sizeof (str)) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to get the device number"); - } - return -1; - } - if (strtoul (str, &endptr, 0) != (buf.st_rdev >> 8)) { - fprintf (stderr, "%s: not a SMPTE 259M-C device\n", argv[0]); - goto NO_STAT; - } - if (*endptr != ':') { - if (!quiet) { - fprintf (stderr, "%s: error reading %s\n", - argv0, name); - } - return -1; - } - - /* Open the file. */ - if (verbose && !quiet) { - printf ("Opening %s.\n", argv[optind]); - } - if ((fd = open (argv[optind], O_RDONLY, 0)) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to open file for reading"); - } - return -1; - } - - /* Get the buffer size */ - snprintf (name, sizeof (name), fmt, num, "bufsize"); - if (util_strtoul (name, &bufsize) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to get " - "the receiver buffer size"); - } - close (fd); - return -1; - } - - /* Allocate some memory */ - if (verbose && !quiet) { - printf ("Allocating %lu bytes of memory.\n", bufsize); - } - if ((data = (unsigned char *)malloc (bufsize)) == NULL) { - if (!quiet) { - fprintf (stderr, "%s: unable to allocate memory\n", - argv0); - } - close (fd); - return -1; - } - - /* Open output file */ - ofd = -1; - if ((argc - optind) == 2) { - if (verbose && !quiet) { - printf ("Opening %s.\n", argv[optind + 1]); - } - if ((ofd = open (argv[optind + 1], - O_CREAT | O_WRONLY | O_TRUNC, - 0664)) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to open output file"); - } - free (data); - close (fd); - return -1; - } - } - - /* Receive the data and estimate the throughput */ - bytes = 0.0; - status_time = 0.0; - pfd.fd = fd; - pfd.events = POLLIN | POLLPRI; - if (verbose && !quiet) { - printf ("Listening for data...\n"); - } - if (gettimeofday (&tv, NULL) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to get time"); - } - free (data); - if (ofd >= 0) { - close (ofd); - } - close (fd); - return -1; - } - lasttime = tv.tv_sec + (double)tv.tv_usec / 1000000; - while (seconds) { - if (poll (&pfd, 1, 1000) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to poll device file"); - } - free (data); - if (ofd >= 0) { - close (ofd); - } - close (fd); - return -1; - } - if (pfd.revents & POLLIN) { - if ((read_ret = read (fd, data, bufsize)) < 0) { - if (!quiet) { - fprintf (stderr, "%s: ", argv0); - perror ("unable to read " - "from device file"); - } - free (data); - if (ofd >= 0) { - close (ofd); - } - close (fd); - return -1; - } - bytes += read_ret; - if (ofd >= 0) { - bytes_written = 0; - while ((read_ret - bytes_written) > 0) { - if ((write_ret = write (ofd, - data + bytes_written, - read_ret - bytes_written)) < 0) { - if (!quiet) { - fprintf (stderr, - "%s: ", - argv0); - perror ("unable to " - "write to " - "output " - "file"); - } - free (data); - close (ofd); - close (fd); - return -1; - } - bytes_written += write_ret; - } - } - } - - - - - if (pfd.revents & POLLPRI) { - if (ioctl (fd, SDI_IOC_RXGETEVENTS, &val) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get receiver event flags"); - goto NO_RUN; - } - if (val & SDI_EVENT_RX_BUFFER) { - fprinttime (stderr, progname); - fprintf (stderr, - "driver receive buffer queue " - "overrun detected\n"); - } - if (val & SDI_EVENT_RX_FIFO) { - fprinttime (stderr, progname); - fprintf (stderr, - "onboard receive FIFO " - "overrun detected\n"); - } - if (val & SDI_EVENT_RX_CARRIER) { - fprinttime (stderr, progname); - fprintf (stderr, - "carrier status " - "change detected\n"); - } - } - - gettimeofday (&tv, NULL); - time_sec = tv.tv_sec + (double)tv.tv_usec / 1000000; - dt = time_sec - lasttime; - if (dt >= 1) { - status_time += dt; - lasttime = time_sec; - if (seconds > 0) { - seconds--; - } - } - if ((period > 0) && (!quiet) && (status_time >= period)) { - printf ("%8.0f bytes in %f seconds = " - "%9.0f bps, status = %i.\n", - bytes, status_time, - 8 * bytes / status_time, val); - bytes = 0.0; - status_time = 0.0; - } - } - free (data); - if (ofd >= 0) { - close (ofd); - } - close (fd); - return 0; - -USAGE: - fprintf (stderr, "Try '%s -h' for more information.\n", argv0); - return -1; - -NO_RUN: - free (data); -NO_STAT: - return -1; -} - diff --git a/quad/Examples/SDI/bt801.c b/quad/Examples/SDI/bt801.c index 952a09295..2c7497e42 100644 --- a/quad/Examples/SDI/bt801.c +++ b/quad/Examples/SDI/bt801.c @@ -3,7 +3,7 @@ * ITU-R BT.801-1 625-line, 50 field/s, 100/0/75/0 colour bar generator for * Linear Systems Ltd. SMPTE 259M-C boards. * - * Copyright (C) 2008 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2008-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -39,6 +39,7 @@ #include #include #include +#include #include "master.h" @@ -52,22 +53,22 @@ struct trs { unsigned short int eav; }; -const struct trs FIELD_1_ACTIVE = { +static const struct trs FIELD_1_ACTIVE = { .sav = 0x200, .eav = 0x274 }; -const struct trs FIELD_1_VERT_BLANKING = { +static const struct trs FIELD_1_VERT_BLANKING = { .sav = 0x2ac, .eav = 0x2d8 }; -const struct trs FIELD_2_ACTIVE = { +static const struct trs FIELD_2_ACTIVE = { .sav = 0x31c, .eav = 0x368 }; -const struct trs FIELD_2_VERT_BLANKING = { +static const struct trs FIELD_2_VERT_BLANKING = { .sav = 0x3b0, .eav = 0x3c4 }; @@ -198,7 +199,7 @@ main (int argc, char **argv) size_t count); char *endptr; unsigned short int buf[TOTAL_SAMPLES]; - uint8_t data[TOTAL_SAMPLES*10/8*TOTAL_LINES], *p = data; + uint8_t *data, *p; size_t framesize, bytes; int i, ret; @@ -234,7 +235,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2008 " + printf ("\nCopyright (C) 2008-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -357,7 +358,16 @@ main (int argc, char **argv) cb[310] = 137; for (i = 311; i <= 359; i++) cb[i] = 128; + /* Allocate memory */ + data = malloc (framesize); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } + /* Generate a frame */ + memset (buf, 0, sizeof (buf)); + p = data; for (i = 1; i <= 22; i++) { mkline (buf, &FIELD_1_VERT_BLANKING); p = pack (p, buf, TOTAL_SAMPLES); @@ -391,6 +401,7 @@ main (int argc, char **argv) data + bytes, framesize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); return -1; } bytes += ret; @@ -399,6 +410,7 @@ main (int argc, char **argv) frames--; } } + free (data); return 0; USAGE: diff --git a/quad/Examples/SDI/capture.c b/quad/Examples/SDI/capture.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDI/eg1.c b/quad/Examples/SDI/eg1.c old mode 100755 new mode 100644 index 7d4558218..33770b2c4 --- a/quad/Examples/SDI/eg1.c +++ b/quad/Examples/SDI/eg1.c @@ -2,7 +2,7 @@ * * SMPTE EG 1 color bar generator for Linear Systems Ltd. SMPTE 259M-C boards. * - * Copyright (C) 2004, 2008 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2004-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -39,6 +39,7 @@ #include #include #include +#include #include "master.h" @@ -366,7 +367,7 @@ main (int argc, char **argv) size_t count); char *endptr; unsigned short int buf[TOTAL_SAMPLES]; - uint8_t data[TOTAL_SAMPLES*10/8*TOTAL_LINES], *p = data; + uint8_t *data, *p; size_t framesize, bytes; int i, ret; @@ -401,7 +402,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2004 " + printf ("\nCopyright (C) 2004-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -424,7 +425,16 @@ main (int argc, char **argv) goto USAGE; } + /* Allocate memory */ + data = malloc (framesize); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } + /* Generate a frame */ + memset (buf, 0, sizeof (buf)); + p = data; for (i = 10; i <= 11; i++) { mkline (buf, FIELD_1, VERT_BLANKING); p = pack (p, buf, TOTAL_SAMPLES); @@ -494,6 +504,7 @@ main (int argc, char **argv) data + bytes, framesize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); return -1; } bytes += ret; @@ -502,6 +513,7 @@ main (int argc, char **argv) frames--; } } + free (data); return 0; USAGE: diff --git a/quad/Examples/SDI/hdsdicfg.c b/quad/Examples/SDI/hdsdicfg.c deleted file mode 100755 index 6a8525af1..000000000 --- a/quad/Examples/SDI/hdsdicfg.c +++ /dev/null @@ -1,395 +0,0 @@ -/* sdicfg.c - * - * SMPTE 259M-C configuration program. - * - * Copyright (C) 2004-2005 Linear Systems Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of Linear Systems Ltd. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY LINEAR SYSTEMS LTD. "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL LINEAR SYSTEMS LTD. OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Linear Systems can be contacted at . - * - */ - -#include -#include -#include -#include -#include -#include - -#include "sdi.h" -#include "master.h" -#include "../util.h" - -#define MAXLEN 256 -#define BUFFERS_FLAG 0x00000001 -#define BUFSIZE_FLAG 0x00000002 -#define CLKSRC_FLAG 0x00000004 -#define MODE_FLAG 0x00000008 - -static const char progname[] = "hdsdicfg"; - -int -main (int argc, char **argv) -{ - const char fmt[] = "/sys/class/sdi/sdi%cx%i/%s"; - int opt; - unsigned int write_flags; - struct stat buf; - int num; - char type, name[MAXLEN], data[MAXLEN]; - unsigned long int buffers, bufsize, clksrc, mode; - int retcode; - char *endptr; - - /* Parse the command line */ - write_flags = 0; - buffers = 0; - bufsize = 0; - clksrc = 0; - mode = 0; - while ((opt = getopt (argc, argv, "b:hm:s:Vx:")) != -1) { - switch (opt) { - case 'b': - write_flags |= BUFFERS_FLAG; - buffers = strtoul (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid number of buffers: %s\n", - argv[0], optarg); - return -1; - } - break; - case 'h': - printf ("Usage: %s [OPTION]... DEVICE_FILE\n", - argv[0]); - printf ("Configure a SMPTE 274M interface.\n\n"); - printf (" -b BUFFERS\tset the number of buffers\n"); - printf (" -h\t\tdisplay this help and exit\n"); - printf (" -m MODE\tset the operating mode\n"); - printf (" -s BUFSIZE\tset the buffer size\n"); - printf (" -V\t\toutput version information " - "and exit\n"); - printf (" -x CLKSRC\tset the clock source\n"); - printf ("\nIf no options are specified, " - "the current configuration is displayed.\n"); - printf ("\nBUFFERS must be two or more.\n"); - printf ("\nCLKSRC is valid only for transmitters and " - "may be:\n" - "\t0 (onboard oscillator)\n" - "\t1 (external reference)\n" - "\t2 (recovered receive clock)\n"); - printf ("\nMODE may be:\n" - "\t0 (raw mode)\n" - "\t1 (sync mode)\n" - "\t2 (deinterlaced mode) \n"); - printf ("\nBUFSIZE must be " - "a positive multiple of four,\n" - "and at least 1024 bytes for transmitters.\n"); - printf ("\nReport bugs to .\n"); - return 0; - case 'm': - write_flags |= MODE_FLAG; - mode = strtoul (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid mode: %s\n", - argv[0], optarg); - return -1; - } - break; - case 's': - write_flags |= BUFSIZE_FLAG; - bufsize = strtoul (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid buffer size: %s\n", - argv[0], optarg); - return -1; - } - break; - case 'V': - printf ("%s from master-%s (%s)\n", progname, - MASTER_DRIVER_VERSION, - MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2004-2005 " - "Linear Systems Ltd.\n" - "This is free software; " - "see the source for copying conditions. " - "There is NO\n" - "warranty; not even for MERCHANTABILITY " - "or FITNESS FOR A PARTICULAR PURPOSE.\n"); - return 0; - case 'x': - write_flags |= CLKSRC_FLAG; - clksrc = strtoul (optarg, &endptr, 0); - if (*endptr != '\0') { - fprintf (stderr, - "%s: invalid clock source: %s\n", - argv[0], optarg); - return -1; - } - break; - case '?': - goto USAGE; - } - } - - /* Check the number of arguments */ - if ((argc - optind) < 1) { - fprintf (stderr, "%s: missing arguments\n", argv[0]); - goto USAGE; - } else if ((argc - optind) > 1) { - fprintf (stderr, "%s: extra operand\n", argv[0]); - goto USAGE; - } - - /* Get the sysfs info */ - memset (&buf, 0, sizeof (buf)); - if (stat (argv[optind], &buf) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the file status"); - return -1; - } - if (!S_ISCHR (buf.st_mode)) { - fprintf (stderr, "%s: not a character device\n", argv[0]); - return -1; - } - type = (buf.st_rdev & 0x0080) ? 'r' : 't'; - num = buf.st_rdev & 0x007f; - snprintf (name, sizeof (name), fmt, type, num, "dev"); - memset (data, 0, sizeof (data)); - if (util_read (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the device number"); - return -1; - } - if (strtoul (data, &endptr, 0) != (buf.st_rdev >> 8)) { - fprintf (stderr, "%s: not a SMPTE 259M-C device\n", argv[0]); - return -1; - } - if (*endptr != ':') { - fprintf (stderr, "%s: error reading %s\n", argv[0], name); - return -1; - } - - retcode = 0; - printf ("%s:\n", argv[optind]); - if (write_flags) { - if (write_flags & BUFFERS_FLAG) { - snprintf (name, sizeof (name), - fmt, type, num, "buffers"); - snprintf (data, sizeof (data), "%lu\n", buffers); - if (util_write (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to set " - "the number of buffers"); - return -1; - } - printf ("\tSet number of buffers = %lu.\n", buffers); - } - if (write_flags & BUFSIZE_FLAG) { - snprintf (name, sizeof (name), - fmt, type, num, "bufsize"); - snprintf (data, sizeof (data), "%lu\n", bufsize); - if (util_write (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to set " - "the buffer size"); - return -1; - } - printf ("\tSet buffer size = %lu bytes.\n", bufsize); - } - if (write_flags & CLKSRC_FLAG) { - snprintf (name, sizeof (name), - fmt, type, num, "clock_source"); - snprintf (data, sizeof (data), "%lu\n", clksrc); - if (util_write (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to set " - "the clock source"); - return -1; - } - switch (clksrc) { - case SDI_CTL_TX_CLKSRC_ONBOARD: - printf ("\tUsing onboard oscillator.\n"); - break; - case SDI_CTL_TX_CLKSRC_EXT: - printf ("\tUsing external reference.\n"); - break; - case SDI_CTL_TX_CLKSRC_RX: - printf ("\tUsing recovered receive clock.\n"); - break; - default: - printf ("\tSet clock source = %lu.\n", clksrc); - break; - } - } - if (write_flags & MODE_FLAG) { - snprintf (name, sizeof (name), - fmt, type, num, "mode"); - snprintf (data, sizeof (data), "%lu\n", mode); - if (util_write (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to set " - "the interface operating mode"); - return -1; - } - if (type == 'r') { - switch (mode) { - case 0: - printf ("\tReceiving in " - "raw mode.\n"); - break; - case 1: - printf ("\tPacking four 10-bit words " - "into every five bytes. Synchronized mode. Data discarded until a TRS sequence is detected\n"); - break; - case 2: - printf ("\tDeinterlacing fields 0 and 1 in onboard memory.\n"); //debug: verify this - break; - default: - printf ("\tSet mode = %lu.\n", mode); - break; - } - } else { - switch (mode) { - case 0: - printf ("\tAssuming " - "raw data.\n"); - break; - case 1: - printf ("\tAssuming " - "synchronized data.\n"); - break; - case 2: - printf ("\tAssuming " - "deinterlaced data.\n"); - break; - default: - printf ("\tSet mode = %lu.\n", mode); - break; - } - } - } - } else { - snprintf (name, sizeof (name), - fmt, type, num, "buffers"); - if (util_strtoul (name, &buffers) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the number of buffers"); - retcode = -1; - } - - snprintf (name, sizeof (name), - fmt, type, num, "bufsize"); - if (util_strtoul (name, &bufsize) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the buffer size"); - retcode = -1; - } - - printf ("\t%lu x %lu-byte buffers\n", - buffers, bufsize); - - if (type == 'r') { - snprintf (name, sizeof (name), - fmt, type, num, "mode"); - if (util_strtoul (name, &mode) > 0) { - /* Don't complain on an error, - * since this parameter may not exist. */ - printf ("\tMode: %lu ", mode); - switch (mode) { - case 0: - printf ("(assume raw data)\n"); - break; - case 1: - printf ("(assume synchronized data)\n"); - break; - case 2: - printf ("(assume deinterlaced data)\n"); - break; - default: - printf ("(unknown)\n"); - break; - } - } - } else { - snprintf (name, sizeof (name), - fmt, type, num, "clock_source"); - if (util_strtoul (name, &clksrc) > 0) { - /* Don't complain on an error, - * since this parameter may not exist. */ - printf ("\tClock source: %lu ", clksrc); - switch (clksrc) { - case SDI_CTL_TX_CLKSRC_ONBOARD: - printf ("(onboard oscillator)\n"); - break; - case SDI_CTL_TX_CLKSRC_EXT: - printf ("(external reference)\n"); - break; - case SDI_CTL_TX_CLKSRC_RX: - printf ("(recovered receive clock)\n"); - break; - default: - printf ("(unknown)\n"); - break; - } - } - - snprintf (name, sizeof (name), - fmt, type, num, "mode"); - if (util_strtoul (name, &mode) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get " - "the interface operating mode"); - retcode = -1; - } - printf ("\tMode: %lu ", mode); - switch (mode) { - case 0: - printf ("(assume raw data)\n"); - break; - case 1: - printf ("(assume synchronized data)\n"); - break; - case 2: - printf ("(assume deinterlaced data)\n"); - break; - default: - printf ("(unknown)\n"); - break; - } - } - } - return retcode; - -USAGE: - fprintf (stderr, "Try '%s -h' for more information.\n", argv[0]); - return -1; -} - diff --git a/quad/Examples/SDI/mcapture.c b/quad/Examples/SDI/mcapture.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDI/mplayout.c b/quad/Examples/SDI/mplayout.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDI/playout.c b/quad/Examples/SDI/playout.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDI/sdicfg.c b/quad/Examples/SDI/sdicfg.c old mode 100755 new mode 100644 index ce6cb31b4..c3532fdef --- a/quad/Examples/SDI/sdicfg.c +++ b/quad/Examples/SDI/sdicfg.c @@ -1,8 +1,8 @@ /* sdicfg.c * - * SMPTE 259M-C configuration program. + * Raw SDI configuration program. * - * Copyright (C) 2004-2005 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2004-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -87,19 +87,19 @@ main (int argc, char **argv) case 'h': printf ("Usage: %s [OPTION]... DEVICE_FILE\n", argv[0]); - printf ("Configure a SMPTE 259M-C interface.\n\n"); + printf ("Configure a raw SDI interface.\n\n"); printf (" -b BUFFERS\tset the number of buffers\n"); printf (" -h\t\tdisplay this help and exit\n"); printf (" -m MODE\tset the operating mode\n"); printf (" -s BUFSIZE\tset the buffer size\n"); printf (" -V\t\toutput version information " "and exit\n"); - printf (" -x CLKSRC\tset the clock source\n"); + printf (" -x CLKSRC\tset the clock source " + "(transmitters only)\n"); printf ("\nIf no options are specified, " "the current configuration is displayed.\n"); printf ("\nBUFFERS must be two or more.\n"); - printf ("\nCLKSRC is valid only for transmitters and " - "may be:\n" + printf ("\nCLKSRC may be:\n" "\t0 (onboard oscillator)\n" "\t1 (external reference)\n" "\t2 (recovered receive clock)\n"); @@ -136,7 +136,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2004-2005 " + printf ("\nCopyright (C) 2004-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -184,12 +184,12 @@ main (int argc, char **argv) snprintf (name, sizeof (name), fmt, type, num, "dev"); memset (data, 0, sizeof (data)); if (util_read (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the device number"); + fprintf (stderr, "%s: error reading %s: ", argv[0], name); + perror (NULL); return -1; } if (strtoul (data, &endptr, 0) != (buf.st_rdev >> 8)) { - fprintf (stderr, "%s: not a SMPTE 259M-C device\n", argv[0]); + fprintf (stderr, "%s: not a raw SDI device\n", argv[0]); return -1; } if (*endptr != ':') { @@ -225,6 +225,12 @@ main (int argc, char **argv) printf ("\tSet buffer size = %lu bytes.\n", bufsize); } if (write_flags & CLKSRC_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the clock source: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "clock_source"); snprintf (data, sizeof (data), "%lu\n", clksrc); diff --git a/quad/Examples/SDI/sdirxcfg.c b/quad/Examples/SDI/sdirxcfg.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDI/sditxcfg.c b/quad/Examples/SDI/sditxcfg.c old mode 100755 new mode 100644 diff --git a/quad/Examples/SDIAUDIO/Makefile b/quad/Examples/SDIAUDIO/Makefile deleted file mode 100644 index b5f6e17a0..000000000 --- a/quad/Examples/SDIAUDIO/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# Makefile for the SMPTE 259M-C and SMPTE 292M audio example programs - -SHELL = /bin/sh -INSTALL = install - -INCLUDEDIR = ../../include -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -CFLAGS = -O2 -Wall -W -I$(INCLUDEDIR) -D_LARGEFILE_SOURCE \ - $(shell getconf LFS_CFLAGS; getconf LFS_LDFLAGS; getconf LFS_LIBS) -TARGETS = rp155 ac3aes3 aes3data audiocapture audioplayout \ - sdiaudiocfg sdiaudiorxcfg sdiaudiotxcfg - -.c: - $(CC) $(CFLAGS) -o $@ $@.c - -all: $(TARGETS) - -rp155: rp155.c $(INCLUDEDIR)/master.h - $(CC) $(CFLAGS) -lm -o $@ $@.c -ac3aes3: ac3aes3.c $(INCLUDEDIR)/master.h -aes3data: aes3data.c $(INCLUDEDIR)/master.h -audiocapture: audiocapture.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -audioplayout: audioplayout.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdiaudiocfg: sdiaudiocfg.c $(INCLUDEDIR)/sdiaudio.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdiaudiorxcfg: sdiaudiorxcfg.c $(INCLUDEDIR)/sdiaudio.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdiaudiotxcfg: sdiaudiotxcfg.c $(INCLUDEDIR)/sdiaudio.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o - -clean: - $(RM) *.o *~ core $(TARGETS) - -install: all - $(INSTALL) $(TARGETS) $(bindir) - -uninstall: - $(RM) $(foreach prog,$(TARGETS),$(bindir)/$(prog)) - diff --git a/quad/Examples/SDIAUDIO/rp155.c b/quad/Examples/SDIAUDIO/rp155.c index ef103fbee..34b3945f1 100644 --- a/quad/Examples/SDIAUDIO/rp155.c +++ b/quad/Examples/SDIAUDIO/rp155.c @@ -2,7 +2,7 @@ * * SMPTE RP 155 tone generator for Linear Systems Ltd. SMPTE 292M boards. * - * Copyright (C) 2009 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2009-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -43,9 +43,6 @@ #include "master.h" -#define MAX_CHANNELS 8 -#define MAX_SAMPLING_RATE 48000 -#define MAX_SAMPLE_SIZE 32 #define PI 3.141592654 static const char progname[] = "rp155"; @@ -56,17 +53,17 @@ main (int argc, char **argv) int opt, seconds; char *endptr; unsigned int channels, sampling_rate, sample_size, i, j; - uint8_t data[MAX_CHANNELS * MAX_SAMPLING_RATE * MAX_SAMPLE_SIZE]; - int32_t *p32 = (int32_t *)data; - int16_t *p16 = (int16_t *)data; + unsigned int avsync_period, silent, avsync_count; + uint8_t *data, *silence, *p; size_t wavelength, bytes; int ret; channels = 2; + avsync_period = 0; seconds = -1; /* Loop forever */ sampling_rate = 48000; sample_size = 16; - while ((opt = getopt (argc, argv, "c:hn:r:s:V")) != -1) { + while ((opt = getopt (argc, argv, "c:hm:n:r:s:V")) != -1) { switch (opt) { case 'c': channels = strtoul (optarg, &endptr, 0); @@ -87,6 +84,8 @@ main (int argc, char **argv) "SMPTE 292M board.\n\n"); printf (" -c CHANNELS\tnumber of channels\n"); printf (" -h\t\tdisplay this help and exit\n"); + printf (" -m PERIOD\tswitch between tone and silence " + "every PERIOD seconds\n"); printf (" -n NUM\tstop after NUM seconds\n"); printf (" -r RATE\tsampling rate in Hz\n"); printf (" -s SIZE\tsample size in bits\n"); @@ -100,6 +99,15 @@ main (int argc, char **argv) "\t16 (default), or 32\n"); printf ("\nReport bugs to .\n"); return 0; + case 'm': + avsync_period = strtol (optarg, &endptr, 0); + if (*endptr != '\0') { + fprintf (stderr, + "%s: invalid period: %s\n", + argv[0], optarg); + return -1; + } + break; case 'n': seconds = strtol (optarg, &endptr, 0); if (*endptr != '\0') { @@ -136,7 +144,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2009 " + printf ("\nCopyright (C) 2009-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -155,8 +163,15 @@ main (int argc, char **argv) goto USAGE; } - /* Generate one second */ + /* Generate one second of data */ + data = malloc (channels * sampling_rate * sample_size / 8); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } if (sample_size == 16) { + int16_t *p16 = (int16_t *)data; + for (i = 0; i < sampling_rate; i++) { for (j = 0; j < channels; j++) { *p16++ = (int)(0x0ccd * sin (2 * PI * i / sampling_rate * 1000) + 0.5); @@ -164,6 +179,8 @@ main (int argc, char **argv) } wavelength = channels * sampling_rate * sizeof (*p16); } else { + int32_t *p32 = (int32_t *)data; + for (i = 0; i < sampling_rate; i++) { for (j = 0; j < channels; j++) { *p32++ = (int)(0x0cccd * sin (2 * PI * i / sampling_rate * 1000) + 0.5) << 12; @@ -172,22 +189,47 @@ main (int argc, char **argv) wavelength = channels * sampling_rate * sizeof (*p32); } + /* Generate one second of silence */ + silence = malloc (channels * sampling_rate * sample_size / 8); + if (!silence) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + free (data); + return -1; + } + memset (silence, 0, sizeof (silence)); + + silent = 0; + avsync_count = 1; + p = data; while (seconds) { /* Output one second */ bytes = 0; while (bytes < wavelength) { if ((ret = write (STDOUT_FILENO, - data + bytes, wavelength - bytes)) < 0) { + p + bytes, wavelength - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); + free (silence); return -1; } bytes += ret; } + if (avsync_period > 0) { + if (avsync_count == avsync_period) { + avsync_count = 1; + silent = !silent; + p = silent ? silence : data; + } else { + avsync_count++; + } + } if (seconds > 0) { seconds--; } } + free (data); + free (silence); return 0; USAGE: diff --git a/quad/Examples/SDIAUDIO/sdiaudiocfg.c b/quad/Examples/SDIAUDIO/sdiaudiocfg.c index 505a7f787..3591ce02b 100644 --- a/quad/Examples/SDIAUDIO/sdiaudiocfg.c +++ b/quad/Examples/SDIAUDIO/sdiaudiocfg.c @@ -1,8 +1,8 @@ /* sdiaudiocfg.c * - * SMPTE 292M and SMPTE 259M-C audio configuration program. + * SDI audio configuration program. * - * Copyright (C) 2009 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2009-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -101,12 +101,14 @@ main (int argc, char **argv) case 'h': printf ("Usage: %s [OPTION]... DEVICE_FILE\n", argv[0]); - printf ("Configure an audio interface.\n\n"); + printf ("Configure an SDI audio interface.\n\n"); printf (" -b BUFFERS\tset the number of buffers\n"); printf (" -c CHANNELS\tset the audio channel enable\n"); printf (" -h\t\tdisplay this help and exit\n"); - printf (" -n NONAUDIO\tset PCM or non-audio\n"); - printf (" -r SAMPLERATE\tset the audio sample rate\n"); + printf (" -n NONAUDIO\tset PCM or non-audio " + "(transmitters only)\n"); + printf (" -r SAMPLERATE\tset the audio sample rate " + "(transmitters only)\n"); printf (" -s BUFSIZE\tset the buffer size\n"); printf (" -V\t\toutput version information " "and exit\n"); @@ -120,13 +122,11 @@ main (int argc, char **argv) "\t4 (4 channels)\n" "\t6 (6 channels)\n" "\t8 (8 channels)\n"); - printf ("\nNONAUDIO is valid only for transmitters " - "and may be:\n" + printf ("\nNONAUDIO may be:\n" "\t0x0000 (PCM)\n" "\t0x00ff (non-audio)\n" "\tbetween 0x0000 and 0x00ff (mixed audio and data)\n"); - printf ("\nSAMPLERATE is valid only for transmitters " - "and may be:\n" + printf ("\nSAMPLERATE may be:\n" "\t32000 (32 kHz)\n" "\t44100 (44.1 kHz)\n" "\t48000 (48 kHz)\n"); @@ -173,7 +173,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2009 " + printf ("\nCopyright (C) 2009-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -221,12 +221,12 @@ main (int argc, char **argv) snprintf (name, sizeof (name), fmt, type, num, "dev"); memset (data, 0, sizeof (data)); if (util_read (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the device number"); + fprintf (stderr, "%s: error reading %s: ", argv[0], name); + perror (NULL); return -1; } if (strtoul (data, &endptr, 0) != (buf.st_rdev >> 8)) { - fprintf (stderr, "%s: not an audio device\n", argv[0]); + fprintf (stderr, "%s: not an SDI audio device\n", argv[0]); return -1; } if (*endptr != ':') { @@ -288,6 +288,13 @@ main (int argc, char **argv) } } if (write_flags & SAMPLERATE_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the " + "interface audio sample rate: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "sample_rate"); snprintf (data, sizeof (data), "%lu\n", samplerate); @@ -346,6 +353,13 @@ main (int argc, char **argv) } } if (write_flags & NONAUDIO_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the " + "interface non-audio: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "non_audio"); snprintf (data, sizeof (data), "0x%04lX\n", nonaudio); diff --git a/quad/Examples/SDIVIDEO/Makefile b/quad/Examples/SDIVIDEO/Makefile deleted file mode 100644 index c80a928d2..000000000 --- a/quad/Examples/SDIVIDEO/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# Makefile for the SMPTE 259M-C and SMPTE 292M video example programs - -SHELL = /bin/sh -INSTALL = install - -INCLUDEDIR = ../../include -prefix = /usr/local -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -CFLAGS = -O2 -Wall -W -I$(INCLUDEDIR) -D_LARGEFILE_SOURCE \ - $(shell getconf LFS_CFLAGS; getconf LFS_LDFLAGS; getconf LFS_LIBS) -TARGETS = bt801video eg1video mvideocapture mvideoplayout rp219 \ - sdivideocfg sdivideorxcfg sdivideotxcfg \ - videocapture videoplayout - -.c: - $(CC) $(CFLAGS) -o $@ $@.c - -all: $(TARGETS) - -bt801video: bt801video.c $(INCLUDEDIR)/master.h -eg1video: eg1video.c $(INCLUDEDIR)/master.h -mvideocapture: mvideocapture.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -mvideoplayout: mvideoplayout.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -rp219: rp219.c $(INCLUDEDIR)/master.h -sdivideocfg: sdivideocfg.c $(INCLUDEDIR)/sdivideo.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdivideorxcfg: sdivideorxcfg.c $(INCLUDEDIR)/sdivideo.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -sdivideotxcfg: sdivideotxcfg.c $(INCLUDEDIR)/sdivideo.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -videocapture: videocapture.c $(INCLUDEDIR)/sdivideo.h $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o -videoplayout: videoplayout.c $(INCLUDEDIR)/master.h ../util.o - $(CC) $(CFLAGS) -o $@ $@.c ../util.o - -clean: - $(RM) *.o *~ core $(TARGETS) - -install: all - $(INSTALL) $(TARGETS) $(bindir) - -uninstall: - $(RM) $(foreach prog,$(TARGETS),$(bindir)/$(prog)) - diff --git a/quad/Examples/SDIVIDEO/bt801video.c b/quad/Examples/SDIVIDEO/bt801video.c index 37e99ea7b..739d77062 100644 --- a/quad/Examples/SDIVIDEO/bt801video.c +++ b/quad/Examples/SDIVIDEO/bt801video.c @@ -3,7 +3,7 @@ * ITU-R BT.801-1 625-line, 50 field/s, 100/0/75/0 colour bar generator for * Linear Systems Ltd. SMPTE 259M-C boards. * - * Copyright (C) 2008-2009 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2008-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -43,6 +43,10 @@ #include "master.h" +#if __BYTE_ORDER == __BIG_ENDIAN +#error Big endian architecture not supported +#endif + #define TOTAL_SAMPLES 1728 #define ACTIVE_SAMPLES 1440 #define TOTAL_LINES 625 @@ -55,22 +59,22 @@ struct trs { unsigned short int eav; }; -const struct trs FIELD_1_ACTIVE = { +static const struct trs FIELD_1_ACTIVE = { .sav = 0x200, .eav = 0x274 }; -const struct trs FIELD_1_VERT_BLANKING = { +static const struct trs FIELD_1_VERT_BLANKING = { .sav = 0x2ac, .eav = 0x2d8 }; -const struct trs FIELD_2_ACTIVE = { +static const struct trs FIELD_2_ACTIVE = { .sav = 0x31c, .eav = 0x368 }; -const struct trs FIELD_2_VERT_BLANKING = { +static const struct trs FIELD_2_VERT_BLANKING = { .sav = 0x3b0, .eav = 0x3c4 }; @@ -86,7 +90,14 @@ unsigned short int cb[360]; /* Static function prototypes */ static int mkline (unsigned short int *buf, - const struct line_info *info); + const struct line_info *info, + int black); +static int mkframe (uint8_t *p, + struct line_info info, + int black, + uint8_t *(*pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count)); static uint8_t *pack_v210 (uint8_t *outbuf, unsigned short int *inbuf, size_t count); @@ -96,44 +107,49 @@ static uint8_t *pack_uyvy (uint8_t *outbuf, static uint8_t *pack10 (uint8_t *outbuf, unsigned short int *inbuf, size_t count); +static uint8_t *pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); /** * mkline - generate one line * @buf: pointer to a buffer * @info: pointer to a line information structure + * @black: black frame flag * * Returns a negative error code on failure and zero on success. **/ static int mkline (unsigned short int *buf, - const struct line_info *info) + const struct line_info *info, + int black) { unsigned short int *p = buf; - unsigned short int *py = y, *pcr = cr, *pcb = cb; - unsigned int samples = info->blanking ? TOTAL_SAMPLES : ACTIVE_SAMPLES; + unsigned short int *py = y, *pcr = cr, *pcb = cb, sum; + unsigned int samples = ACTIVE_SAMPLES; - if (info->blanking) { - /* EAV */ - *p++ = 0x3ff; - *p++ = 0x000; - *p++ = 0x000; - *p++ = info->xyz->eav; - /* Horizontal blanking */ - while (p < (buf + 284)) { + if (black) { + while (p < (buf + samples)) { *p++ = 0x200; *p++ = 0x040; *p++ = 0x200; *p++ = 0x040; } - /* SAV */ - *p++ = 0x3ff; - *p++ = 0x000; - *p++ = 0x000; - *p++ = info->xyz->sav; - } - /* Active region */ - if ((info->xyz == &FIELD_1_VERT_BLANKING) || + } else if ((info->xyz == &FIELD_1_VERT_BLANKING) || (info->xyz == &FIELD_2_VERT_BLANKING)) { + /* Ancillary data packet marked for deletion */ + *p++ = 0; + *p++ = 0x3ff; + *p++ = 0x3ff; + *p++ = 0x180; sum = 0x180 & 0x1ff; /* DID */ + *p++ = 0x200; sum += 0x200 & 0x1ff; + *p++ = 0x203; sum += 0x203 & 0x1ff; /* DC */ + *p++ = 0x18a; sum += 0x18a & 0x1ff; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = (sum & 0x1ff) | ((sum & 0x100) ? 0 : 0x200); + *p++ = 0x200; + *p++ = 0x040; while (p < (buf + samples)) { *p++ = 0x200; *p++ = 0x040; @@ -151,6 +167,77 @@ mkline (unsigned short int *buf, return 0; } +/** + * mkframe - generate one frame + * @p: pointer to a buffer + * @info: line information structure + * @black: black frame flag + * @pack: pointer to packing function + * + * Returns a negative error code on failure and zero on success. + **/ +static int +mkframe (uint8_t *p, + struct line_info info, + int black, + uint8_t *(*pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count)) +{ + uint8_t *(*vanc_pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); + unsigned short int buf[TOTAL_SAMPLES]; + size_t elements = ACTIVE_SAMPLES; + unsigned int i; + + if (pack == pack_v210) { + vanc_pack = pack_v210; + } else { + vanc_pack = pack_v216; + } + memset (buf, 0, sizeof (buf)); + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (i = 1; i <= 21; i++) { + mkline (buf, &info, 1); + p = vanc_pack (p, buf, elements); + } + mkline (buf, &info, 0); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_ACTIVE; + for (i = 23; i <= 310; i++) { + mkline (buf, &info, black); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (i = 311; i <= 312; i++) { + mkline (buf, &info, 1); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_2_VERT_BLANKING; + for (i = 313; i <= 335; i++) { + mkline (buf, &info, 1); + p = vanc_pack (p, buf, elements); + } + } + info.xyz = &FIELD_2_ACTIVE; + for (i = 336; i <= 623; i++) { + mkline (buf, &info, black); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_2_VERT_BLANKING; + for (i = 624; i <= 625; i++) { + mkline (buf, &info, 1); + p = vanc_pack (p, buf, elements); + } + } + return 0; +} + /** * pack_v210 - pack a line of v210 data * @outbuf: pointer to the output buffer @@ -167,7 +254,7 @@ pack_v210 (uint8_t *outbuf, unsigned short int *inp = inbuf; uint8_t *outp = outbuf; - count = (count / 96) * 96 + ((count % 96) ? 96 : 0); + count = (count / 48) * 48 + ((count % 48) ? 48 : 0); while (inp < (inbuf + count)) { *outp++ = *inp & 0xff; *outp = *inp++ >> 8; @@ -231,29 +318,50 @@ pack10 (uint8_t *outbuf, return outp; } +/** + * pack_v216 - pack a line of v216 data + * @outbuf: pointer to the output buffer + * @inbuf: pointer to the input buffer + * @count: number of elements in the buffer + * + * Returns a pointer to the next output location. + **/ +static uint8_t * +pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count) +{ + unsigned short int *inp = inbuf; + uint16_t *outp = (uint16_t *)outbuf; + + while (inp < (inbuf + count)) { + *outp++ = *inp++ << 6; /* Little endian only */ + } + return (uint8_t *)outp; +} + int main (int argc, char **argv) { - int opt, frames; + int opt, frames, avsync_period; uint8_t *(*pack)(uint8_t *outbuf, unsigned short int *inbuf, size_t count); struct line_info info; char *endptr; - unsigned short int buf[TOTAL_SAMPLES]; - uint8_t data[TOTAL_SAMPLES*4/3*TOTAL_LINES], *p = data; - size_t samples, framesize, bytes; + uint8_t *data, *black_frame, *p; + size_t framesize, bytes; + unsigned int black, avsync_sum, n, d; int i, ret; + avsync_period = 0; frames = -1; /* Generate an infinite number of frames */ pack = pack_uyvy; info.blanking = 0; - samples = ACTIVE_SAMPLES; - while ((opt = getopt (argc, argv, "bhn:p:V")) != -1) { + while ((opt = getopt (argc, argv, "ahm:n:p:V")) != -1) { switch (opt) { - case 'b': + case 'a': info.blanking = 1; - samples = TOTAL_SAMPLES; break; case 'h': printf ("Usage: %s [OPTION]...\n", argv[0]); @@ -262,8 +370,10 @@ main (int argc, char **argv) "for transmission by " "a Linear Systems Ltd. " "SMPTE 259M-C board.\n\n"); - printf (" -b\t\tadd blanking\n"); + printf (" -a\t\tinclude vertical ancillary space\n"); printf (" -h\t\tdisplay this help and exit\n"); + printf (" -m PERIOD\tswitch between bars and black " + "every PERIOD seconds\n"); printf (" -n NUM\tstop after NUM frames\n"); printf (" -p PACKING\tpixel packing\n"); printf (" -V\t\toutput version information " @@ -274,6 +384,16 @@ main (int argc, char **argv) "\traw\n"); printf ("\nReport bugs to .\n"); return 0; + case 'm': + avsync_period = strtol (optarg, &endptr, 0); + if ((*endptr != '\0') || + (avsync_period > 35000)) { + fprintf (stderr, + "%s: invalid period: %s\n", + argv[0], optarg); + return -1; + } + break; case 'n': frames = strtol (optarg, &endptr, 0); if (*endptr != '\0') { @@ -301,7 +421,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2008-2009 " + printf ("\nCopyright (C) 2008-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -420,51 +540,15 @@ main (int argc, char **argv) cb[310] = 137; for (i = 311; i <= 359; i++) cb[i] = 128; - /* Generate a frame */ - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (i = 1; i <= 22; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - } - info.xyz = &FIELD_1_ACTIVE; - for (i = 23; i <= 310; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (i = 311; i <= 312; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - info.xyz = &FIELD_2_VERT_BLANKING; - for (i = 313; i <= 335; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - } - info.xyz = &FIELD_2_ACTIVE; - for (i = 336; i <= 623; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - if (info.blanking) { - info.xyz = &FIELD_2_VERT_BLANKING; - for (i = 624; i <= 625; i++) { - mkline (buf, &info); - p = pack (p, buf, samples); - } - } - + /* Calculate the frame size */ if (info.blanking) { if (pack == pack_v210) { - framesize = TOTAL_SAMPLES * 4 / 3 * TOTAL_LINES; + framesize = ACTIVE_SAMPLES * 4 / 3 * TOTAL_LINES; } else if (pack == pack_uyvy) { - framesize = TOTAL_SAMPLES * TOTAL_LINES; + framesize = ACTIVE_SAMPLES * ACTIVE_LINES + + ACTIVE_SAMPLES * (TOTAL_LINES - ACTIVE_LINES) * 2; } else { - framesize = TOTAL_SAMPLES * 10 / 8 * TOTAL_LINES; + framesize = ACTIVE_SAMPLES * 10 / 8 * TOTAL_LINES; } } else { if (pack == pack_v210) { @@ -475,22 +559,67 @@ main (int argc, char **argv) framesize = ACTIVE_SAMPLES * 10 / 8 * ACTIVE_LINES; } } + + /* Allocate memory */ + data = malloc (framesize); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } + + /* Generate a frame */ + mkframe (data, info, 0, pack); + + if (avsync_period > 0) { + /* Allocate memory */ + black_frame = malloc (framesize); + if (!black_frame) { + fprintf (stderr, "%s: unable to allocate memory\n", + argv[0]); + free (data); + return -1; + } + + /* Generate a black frame */ + mkframe (black_frame, info, 1, pack); + } else { + black_frame = NULL; + } + + black = 0; + avsync_sum = 0; + n = 25 * avsync_period; + d = 1; + p = data; while (frames) { /* Output the frame */ bytes = 0; while (bytes < framesize) { if ((ret = write (STDOUT_FILENO, - data + bytes, framesize - bytes)) < 0) { + p + bytes, framesize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); + free (black_frame); return -1; } bytes += ret; } + if (avsync_period > 0) { + if (avsync_sum >= n) { + avsync_sum = avsync_sum - n + d; + black = !black; + p = black ? black_frame : data; + } else { + avsync_sum += d; + } + } if (frames > 0) { frames--; } } + free (data); + free (black_frame); return 0; USAGE: diff --git a/quad/Examples/SDIVIDEO/eg1video.c b/quad/Examples/SDIVIDEO/eg1video.c index 0104d8161..bc4c6f796 100644 --- a/quad/Examples/SDIVIDEO/eg1video.c +++ b/quad/Examples/SDIVIDEO/eg1video.c @@ -2,7 +2,7 @@ * * SMPTE EG 1 color bar generator for Linear Systems Ltd. SMPTE 259M-C boards. * - * Copyright (C) 2004-2009 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2004-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -43,6 +43,10 @@ #include "master.h" +#if __BYTE_ORDER == __BIG_ENDIAN +#error Big endian architecture not supported +#endif + #define TOTAL_SAMPLES 1716 #define ACTIVE_SAMPLES 1440 #define TOTAL_LINES 525 @@ -53,28 +57,29 @@ #define MAIN_SET 1 #define CHROMA_SET 2 #define BLACK_SET 3 +#define CEA_608 4 struct trs { unsigned short int sav; unsigned short int eav; }; -const struct trs FIELD_1_ACTIVE = { +static const struct trs FIELD_1_ACTIVE = { .sav = 0x200, .eav = 0x274 }; -const struct trs FIELD_1_VERT_BLANKING = { +static const struct trs FIELD_1_VERT_BLANKING = { .sav = 0x2ac, .eav = 0x2d8 }; -const struct trs FIELD_2_ACTIVE = { +static const struct trs FIELD_2_ACTIVE = { .sav = 0x31c, .eav = 0x368 }; -const struct trs FIELD_2_VERT_BLANKING = { +static const struct trs FIELD_2_VERT_BLANKING = { .sav = 0x3b0, .eav = 0x3c4 }; @@ -97,6 +102,9 @@ static uint8_t *pack_uyvy (uint8_t *outbuf, static uint8_t *pack10 (uint8_t *outbuf, unsigned short int *inbuf, size_t count); +static uint8_t *pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); static const char progname[] = "eg1video"; @@ -110,33 +118,13 @@ static const char progname[] = "eg1video"; **/ static int mkline (unsigned short int *buf, - const struct line_info *info, + const struct line_info *info __attribute__((unused)), unsigned int pattern) { const unsigned int b = 205; - unsigned short int *p = buf, *endp; - unsigned int samples = info->blanking ? TOTAL_SAMPLES : ACTIVE_SAMPLES; + unsigned short int *p = buf, *endp, sum; + unsigned int samples = ACTIVE_SAMPLES; - if (info->blanking) { - /* EAV */ - *p++ = 0x3ff; - *p++ = 0x000; - *p++ = 0x000; - *p++ = info->xyz->eav; - /* Horizontal blanking */ - while (p < (buf + 272)) { - *p++ = 0x200; - *p++ = 0x040; - *p++ = 0x200; - *p++ = 0x040; - } - /* SAV */ - *p++ = 0x3ff; - *p++ = 0x000; - *p++ = 0x000; - *p++ = info->xyz->sav; - } - /* Active region */ endp = p; switch (pattern) { default: @@ -327,6 +315,123 @@ mkline (unsigned short int *buf, *p++ = 0x040; } break; + case CEA_608: + /* CEA-608 packet */ + *p++ = 0; + *p++ = 0x3ff; + *p++ = 0x3ff; + *p++ = 0x161; sum = 0x161 & 0x1ff; /* DID */ + *p++ = 0x102; sum += 0x102 & 0x1ff; /* SDID */ + *p++ = 0x203; sum += 0x203 & 0x1ff; /* DC */ + *p++ = 0x18a; sum += 0x18a & 0x1ff; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = (sum & 0x1ff) | ((sum & 0x100) ? 0 : 0x200); + *p++ = 0x200; + *p++ = 0x040; + while (p < (buf + samples)) { + *p++ = 0x200; + *p++ = 0x040; + *p++ = 0x200; + *p++ = 0x040; + } + break; + } + return 0; +} + +/** + * mkframe - generate one frame + * @p: pointer to a buffer + * @info: line information structure + * @pat1: pattern 1 + * @pat2: pattern 2 + * @pat3: pattern 3 + * @pack: pointer to packing function + * + * Returns a negative error code on failure and zero on success. + **/ +static int +mkframe (uint8_t *p, + struct line_info info, + unsigned int pat1, + unsigned int pat2, + unsigned int pat3, + uint8_t *(*pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count)) +{ + uint8_t *(*vanc_pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); + unsigned short int buf[ACTIVE_SAMPLES]; + size_t elements = ACTIVE_SAMPLES; + unsigned int i; + + if (pack == pack_v210) { + vanc_pack = pack_v210; + } else { + vanc_pack = pack_v216; + } + memset (buf, 0, sizeof (buf)); + if (info.blanking) { + info.xyz = &FIELD_2_VERT_BLANKING; + for (i = 1; i <= 3; i++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_VERT_BLANKING; + for (i = 4; i <= 18; i++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + mkline (buf, &info, CEA_608); + p = vanc_pack (p, buf, elements); + info.xyz = &FIELD_1_ACTIVE; + mkline (buf, &info, pat1); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_ACTIVE; + for (i = 21; i <= 182; i++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (i = 183; i <= 202; i++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (i = 203; i <= 263; i++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (i = 264; i <= 265; i++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_2_VERT_BLANKING; + for (i = 266; i <= 272; i++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + for (i = 273; i <= 282; i++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + } + info.xyz = &FIELD_2_ACTIVE; + for (i = 283; i <= 445; i++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (i = 446; i <= 464; i++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (i = 465; i <= 525; i++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); } return 0; } @@ -347,7 +452,7 @@ pack_v210 (uint8_t *outbuf, unsigned short int *inp = inbuf; uint8_t *outp = outbuf; - count = (count / 96) * 96 + ((count % 96) ? 96 : 0); + count = (count / 48) * 48 + ((count % 48) ? 48 : 0); while (inp < (inbuf + count)) { *outp++ = *inp & 0xff; *outp = *inp++ >> 8; @@ -411,29 +516,50 @@ pack10 (uint8_t *outbuf, return outp; } +/** + * pack_v216 - pack a line of v216 data + * @outbuf: pointer to the output buffer + * @inbuf: pointer to the input buffer + * @count: number of elements in the buffer + * + * Returns a pointer to the next output location. + **/ +static uint8_t * +pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count) +{ + unsigned short int *inp = inbuf; + uint16_t *outp = (uint16_t *)outbuf; + + while (inp < (inbuf + count)) { + *outp++ = *inp++ << 6; /* Little endian only */ + } + return (uint8_t *)outp; +} + int main (int argc, char **argv) { - int opt, frames; + int opt, frames, avsync_period; uint8_t *(*pack)(uint8_t *outbuf, unsigned short int *inbuf, size_t count); struct line_info info; char *endptr; - unsigned short int buf[TOTAL_SAMPLES]; - uint8_t data[TOTAL_SAMPLES*4/3*TOTAL_LINES], *p = data; + uint8_t *data, *black_frame, *p; size_t samples, framesize, bytes; - int i, ret; + unsigned int black, avsync_sum, n, d; + int ret; + avsync_period = 0; frames = -1; /* Generate an infinite number of frames */ pack = pack_uyvy; info.blanking = 0; - samples = ACTIVE_SAMPLES; - while ((opt = getopt (argc, argv, "bhn:p:V")) != -1) { + while ((opt = getopt (argc, argv, "ahm:n:p:V")) != -1) { switch (opt) { - case 'b': + case 'a': info.blanking = 1; - samples = TOTAL_SAMPLES; break; case 'h': printf ("Usage: %s [OPTION]...\n", argv[0]); @@ -441,8 +567,10 @@ main (int argc, char **argv) "for transmission by\n" "a Linear Systems Ltd. " "SMPTE 259M-C board.\n\n"); - printf (" -b\t\tadd blanking\n"); + printf (" -a\t\tinclude vertical ancillary space\n"); printf (" -h\t\tdisplay this help and exit\n"); + printf (" -m PERIOD\tswitch between bars and black " + "every PERIOD seconds\n"); printf (" -n NUM\tstop after NUM frames\n"); printf (" -p PACKING\tpixel packing\n"); printf (" -V\t\toutput version information " @@ -453,6 +581,16 @@ main (int argc, char **argv) "\traw\n"); printf ("\nReport bugs to .\n"); return 0; + case 'm': + avsync_period = strtol (optarg, &endptr, 0); + if ((*endptr != '\0') || + (avsync_period > 35000)) { + fprintf (stderr, + "%s: invalid period: %s\n", + argv[0], optarg); + return -1; + } + break; case 'n': frames = strtol (optarg, &endptr, 0); if (*endptr != '\0') { @@ -480,7 +618,7 @@ main (int argc, char **argv) printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2004-2009 " + printf ("\nCopyright (C) 2004-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -499,105 +637,97 @@ main (int argc, char **argv) goto USAGE; } - /* Generate a frame */ - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (i = 10; i <= 19; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - info.xyz = &FIELD_1_ACTIVE; - mkline (buf, &info, MAIN_SET); - p = pack (p, buf, samples); - } - info.xyz = &FIELD_1_ACTIVE; - for (i = 21; i <= 182; i++) { - mkline (buf, &info, MAIN_SET); - p = pack (p, buf, samples); - } - for (i = 183; i <= 202; i++) { - mkline (buf, &info, CHROMA_SET); - p = pack (p, buf, samples); - } - for (i = 203; i <= 263; i++) { - mkline (buf, &info, BLACK_SET); - p = pack (p, buf, samples); - } - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (i = 264; i <= 265; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - info.xyz = &FIELD_2_VERT_BLANKING; - for (i = 266; i <= 272; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - for (i = 273; i <= 282; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - } - info.xyz = &FIELD_2_ACTIVE; - for (i = 283; i <= 445; i++) { - mkline (buf, &info, MAIN_SET); - p = pack (p, buf, samples); - } - for (i = 446; i <= 464; i++) { - mkline (buf, &info, CHROMA_SET); - p = pack (p, buf, samples); - } - for (i = 465; i <= 525; i++) { - mkline (buf, &info, BLACK_SET); - p = pack (p, buf, samples); - } - if (info.blanking) { - info.xyz = &FIELD_2_VERT_BLANKING; - for (i = 1; i <= 3; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - info.xyz = &FIELD_1_VERT_BLANKING; - for (i = 4; i <= 9; i++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, samples); - } - } - + /* Calculate the frame size */ + samples = ACTIVE_SAMPLES; if (info.blanking) { if (pack == pack_v210) { - framesize = TOTAL_SAMPLES * 4 / 3 * TOTAL_LINES; + framesize = samples * 4 / 3 * TOTAL_LINES; } else if (pack == pack_uyvy) { - framesize = TOTAL_SAMPLES * TOTAL_LINES; + framesize = samples * PRODUCTION_LINES + + samples * (TOTAL_LINES - PRODUCTION_LINES) * 2; } else { - framesize = TOTAL_SAMPLES * 10 / 8 * TOTAL_LINES; + framesize = samples * 10 / 8 * TOTAL_LINES; } } else { if (pack == pack_v210) { - framesize = ACTIVE_SAMPLES * 4 / 3 * PRODUCTION_LINES; + framesize = samples * 4 / 3 * PRODUCTION_LINES; } else if (pack == pack_uyvy) { - framesize = ACTIVE_SAMPLES * PRODUCTION_LINES; + framesize = samples * PRODUCTION_LINES; } else { - framesize = ACTIVE_SAMPLES * 10 / 8 * PRODUCTION_LINES; + framesize = samples * 10 / 8 * PRODUCTION_LINES; } } + + /* Allocate memory */ + data = malloc (framesize); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } + + /* Generate a frame */ + mkframe (data, + info, + MAIN_SET, + CHROMA_SET, + BLACK_SET, + pack); + + if (avsync_period > 0) { + /* Allocate memory */ + black_frame = malloc (framesize); + if (!black_frame) { + fprintf (stderr, "%s: unable to allocate memory\n", + argv[0]); + free (data); + return -1; + } + + /* Generate a black frame */ + mkframe (black_frame, + info, + VERT_BLANKING, + VERT_BLANKING, + VERT_BLANKING, + pack); + } else { + black_frame = NULL; + } + + black = 0; + avsync_sum = 0; + n = 30 * 1000 * avsync_period; + d = 1001; + p = data; while (frames) { /* Output the frame */ bytes = 0; while (bytes < framesize) { if ((ret = write (STDOUT_FILENO, - data + bytes, framesize - bytes)) < 0) { + p + bytes, framesize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); + free (black_frame); return -1; } bytes += ret; } + if (avsync_period > 0) { + if (avsync_sum >= n) { + avsync_sum = avsync_sum - n + d; + black = !black; + p = black ? black_frame : data; + } else { + avsync_sum += d; + } + } if (frames > 0) { frames--; } } + free (data); + free (black_frame); return 0; USAGE: diff --git a/quad/Examples/SDIVIDEO/rp219.c b/quad/Examples/SDIVIDEO/rp219.c index 733b11c31..efec6ddce 100644 --- a/quad/Examples/SDIVIDEO/rp219.c +++ b/quad/Examples/SDIVIDEO/rp219.c @@ -2,7 +2,7 @@ * * SMPTE RP 219 color bar generator for Linear Systems Ltd. SMPTE 292M boards. * - * Copyright (C) 2008-2009 Linear Systems Ltd. All rights reserved. + * Copyright (C) 2008-2010 Linear Systems Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -42,14 +42,63 @@ #include "master.h" +#if __BYTE_ORDER == __BIG_ENDIAN +#error Big endian architecture not supported +#endif + #define MAX_SAMPLES_PER_LINE (2*2750) -#define MAX_LINES_PER_FRAME 1125 #define VERT_BLANKING 0 #define PATTERN_1 1 #define PATTERN_2 2 #define PATTERN_3 3 #define PATTERN_4 4 +#define DELETED_PACKET 5 + +struct rp219_bars { + unsigned int d; + unsigned int f; + unsigned int c; + unsigned int e; + unsigned int k; + unsigned int g; + unsigned int h; + unsigned int i_side; + unsigned int i_middle; + unsigned int j_left; + unsigned int j_right; + unsigned int m; +}; + +static const struct rp219_bars RP219_1080 = { + .d = 2*240, + .f = 2*206, + .c = 2*206, + .e = 2*204, + .k = 2*308, + .g = 2*412, + .h = 2*170, + .i_side = 2*68, + .i_middle = 2*70, + .j_left = 2*70, + .j_right = 2*68, + .m = 2*206 +}; + +static const struct rp219_bars RP219_720 = { + .d = 2*160, + .f = 2*136, + .c = 2*138, + .e = 2*136, + .k = 2*206, + .g = 2*274, + .h = 2*114, + .i_side = 2*46, + .i_middle = 2*46, + .j_left = 2*46, + .j_right = 2*46, + .m = 2*136 +}; struct source_format { unsigned int lines_per_frame; @@ -57,166 +106,243 @@ struct source_format { unsigned int samples_per_line; unsigned int active_samples_per_line; unsigned int interlaced; - unsigned int rp219_d; - unsigned int rp219_f; - unsigned int rp219_c; - unsigned int rp219_e; - unsigned int rp219_k; - unsigned int rp219_g; - unsigned int rp219_h; - unsigned int rp219_i_side; - unsigned int rp219_i_middle; - unsigned int rp219_j_left; - unsigned int rp219_j_right; - unsigned int rp219_m; + unsigned int frame_rate; + unsigned int m; + const struct rp219_bars *rp219; }; -const struct source_format FMT_1080i60 = { +static const struct source_format FMT_1080i60 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200, .active_samples_per_line = 2*1920, .interlaced = 1, - .rp219_d = 2*240, - .rp219_f = 2*206, - .rp219_c = 2*206, - .rp219_e = 2*204, - .rp219_k = 2*308, - .rp219_g = 2*412, - .rp219_h = 2*170, - .rp219_i_side = 2*68, - .rp219_i_middle = 2*70, - .rp219_j_left = 2*70, - .rp219_j_right = 2*68, - .rp219_m = 2*206 + .frame_rate = 30, + .m = 0, + .rp219 = &RP219_1080, }; -const struct source_format FMT_1080i50 = { +static const struct source_format FMT_1080i59 = { + .lines_per_frame = 1125, + .active_lines_per_frame = 1080, + .samples_per_line = 2*2200, + .active_samples_per_line = 2*1920, + .interlaced = 1, + .frame_rate = 30, + .m = 1, + .rp219 = &RP219_1080, +}; + +static const struct source_format FMT_1080i50 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2640, .active_samples_per_line = 2*1920, .interlaced = 1, - .rp219_d = 2*240, - .rp219_f = 2*206, - .rp219_c = 2*206, - .rp219_e = 2*204, - .rp219_k = 2*308, - .rp219_g = 2*412, - .rp219_h = 2*170, - .rp219_i_side = 2*68, - .rp219_i_middle = 2*70, - .rp219_j_left = 2*70, - .rp219_j_right = 2*68, - .rp219_m = 2*206 + .frame_rate = 25, + .m = 0, + .rp219 = &RP219_1080 }; -const struct source_format FMT_1080p30 = { +static const struct source_format FMT_1080p30 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200, .active_samples_per_line = 2*1920, .interlaced = 0, - .rp219_d = 2*240, - .rp219_f = 2*206, - .rp219_c = 2*206, - .rp219_e = 2*204, - .rp219_k = 2*308, - .rp219_g = 2*412, - .rp219_h = 2*170, - .rp219_i_side = 2*68, - .rp219_i_middle = 2*70, - .rp219_j_left = 2*70, - .rp219_j_right = 2*68, - .rp219_m = 2*206 + .frame_rate = 30, + .m = 0, + .rp219 = &RP219_1080 }; -const struct source_format FMT_1080p25 = { +static const struct source_format FMT_1080p29 = { + .lines_per_frame = 1125, + .active_lines_per_frame = 1080, + .samples_per_line = 2*2200, + .active_samples_per_line = 2*1920, + .interlaced = 0, + .frame_rate = 30, + .m = 1, + .rp219 = &RP219_1080 +}; + +static const struct source_format FMT_1080p25 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2640, .active_samples_per_line = 2*1920, .interlaced = 0, - .rp219_d = 2*240, - .rp219_f = 2*206, - .rp219_c = 2*206, - .rp219_e = 2*204, - .rp219_k = 2*308, - .rp219_g = 2*412, - .rp219_h = 2*170, - .rp219_i_side = 2*68, - .rp219_i_middle = 2*70, - .rp219_j_left = 2*70, - .rp219_j_right = 2*68, - .rp219_m = 2*206 + .frame_rate = 25, + .m = 0, + .rp219 = &RP219_1080 }; -const struct source_format FMT_1080p24 = { +static const struct source_format FMT_1080p24 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2750, .active_samples_per_line = 2*1920, .interlaced = 0, - .rp219_d = 2*240, - .rp219_f = 2*206, - .rp219_c = 2*206, - .rp219_e = 2*204, - .rp219_k = 2*308, - .rp219_g = 2*412, - .rp219_h = 2*170, - .rp219_i_side = 2*68, - .rp219_i_middle = 2*70, - .rp219_j_left = 2*70, - .rp219_j_right = 2*68, - .rp219_m = 2*206 + .frame_rate = 24, + .m = 0, + .rp219 = &RP219_1080 }; -const struct source_format FMT_720p60 = { +static const struct source_format FMT_1080p23 = { + .lines_per_frame = 1125, + .active_lines_per_frame = 1080, + .samples_per_line = 2*2750, + .active_samples_per_line = 2*1920, + .interlaced = 0, + .frame_rate = 24, + .m = 1, + .rp219 = &RP219_1080 +}; + +static const struct source_format FMT_720p60 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*1650, .active_samples_per_line = 2*1280, .interlaced = 0, - .rp219_d = 2*160, - .rp219_f = 2*136, - .rp219_c = 2*138, - .rp219_e = 2*136, - .rp219_k = 2*206, - .rp219_g = 2*274, - .rp219_h = 2*114, - .rp219_i_side = 2*46, - .rp219_i_middle = 2*46, - .rp219_j_left = 2*46, - .rp219_j_right = 2*46, - .rp219_m = 2*136 + .frame_rate = 60, + .m = 0, + .rp219 = &RP219_720 }; +static const struct source_format FMT_720p59 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*1650, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 60, + .m = 1, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p50 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*1980, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 50, + .m = 0, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p30 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*3300, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 30, + .m = 0, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p29 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*3300, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 30, + .m = 1, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p25 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*3960, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 25, + .m = 0, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p24 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*4125, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 24, + .m = 0, + .rp219 = &RP219_720 +}; + +static const struct source_format FMT_720p23 = { + .lines_per_frame = 750, + .active_lines_per_frame = 720, + .samples_per_line = 2*4125, + .active_samples_per_line = 2*1280, + .interlaced = 0, + .frame_rate = 24, + .m = 1, + .rp219 = &RP219_720 +}; + +struct format_map { + const char *name; + const struct source_format *fmt; +}; + +static const struct format_map fmt_map[] = { + {.name = "1080i", .fmt = &FMT_1080i59}, + {.name = "1080p", .fmt = &FMT_1080p29}, + {.name = "720p", .fmt = &FMT_720p59}, + {.name = "1080i60", .fmt = &FMT_1080i60}, + {.name = "1080i59", .fmt = &FMT_1080i59}, + {.name = "1080i50", .fmt = &FMT_1080i50}, + {.name = "1080p30", .fmt = &FMT_1080p30}, + {.name = "1080p29", .fmt = &FMT_1080p29}, + {.name = "1080p25", .fmt = &FMT_1080p25}, + {.name = "1080p24", .fmt = &FMT_1080p24}, + {.name = "1080p23", .fmt = &FMT_1080p23}, + {.name = "720p60", .fmt = &FMT_720p60}, + {.name = "720p59", .fmt = &FMT_720p59}, + {.name = "720p50", .fmt = &FMT_720p50}, + {.name = "720p30", .fmt = &FMT_720p30}, + {.name = "720p29", .fmt = &FMT_720p29}, + {.name = "720p25", .fmt = &FMT_720p25}, + {.name = "720p24", .fmt = &FMT_720p24}, + {.name = "720p23", .fmt = &FMT_720p23} +}; + +static const unsigned int fmt_count = + sizeof (fmt_map) / sizeof (struct format_map); + struct trs { unsigned short int sav; unsigned short int eav; }; -const struct trs FIELD_1_ACTIVE = { +static const struct trs FIELD_1_ACTIVE = { .sav = 0x200, .eav = 0x274 }; -const struct trs FIELD_1_VERT_BLANKING = { +static const struct trs FIELD_1_VERT_BLANKING = { .sav = 0x2ac, .eav = 0x2d8 }; -const struct trs FIELD_2_ACTIVE = { +static const struct trs FIELD_2_ACTIVE = { .sav = 0x31c, .eav = 0x368 }; -const struct trs FIELD_2_VERT_BLANKING = { +static const struct trs FIELD_2_VERT_BLANKING = { .sav = 0x3b0, .eav = 0x3c4 }; -struct rp219_parameters { +struct rp219_opts { unsigned short int star1_y; unsigned short int star1_cb; unsigned short int star1_cr; @@ -228,7 +354,7 @@ struct rp219_parameters { unsigned short int star3_cr; }; -const struct rp219_parameters WHITE_75 = { +static const struct rp219_opts WHITE_75 = { .star1_y = 414, .star1_cb = 512, .star1_cr = 512, @@ -240,7 +366,7 @@ const struct rp219_parameters WHITE_75 = { .star3_cr = 512 }; -const struct rp219_parameters WHITE_100 = { +static const struct rp219_opts WHITE_100 = { .star1_y = 414, .star1_cb = 512, .star1_cr = 512, @@ -252,7 +378,7 @@ const struct rp219_parameters WHITE_100 = { .star3_cr = 512 }; -const struct rp219_parameters PLUS_I = { +static const struct rp219_opts PLUS_I = { .star1_y = 414, .star1_cb = 512, .star1_cr = 512, @@ -264,7 +390,7 @@ const struct rp219_parameters PLUS_I = { .star3_cr = 512 }; -const struct rp219_parameters MINUS_I = { +static const struct rp219_opts MINUS_I = { .star1_y = 414, .star1_cb = 512, .star1_cr = 512, @@ -280,7 +406,7 @@ struct line_info { const struct source_format *fmt; unsigned int ln; const struct trs *xyz; - const struct rp219_parameters *rp219; + const struct rp219_opts *opt; unsigned int blanking; }; @@ -294,6 +420,9 @@ static uint8_t *pack_v210 (uint8_t *outbuf, static uint8_t *pack_uyvy (uint8_t *outbuf, unsigned short int *inbuf, size_t count); +static uint8_t *pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); static const char progname[] = "rp219"; @@ -310,53 +439,10 @@ mkline (unsigned short int *buf, const struct line_info *info, unsigned int pattern) { - unsigned short int *p = buf, *endp, ln, y; - unsigned int samples = info->blanking ? - info->fmt->samples_per_line : - info->fmt->active_samples_per_line; + unsigned short int *p = buf, *endp, y, sum; + unsigned int samples = info->fmt->active_samples_per_line; double slope; - if (info->blanking) { - /* EAV */ - *p++ = 1023; - *p++ = 1023; - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = info->xyz->eav; - *p++ = info->xyz->eav; - /* LN */ - ln = ((info->ln & 0x07f) << 2) | (~info->ln & 0x040) << 3; - *p++ = ln; - *p++ = ln; - ln = ((info->ln & 0x780) >> 5) | 0x200; - *p++ = ln; - *p++ = ln; - /* CRC, added by serializer */ - *p++ = 512; - *p++ = 64; - *p++ = 512; - *p++ = 64; - /* Horizontal blanking */ - while (p < (buf + info->fmt->samples_per_line - - info->fmt->active_samples_per_line - 8)) { - *p++ = 512; - *p++ = 64; - *p++ = 512; - *p++ = 64; - } - /* SAV */ - *p++ = 1023; - *p++ = 1023; - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = 0; - *p++ = info->xyz->sav; - *p++ = info->xyz->sav; - } - /* Active region */ endp = p; switch (pattern) { default: @@ -370,15 +456,15 @@ mkline (unsigned short int *buf, break; case PATTERN_1: /* 40% gray (star 1) */ - endp += info->fmt->rp219_d; + endp += info->fmt->rp219->d; while (p < endp) { - *p++ = info->rp219->star1_cb; - *p++ = info->rp219->star1_y; - *p++ = info->rp219->star1_cr; - *p++ = info->rp219->star1_y; + *p++ = info->opt->star1_cb; + *p++ = info->opt->star1_y; + *p++ = info->opt->star1_cr; + *p++ = info->opt->star1_y; } /* 75% white */ - endp += info->fmt->rp219_f; + endp += info->fmt->rp219->f; while (p < endp) { *p++ = 512; *p++ = 721; @@ -386,7 +472,7 @@ mkline (unsigned short int *buf, *p++ = 721; } /* 75% yellow */ - endp += info->fmt->rp219_c; + endp += info->fmt->rp219->c; while (p < endp) { *p++ = 176; *p++ = 674; @@ -394,7 +480,7 @@ mkline (unsigned short int *buf, *p++ = 674; } /* 75% cyan */ - endp += info->fmt->rp219_c; + endp += info->fmt->rp219->c; while (p < endp) { *p++ = 589; *p++ = 581; @@ -402,7 +488,7 @@ mkline (unsigned short int *buf, *p++ = 581; } /* 75% green */ - endp += info->fmt->rp219_e; + endp += info->fmt->rp219->e; while (p < endp) { *p++ = 253; *p++ = 534; @@ -410,7 +496,7 @@ mkline (unsigned short int *buf, *p++ = 534; } /* 75% magenta */ - endp += info->fmt->rp219_c; + endp += info->fmt->rp219->c; while (p < endp) { *p++ = 771; *p++ = 251; @@ -418,7 +504,7 @@ mkline (unsigned short int *buf, *p++ = 251; } /* 75% red */ - endp += info->fmt->rp219_c; + endp += info->fmt->rp219->c; while (p < endp) { *p++ = 435; *p++ = 204; @@ -426,7 +512,7 @@ mkline (unsigned short int *buf, *p++ = 204; } /* 75% blue */ - endp += info->fmt->rp219_f; + endp += info->fmt->rp219->f; while (p < endp) { *p++ = 848; *p++ = 111; @@ -435,15 +521,15 @@ mkline (unsigned short int *buf, } /* 40% gray */ while (p < (buf + samples)) { - *p++ = info->rp219->star1_cb; - *p++ = info->rp219->star1_y; - *p++ = info->rp219->star1_cr; - *p++ = info->rp219->star1_y; + *p++ = info->opt->star1_cb; + *p++ = info->opt->star1_y; + *p++ = info->opt->star1_cr; + *p++ = info->opt->star1_y; } break; case PATTERN_2: /* 100% cyan */ - endp += info->fmt->rp219_d; + endp += info->fmt->rp219->d; while (p < endp) { *p++ = 615; *p++ = 754; @@ -451,15 +537,15 @@ mkline (unsigned short int *buf, *p++ = 754; } /* 75% white (star 2) */ - endp += info->fmt->rp219_f; + endp += info->fmt->rp219->f; while (p < endp) { - *p++ = info->rp219->star2_cb; - *p++ = info->rp219->star2_y; - *p++ = info->rp219->star2_cr; - *p++ = info->rp219->star2_y; + *p++ = info->opt->star2_cb; + *p++ = info->opt->star2_y; + *p++ = info->opt->star2_cr; + *p++ = info->opt->star2_y; } /* 75% white */ - endp = buf + samples - info->fmt->rp219_d; + endp = buf + samples - info->fmt->rp219->d; while (p < endp) { *p++ = 512; *p++ = 721; @@ -476,7 +562,7 @@ mkline (unsigned short int *buf, break; case PATTERN_3: /* 100% yellow */ - endp += info->fmt->rp219_d; + endp += info->fmt->rp219->d; while (p < endp) { *p++ = 64; *p++ = 877; @@ -484,15 +570,15 @@ mkline (unsigned short int *buf, *p++ = 877; } /* black (star 3) */ - endp += info->fmt->rp219_f; + endp += info->fmt->rp219->f; while (p < endp) { - *p++ = info->rp219->star3_cb; - *p++ = info->rp219->star3_y; - *p++ = info->rp219->star3_cr; - *p++ = info->rp219->star3_y; + *p++ = info->opt->star3_cb; + *p++ = info->opt->star3_y; + *p++ = info->opt->star3_cr; + *p++ = info->opt->star3_y; } /* Y-ramp */ - endp = buf + samples - info->fmt->rp219_d; + endp = buf + samples - info->fmt->rp219->d; slope = (double)(940 - 64) / (endp - p); while (p < endp) { *p++ = 512; @@ -509,7 +595,7 @@ mkline (unsigned short int *buf, break; case PATTERN_4: /* 15% gray */ - endp += info->fmt->rp219_d; + endp += info->fmt->rp219->d; while (p < endp) { *p++ = 512; *p++ = 195; @@ -517,7 +603,7 @@ mkline (unsigned short int *buf, *p++ = 195; } /* black */ - endp += info->fmt->rp219_k; + endp += info->fmt->rp219->k; while (p < endp) { *p++ = 512; *p++ = 64; @@ -525,7 +611,7 @@ mkline (unsigned short int *buf, *p++ = 64; } /* 100% white */ - endp += info->fmt->rp219_g; + endp += info->fmt->rp219->g; while (p < endp) { *p++ = 512; *p++ = 940; @@ -533,7 +619,7 @@ mkline (unsigned short int *buf, *p++ = 940; } /* black */ - endp += info->fmt->rp219_h; + endp += info->fmt->rp219->h; while (p < endp) { *p++ = 512; *p++ = 64; @@ -541,7 +627,7 @@ mkline (unsigned short int *buf, *p++ = 64; } /* -2% black */ - endp += info->fmt->rp219_i_side; + endp += info->fmt->rp219->i_side; while (p < endp) { *p++ = 512; *p++ = 46; @@ -549,7 +635,7 @@ mkline (unsigned short int *buf, *p++ = 46; } /* black */ - endp += info->fmt->rp219_i_middle; + endp += info->fmt->rp219->i_middle; while (p < endp) { *p++ = 512; *p++ = 64; @@ -557,7 +643,7 @@ mkline (unsigned short int *buf, *p++ = 64; } /* +2% black */ - endp += info->fmt->rp219_i_side; + endp += info->fmt->rp219->i_side; while (p < endp) { *p++ = 512; *p++ = 82; @@ -565,7 +651,7 @@ mkline (unsigned short int *buf, *p++ = 82; } /* black */ - endp += info->fmt->rp219_j_left; + endp += info->fmt->rp219->j_left; while (p < endp) { *p++ = 512; *p++ = 64; @@ -573,7 +659,7 @@ mkline (unsigned short int *buf, *p++ = 64; } /* +4% black */ - endp += info->fmt->rp219_j_right; + endp += info->fmt->rp219->j_right; while (p < endp) { *p++ = 512; *p++ = 99; @@ -581,7 +667,7 @@ mkline (unsigned short int *buf, *p++ = 99; } /* black */ - endp += info->fmt->rp219_m; + endp += info->fmt->rp219->m; while (p < endp) { *p++ = 512; *p++ = 64; @@ -596,6 +682,207 @@ mkline (unsigned short int *buf, *p++ = 195; } break; + case DELETED_PACKET: + /* Ancillary data packet marked for deletion */ + *p++ = 512; + *p++ = 0; + *p++ = 512; + *p++ = 0x3ff; + *p++ = 512; + *p++ = 0x3ff; + *p++ = 512; + *p++ = 0x180; sum = 0x180 & 0x1ff; /* DID */ + *p++ = 512; + *p++ = 0x200; sum += 0x200 & 0x1ff; + *p++ = 512; + *p++ = 0x203; sum += 0x203 & 0x1ff; /* DC */ + *p++ = 512; + *p++ = 0x18a; sum += 0x18a & 0x1ff; + *p++ = 512; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = 512; + *p++ = 0x180; sum += 0x180 & 0x1ff; + *p++ = 512; + *p++ = (sum & 0x1ff) | ((sum & 0x100) ? 0 : 0x200); + while (p < (buf + samples)) { + *p++ = 512; + *p++ = 64; + *p++ = 512; + *p++ = 64; + } + break; + } + return 0; +} + +/** + * mkframe - generate one frame + * @p: pointer to a buffer + * @info: line information structure + * @pat1: pattern 1 + * @pat2: pattern 2 + * @pat3: pattern 3 + * @pat4: pattern 4 + * @pack: pointer to packing function + * + * Returns a negative error code on failure and zero on success. + **/ +static int +mkframe (uint8_t *p, + struct line_info info, + unsigned int pat1, + unsigned int pat2, + unsigned int pat3, + unsigned int pat4, + uint8_t *(*pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count)) +{ + uint8_t *(*vanc_pack)(uint8_t *outbuf, + unsigned short int *inbuf, + size_t count); + unsigned short int buf[MAX_SAMPLES_PER_LINE]; + size_t elements = info.fmt->active_samples_per_line; + + if (pack == pack_v210) { + vanc_pack = pack_v210; + } else { + vanc_pack = pack_v216; + } + memset (buf, 0, sizeof (buf)); + if (info.fmt->interlaced) { + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 1; info.ln <= 19; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + mkline (buf, &info, DELETED_PACKET); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_ACTIVE; + for (info.ln = 21; info.ln <= 335; info.ln++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (info.ln = 336; info.ln <= 380; info.ln++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (info.ln = 381; info.ln <= 425; info.ln++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); + } + for (info.ln = 426; info.ln <= 560; info.ln++) { + mkline (buf, &info, pat4); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 561; info.ln <= 563; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_2_VERT_BLANKING; + for (info.ln = 564; info.ln <= 583; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + } + info.xyz = &FIELD_2_ACTIVE; + for (info.ln = 584; info.ln <= 898; info.ln++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (info.ln = 899; info.ln <= 943; info.ln++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (info.ln = 944; info.ln <= 988; info.ln++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); + } + for (info.ln = 989; info.ln <= 1123; info.ln++) { + mkline (buf, &info, pat4); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_2_VERT_BLANKING; + for (info.ln = 1124; info.ln <= 1125; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + } + } else { + if (info.fmt->lines_per_frame == 1125) { + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 1; info.ln <= 40; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + mkline (buf, &info, DELETED_PACKET); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_ACTIVE; + for (info.ln = 42; info.ln <= 671; info.ln++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (info.ln = 672; info.ln <= 761; info.ln++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (info.ln = 762; info.ln <= 851; info.ln++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); + } + for (info.ln = 852; info.ln <= 1121; info.ln++) { + mkline (buf, &info, pat4); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 1122; info.ln <= 1125; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + } + } else { + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 1; info.ln <= 24; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + mkline (buf, &info, DELETED_PACKET); + p = vanc_pack (p, buf, elements); + } + info.xyz = &FIELD_1_ACTIVE; + for (info.ln = 26; info.ln <= 445; info.ln++) { + mkline (buf, &info, pat1); + p = pack (p, buf, elements); + } + for (info.ln = 446; info.ln <= 505; info.ln++) { + mkline (buf, &info, pat2); + p = pack (p, buf, elements); + } + for (info.ln = 506; info.ln <= 565; info.ln++) { + mkline (buf, &info, pat3); + p = pack (p, buf, elements); + } + for (info.ln = 566; info.ln <= 745; info.ln++) { + mkline (buf, &info, pat4); + p = pack (p, buf, elements); + } + if (info.blanking) { + info.xyz = &FIELD_1_VERT_BLANKING; + for (info.ln = 746; info.ln <= 750; info.ln++) { + mkline (buf, &info, VERT_BLANKING); + p = vanc_pack (p, buf, elements); + } + } + } } return 0; } @@ -650,37 +937,62 @@ pack_uyvy (uint8_t *outbuf, return outp; } +/** + * pack_v216 - pack a line of v216 data + * @outbuf: pointer to the output buffer + * @inbuf: pointer to the input buffer + * @count: number of elements in the buffer + * + * Returns a pointer to the next output location. + **/ +static uint8_t * +pack_v216 (uint8_t *outbuf, + unsigned short int *inbuf, + size_t count) +{ + unsigned short int *inp = inbuf; + uint16_t *outp = (uint16_t *)outbuf; + + while (inp < (inbuf + count)) { + *outp++ = *inp++ << 6; /* Little endian only */ + } + return (uint8_t *)outp; +} + int main (int argc, char **argv) { int opt; struct line_info info; - int frames; + int frames, avsync_period; uint8_t *(*pack)(uint8_t *outbuf, unsigned short int *inbuf, size_t count); char *endptr; - unsigned short int buf[MAX_SAMPLES_PER_LINE]; - uint8_t data[MAX_SAMPLES_PER_LINE*10/8*MAX_LINES_PER_FRAME], *p = data; - size_t elements, framesize, bytes; - unsigned int samples; + uint8_t *data, *black_frame, *p; + size_t samples, framesize, bytes; + unsigned int i, black, avsync_sum, n, d; int ret; - info.fmt = &FMT_720p60; - info.rp219 = &WHITE_75; info.blanking = 0; + info.fmt = &FMT_720p59; + info.opt = &WHITE_75; + avsync_period = 0; frames = -1; /* Generate an infinite number of frames */ pack = pack_uyvy; - while ((opt = getopt (argc, argv, "f:hin:p:qwV")) != -1) { + while ((opt = getopt (argc, argv, "af:him:n:p:qwV")) != -1) { switch (opt) { + case 'a': + info.blanking = 1; + break; case 'f': - if (!strcmp (optarg, "1080i")) { - info.fmt = &FMT_1080i60; - } else if (!strcmp (optarg, "1080p")) { - info.fmt = &FMT_1080p30; - } else if (!strcmp (optarg, "720p")) { - info.fmt = &FMT_720p60; - } else { + for (i = 0; i < fmt_count; i++) { + if (!strcmp (optarg, fmt_map[i].name)) { + info.fmt = fmt_map[i].fmt; + break; + } + } + if (i == fmt_count) { fprintf (stderr, "%s: invalid source format: %s\n", argv[0], optarg); @@ -693,9 +1005,12 @@ main (int argc, char **argv) "for transmission by\n" "a Linear Systems Ltd. " "SMPTE 292M board.\n\n"); - printf (" -f FORMAT\tselect source format\n"); + printf (" -a\t\tinclude vertical ancillary space\n"); + printf (" -f FORMAT\tsource format\n"); printf (" -h\t\tdisplay this help and exit\n"); printf (" -i\t\tselect +I signal in pattern 2\n"); + printf (" -m PERIOD\tswitch between bars and black " + "every PERIOD seconds\n"); printf (" -n NUM\tstop after NUM frames\n"); printf (" -p PACKING\tpixel packing\n"); printf (" -q\t\tselect -I signal in pattern 2 " @@ -705,16 +1020,41 @@ main (int argc, char **argv) printf (" -V\t\toutput version information " "and exit\n"); printf ("\nFORMAT may be:\n" - "\t720p (default)\n" - "\t1080i\n" - "\t1080p\n"); + "\t1080i60,\n" + "\t1080i59 or 1080i,\n" + "\t1080i50,\n" + "\t1080p30,\n" + "\t1080p29 or 1080p,\n" + "\t1080p25,\n" + "\t1080p24,\n" + "\t1080p23,\n" + "\t720p60,\n" + "\t720p59 or 720p (default),\n" + "\t720p50,\n" + "\t720p30,\n" + "\t720p29,\n" + "\t720p25,\n" + "\t720p24,\n" + "\t720p23\n" + "\tThe frame rate is only meaningful\n" + "\twhen switching between bars and black.\n"); printf ("\nPACKING may be:\n" "\tuyvy (default)\n" "\tv210\n"); printf ("\nReport bugs to .\n"); return 0; case 'i': - info.rp219 = &PLUS_I; + info.opt = &PLUS_I; + break; + case 'm': + avsync_period = strtol (optarg, &endptr, 0); + if ((*endptr != '\0') || + (avsync_period > 35000)) { + fprintf (stderr, + "%s: invalid period: %s\n", + argv[0], optarg); + return -1; + } break; case 'n': frames = strtol (optarg, &endptr, 0); @@ -738,16 +1078,16 @@ main (int argc, char **argv) } break; case 'q': - info.rp219 = &MINUS_I; + info.opt = &MINUS_I; break; case 'w': - info.rp219 = &WHITE_100; + info.opt = &WHITE_100; break; case 'V': printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - printf ("\nCopyright (C) 2008-2009 " + printf ("\nCopyright (C) 2008-2010 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " @@ -766,154 +1106,19 @@ main (int argc, char **argv) goto USAGE; } - /* Generate a frame */ - if (info.fmt->interlaced) { - if (info.blanking) { - elements = info.fmt->samples_per_line; - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 1; info.ln <= 20; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } else { - elements = info.fmt->active_samples_per_line; - } - info.xyz = &FIELD_1_ACTIVE; - for (info.ln = 21; info.ln <= 335; info.ln++) { - mkline (buf, &info, PATTERN_1); - p = pack (p, buf, elements); - } - for (info.ln = 336; info.ln <= 380; info.ln++) { - mkline (buf, &info, PATTERN_2); - p = pack (p, buf, elements); - } - for (info.ln = 381; info.ln <= 425; info.ln++) { - mkline (buf, &info, PATTERN_3); - p = pack (p, buf, elements); - } - for (info.ln = 426; info.ln <= 560; info.ln++) { - mkline (buf, &info, PATTERN_4); - p = pack (p, buf, elements); - } - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 561; info.ln <= 563; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - info.xyz = &FIELD_2_VERT_BLANKING; - for (info.ln = 564; info.ln <= 583; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } - info.xyz = &FIELD_2_ACTIVE; - for (info.ln = 584; info.ln <= 898; info.ln++) { - mkline (buf, &info, PATTERN_1); - p = pack (p, buf, elements); - } - for (info.ln = 899; info.ln <= 943; info.ln++) { - mkline (buf, &info, PATTERN_2); - p = pack (p, buf, elements); - } - for (info.ln = 944; info.ln <= 988; info.ln++) { - mkline (buf, &info, PATTERN_3); - p = pack (p, buf, elements); - } - for (info.ln = 989; info.ln <= 1123; info.ln++) { - mkline (buf, &info, PATTERN_4); - p = pack (p, buf, elements); - } - if (info.blanking) { - info.xyz = &FIELD_2_VERT_BLANKING; - for (info.ln = 1124; info.ln <= 1125; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } - } else { - if (info.fmt->lines_per_frame == 1125) { - if (info.blanking) { - elements = info.fmt->samples_per_line; - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 1; info.ln <= 41; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } else { - elements = info.fmt->active_samples_per_line; - } - info.xyz = &FIELD_1_ACTIVE; - for (info.ln = 42; info.ln <= 671; info.ln++) { - mkline (buf, &info, PATTERN_1); - p = pack (p, buf, elements); - } - for (info.ln = 672; info.ln <= 761; info.ln++) { - mkline (buf, &info, PATTERN_2); - p = pack (p, buf, elements); - } - for (info.ln = 762; info.ln <= 851; info.ln++) { - mkline (buf, &info, PATTERN_3); - p = pack (p, buf, elements); - } - for (info.ln = 852; info.ln <= 1121; info.ln++) { - mkline (buf, &info, PATTERN_4); - p = pack (p, buf, elements); - } - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 1122; info.ln <= 1125; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } - } else { - if (info.blanking) { - elements = info.fmt->samples_per_line; - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 1; info.ln <= 25; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } else { - elements = info.fmt->active_samples_per_line; - } - info.xyz = &FIELD_1_ACTIVE; - for (info.ln = 26; info.ln <= 445; info.ln++) { - mkline (buf, &info, PATTERN_1); - p = pack (p, buf, elements); - } - for (info.ln = 446; info.ln <= 505; info.ln++) { - mkline (buf, &info, PATTERN_2); - p = pack (p, buf, elements); - } - for (info.ln = 506; info.ln <= 565; info.ln++) { - mkline (buf, &info, PATTERN_3); - p = pack (p, buf, elements); - } - for (info.ln = 566; info.ln <= 745; info.ln++) { - mkline (buf, &info, PATTERN_4); - p = pack (p, buf, elements); - } - if (info.blanking) { - info.xyz = &FIELD_1_VERT_BLANKING; - for (info.ln = 746; info.ln <= 750; info.ln++) { - mkline (buf, &info, VERT_BLANKING); - p = pack (p, buf, elements); - } - } - } - } - + /* Calculate the frame size */ if (info.blanking) { if (pack == pack_v210) { - samples = (info.fmt->samples_per_line / 96 * 48) + - ((info.fmt->samples_per_line % 96) ? 48 : 0); + samples = (info.fmt->active_samples_per_line / 96 * 48) + + ((info.fmt->active_samples_per_line % 96) ? 48 : 0); framesize = samples * info.fmt->lines_per_frame * 8 / 3; } else { - framesize = info.fmt->samples_per_line * - info.fmt->lines_per_frame; + framesize = info.fmt->active_samples_per_line * + info.fmt->active_lines_per_frame + + info.fmt->active_samples_per_line * + (info.fmt->lines_per_frame - + info.fmt->active_lines_per_frame) * 2; } } else { if (pack == pack_v210) { @@ -926,22 +1131,79 @@ main (int argc, char **argv) info.fmt->active_lines_per_frame; } } + + /* Allocate memory */ + data = malloc (framesize); + if (!data) { + fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); + return -1; + } + + /* Generate a frame */ + mkframe (data, + info, + PATTERN_1, + PATTERN_2, + PATTERN_3, + PATTERN_4, + pack); + + if (avsync_period > 0) { + /* Allocate memory */ + black_frame = malloc (framesize); + if (!black_frame) { + fprintf (stderr, "%s: unable to allocate memory\n", + argv[0]); + free (data); + return -1; + } + + /* Generate a black frame */ + mkframe (black_frame, + info, + VERT_BLANKING, + VERT_BLANKING, + VERT_BLANKING, + VERT_BLANKING, + pack); + } else { + black_frame = NULL; + } + + black = 0; + avsync_sum = 0; + n = info.fmt->frame_rate * 1000 * avsync_period; + d = info.fmt->m ? 1001 : 1000; + p = data; while (frames) { /* Output the frame */ bytes = 0; while (bytes < framesize) { if ((ret = write (STDOUT_FILENO, - data + bytes, framesize - bytes)) < 0) { + p + bytes, framesize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write"); + free (data); + free (black_frame); return -1; } bytes += ret; } + if (avsync_period > 0) { + if (avsync_sum >= n) { + avsync_sum = avsync_sum - n + d; + black = !black; + p = black ? black_frame : data; + } else { + avsync_sum += d; + } + } if (frames > 0) { frames--; } } + free (data); + free (black_frame); return 0; USAGE: diff --git a/quad/Examples/SDIVIDEO/sdivideocfg.c b/quad/Examples/SDIVIDEO/sdivideocfg.c index 39fd8bdd9..675faecb8 100644 --- a/quad/Examples/SDIVIDEO/sdivideocfg.c +++ b/quad/Examples/SDIVIDEO/sdivideocfg.c @@ -1,6 +1,6 @@ /* sdivideocfg.c * - * SMPTE 292M and SMPTE 259M-C configuration program. + * SDI video configuration program. * * Copyright (C) 2009-2010 Linear Systems Ltd. All rights reserved. * @@ -51,10 +51,10 @@ #define CLKSRC_FLAG 0x00000004 #define MODE_FLAG 0x00000008 #define FRMODE_FLAG 0x00000010 +#define VANC_FLAG 0x00000020 static const char progname[] = "sdivideocfg"; - int main (int argc, char **argv) { @@ -64,7 +64,7 @@ main (int argc, char **argv) struct stat buf; int num; char type, name[MAXLEN], data[MAXLEN]; - unsigned long int buffers, bufsize, clksrc, mode, frmode; + unsigned long int buffers, bufsize, clksrc, mode, frmode, vanc; int retcode; char *endptr; @@ -75,8 +75,17 @@ main (int argc, char **argv) clksrc = 0; mode = 0; frmode = 0; - while ((opt = getopt (argc, argv, "b:f:hm:s:Vx:")) != -1) { + vanc = 0; + while ((opt = getopt (argc, argv, "aAb:f:hm:s:Vx:")) != -1) { switch (opt) { + case 'a': + write_flags |= VANC_FLAG; + vanc = 1; + break; + case 'A': + write_flags |= VANC_FLAG; + vanc = 0; + break; case 'b': write_flags |= BUFFERS_FLAG; buffers = strtoul (optarg, &endptr, 0); @@ -100,20 +109,23 @@ main (int argc, char **argv) case 'h': printf ("Usage: %s [OPTION]... DEVICE_FILE\n", argv[0]); - printf ("Configure a video interface.\n\n"); + printf ("Configure an SDI video interface.\n\n"); + printf (" -a\t\tenable vertical ancillary space\n"); + printf (" -A\t\tdisable vertical ancillary space\n"); printf (" -b BUFFERS\tset the number of buffers\n"); - printf (" -f FRMODE\tset the frame mode\n"); + printf (" -f FRMODE\tset the frame mode " + "(transmitters only)\n"); printf (" -h\t\tdisplay this help and exit\n"); printf (" -m MODE\tset the operating mode\n"); printf (" -s BUFSIZE\tset the buffer size\n"); printf (" -V\t\toutput version information " "and exit\n"); - printf (" -x CLKSRC\tset the clock source\n"); + printf (" -x CLKSRC\tset the clock source " + "(transmitters only)\n"); printf ("\nIf no options are specified, " "the current configuration is displayed.\n"); printf ("\nBUFFERS must be two or more.\n"); - printf ("\nCLKSRC is valid only for transmitters and " - "may be:\n" + printf ("\nCLKSRC may be:\n" "\t0 (onboard oscillator)\n" "\t1 (external 525i or NTSC reference)\n" "\t2 (external 625i or PAL reference)\n" @@ -138,8 +150,7 @@ main (int argc, char **argv) "\t21 (external 1080i/60 reference)\n" "\t22 (external 1080i/59.94 reference)\n" "\t23 (external 1080i/50 reference)\n"); - printf ("\nFRMODE is valid only for transmitters and " - "may be:\n" + printf ("\nFRMODE may be:\n" "\t1 (SMPTE 125M 486i 59.94 Hz)\n" "\t2 (ITU-R BT.601 720x576i 50 Hz)\n" "\t5 (SMPTE 260M 1035i 60 Hz)\n" @@ -161,7 +172,7 @@ main (int argc, char **argv) "\t22 (SMPTE 296M 720p 59.94 Hz)\n" "\t23 (SMPTE 296M 720p 50 Hz)\n" "\t24 (SMPTE 296M 720p 30 Hz)\n" - "\t25 (SMPTE 296M 720p 29.96 Hz)\n" + "\t25 (SMPTE 296M 720p 29.97 Hz)\n" "\t26 (SMPTE 296M 720p 25 Hz)\n" "\t27 (SMPTE 296M 720p 24 Hz)\n" "\t28 (SMPTE 296M 720p 23.98 Hz)\n"); @@ -255,13 +266,13 @@ main (int argc, char **argv) memset (data, 0, sizeof (data)); /* Read sysfs file (dev) */ if (util_read (name, data, sizeof (data)) < 0) { - fprintf (stderr, "%s: ", argv[0]); - perror ("unable to get the device number"); + fprintf (stderr, "%s: error reading %s: ", argv[0], name); + perror (NULL); return -1; } /* Compare the major number taken from sysfs file to the one taken from device node */ if (strtoul (data, &endptr, 0) != (buf.st_rdev >> 8)) { - fprintf (stderr, "%s: not a SMPTE 292M/SMPTE 259M-C device\n", argv[0]); + fprintf (stderr, "%s: not an SDI video device\n", argv[0]); return -1; } if (*endptr != ':') { @@ -297,6 +308,12 @@ main (int argc, char **argv) printf ("\tSet buffer size = %lu bytes.\n", bufsize); } if (write_flags & CLKSRC_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the clock source: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "clock_source"); snprintf (data, sizeof (data), "%lu\n", clksrc); @@ -419,6 +436,12 @@ main (int argc, char **argv) } } if (write_flags & FRMODE_FLAG) { + if (type == 'r') { + fprintf (stderr, "%s: " + "unable to set the interface frame mode: " + "Not a transmitter\n", argv[0]); + return -1; + } snprintf (name, sizeof (name), fmt, type, num, "frame_mode"); snprintf (data, sizeof (data), "%lu\n", frmode); @@ -539,6 +562,24 @@ main (int argc, char **argv) break; } } + if (write_flags & VANC_FLAG) { + snprintf (name, sizeof (name), + fmt, type, num, "vanc"); + snprintf (data, sizeof (data), "%lu\n", vanc); + if (util_write (name, data, sizeof (data)) < 0) { + fprintf (stderr, "%s: ", argv[0]); + if (vanc) { + perror ("unable to enable " + "vertical ancillary space"); + } else { + perror ("unable to disable " + "vertical ancillary space"); + } + return -1; + } + printf ("\t%sabled vertical ancillary space.\n", + vanc ? "En" : "Dis"); + } } else { snprintf (name, sizeof (name), fmt, type, num, "buffers"); @@ -585,11 +626,14 @@ main (int argc, char **argv) break; } - snprintf (name, sizeof (name), - fmt, type, num, "frame_mode"); - if (util_strtoul (name, &frmode) > 0) { - /* Don't complain on an error, - * since this parameter may not exist. */ + if (type == 't') { + snprintf (name, sizeof (name), + fmt, type, num, "frame_mode"); + if (util_strtoul (name, &frmode) < 0) { + fprintf (stderr, "%s: ", argv[0]); + perror ("unable to get the frame mode"); + retcode = -1; + } printf ("\tFrame mode: %lu ", frmode); switch (frmode) { case SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ: @@ -702,11 +746,14 @@ main (int argc, char **argv) } } - snprintf (name, sizeof (name), - fmt, type, num, "clock_source"); - if (util_strtoul (name, &clksrc) > 0) { - /* Don't complain on an error, - * since this parameter may not exist. */ + if (type == 't') { + snprintf (name, sizeof (name), + fmt, type, num, "clock_source"); + if (util_strtoul (name, &clksrc) < 0) { + fprintf (stderr, "%s: ", argv[0]); + perror ("unable to get the clock source"); + retcode = -1; + } printf ("\tClock source: %lu ", clksrc); switch (clksrc) { case SDIVIDEO_CTL_TX_CLKSRC_ONBOARD: @@ -786,6 +833,15 @@ main (int argc, char **argv) break; } } + + snprintf (name, sizeof (name), + fmt, type, num, "vanc"); + if (util_strtoul (name, &vanc) > 0) { + /* Don't complain on an error, + * since this parameter may not exist. */ + printf ("\tVertical ancillary space: %sabled\n", + vanc ? "en" : "dis"); + } } return retcode; diff --git a/quad/Examples/SDIVIDEO/sdivideotxcfg.c b/quad/Examples/SDIVIDEO/sdivideotxcfg.c index fb939fc9d..49a58bbc3 100644 --- a/quad/Examples/SDIVIDEO/sdivideotxcfg.c +++ b/quad/Examples/SDIVIDEO/sdivideotxcfg.c @@ -55,11 +55,8 @@ show_cap (unsigned int cap) { char str[TMP_BUFLEN] = "[ ] "; - if (cap) { - printf ("Unknown capabilities.\n"); - } else { - printf ("No capabilities.\n"); - } + str[1] = (cap & SDIVIDEO_CAP_TX_VANC) ? 'X' : ' '; + printf ("%sVertical ancillary space\n", str); printf ("\nPress Enter to continue: "); fgets (str, TMP_BUFLEN, stdin); diff --git a/quad/Examples/mastercfg.c b/quad/Examples/mastercfg.c old mode 100755 new mode 100644 diff --git a/quad/Examples/pci_ids.h b/quad/Examples/pci_ids.h old mode 100755 new mode 100644 diff --git a/quad/Examples/util.c b/quad/Examples/util.c old mode 100755 new mode 100644 index 3b95a5d1f..a7b72587f --- a/quad/Examples/util.c +++ b/quad/Examples/util.c @@ -343,7 +343,7 @@ static struct util_info info[] = { }, { .id = PCI_DEVICE_ID_LINSYS_HDSDIQI, - .name = "VidPort Q/i", + .name = "QuadPort H/i", .flags = UTIL_SDIRX }, { diff --git a/quad/Examples/util.h b/quad/Examples/util.h old mode 100755 new mode 100644 diff --git a/quad/INSTALL b/quad/INSTALL index 2e9631688..fa8fdda8b 100644 --- a/quad/INSTALL +++ b/quad/INSTALL @@ -19,9 +19,9 @@ in the top-level directory of this archive. This should create the following files in the src directory: asi.ko - DVB ASI API module - sdi.ko - SMPTE 259M-C API module - sdivideo.ko - SMPTE 292M video API module - sdiaudio.ko - SMPTE 292M audio API module + sdi.ko - raw SDI API module + sdivideo.ko - SDI video API module + sdiaudio.ko - SDI audio API module dvbm.ko - driver module for ATSC Master II FD and DVB Master boards mmas.ko - MultiMaster SDI-T driver module @@ -84,7 +84,7 @@ for DVB ASI, and ./mkdev.sdi -for SMPTE 259M-C. You must be root to create these device files. +for raw SDI. You must be root to create these device files. See doc/ASI/devices.txt and doc/SDI/devices.txt for a description of these device files. @@ -93,7 +93,7 @@ on the device files; mkdev.asi and mkdev.sdi allow read and write access to the root user only. Users who need access to the hardware should be given read permission on the receiver device files and write permission on the transmitter device files. -Mmap support on SMPTE 259M-C and SMPTE 292M interfaces requires +Mmap support on raw SDI and SDI audio/video interfaces requires both read and write permission. If your system uses udev, you can create a rule to change the permission. For example, creating a file called @@ -101,7 +101,7 @@ For example, creating a file called KERNEL=="sdivideo[rt]x[0-9]*",NAME="%k",MODE="0666",OPTIONS="last_rule" -will give all SMPTE 292M video interfaces global read and write permissions. +will give all SDI video interfaces global read and write permissions. Loading the kernel modules @@ -142,7 +142,7 @@ loaded automatically. SDI Master Q/i - sdiqie.ko (sdi.ko) DVB Master III Tx LP - dvbm.ko (asi.ko) DVB Master III Rx LP - dvbm.ko (asi.ko) - VidPort Q/i - hdsdim.ko (sdivideo.ko, sdiaudio.ko) + QuadPort H/i - hdsdim.ko (sdivideo.ko, sdiaudio.ko) VidPort SD/HD - hdsdim.ko (sdivideo.ko, sdiaudio.ko) As root, load the DVB Master driver module by typing @@ -179,9 +179,9 @@ module first. For example, unload the DVB Master driver module with Changing the API major number ----------------------------- -The DVB ASI API and SMPTE 259M-C API handle character device files with +The DVB ASI API and raw SDI API handle character device files with major numbers 61 and 121 by default. -The SMPTE 292M API uses dynamically assigned major numbers. +The SDI video/audio API uses dynamically assigned major numbers. If these numbers conflict with other devices, you can specify a different number by loading the API module explicitly: diff --git a/quad/Makefile b/quad/Makefile deleted file mode 100755 index 013a5ea23..000000000 --- a/quad/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Makefile for the Master Linux Software Development Kit - -SHELL = /bin/sh - -SUBDIRS = src Examples - -.PHONY: all clean install uninstall - -all: - for n in $(SUBDIRS); do $(MAKE) -C $$n || exit 1; done - -clean: - for n in $(SUBDIRS); do $(MAKE) -C $$n clean; done - -install: - for n in $(SUBDIRS); do $(MAKE) -C $$n install || exit 1; done - -uninstall: - for n in $(SUBDIRS); do $(MAKE) -C $$n uninstall || exit 1; done - diff --git a/quad/NEWS b/quad/NEWS index aa9a14793..055cc94fa 100644 --- a/quad/NEWS +++ b/quad/NEWS @@ -1,3 +1,44 @@ +Version 2.7.2 (2010-12-17) +============= + +Added support for vertical ancillary space on +VidPort SD/HD O, firmware 0x0202 or higher, and +VidPort SD/HD I, firmware 0x0102 or higher. + +Fixed a bug which prevented the SDI Master Q/o PCIe clock_source +from being changed from 1 (external reference) to 0 (onboard oscillator). +Applications which rely on this behaviour +to use the external reference without changing clock_source +should explicitly change clock_source. + +Fixed driver buffer queue overrun reporting on VidPort SD/HD I. + +Fixed a bug which could allow memory to be written after it is freed +on VidPort SD/HD I. + +Fixed a bug which could hang sdiaudio fsync() on VidPort SD/HD I. + +Prevent blackburst_type from being changed +while any related transmitter is open. + +Fixed clock_source and added blackburst_type +on DVB Master Q/o LP PCIe Mini BNC. + +Added blackburst_type to DVB Master Quad-2in2out, +DVB Master Quad-1in3out, DVB Master Quad-3in1out, and DVB Master Q/o. + +Added ASI_IOC_TXGET27COUNT to +DVB Master Q/o LP PCIe Mini BNC, firmware 0x0101 or higher, and +DVB Master III Tx LP PCIe, firmware 0x0101 or higher. + +Added ASI_IOC_TXGET27COUNT and ASI_IOC_RXGET27COUNT to +DVB Master Quad-2in2out. + +Added ASI_IOC_TXGET27COUNT and ASI_IOC_RXGET27COUNT to +DVB Master Quad-2in2out LP PCIe Mini BNC, firmware 0x0102 or higher. + +Merged changes from Linux kernels 2.6.34 and 2.6.35. + Version 2.7.1 (2010-03-23) ============= diff --git a/quad/README b/quad/README index 2368e060f..34ecc4e64 100644 --- a/quad/README +++ b/quad/README @@ -12,12 +12,12 @@ Table of Contents 5. Installation 6. Capturing an MPEG-2 transport stream over DVB ASI or SMPTE 310M 7. Playing an MPEG-2 transport stream over DVB ASI or SMPTE 310M - 8. Capturing 4:2:2 component digital video over SMPTE 259M-C - 9. Playing 4:2:2 component digital video over SMPTE 259M-C -10. Capturing 4:2:2 component digital video over SMPTE 292M -11. Capturing audio over SMPTE 292M -12. Playing 4:2:2 component digital video over SMPTE 292M -13. Playing audio over SMPTE 292M + 8. Capturing SMPTE 259M-C with SDI Master + 9. Playing SMPTE 259M-C with SDI Master +10. Capturing 4:2:2 component digital video over SDI +11. Capturing audio over SDI +12. Playing 4:2:2 component digital video over SDI +13. Playing audio over SDI 14. Driver limitations and known bugs @@ -67,7 +67,7 @@ This SDK supports the following products: DVB Master Quad-3in1out PCIe DVB Master III Tx LP DVB Master III Rx LP - VidPort Q/i + QuadPort H/i VidPort SD/HD O VidPort SD/HD I @@ -263,8 +263,8 @@ If you receive an error message, make sure you have write permission on the device file. Press Ctrl+C to quit mknull. - 8. Capturing 4:2:2 component digital video over SMPTE 259M-C -------------------------------------------------------------- + 8. Capturing SMPTE 259M-C with SDI Master +------------------------------------------ Connect a SMPTE 259M-C source to your board's receive port with a 75 ohm cable. @@ -291,7 +291,7 @@ Use to view information about other options. -Capture one second of video to a file called test.sdi by typing +Capture one second to a file called test.sdi by typing capture -n1 /dev/sdirx0 > test.sdi @@ -301,8 +301,8 @@ without overrunning the driver's buffers will probably require a disk array. - 9. Playing 4:2:2 component digital video over SMPTE 259M-C ------------------------------------------------------------ + 9. Playing SMPTE 259M-C with SDI Master +---------------------------------------- Connect a SMPTE 259M-C receiver to your board's transmit port with a 75 ohm cable. @@ -327,7 +327,7 @@ Use to view information about other options. -If you have a video file, transmit it with +If you have a file, transmit it with playout /dev/sditx0 < test.sdi @@ -343,10 +343,12 @@ If you receive an error message, make sure you have write permission on the device file. Press Ctrl+C to quit eg1. -10. Capturing 4:2:2 component digital video over SMPTE 292M ------------------------------------------------------------ +10. Capturing 4:2:2 component digital video over SDI +---------------------------------------------------- -Connect a SMPTE 292M source to your board's receive port +This section applies to QuadPort and VidPort boards, not SDI Master. + +Connect an SDI source to your board's receive port with a 75 ohm cable. Assuming that you are using the first receive port @@ -377,7 +379,11 @@ on the device file. Capturing longer segments to disk without overrunning the driver's buffers will probably require a disk array. -You can also use VideoLAN, MPlayer, or FFmpeg to display the captured video. +You can also use FFmpeg, MPlayer, or VideoLAN to display the captured video. + +Display 720p video with UYVY packing format with FFmpeg by typing + + ffplay -f rawvideo -s 1280x720 -pix_fmt uyvy422 /dev/sdivideorx0 Display 720p video with UYVY packing format with MPlayer by typing @@ -387,15 +393,13 @@ Display 720p video with UYVY packing format with VideoLAN by typing vlc --demux rawvideo --rawvid-width 1280 --rawvid-height 720 --rawvid-chroma=UYVY --zoom 0.25 --rawvid-fps 60 /dev/sdivideorx0 -Display 720p video with UYVY packing format with FFmpeg by typing - ffplay -f rawvideo -s 1280x720 -pix_fmt uyvy422 /dev/sdivideorx0 +11. Capturing audio over SDI +---------------------------- +This section applies to QuadPort and VidPort boards, not SDI Master. -11. Capturing audio over SMPTE 292M ------------------------------------ - -Connect a SMPTE 292M source to your board's receive port +Connect an SDI source to your board's receive port with a 75 ohm cable. Assuming that you are using the first receive port @@ -408,7 +412,7 @@ Other interfaces may be viewed by providing the appropriate device file name. By default, the interface is set to capture 2-channel audio. If you want to capture 8-channel audio, change the mode by typing - sdiaudiocfg -c3 /dev/sdiaudiorx0 + sdiaudiocfg -c8 /dev/sdiaudiorx0 as root. Use @@ -424,21 +428,27 @@ Capture one second of audio to a file called test.raw by typing If you receive an error message, make sure you have read permission on the device file. -Play back 2 channel, 16-bit audio with 48000 Hz sample rate with MPlayer +Listen to 2 channel, 16-bit audio with 48000 Hz sample rate with MPlayer by typing mplayer -demuxer rawaudio -rawaudio channels=2:rate=48000:samplesize=2 /dev/sdiaudiorx0 -Play back 2 channel, 16-bit audio with 48000 Hz sample rate with VideoLAN +Listen to 2 channel, 16-bit audio with 48000 Hz sample rate with VideoLAN by typing vlc --demux rawaud --rawaud-channels 2 --rawaud-samplerate 48000 --rawaud-fourcc s16l /dev/sdiaudiorx0 +Display video and listen to audio with MPlayer by typing -12. Playing 4:2:2 component digital video over SMPTE 292M ---------------------------------------------------------- + mplayer -demuxer rawvideo -rawvideo w=1280:h=720:format=uyvy:fps=60 /dev/sdivideorx0 -audio-demuxer rawaudio -rawaudio channels=2:rate=48000:samplesize=2 -audiofile /dev/sdiaudiorx0 -Connect a SMPTE 292M receiver to your board's transmit port + +12. Playing 4:2:2 component digital video over SDI +-------------------------------------------------- + +This section applies to VidPort boards, not SDI Master. + +Connect an SDI receiver to your board's transmit port with a 75 ohm cable. Assuming that you are using the first transmit port @@ -467,7 +477,11 @@ If you have a video file, transmit it with Playing long files from disk without underrunning the driver's buffers will probably require a disk array. -Transmit a compressed video file with MPlayer with +Transmit a compressed video file with FFmpeg by typing + + ffmpeg -y -i test.ts -f rawvideo -pix_fmt uyvy422 /dev/sdivideotx0 + +Transmit a compressed video file with MPlayer by typing mencoder -nosound -ovc raw -vf format=uyvy -of rawvideo -o /dev/sdivideotx0 test.ts @@ -487,10 +501,12 @@ If you receive an error message, make sure you have write permission on the device file. Press Ctrl+C to quit rp219. -13. Playing audio over SMPTE 292M ---------------------------------- +13. Playing audio over SDI +-------------------------- -Connect a SMPTE 292M receiver to your board's transmit port +This section applies to VidPort boards, not SDI Master. + +Connect an SDI receiver to your board's transmit port with a 75 ohm cable. Assuming that you are using the first transmit port @@ -503,10 +519,9 @@ Other interfaces may be viewed by providing the appropriate device file name. By default, the interface assumes 2-channel audio. If you want to play 8-channel audio data, change the mode by typing - sdiaudiocfg -c3 /dev/sdiaudiotx0 + sdiaudiocfg -c8 /dev/sdiaudiotx0 -as root. This process will block until video data is also provided; -this can be used to synchronize audio and video. +as root. Use sdiaudiocfg -h @@ -517,6 +532,18 @@ If you have an audio file, transmit it with audioplayout /dev/sdiaudiotx0 < test.raw +This process will block until video data is also provided; +this can be used to synchronize audio and video. + +Transmit 2 channel, 16-bit audio with 48 kHz sampling rate +from a compressed audio file with FFmpeg by typing + + ffmpeg -y -i test.ts -f s16le -ar 48000 -ac 2 /dev/sdiaudiotx0 + +Transmit video and audio from a compressed file with FFmpeg by typing + + ffmpeg -y -i test.ts -f rawvideo -pix_fmt uyvy422 /dev/sdivideotx0 -f s16le /dev/sdiaudiotx0 + If you don't have a file, it is possible to transmit a SMPTE RP155 tone. To transmit a RP155 tone diff --git a/quad/copying b/quad/copying deleted file mode 100755 index 60549be51..000000000 --- a/quad/copying +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/quad/doc/ASI/devices.txt b/quad/doc/ASI/devices.txt old mode 100755 new mode 100644 diff --git a/quad/doc/ASI/examples.txt b/quad/doc/ASI/examples.txt old mode 100755 new mode 100644 diff --git a/quad/doc/ASI/features.txt b/quad/doc/ASI/features.txt old mode 100755 new mode 100644 diff --git a/quad/doc/ASI/ioctls.txt b/quad/doc/ASI/ioctls.txt old mode 100755 new mode 100644 diff --git a/quad/doc/ASI/sysfs.txt b/quad/doc/ASI/sysfs.txt old mode 100755 new mode 100644 diff --git a/quad/doc/SDI/devices.txt b/quad/doc/SDI/devices.txt old mode 100755 new mode 100644 index 1ecca5aa8..911326c58 --- a/quad/doc/SDI/devices.txt +++ b/quad/doc/SDI/devices.txt @@ -1,17 +1,17 @@ This file briefly explains how the device files are used. -When the driver module is loaded, each SMPTE 259M-C transmit interface +When the driver module is loaded, each raw SDI transmit interface is assigned a number between 0 and 127. -Similarly, each SMPTE 259M-C receive interface +Similarly, each raw SDI receive interface is assigned a number. The first interface detected in each case is called interface 0, the second is called interface 1, and so on. Each interface is represented by a device file. Device files have characteristic major and minor numbers. The major number determines which driver responds to activity directed -at that file. SMPTE 259M-C drivers respond to activity directed at +at that file. Raw SDI drivers respond to activity directed at files with major number 121 by default. The minor number may be used -by the driver for any purpose. The SMPTE 259M-C API uses it to +by the driver for any purpose. The raw SDI API uses it to identify the interface associated with that file. The 7 least significant bits of the minor number hold the interface number, while bit 8 is zero for transmitters and one for receivers. diff --git a/quad/doc/SDI/examples.txt b/quad/doc/SDI/examples.txt old mode 100755 new mode 100644 index 088ee6e4e..bcb72e1dc --- a/quad/doc/SDI/examples.txt +++ b/quad/doc/SDI/examples.txt @@ -6,7 +6,7 @@ Capture ------- NAME - capture, mcapture - example SMPTE 259M-C receiver application + capture, mcapture - example raw SDI receiver application SYNOPSIS capture [OPTION]... DEVICE_FILE @@ -16,7 +16,7 @@ SYNOPSIS DESCRIPTION Capture reads data from DEVICE_FILE and writes it to standard output, - while monitoring for SMPTE 259M-C receiver events. + while monitoring for raw SDI receiver events. Mcapture uses mmap instead of read. @@ -33,7 +33,7 @@ Playout ------- NAME - playout, mplayout - example SMPTE 259M-C transmitter application + playout, mplayout - example raw SDI transmitter application SYNOPSIS playout [OPTION]... DEVICE_FILE @@ -42,7 +42,7 @@ SYNOPSIS DESCRIPTION Playout reads data from standard input and writes it to DEVICE_FILE, - while monitoring for SMPTE 259M-C transmitter events. + while monitoring for raw SDI transmitter events. At end-of-file, playout issues a fsync () to the interface. @@ -61,14 +61,14 @@ Sdicfg ------ NAME - sdicfg - configure a SMPTE 259M-C interface + sdicfg - configure a raw SDI interface SYNOPSIS sdicfg [OPTION]... DEVICE_FILE DESCRIPTION Sdicfg uses the sysfs virtual filesystem to configure certain parameters - of a SMPTE 259M-C interface. If no options are given, sdicfg + of a raw SDI interface. If no options are given, sdicfg displays the current configuration of the interface. OPTIONS @@ -100,16 +100,16 @@ Sdirxcfg -------- NAME - sdirxcfg - interactively issue SMPTE 259M-C receiver ioctls + sdirxcfg - interactively issue raw SDI receiver ioctls SYNOPSIS sdirxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sdirxcfg is a simple program which demonstrates - the SMPTE 259M-C receiver ioctl commands. + the raw SDI receiver ioctl commands. It can be used interactively to control or monitor - a SMPTE 259M-C receiver, or noninteractively + a raw SDI receiver, or noninteractively with a script piped to its standard input. OPTIONS @@ -123,16 +123,16 @@ Sditxcfg -------- NAME - sditxcfg - interactively issue SMPTE 259M-C transmitter ioctls + sditxcfg - interactively issue raw SDI transmitter ioctls SYNOPSIS sditxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sditxcfg is a simple program which demonstrates - the SMPTE 259M-C transmitter ioctl commands. + the raw SDI transmitter ioctl commands. It can be used interactively to control or monitor - a SMPTE 259M-C transmitter, or noninteractively + a raw SDI transmitter, or noninteractively with a script piped to its standard input. OPTIONS diff --git a/quad/doc/SDI/features.txt b/quad/doc/SDI/features.txt old mode 100755 new mode 100644 index 39ae82e79..ae3131365 --- a/quad/doc/SDI/features.txt +++ b/quad/doc/SDI/features.txt @@ -1,5 +1,5 @@ This file describes some of the major features provided by -Linear Systems Ltd.'s SMPTE 259M-C interface boards and the Linux driver. +Linear Systems Ltd.'s raw SDI API. What features does my board support? ==================================== diff --git a/quad/doc/SDI/ioctls.txt b/quad/doc/SDI/ioctls.txt old mode 100755 new mode 100644 diff --git a/quad/doc/SDI/sysfs.txt b/quad/doc/SDI/sysfs.txt old mode 100755 new mode 100644 index 0908eea9f..fc2f2ca5f --- a/quad/doc/SDI/sysfs.txt +++ b/quad/doc/SDI/sysfs.txt @@ -1,4 +1,4 @@ -This file briefly explains how the SMPTE 259M-C API uses the +This file briefly explains how the raw SDI API uses the sysfs virtual filesystem. Some interface parameters are controlled through sysfs. diff --git a/quad/doc/SDIAUDIO/examples.txt b/quad/doc/SDIAUDIO/examples.txt index c64c47dfb..f7243d611 100644 --- a/quad/doc/SDIAUDIO/examples.txt +++ b/quad/doc/SDIAUDIO/examples.txt @@ -60,7 +60,7 @@ Audiocapture ------------ NAME - audiocapture - example SMPTE 292M audio receiver application + audiocapture - example SDI audio receiver application SYNOPSIS audiocapture [OPTION]... DEVICE_FILE @@ -68,7 +68,7 @@ SYNOPSIS DESCRIPTION Audiocapture reads data from DEVICE_FILE and writes it to standard output, - while monitoring for SMPTE 292M audio receiver events. + while monitoring for SDI audio receiver events. OPTIONS -h @@ -83,7 +83,7 @@ Audioplayout ------------ NAME - audioplayout - example SMPTE 292M audio transmitter application + audioplayout - example SDI audio transmitter application SYNOPSIS audioplayout [OPTION]... DEVICE_FILE @@ -91,7 +91,7 @@ SYNOPSIS DESCRIPTION audioplayout reads data from standard input and writes it to DEVICE_FILE, - while monitoring for SMPTE 292M audio transmitter events. + while monitoring for SDI audio transmitter events. At end-of-file, playout issues a fsync () to the interface. @@ -108,7 +108,7 @@ Sdiaudiocfg ----------- NAME - sdiaudiocfg - configure a SMPTE 292M audio interface + sdiaudiocfg - configure an SDI audio interface SYNOPSIS sdiaudiocfg [OPTION]... DEVICE_FILE @@ -116,7 +116,7 @@ SYNOPSIS DESCRIPTION Sdiaudiocfg uses the sysfs virtual filesystem to configure certain parameters - of a SMPTE 292M audio interface. If no options are given, sdiaudiocfg + of an SDI audio interface. If no options are given, sdiaudiocfg displays the current configuration of the interface. OPTIONS @@ -157,16 +157,16 @@ Sdiaudiorxcfg ------------- NAME - sdiaudiorxcfg - interactively issue SMPTE 292M audio receiver ioctls + sdiaudiorxcfg - interactively issue SDI audio receiver ioctls SYNOPSIS sdiaudiorxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sdiaudiorxcfg is a simple program which demonstrates - the SMPTE 292M audio receiver ioctl commands. + the SDI audio receiver ioctl commands. It can be used interactively to control or monitor - a SMPTE 292M audio receiver, or noninteractively + an SDI audio receiver, or noninteractively with a script piped to its standard input. OPTIONS @@ -180,16 +180,16 @@ Sdiaudiotxcfg ------------- NAME - sdiaudiotxcfg - interactively issue SMPTE 292M audio transmitter ioctls + sdiaudiotxcfg - interactively issue SDI audio transmitter ioctls SYNOPSIS sdiaudiotxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sdiaudiotxcfg is a simple program which demonstrates - the SMPTE 292M audio transmitter ioctl commands. + the SDI audio transmitter ioctl commands. It can be used interactively to control or monitor - a SMPTE 292M audio transmitter, or noninteractively + an SDI audio transmitter, or noninteractively with a script piped to its standard input. OPTIONS diff --git a/quad/doc/SDIAUDIO/features.txt b/quad/doc/SDIAUDIO/features.txt index 5f6730dfe..a84edb0f4 100644 --- a/quad/doc/SDIAUDIO/features.txt +++ b/quad/doc/SDIAUDIO/features.txt @@ -1,5 +1,5 @@ This file describes some of the major features provided by -Linear Systems Ltd.'s SMPTE 292M interface boards and the Linux driver. +Linear Systems Ltd.'s SDI audio API. What features does my board support? ==================================== diff --git a/quad/doc/SDIAUDIO/ioctls.txt b/quad/doc/SDIAUDIO/ioctls.txt index 207f8e0ae..3b4457f71 100644 --- a/quad/doc/SDIAUDIO/ioctls.txt +++ b/quad/doc/SDIAUDIO/ioctls.txt @@ -10,7 +10,7 @@ SDIAUDIO_IOC_GETID Argument type: pointer to unsigned int Read/write: read Valid values: - 0x00b6 - VidPort Q/i + 0x00b6 - QuadPort H/i 0x00c1 - VidPort SD/HD O 0x00c8 - VidPort SD/HD I diff --git a/quad/doc/SDIAUDIO/sysfs.txt b/quad/doc/SDIAUDIO/sysfs.txt index bddbe4754..a3041b0cf 100644 --- a/quad/doc/SDIAUDIO/sysfs.txt +++ b/quad/doc/SDIAUDIO/sysfs.txt @@ -1,4 +1,4 @@ -This file briefly explains how the SMPTE 292M audio API uses the +This file briefly explains how the SDI audio API uses the sysfs virtual filesystem. Some interface parameters are controlled through sysfs. diff --git a/quad/doc/SDIVIDEO/examples.txt b/quad/doc/SDIVIDEO/examples.txt index 8fdc9fd6b..4d9dcfd2d 100644 --- a/quad/doc/SDIVIDEO/examples.txt +++ b/quad/doc/SDIVIDEO/examples.txt @@ -6,7 +6,7 @@ Videocapture ------------ NAME - videocapture, mvideocapture - example SMPTE 292M video receiver application + videocapture, mvideocapture - example SDI video receiver application SYNOPSIS videocapture [OPTION]... DEVICE_FILE @@ -16,7 +16,7 @@ SYNOPSIS DESCRIPTION Videocapture reads data from DEVICE_FILE and writes it to standard output, - while monitoring for SMPTE 292M video receiver events. + while monitoring for SDI video receiver events. Mvideocapture uses mmap instead of read. @@ -33,7 +33,7 @@ Videoplayout ------------ NAME - videoplayout, mvideoplayout - example SMPTE 292M video transmitter application + videoplayout, mvideoplayout - example SDI video transmitter application SYNOPSIS videoplayout [OPTION]... DEVICE_FILE @@ -43,7 +43,7 @@ SYNOPSIS DESCRIPTION videoplayout reads data from standard input and writes it to DEVICE_FILE, - while monitoring for SMPTE 292M video transmitter events. + while monitoring for SDI video transmitter events. At end-of-file, playout issues a fsync () to the interface. @@ -62,7 +62,7 @@ Sdivideocfg ----------- NAME - sdivideocfg - configure a SMPTE 292M video interface + sdivideocfg - configure an SDI video interface SYNOPSIS sdivideocfg [OPTION]... DEVICE_FILE @@ -70,10 +70,14 @@ SYNOPSIS DESCRIPTION Sdivideocfg uses the sysfs virtual filesystem to configure certain parameters - of a SMPTE 292M video interface. If no options are given, sdivideocfg + of an SDI video interface. If no options are given, sdivideocfg displays the current configuration of the interface. OPTIONS + -a + Enable vertical ancillary space on DEVICE_FILE. + -A + Disable vertical ancillary space on DEVICE_FILE. -b BUFFERS Set the number of driver buffers on DEVICE_FILE to BUFFERS. There must be at least two buffers. @@ -83,7 +87,6 @@ OPTIONS Possible values are 1 (SMPTE 125M 486i 59.94 Hz), 2 (ITU-R BT.601 720x576i 50 Hz). - 3 (SMPTE 267M 960x486i 59.94 Hz), 5 (SMPTE 260M 1035i 60 Hz), 6 (SMPTE 260M 1035i 59.94 Hz), 8 (SMPTE 274M 1080i 60 Hz), @@ -121,22 +124,50 @@ OPTIONS BUFSIZE bytes. This must be a positive multiple of four. -V Display the version information and quit. + -x CLKSRC + Set the clock source to CLKSRC. + This is valid only for transmitters. + Possible values are + 0 (onboard oscillator) + 1 (external 525i or NTSC reference) + 2 (external 625i or PAL reference) + 3 (external 525p reference) + 4 (external 625p reference) + 5 (external 720p/60 reference) + 6 (external 720p/59.94 reference) + 7 (external 720p/50 reference) + 8 (external 720p/30 reference) + 9 (external 720p/29.97 reference) + 10 (external 720p/25 reference) + 11 (external 720p/24 reference) + 12 (external 720p/23.98 reference) + 13 (external 1080p/60 reference) + 14 (external 1080p/59.94 reference) + 15 (external 1080p/50 reference) + 16 (external 1080p/30 reference) + 17 (external 1080p/29.97 reference) + 18 (external 1080p/25 reference) + 19 (external 1080p/24 reference) + 20 (external 1080p/23.98 reference) + 21 (external 1080i/60 reference) + 22 (external 1080i/59.94 reference) + 23 (external 1080i/50 reference) Sdivideorxcfg ------------- NAME - sdivideorxcfg - interactively issue SMPTE 292M video receiver ioctls + sdivideorxcfg - interactively issue SDI video receiver ioctls SYNOPSIS sdivideorxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sdivideorxcfg is a simple program which demonstrates - the SMPTE 292M video receiver ioctl commands. + the SDI video receiver ioctl commands. It can be used interactively to control or monitor - a SMPTE 292M video receiver, or noninteractively + an SDI video receiver, or noninteractively with a script piped to its standard input. OPTIONS @@ -150,16 +181,16 @@ Sdivideotxcfg ------------- NAME - sdivideotxcfg - interactively issue SMPTE 292M video transmitter ioctls + sdivideotxcfg - interactively issue SDI video transmitter ioctls SYNOPSIS sdivideotxcfg [OPTION]... DEVICE_FILE DESCRIPTION Sdivideotxcfg is a simple program which demonstrates - the SMPTE 292M video transmitter ioctl commands. + the SDI video transmitter ioctl commands. It can be used interactively to control or monitor - a SMPTE 292M video transmitter, or noninteractively + an SDI video transmitter, or noninteractively with a script piped to its standard input. OPTIONS diff --git a/quad/doc/SDIVIDEO/features.txt b/quad/doc/SDIVIDEO/features.txt index 07a25726a..4095e7f5e 100644 --- a/quad/doc/SDIVIDEO/features.txt +++ b/quad/doc/SDIVIDEO/features.txt @@ -1,5 +1,5 @@ This file describes some of the major features provided by -Linear Systems Ltd.'s SMPTE 292M interface boards and the Linux driver. +Linear Systems Ltd.'s SDI video API. What features does my board support? ==================================== @@ -10,6 +10,17 @@ return bitfields which describe the capabilities of that interface. Packing ======= -By default, video samples are packed in uyvy format. +By default, video samples are packed in UYVY format. Other formats can be selected by changing the mode sysfs parameter. +By default, only the region between SAV and EAV +on production lines is available to applications. +Alternatively, the region between SAV and EAV +on all lines can be included in order, +with frame boundaries occurring at field boundaries. +This gives access to the entire vertical ancillary space. +This is controlled by the vanc sysfs parameter. +When production lines are packed in UYVY format, +the other lines are packed in v216 format +to provide complete ten-bit words. + diff --git a/quad/doc/SDIVIDEO/ioctls.txt b/quad/doc/SDIVIDEO/ioctls.txt index 1dc2c5d09..2c5cb2466 100644 --- a/quad/doc/SDIVIDEO/ioctls.txt +++ b/quad/doc/SDIVIDEO/ioctls.txt @@ -10,7 +10,7 @@ SDIVIDEO_IOC_GETID Argument type: pointer to unsigned int Read/write: read Valid values: - 0x00b6 - VidPort Q/i + 0x00b6 - QuadPort H/i 0x00c1 - VidPort SD/HD O 0x00c8 - VidPort SD/HD I diff --git a/quad/doc/SDIVIDEO/sysfs.txt b/quad/doc/SDIVIDEO/sysfs.txt index beab9718f..2aa578f98 100644 --- a/quad/doc/SDIVIDEO/sysfs.txt +++ b/quad/doc/SDIVIDEO/sysfs.txt @@ -1,4 +1,4 @@ -This file briefly explains how the SMPTE 292M video API uses the +This file briefly explains how the SDI video API uses the sysfs virtual filesystem. Some interface parameters are controlled through sysfs. @@ -106,6 +106,12 @@ mode 2 - v210 deinterlaced 3 - raw +vanc + Enable or disable vertical ancillary space. + Valid values: + 0 - disable (default) + non-zero - enable + Many methods of writing sysfs parameters do not check for errors. Confirming the change by reading the value after a write is recommended in these cases. Sdivideocfg checks for write errors. diff --git a/quad/doc/buffers.txt b/quad/doc/buffers.txt old mode 100755 new mode 100644 diff --git a/quad/doc/examples.txt b/quad/doc/examples.txt old mode 100755 new mode 100644 diff --git a/quad/doc/functions.txt b/quad/doc/functions.txt old mode 100755 new mode 100644 index 67d094b40..a4cf2bcad --- a/quad/doc/functions.txt +++ b/quad/doc/functions.txt @@ -44,7 +44,7 @@ ioctl() Not all ioctls are supported on all interfaces. mmap() - SMPTE 259M-C and SMPTE 292M interfaces only; + Raw SDI and SDI audio/video interfaces only; map the driver buffers into an application's memory space. The first buffer begins at offset zero. Successive buffers begin at the start of the page diff --git a/quad/doc/memory.txt b/quad/doc/memory.txt old mode 100755 new mode 100644 index add019699..655bf13ea --- a/quad/doc/memory.txt +++ b/quad/doc/memory.txt @@ -39,7 +39,7 @@ Memory for all of the buffers is allocated with get_free_page(). For DVB ASI, the "tails" of buffers which are not integer multiples of the page size are "packed" into pages at the end of this memory; ie. several buffers may share a single page. -For SMPTE 259M-C and SMPTE 292M, each tail has its own page. +For raw SDI and SDI audio/video, each tail has its own page. The pointers to these pages are stored in a kmalloc'd array. Another kmalloc'd array is used to store pointers to each page and tail in the order they will be accessed. diff --git a/quad/doc/sysfs.txt b/quad/doc/sysfs.txt old mode 100755 new mode 100644 diff --git a/quad/include/asi.h b/quad/include/asi.h old mode 100755 new mode 100644 diff --git a/quad/include/master.h b/quad/include/master.h old mode 100755 new mode 100644 index 80e875987..8194ff3fe --- a/quad/include/master.h +++ b/quad/include/master.h @@ -38,9 +38,9 @@ #ifndef _MASTER_H #define _MASTER_H -#define MASTER_DRIVER_VERSION "2.7.1" -#define MASTER_DRIVER_VERSION_CODE 0x020701 -#define MASTER_DRIVER_DATE "2010-03-23" +#define MASTER_DRIVER_VERSION "2.7.2" +#define MASTER_DRIVER_VERSION_CODE 0x020702 +#define MASTER_DRIVER_DATE "2010-12-17" #define MASTER_PCI_VENDOR_ID_LINSYS 0x1254 diff --git a/quad/include/sdi.h b/quad/include/sdi.h old mode 100755 new mode 100644 diff --git a/quad/include/sdivideo.h b/quad/include/sdivideo.h index b85436aba..c27f54300 100644 --- a/quad/include/sdivideo.h +++ b/quad/include/sdivideo.h @@ -111,12 +111,15 @@ #define SDIVIDEO_EVENT_RX_STD (1 << SDIVIDEO_EVENT_RX_STD_ORDER) /* Interface capabilities */ +#define SDIVIDEO_CAP_TX_VANC 0x00000040 + #define SDIVIDEO_CAP_RX_CD 0x00000001 #define SDIVIDEO_CAP_RX_DATA 0x00000002 #define SDIVIDEO_CAP_RX_ERR_COUNT 0x00000004 #define SDIVIDEO_CAP_RX_VBI 0x00000008 #define SDIVIDEO_CAP_RX_RAWMODE 0x00000010 #define SDIVIDEO_CAP_RX_DEINTERLACING 0x00000020 +#define SDIVIDEO_CAP_RX_VANC 0x00000040 /* Transmitter clock source settings */ #define SDIVIDEO_CTL_TX_CLKSRC_ONBOARD 0 diff --git a/quad/install b/quad/install deleted file mode 100755 index 247492e04..000000000 --- a/quad/install +++ /dev/null @@ -1,218 +0,0 @@ -Installation instructions for the Master Linux Software Development Kit -======================================================================= - - -Compiling the kernel modules and example programs -------------------------------------------------- - -Kernel module compilation requires the kernel header files. -No action is needed for some Fedora distributions -which include these files in the kernel packages. -Other distributions may need to install a separate -kernel-sourcecode or kernel-devel package before continuing. - -Compile the kernel modules and the example programs by typing - - make - -in the top-level directory of this archive. -This should create the following files in the src directory: - - asi.ko - DVB ASI API module - sdi.ko - SMPTE 259M-C API module - - dvbm.ko - driver module for ATSC Master II FD and DVB Master boards - mmas.ko - MultiMaster SDI-T driver module - mmsa.ko - MultiMaster SDI-R driver module - sdim.ko - SDI Master driver module - sdilpm.ko - SDI Master LP driver module - sdiqoe.ko - SDI Master Q/o driver module - sdiqie.ko - SDI Master Q/i driver module - - ls_as.ko - Active Serial firmware upgrade support module - ls_jtag.ko - JTAG firmware upgrade support module - -The example programs are in the Examples directory. - -If you receive an error message such as -"/lib/modules/2.6.8-24.14-smp/build not found", -the compiler cannot find the kernel header files. -Typically /lib/modules/$(uname -r)/build is -a symbolic link which points to the kernel source. -If this link is missing, you can create it by typing - - ln -s /usr/src/linux-$(uname -r) /lib/modules/$(uname -r)/build - -as root, assuming the kernel source is installed in -/usr/src/linux-$(uname -r). - - -Installing the kernel modules and example programs --------------------------------------------------- - -The kernel modules and example programs may be copied to -the appropriate system directories by typing - - make install - -as root in the top-level directory of this archive. -This copies the example programs to /usr/local/bin, -copies the kernel modules to /lib/modules/$(uname -r)/master, -and rebuilds the module dependency database. - - -Creating device files ---------------------- - -A device file must exist for each interface you wish to use. -Some systems will automatically create a device file for -each interface when the driver module is loaded. -Alternatively, scripts which create device files for -sixteen transmit and sixteen receive interfaces -have been provided for your convenience. -To run these scripts, simply type - - ./mkdev.asi - -and/or - - ./mkdev.sdi - -as root. - -See doc/ASI/devices.txt and doc/SDI/devices.txt -for a description of these device files. -This would also be a good time to change the permissions -on the device files; mkdev.asi and mkdev.sdi allow read and write access -to the root user only. Users who need access to the hardware -should be given read permission on the receiver device files and -write permission on the transmitter device files. -Mmap support on SMPTE 259M-C transmitters requires -both read and write permission. - - -Loading the kernel modules --------------------------- - -Each board needs one driver module and at least one API module -to be loaded before its interfaces can be used. -The required modules for each supported board are listed below. -If the kernel modules have been added to the module dependency database -as described in "Installing the kernel modules and example programs", -only the first module listed (the driver module) needs to be loaded -explicitly; the modules in parentheses (the API modules) will be -loaded automatically. - - DVB Master Send - dvbm.ko (asi.ko) - DVB Master II Send - dvbm.ko (asi.ko) - DVB Master Receive - dvbm.ko (asi.ko) - DVB Master II Receive - dvbm.ko (asi.ko) - DVB Master FD - dvbm.ko (asi.ko) - DVB Master FD-U - dvbm.ko (asi.ko) - DVB Master FD-B - dvbm.ko (asi.ko) - DVB Master III Tx - dvbm.ko (asi.ko) - DVB Master III Rx - dvbm.ko (asi.ko) - DVB Master Dual In - dvbm.ko (asi.ko) - DVB Master LP - dvbm.ko (asi.ko) - DVB Master Q/i - dvbm.ko (asi.ko) - DVB Master Q/o - dvbm.ko (asi.ko) - DVB Master Q/io - dvbm.ko (asi.ko) - DVB Master Quad-2in2out - dvbm.ko (asi.ko) - DVB Master Quad-1in3out - dvbm.ko (asi.ko) - DVB Master Quad-3in1out - dvbm.ko (asi.ko) - ATSC Master II FD - dvbm.ko (asi.ko) - SDI Master - sdim.ko (sdi.ko) - MultiMaster SDI-T - mmas.ko (asi.ko, sdi.ko) - MultiMaster SDI-R - mmsa.ko (asi.ko, sdi.ko) - SDI Master LP - sdilpm.ko (sdi.ko) - SDI Master Q/o - sdiqoe.ko (sdi.ko) - SDI Master Q/i - sdiqie.ko (sdi.ko) - -As root, load the DVB Master driver module by typing - - modprobe dvbm - -Then, type - - lsmod - -to list the loaded modules. -Both "dvbm" and "asi" should be listed. - -Type - - dmesg - -to view the kernel message buffer; -there should be banner messages from the kernel modules -at the end of the buffer. - - -Unloading the kernel modules ----------------------------- - -If you want to load a kernel module but -a module with the same name has already been loaded -(perhaps an older version), you need to unload the existing -module first. For example, unload the DVB Master driver module with - - modprobe -r dvbm - - -Changing the API major number ------------------------------ - -The DVB ASI API and SMPTE 259M-C API handle character device files with -major numbers 61 and 121 by default. -If these numbers conflict with other devices, -you can specify a different number by -loading the API module explicitly: - - modprobe asi major= - -The major numbers used in your system are listed in /proc/devices. -Many major numbers are reserved; -see http://www.lanana.org/ for details. -You will also have to change the major number of the device files, -either manually or by editing mkdev script and running it again. - -If you want to use dynamic major number allocation, -load the module with - - modprobe asi major=0 - -and check the major number in /proc/devices. -You will have to recreate the device files each time -the module is loaded, if they are not automatically created. - - -Loading the kernel modules at boot ----------------------------------- - -Some systems will automatically load the kernel modules at boot -when the boards are detected. -Modules can also be explicitly loaded when the system boots by adding - - modprobe dvbm - -or a similar line for the driver module you wish to load -to /etc/rc.d/rc.local (or any other file which is executed at boot). - -If you need to change the major number of one of the API modules, add - - options asi major= - options sdi major= - -to /etc/modprobe.conf. - - -Uninstalling the kernel modules and example programs ----------------------------------------------------- - -The kernel modules and example programs may be removed from -the system directories by typing - - make uninstall - -as root in the top-level directory of this archive. - diff --git a/quad/mkdist b/quad/mkdist deleted file mode 100755 index c8773d861..000000000 --- a/quad/mkdist +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/sh - -dir=master-$(sed -e '/MASTER_DRIVER_VERSION /!d' \ - -e 's/[^\"]*\"\([^\"]*\)\"/\1/' include/master.h) - -mkdir ${dir} -cp COPYING ${dir} -cp INSTALL ${dir} -cp Makefile ${dir} -cp mkdev.asi ${dir} -cp mkdev.fw ${dir} -cp mkdev.sdi ${dir} -cp NEWS ${dir} -cp README ${dir} - -mkdir ${dir}/src -cp src/as.c ${dir}/src -cp src/asicore.c ${dir}/src -cp src/asicore.h ${dir}/src -cp src/asmi.c ${dir}/src -cp src/dvbmaster.c ${dir}/src -cp src/dvbm_fd.c ${dir}/src -cp src/dvbm_fd.h ${dir}/src -cp src/dvbm_fdu.c ${dir}/src -cp src/dvbm_fdu.h ${dir}/src -cp src/dvbm_lpfd.c ${dir}/src -cp src/dvbm_lpfd.h ${dir}/src -cp src/dvbm.h ${dir}/src -cp src/dvbm_qi.c ${dir}/src -cp src/dvbm_qi.h ${dir}/src -cp src/dvbm_qlf.c ${dir}/src -cp src/dvbm_qlf.h ${dir}/src -cp src/dvbm_qo.c ${dir}/src -cp src/dvbm_qo.h ${dir}/src -cp src/dvbm_qdual.h ${dir}/src -cp src/dvbm_qdual.c ${dir}/src -cp src/dvbm_rx.c ${dir}/src -cp src/dvbm_rx.h ${dir}/src -cp src/dvbm_rxu.c ${dir}/src -cp src/dvbm_tx.c ${dir}/src -cp src/dvbm_tx.h ${dir}/src -cp src/dvbm_txu.c ${dir}/src -cp src/eeprom.c ${dir}/src -cp src/eeprom.h ${dir}/src -cp src/gt64131.c ${dir}/src -cp src/gt64131.h ${dir}/src -cp src/jtag.c ${dir}/src -cp src/lsdma.c ${dir}/src -cp src/lsdma.h ${dir}/src -cp src/Makefile ${dir}/src -cp src/masterlsdma.c ${dir}/src -cp src/masterlsdma.h ${dir}/src -cp src/masterplx.c ${dir}/src -cp src/masterplx.h ${dir}/src -cp src/mdev.c ${dir}/src -cp src/mdev.h ${dir}/src -cp src/miface.c ${dir}/src -cp src/miface.h ${dir}/src -cp src/mmas.h ${dir}/src -cp src/mmsa.h ${dir}/src -cp src/plx9080.c ${dir}/src -cp src/plx9080.h ${dir}/src -cp src/sa.c ${dir}/src -cp src/sdicore.c ${dir}/src -cp src/sdicore.h ${dir}/src -cp src/sdimaster.c ${dir}/src -cp src/sdim.h ${dir}/src -cp src/sdim_lpfd.c ${dir}/src -cp src/sdim_qie.c ${dir}/src -cp src/sdim_qie.h ${dir}/src -cp src/sdim_qoe.c ${dir}/src -cp src/sdim_qoe.h ${dir}/src -cp src/dvbm_q3ioe.c ${dir}/src -cp src/dvbm_q3ioe.h ${dir}/src -cp src/dvbm_q3inoe.c ${dir}/src -cp src/dvbm_q3inoe.h ${dir}/src - -mkdir ${dir}/include -cp include/asi.h ${dir}/include -cp include/master.h ${dir}/include -cp include/sdi.h ${dir}/include - -mkdir ${dir}/doc -cp doc/buffers.txt ${dir}/doc -cp doc/examples.txt ${dir}/doc -cp doc/functions.txt ${dir}/doc -cp doc/memory.txt ${dir}/doc -cp doc/sysfs.txt ${dir}/doc - -mkdir ${dir}/doc/ASI -cp doc/ASI/devices.txt ${dir}/doc/ASI -cp doc/ASI/examples.txt ${dir}/doc/ASI -cp doc/ASI/features.txt ${dir}/doc/ASI -cp doc/ASI/ioctls.txt ${dir}/doc/ASI -cp doc/ASI/sysfs.txt ${dir}/doc/ASI - -mkdir ${dir}/doc/SDI -cp doc/SDI/devices.txt ${dir}/doc/SDI -cp doc/SDI/examples.txt ${dir}/doc/SDI -cp doc/SDI/features.txt ${dir}/doc/SDI -cp doc/SDI/ioctls.txt ${dir}/doc/SDI -cp doc/SDI/sysfs.txt ${dir}/doc/SDI - -mkdir ${dir}/Examples -cp Examples/Makefile ${dir}/Examples -cp Examples/mastercfg.c ${dir}/Examples -cp Examples/pci_ids.h ${dir}/Examples -cp Examples/util.c ${dir}/Examples -cp Examples/util.h ${dir}/Examples - -mkdir ${dir}/Examples/ASI -cp Examples/ASI/asicfg.c ${dir}/Examples/ASI -cp Examples/ASI/calcstuff.c ${dir}/Examples/ASI -cp Examples/ASI/cknull.c ${dir}/Examples/ASI -cp Examples/ASI/Makefile ${dir}/Examples/ASI -cp Examples/ASI/mknull.c ${dir}/Examples/ASI -cp Examples/ASI/rxcfg.c ${dir}/Examples/ASI -cp Examples/ASI/rxmon.c ${dir}/Examples/ASI -cp Examples/ASI/rxtest.c ${dir}/Examples/ASI -cp Examples/ASI/stampinfo.c ${dir}/Examples/ASI -cp Examples/ASI/txcfg.c ${dir}/Examples/ASI -cp Examples/ASI/txmon.c ${dir}/Examples/ASI -cp Examples/ASI/txtest.c ${dir}/Examples/ASI - -mkdir ${dir}/Examples/SDI -cp Examples/SDI/capture.c ${dir}/Examples/SDI -cp Examples/SDI/eg1.c ${dir}/Examples/SDI -cp Examples/SDI/Makefile ${dir}/Examples/SDI -cp Examples/SDI/mcapture.c ${dir}/Examples/SDI -cp Examples/SDI/mplayout.c ${dir}/Examples/SDI -cp Examples/SDI/playout.c ${dir}/Examples/SDI -cp Examples/SDI/sdicfg.c ${dir}/Examples/SDI -cp Examples/SDI/sdirxcfg.c ${dir}/Examples/SDI -cp Examples/SDI/sditxcfg.c ${dir}/Examples/SDI - -chmod -R go-w ${dir} -tar -c --owner=0 --group=0 -v -z -f ${dir}.tar.gz ${dir} -md5sum ${dir}.tar.gz - diff --git a/quad/news b/quad/news deleted file mode 100755 index fb82f98ee..000000000 --- a/quad/news +++ /dev/null @@ -1,196 +0,0 @@ -Version 2.5.1.2 (2008-10-08) - beta version: - -Modified capture.c to print out the 27 MHz counter and timestamp values. - -Added SDI_IOC_RXGET27COUNT and SDI_IOC_RXGETTIMESTAMP ioctls. - -Changed the mode supported by HD-SDI Q/i PCIe (raw, synchronization, and deinterlacing). - -============= - -Added support for DVB Master Quad-3in1out PCIe - -Fixed incorrect channel stopping in DVB Master PCI/PCIe Q/o driver - -Version 2.5.0 (2008-02-11) -============= - -Added support for: - SDI Master Q/i - SDI Master Q/i PCIe - SDI Master Q/o PCIe - DVB Master Q/i LP PCIe - DVB Master Quad-2in2out LP PCIe - DVB Master Quad-1in3out PCIe - -Version 2.4.1 (2007-07-13) -============= - -Added support for SDI Master LP PCIe. - -Fixed device node creation. - -Fixed a bug which prevented transmitter DMA from restarting -on the DVB Master LP PCIe. - -Fixed append/prepend register addresses for DVB Master Quad-2in2out driver. - -Version 2.4.0 (2007-05-01) -============= - -Added support for: - DVB Master II FD PCIe - DVB Master II FD-R PCIe - DVB Master Dual In PCIe - DVB Master FD PCIe - DVB Master FD-R PCIe - DVB Master FDB PCIe - DVB Master FDB-R PCIe - ATSC Master II FD PCIe - ATSC Master II FD-R PCIe - MultiMaster S/A PCIe - MultiMaster A/S PCIe - SDI Master PCIe - DVB Master III TX PCIe - DVB Master III RX PCIe - DVB Master LP PCIe - ATSC Master II FD-RS - DVB Master Q/i PCIe - DVB Master Q/o - DVB Master Q/o PCIe - DVB Master Q/o LP PCIe - DVB Master Quad-2in2out - DVB Master Quad-2in2out PCIe - SDI Master LP - -Added support for RP178 pattern generation in newer SDI Master firmware. - -Version 2.3.1 (2006-12-22) -============= - -Fixed a bug when fsyncing LSDMA-based receivers. - -Removed the Big Kernel Lock from all ioctl calls. - -Merged changes from Linux kernels 2.6.18 and 2.6.19. - -Version 2.3.0 (2006-07-25) -============= - -Merged the DVB Master Q/i into the dvbm module. - -Added support for the DVB Master Q/i (RoHS). - -Fixed a bug in blackburst_type. - -Changed the gpi and gpo sysfs values from decimal to hex. - -Added support for 32-bit ioctls on x86_64. - -Improved the PCI bus efficiency of PLX-based transmitters on some systems. - -Added support for transmitter prepended timestamps -in newer DVB Master FD-U firmware. - -Changed the minimum DVB Master III Tx firmware needed for -prepended timestamp support. - -Merged changes from Linux kernel 2.6.15. - -Version 2.2.0 (2006-01-31) -============= - -Added support for DVB Master LP. - -Split the black burst mode setting into a separate control -accessible per board. - -Modified the watchdog timer to work in units of milliseconds. - -Added PCR departure timestamping and single-shot bitrate correction -for new DVB Master FD-B and DVB Master II FD firmware. - -Added UID to the DVB Master II FD-RS. - -Merged changes from Linux kernel 2.6.13. - -Version 2.1.1 (2005-09-16) -============= - -Added UID to the DVB Master II FD and ATSC Master II FD. - -Added a workaround for rarely-occurring hangs at close -on PLX-based receivers. - -Clarified the licensing terms of the API header files. - -Changed the main loop of the txtest example program to remove -unnecessary read () and write () calls with size zero. - -Version 2.1.0 (2005-06-24) -============= - -Added bypass and GPO to the DVB Master II FD and ATSC Master II FD. - -Added support for the DVB Master Q/i, firmware version 0x0107. - -Fixed typo which broke ASI_IOC_RXGETPID0COUNT and ASI_IOC_RXGETPID2COUNT -on the DVB Master Q/i. - -Version 2.0.0 (2005-05-17) -============= - -Ported to Linux kernel 2.6. - -Moved parameters from procfs to sysfs. - -Version 1.1.0 (2005-04-01) -============= - -Added fw_version, gpi, transport, and version procfs files. - -Added documentation for the bypass_mode, bypass_status, and watchdog -procfs files. - -Added support for the DVB Master II FD and ATSC Master II FD. - -Added an ASI_CAP_RX_REDUNDANT capability. - -Added ASI_IOC_RXGETSTATUS2 and ASI_IOC_RXSETINPUT ioctls. - -Standardized the firmware version format. - -Version 1.0.0 (2004-11-19) -============= - -Added mmap () support and the SDI_IOC_QBUF and SDI_IOC_DQBUF ioctls -to the SMPTE 259M-C API. - -Fixed some bugs in DMA buffer allocation and synchronization. - -Changed the default SMPTE 259M-C buffer parameters. - -Added kernel modules which enable firmware upgrades. - -Version 0.9.0 (2004-11-04) -============= - -First release; based on asi-0.7.3. - -Split the asi module into an asi API module and dvbm and dvbm_qi -driver modules. - -Added support for an external PAL reference signal with -ASI_CTL_TX_CLKSRC_EXT_PAL; check the ASI_CAP_TX_COMPOSITEREF capability. - -Added a directory in /proc/driver for each board. - -Added support for the DVB Master FD-B/R. - -Fixed a buffer overrun on interfaces with more than six sysctls. - -Removed the ASI_IOC_RXGETSTAMP ioctl. - -Added a SMPTE 259M-C API and drivers for -the SDI Master, MultiMaster SDI-T, and MultiMaster SDI-R. - diff --git a/quad/readme b/quad/readme deleted file mode 100755 index db2e0b60c..000000000 --- a/quad/readme +++ /dev/null @@ -1,391 +0,0 @@ -README for the Master Linux Software Development Kit -==================================================== - - -Table of Contents ------------------ - - 1. Introduction - 2. Products supported - 3. Identifying your board - 4. Changes in this version - 5. Installation - 6. Capturing an MPEG-2 transport stream over DVB ASI or SMPTE 310M - 7. Playing an MPEG-2 transport stream over DVB ASI or SMPTE 310M - 8. Capturing 4:2:2 component digital video over SMPTE 259M-C - 9. Playing 4:2:2 component digital video over SMPTE 259M-C -10. Driver limitations and known bugs - - - 1. Introduction ----------------- - -This file is part of Linear Systems Ltd.'s Master Linux -Software Development Kit. This kit includes kernel modules -and several example programs. It is intended for -Linux kernel 2.6.x, and has been tested under Fedora 8 -with kernel 2.6.24. - -Additional documentation is in the doc directory. -The latest version of this kit is available at . -For technical support, or to report bugs or errors in the documentation, -contact . - - - 2. Products supported ----------------------- - -This SDK supports the following products: - - DVB Master Send - DVB Master II Send - DVB Master Receive (Rev. 3 board or higher only, see limitations below) - DVB Master II Receive - DVB Master FD - DVB Master FD-U - DVB Master FD-B - DVB Master III Tx - DVB Master III Rx - DVB Master LP - DVB Master Q/i - SDI Master - MultiMaster SDI-T / MultiMaster A/S - MultiMaster SDI-R / MultiMaster S/A - DVB Master Dual In - ATSC Master II FD - SDI Master LP - DVB Master Q/o - DVB Master Q/io - DVB Master Q/i LP - DVB Master Quad-2in2out - SDI Master Q/o - SDI Master Q/i - DVB Master Quad-1in3out PCIe - DVB Master Quad-3in1out PCIe - HD-SDI Master Q/i PCIe - - - 3. Identifying your board --------------------------- - -Both the DVB Master Send and DVB Master II Send are marked -"DVB-ASI TRANSMITTER". The DVB Master II Send should have a -small 8-pin chip labelled "Tx#", where # is the firmware version. - -Similarly, both the DVB Master Receive and DVB Master II Receive -are marked "DVB-ASI RECEIVER". The DVB Master II Receive should have -a small 8-pin chip labelled "Rx#", where # is the firmware version. - -The DVB Master FD is marked "DVB Master FD". -The standard PID filtering version should have a small 8-pin chip -labelled "FDPF##", where ## is the firmware version. -The PID monitoring version should have -a small 8-pin chip labelled "FDPM##", where ## is the firmware version. - -The firmware version of all boards is also added to the kernel log -when each board is detected by the driver. -This log is viewable with the "dmesg" command. - -In all cases, the board revision is marked on the board itself -as "REV #". - - - 4. Changes in this version ---------------------------- - -See NEWS for user-visible changes. - - - 5. Installation ----------------- - -For complete installation instructions, read INSTALL. - - - 6. Capturing an MPEG-2 transport stream over DVB ASI or SMPTE 310M -------------------------------------------------------------------- - -Connect a DVB ASI or SMPTE 310M source to your board's receive port -with a 75 ohm cable. -If there is a carrier detect LED on the receiver, -it should light up. - -Assuming that you are using the first receive port -discovered in the machine, view its configuration with - - asicfg /dev/asirx0 - -Other interfaces may be viewed by providing the appropriate device file name. - -By default, the interface should be synchronizing on 188-byte packets. -If you want to capture 204-byte packets, change the mode by typing - - asicfg -m2 /dev/asirx0 - -as root. -Use - - asicfg -h - -to view information about other options. - -Run the rxtest program by typing - - rxtest -s1 /dev/asirx0 test.ts - -to copy data from the first receiver to a file called test.ts and -display status messages every second. -If you receive an error message, make sure you have read permission -on the device file. Press Ctrl+C to quit rxtest. - - - 7. Playing an MPEG-2 transport stream over DVB ASI or SMPTE 310M ------------------------------------------------------------------ - -Connect a DVB ASI or SMPTE 310M receiver to your board's transmit port -with a 75 ohm cable. - -If you have a board which can bypass the system and forward a -received stream directly to the transmit port, you will have to -disable the bypass. Assuming this is the first board detected by -the dvbm.ko driver, view the bypass mode with - - mastercfg dvbm 0 - -Other boards may be viewed by providing the appropriate device number. - -This feature is enabled by default, which will discard any data -transmitted from the system. Disable the bypass by typing - - mastercfg -b1 dvbm 0 - -as root. - -Assuming that you are using the first transmit port -discovered in the machine, view its configuration with - - asicfg /dev/asitx0 - -Other interfaces may be viewed by providing the appropriate device file name. - -By default, the interface assumes 188-byte packets. -If you want to play a stream with 204-byte packets, -change the mode by typing - - asicfg -m1 /dev/asitx0 - -as root. -Use - - asicfg -h - -to view information about other options. - -Use - - txcfg /dev/asitx0 - -and select "Show transmitter capabilities" -to view the capabilities of this interface. -This information will be needed to correctly set the transmit bitrate -for DVB ASI. - -For SMPTE 310M, a transport stream file may be transmitted with - - txtest /dev/asitx0 < test.ts - -If you don't have a file, it is possible to transmit a stream -of MPEG-2 null packets with - - mknull | txtest /dev/asitx0 - -If you receive an error message, make sure you have write permission -on the device file. Press Ctrl+C to quit mknull. - -The remainder of this section applies to DVB ASI only. - -Your DVB ASI board uses a set of "stuffing parameters" -to scale its transmit bitrate relative to its reference frequency. -Use - - calcstuff - -to calculate recommended stuffing parameters. -This will display several sets of stuffing parameters, -divided into three groups. -The "without finetuning" group should be used with -older boards which do not support bitrate finetuning. -The "finetuning" group should be used with -boards which support bitrate finetuning. -Bitrate finetuning provides more precise bitrate control, -but typically higher network jitter. -The "interleaved finetuning" group should be used with -boards which support interleaved bitrate finetuning. -Interleaved bitrate finetuning MAY provide -less network jitter than bitrate finetuning. - -Within each group, there are two or three sets of stuffing parameters. -Each set will provide the same bitrate and network jitter, -but different spacing between packets. -Some equipment may be sensitive to this. -The "burst mode" set of stuffing parameters transmits each packet in a -continuous burst, with long gaps between packets. -An alternative set of stuffing parameters transmits -the stream with a gap between each byte. -Interfaces which support large interbyte stuffing values -can use the "large ib" stuffing parameters -displayed for extremely low bitrates. - -Suppose we wish to transmit a stream of 188-byte packets -at 19392658.46 bps (the ATSC rate). -With interleaved finetuning, calcstuff provides -the following stuffing parameters: - - ib = 10, ip = 33, normal_ip = 2, big_ip = 169, - il_normal = 1, il_big = 14 - -If you have a transport stream file, transmit it with - - txtest /dev/asitx0 10 33 2 169 1 14 < test.ts - -If you don't have a file, it is possible to transmit a stream -of MPEG-2 null packets with - - mknull | txtest /dev/asitx0 10 33 2 169 1 14 - -If you receive an error message, make sure you have write permission -on the device file. Press Ctrl+C to quit mknull. - - - 8. Capturing 4:2:2 component digital video over SMPTE 259M-C -------------------------------------------------------------- - -Connect a SMPTE 259M-C source to your board's receive port -with a 75 ohm cable. -If there is a carrier detect LED on the receiver, -it should light up. - -Assuming that you are using the first receive port -discovered in the machine, view its configuration with - - sdicfg /dev/sdirx0 - -Other interfaces may be viewed by providing the appropriate device file name. - -By default, the interface should be capturing with 10-bit precision -and packing four 10-bit words into every five bytes. -If you want to capture with 8-bit precision, change the mode by typing - - sdicfg -m0 /dev/sdirx0 - -as root. -Use - - sdicfg -h - -to view information about other options. - -Capture one second of video to a file called test.sdi by typing - - capture -n1 /dev/sdirx0 > test.sdi - -If you receive an error message, make sure you have read permission -on the device file. Capturing longer segments to disk -without overrunning the driver's buffers will probably require -a disk array. - - - 9. Playing 4:2:2 component digital video over SMPTE 259M-C ------------------------------------------------------------ - -Connect a SMPTE 259M-C receiver to your board's transmit port -with a 75 ohm cable. - -Assuming that you are using the first transmit port -discovered in the machine, view its configuration with - - sdicfg /dev/sditx0 - -Other interfaces may be viewed by providing the appropriate device file name. - -By default, the interface assumes 10-bit data with -four 10-bit words packed into every five bytes. -If you want to play 8-bit data, change the mode by typing - - sdicfg -m0 /dev/sditx0 - -as root. -Use - - sdicfg -h - -to view information about other options. - -If you have a video file, transmit it with - - playout /dev/sditx0 < test.sdi - -Playing long files from disk without underrunning the driver's buffers -will probably require a disk array. - -If you don't have a file, it is possible to transmit -a SMPTE EG 1 color bar pattern with - - eg1 | playout /dev/sditx0 - -If you receive an error message, make sure you have write permission -on the device file. Press Ctrl+C to quit eg1. - - 10. Capturing 4:2:2 component digital video over SMPTE 274M -------------------------------------------------------------- - -Connect a SMPTE 274M source to your board's receive port -with a 75 ohm cable. -If there is a carrier detect LED on the receiver, -it should light up. - -Assuming that you are using the first receive port -discovered in the machine, view its configuration with - - hdsdicfg /dev/sdirx0 - -Other interfaces may be viewed by providing the appropriate device file name. - -By default, the interface should be capturing with 10-bit precision -and packing four 10-bit words into every five bytes. -If you want to capture raw data, change the mode by typing - - hdsdicfg -m0 /dev/sdirx0 - -as root. -Use - - hdsdicfg -h - -to view information about other options. - -Display the bitrate of the icoming stream by typing - - bitrate -s1 /dev/sdirx0 - -Capture video to a file called test.sdi by typing - - bitrate /dev/sdirx0 test.hdsdi - -If you receive an error message, make sure you have read permission -on the device file. Capturing longer segments to disk -without overrunning the driver's buffers will probably require -a disk array. - - -11. Driver limitations and known bugs -------------------------------------- - -Streaming data to or from disk requires a fast CPU and a fast disk. -The hdparm utility may be useful for benchmarking and optimizing disk access. - -Rev. 2 DVB Master Receive boards frequently refuse to allow -the status register to be read at the start of the -interrupt service routine, effectively hanging the machine. -Contact your distributor to obtain a replacement board. - diff --git a/quad/src/Makefile b/quad/src/Makefile deleted file mode 100755 index 05901cbe4..000000000 --- a/quad/src/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -# Makefile for the Master Linux drivers and APIs - -ifneq ($(KERNELRELEASE),) -obj-m := asi.o dvbm.o sdi.o sdiaudio.o sdivideo.o \ - sdim.o sdilpm.o mmas.o mmsa.o sdiqoe.o \ - sdiqie.o ls_as.o ls_jtag.o hdsdim.o -asi-objs := asicore.o miface.o mdma.o -dvbm-objs := dvbmaster.o mdev.o \ - lsdma.o plx9080.o gt64131.o \ - dvbm_fd.o dvbm_fdu.o dvbm_rx.o dvbm_rxu.o dvbm_tx.o dvbm_txu.o \ - dvbm_lpfd.o dvbm_qlf.o dvbm_qi.o dvbm_qo.o dvbm_qdual.o dvbm_q3ioe.o \ - dvbm_q3inoe.o dvbm_lptxe.o dvbm_lprxe.o -ls_as-objs := asmi.o eeprom.o -ls_jtag-objs := jtag.o eeprom.o -sdi-objs := sdicore.o miface.o mdma.o -sdiaudio-objs := sdiaudiocore.o miface.o mdma.o -sdivideo-objs := sdivideocore.o miface.o mdma.o -sdim-objs := sdimaster.o mdev.o plx9080.o -sdilpm-objs := sdim_lpfd.o mdev.o lsdma.o -sdiqoe-objs := sdim_qoe.o mdev.o lsdma.o -sdiqie-objs := sdim_qie.o mdev.o plx9080.o lsdma.o -hdsdim-objs := hdsdimaster.o mdev.o lsdma.o \ - hdsdim_qie.o hdsdim_txe.o hdsdim_rxe.o -mmas-objs := as.o mdev.o plx9080.o -mmsa-objs := sa.o mdev.o plx9080.o - -else - -SHELL = /bin/sh -INSTALL = install -DEPMOD = /sbin/depmod - -.SUFFIXES: -.SUFFIXES: .c .o - -.PHONY: all clean install uninstall - -KERNELPTR := /lib/modules/$(shell uname -r)/build -KERNELSRC := $(shell if [ -e $(KERNELPTR) ]; then echo $(KERNELPTR); fi) -ifeq ($(KERNELSRC),) -$(error $(KERNELPTR) not found) -endif -PWD := $(shell pwd) -INSTALLDIR := /lib/modules/$(shell uname -r)/master -TARGETS = asi.ko dvbm.ko sdi.ko sdiaudio.ko sdivideo.ko \ - sdim.ko sdilpm.ko sdiqoe.ko sdiqie.ko mmas.ko mmsa.ko hdsdim.ko - -all: - $(MAKE) -C $(KERNELSRC) M=$(PWD) modules - -clean: - $(MAKE) -C $(KERNELSRC) M=$(PWD) clean - -install: all -# Don't use kbuild to install unless you blacklist the ASMI and JTAG modules, -# because they silently conflict with the other modules. -# $(MAKE) -C $(KERNELSRC) M=$(PWD) modules_install - $(INSTALL) -d $(INSTALLDIR) - $(INSTALL) -m 0644 $(TARGETS) $(INSTALLDIR) - $(DEPMOD) -a - -uninstall: - $(RM) $(foreach module,$(TARGETS),$(INSTALLDIR)/$(module)) - $(DEPMOD) -a - rmdir $(INSTALLDIR) -endif - diff --git a/quad/src/as.c b/quad/src/as.c old mode 100755 new mode 100644 index 2537ee24d..ea6878f43 --- a/quad/src/as.c +++ b/quad/src/as.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* MODULE_LICENSE */ @@ -86,9 +85,7 @@ static void mmas_start_tx_dma (struct master_iface *iface); static long mmas_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int mmas_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(mmas_txfsync,filp,datasync); static void mmas_rxinit (struct master_iface *iface); static void mmas_rxstart (struct master_iface *iface); static void mmas_rxstop (struct master_iface *iface); @@ -96,9 +93,7 @@ static void mmas_rxexit (struct master_iface *iface); static long mmas_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int mmas_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(mmas_rxfsync,filp,datasync); static int mmas_init_module (void) __init; static void mmas_cleanup_module (void) __exit; @@ -136,7 +131,7 @@ static struct file_operations mmas_txfops = { .write = sdi_write, .poll = sdi_txpoll, .unlocked_ioctl = mmas_txunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = mmas_txunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -150,7 +145,7 @@ static struct file_operations mmas_rxfops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = mmas_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = mmas_rxunlocked_ioctl, .mmap = NULL, .open = asi_open, .release = asi_release, @@ -213,14 +208,23 @@ mmas_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } spin_lock (&card->reg_lock); reg = master_inl (card, MMAS_TCSR) & ~MMAS_TCSR_PAL; master_outl (card, MMAS_TCSR, reg | (val << 9)); spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -389,7 +393,17 @@ mmas_pci_probe (struct pci_dev *pdev, } /* Register a transmit interface */ - cap = (card->version >= 0x0102) ? SDI_CAP_TX_RXCLKSRC : 0; + switch (pdev->device) { + default: + case MMAS_PCI_DEVICE_ID_LINSYS: + if (card->version >= 0x0102) { + cap = SDI_CAP_TX_RXCLKSRC; + } + break; + case MMASE_PCI_DEVICE_ID_LINSYS: + cap = SDI_CAP_TX_RXCLKSRC; + break; + } if ((err = sdi_register_iface (card, &plx_dma_ops, MMAS_FIFO, @@ -776,15 +790,12 @@ mmas_txunlocked_ioctl (struct file *filp, /** * mmas_txfsync - MultiMaster SDI-T transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -mmas_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(mmas_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -1188,15 +1199,12 @@ mmas_rxunlocked_ioctl (struct file *filp, /** * mmas_rxfsync - MultiMaster SDI-T receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -mmas_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(mmas_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/asicore.c b/quad/src/asicore.c old mode 100755 new mode 100644 index 11243be21..af4dbf873 --- a/quad/src/asicore.c +++ b/quad/src/asicore.c @@ -104,7 +104,6 @@ EXPORT_SYMBOL(asi_txpoll); EXPORT_SYMBOL(asi_rxpoll); EXPORT_SYMBOL(asi_txioctl); EXPORT_SYMBOL(asi_rxioctl); -EXPORT_SYMBOL(asi_compat_ioctl); EXPORT_SYMBOL(asi_mmap); EXPORT_SYMBOL(asi_release); EXPORT_SYMBOL(asi_register_iface); @@ -321,24 +320,6 @@ asi_rxioctl (struct file *filp, return 0; } -/** - * asi_compat_ioctl - 32-bit ioctl handler - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -long -asi_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = filp->f_dentry->d_inode; - - return filp->f_op->ioctl (inode, filp, cmd, arg); -} - /** * asi_mmap - ASI interface mmap() method * @filp: file diff --git a/quad/src/asicore.h b/quad/src/asicore.h old mode 100755 new mode 100644 index 61c17ac3b..295a82d28 --- a/quad/src/asicore.h +++ b/quad/src/asicore.h @@ -4,7 +4,7 @@ * Linear Systems Ltd. DVB Master ASI interface boards. * * Copyright (C) 1999 Tony Bolger - * Copyright (C) 2000-2009 Linear Systems Ltd. + * Copyright (C) 2000-2010 Linear Systems Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -58,9 +58,6 @@ long asi_txioctl (struct file *filp, long asi_rxioctl (struct file *filp, unsigned int cmd, unsigned long arg); -long asi_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); int asi_mmap (struct file *filp, struct vm_area_struct *vma); int asi_release (struct inode *inode, struct file *filp); int asi_register_iface (struct master_dev *card, diff --git a/quad/src/asmi.c b/quad/src/asmi.c old mode 100755 new mode 100644 index 3d0899875..55631d2d4 --- a/quad/src/asmi.c +++ b/quad/src/asmi.c @@ -48,8 +48,7 @@ #include "dvbm_qi.h" #include "dvbm_fdu.h" #include "dvbm_qlf.h" -#include "dvbm_qo.h" -#include "dvbm_q3ioe.h" +#include "dvbm_qio.h" #include "eeprom.h" #include "dvbm_qdual.h" #include "dvbm_qlf.h" @@ -57,7 +56,6 @@ #include "mmsa.h" #include "sdim.h" #include "sdim_qie.h" -#include "dvbm_q3inoe.h" #ifndef DEFINE_PCI_DEVICE_TABLE #define DEFINE_PCI_DEVICE_TABLE(_table) \ @@ -626,7 +624,7 @@ lsa_pci_probe (struct pci_dev *pdev, name = DVBM_NAME_QO; card->flash_addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->data_addr = card->flash_addr + DVBM_QO_ASMIR; + card->data_addr = card->flash_addr + DVBM_QIO_ASMIR; card->bridge_addr = ioremap_nocache ( pci_resource_start(pdev, 0), pci_resource_len (pdev, 0)); @@ -635,7 +633,7 @@ lsa_pci_probe (struct pci_dev *pdev, name = DVBM_NAME_QOE; card->flash_addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->data_addr = card->flash_addr + DVBM_QO_ASMIR; + card->data_addr = card->flash_addr + DVBM_QIO_ASMIR; card->bridge_addr = ioremap_nocache ( pci_resource_start(pdev, 0), pci_resource_len (pdev, 0)); @@ -887,7 +885,7 @@ lsa_pci_probe (struct pci_dev *pdev, name = DVBM_NAME_Q3IOE; card->flash_addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->data_addr = card->flash_addr + DVBM_Q3IO_ASMIR; + card->data_addr = card->flash_addr + DVBM_QIO_ASMIR; card->bridge_addr = ioremap_nocache ( pci_resource_start(pdev, 0), pci_resource_len (pdev, 0)); @@ -896,7 +894,7 @@ lsa_pci_probe (struct pci_dev *pdev, name = DVBM_NAME_Q3INOE; card->flash_addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->data_addr = card->flash_addr + DVBM_Q3INO_ASMIR; + card->data_addr = card->flash_addr + DVBM_QIO_ASMIR; card->bridge_addr = ioremap_nocache ( pci_resource_start(pdev, 0), pci_resource_len (pdev, 0)); diff --git a/quad/src/dvbm.h b/quad/src/dvbm.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_fd.c b/quad/src/dvbm_fd.c old mode 100755 new mode 100644 index d71643414..e3e19b0d6 --- a/quad/src/dvbm_fd.c +++ b/quad/src/dvbm_fd.c @@ -58,18 +58,14 @@ static void dvbm_fd_start_tx_dma (struct master_iface *iface); static long dvbm_fd_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_fd_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_fd_txfsync,filp,datasync); static void dvbm_fd_rxinit (struct master_iface *iface); static void dvbm_fd_rxstart (struct master_iface *iface); static void dvbm_fd_rxstop (struct master_iface *iface); static long dvbm_fd_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_fd_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_fd_rxfsync,filp,datasync); static struct file_operations dvbm_fd_txfops = { .owner = THIS_MODULE, @@ -77,7 +73,7 @@ static struct file_operations dvbm_fd_txfops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = dvbm_fd_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_fd_txunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_fd_txfsync, @@ -90,7 +86,7 @@ static struct file_operations dvbm_fd_rxfops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_fd_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_fd_rxunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_fd_rxfsync, @@ -644,15 +640,12 @@ dvbm_fd_txunlocked_ioctl (struct file *filp, /** * dvbm_fd_txfsync - DVB Master FD transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_fd_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_fd_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -1066,15 +1059,12 @@ dvbm_fd_rxunlocked_ioctl (struct file *filp, /** * dvbm_fd_rxfsync - DVB Master FD receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_fd_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_fd_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/dvbm_fd.h b/quad/src/dvbm_fd.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_fdu.c b/quad/src/dvbm_fdu.c old mode 100755 new mode 100644 index 19005492f..415eb9c08 --- a/quad/src/dvbm_fdu.c +++ b/quad/src/dvbm_fdu.c @@ -113,9 +113,7 @@ static void dvbm_fdu_start_tx_dma (struct master_iface *iface); static long dvbm_fdu_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_fdu_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_fdu_txfsync,filp,datasync); static void dvbm_fdu_rxinit (struct master_iface *iface); static void dvbm_fdu_rxstart (struct master_iface *iface); static void dvbm_fdu_rxstop (struct master_iface *iface); @@ -123,9 +121,7 @@ static void dvbm_fdu_rxexit (struct master_iface *iface); static long dvbm_fdu_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_fdu_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_fdu_rxfsync,filp,datasync); struct file_operations dvbm_fdu_txfops = { .owner = THIS_MODULE, @@ -133,7 +129,7 @@ struct file_operations dvbm_fdu_txfops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = dvbm_fdu_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_fdu_txunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_fdu_txfsync, @@ -146,7 +142,7 @@ struct file_operations dvbm_fdu_rxfops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_fdu_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_fdu_rxunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_fdu_rxfsync, @@ -271,14 +267,23 @@ dvbm_fdu_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } spin_lock (&card->reg_lock); reg = master_inl (card, DVBM_FDU_TCSR) & ~DVBM_FDU_TCSR_PAL; master_outl (card, DVBM_FDU_TCSR, reg | (val << 13)); spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -705,8 +710,6 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) default: case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDU: case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDU_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE_R: cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | ASI_CAP_TX_BYTECOUNTER | ASI_CAP_TX_LARGEIB | @@ -719,8 +722,23 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) } transport = ASI_CTL_TRANSPORT_DVB_ASI; break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE_R: + cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | + ASI_CAP_TX_BYTECOUNTER | + ASI_CAP_TX_LARGEIB | + ASI_CAP_TX_INTERLEAVING | + ASI_CAP_TX_CHANGENEXTIP | + ASI_CAP_TX_27COUNTER | + ASI_CAP_TX_TIMESTAMPS | + ASI_CAP_TX_PTIMESTAMPS | + ASI_CAP_TX_NULLPACKETS; + if (pci_resource_len (pdev, 2) == 256) { + cap |= ASI_CAP_TX_PCRSTAMP; + } + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDB: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB: cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | ASI_CAP_TX_BYTECOUNTER | ASI_CAP_TX_LARGEIB | @@ -739,8 +757,22 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) } transport = ASI_CTL_TRANSPORT_DVB_ASI; break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB: + cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | + ASI_CAP_TX_BYTECOUNTER | + ASI_CAP_TX_LARGEIB | + ASI_CAP_TX_INTERLEAVING | + ASI_CAP_TX_CHANGENEXTIP | + ASI_CAP_TX_27COUNTER | + ASI_CAP_TX_TIMESTAMPS | + ASI_CAP_TX_PTIMESTAMPS | + ASI_CAP_TX_NULLPACKETS; + if (pci_resource_len (pdev, 2) == 256) { + cap |= ASI_CAP_TX_PCRSTAMP; + } + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDB_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB_R: cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | ASI_CAP_TX_BYTECOUNTER | ASI_CAP_TX_LARGEIB | @@ -753,6 +785,21 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) } transport = ASI_CTL_TRANSPORT_DVB_ASI; break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB_R: + cap |= ASI_CAP_TX_MAKE204 | ASI_CAP_TX_FINETUNING | + ASI_CAP_TX_BYTECOUNTER | + ASI_CAP_TX_LARGEIB | + ASI_CAP_TX_INTERLEAVING | + ASI_CAP_TX_CHANGENEXTIP | + ASI_CAP_TX_27COUNTER | + ASI_CAP_TX_TIMESTAMPS | + ASI_CAP_TX_PTIMESTAMPS | + ASI_CAP_TX_NULLPACKETS; + if (pci_resource_len (pdev, 2) == 256) { + cap |= ASI_CAP_TX_PCRSTAMP; + } + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD: case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD_R: case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD_RS: @@ -801,8 +848,6 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) default: case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDU: case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDU_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE_R: cap |= ASI_CAP_RX_MAKE188 | ASI_CAP_RX_BYTECOUNTER | ASI_CAP_RX_DATA | @@ -816,14 +861,22 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) } transport = ASI_CTL_TRANSPORT_DVB_ASI; break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDE_R: + cap |= ASI_CAP_RX_MAKE188 | + ASI_CAP_RX_BYTECOUNTER | + ASI_CAP_RX_DATA | + ASI_CAP_RX_PIDFILTER | + ASI_CAP_RX_PIDCOUNTER | + ASI_CAP_RX_4PIDCOUNTER | + ASI_CAP_RX_27COUNTER | + ASI_CAP_RX_TIMESTAMPS | + ASI_CAP_RX_PTIMESTAMPS | + ASI_CAP_RX_NULLPACKETS; + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDB: case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDB_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD: - case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FDE: - case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FDE_R: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB_R: cap |= ASI_CAP_RX_MAKE188 | ASI_CAP_RX_BYTECOUNTER | ASI_CAP_RX_DATA | @@ -835,6 +888,32 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) } transport = ASI_CTL_TRANSPORT_DVB_ASI; break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBFDEB_R: + cap |= ASI_CAP_RX_MAKE188 | + ASI_CAP_RX_BYTECOUNTER | + ASI_CAP_RX_DATA | + ASI_CAP_RX_PIDFILTER | + ASI_CAP_RX_27COUNTER | + ASI_CAP_RX_TIMESTAMPS | + ASI_CAP_RX_PTIMESTAMPS | + ASI_CAP_RX_NULLPACKETS; + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD: + case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD_R: + case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FDE: + case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FDE_R: + cap |= ASI_CAP_RX_MAKE188 | + ASI_CAP_RX_BYTECOUNTER | + ASI_CAP_RX_DATA | + ASI_CAP_RX_PIDFILTER | + ASI_CAP_RX_27COUNTER | + ASI_CAP_RX_TIMESTAMPS | + ASI_CAP_RX_PTIMESTAMPS | + ASI_CAP_RX_NULLPACKETS; + transport = ASI_CTL_TRANSPORT_DVB_ASI; + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FD_RS: case DVBM_PCI_DEVICE_ID_LINSYS_DVB2FDE_RS: cap |= ASI_CAP_RX_MAKE188 | @@ -854,6 +933,8 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) break; case ATSCM_PCI_DEVICE_ID_LINSYS_2FD: case ATSCM_PCI_DEVICE_ID_LINSYS_2FD_R: + case ATSCM_PCI_DEVICE_ID_LINSYS_2FDE: + case ATSCM_PCI_DEVICE_ID_LINSYS_2FDE_R: transport = ASI_CTL_TRANSPORT_SMPTE_310M; break; case ATSCM_PCI_DEVICE_ID_LINSYS_2FD_RS: @@ -861,10 +942,6 @@ dvbm_fdu_pci_probe (struct pci_dev *pdev) ASI_CAP_RX_4PIDCOUNTER; transport = ASI_CTL_TRANSPORT_SMPTE_310M; break; - case ATSCM_PCI_DEVICE_ID_LINSYS_2FDE: - case ATSCM_PCI_DEVICE_ID_LINSYS_2FDE_R: - transport = ASI_CTL_TRANSPORT_SMPTE_310M; - break; } if ((err = asi_register_iface (card, &plx_dma_ops, @@ -1365,15 +1442,12 @@ dvbm_fdu_txunlocked_ioctl (struct file *filp, /** * dvbm_fdu_txfsync - DVB Master FD-U transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_fdu_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_fdu_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dma *dma = iface->dma; @@ -1855,15 +1929,12 @@ dvbm_fdu_rxunlocked_ioctl (struct file *filp, /** * dvbm_fdu_rxfsync - DVB Master FD-U receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_fdu_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_fdu_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/dvbm_fdu.h b/quad/src/dvbm_fdu.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_lpfd.c b/quad/src/dvbm_lpfd.c old mode 100755 new mode 100644 index d16cc92d4..c66530c98 --- a/quad/src/dvbm_lpfd.c +++ b/quad/src/dvbm_lpfd.c @@ -78,9 +78,7 @@ static void dvbm_lpfd_start_tx_dma (struct master_iface *iface); static long dvbm_lpfd_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_lpfd_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_lpfd_txfsync,filp,datasync); static void dvbm_lpfd_rxinit (struct master_iface *iface); static void dvbm_lpfd_rxstart (struct master_iface *iface); static void dvbm_lpfd_rxstop (struct master_iface *iface); @@ -88,9 +86,7 @@ static void dvbm_lpfd_rxexit (struct master_iface *iface); static long dvbm_lpfd_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_lpfd_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_lpfd_rxfsync,filp,datasync); struct file_operations dvbm_lpfd_txfops = { .owner = THIS_MODULE, @@ -98,7 +94,7 @@ struct file_operations dvbm_lpfd_txfops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = dvbm_lpfd_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_lpfd_txunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_lpfd_txfsync, @@ -111,7 +107,7 @@ struct file_operations dvbm_lpfd_rxfops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_lpfd_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_lpfd_rxunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_lpfd_rxfsync, @@ -239,14 +235,21 @@ dvbm_lpfd_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } - spin_lock (&card->reg_lock); + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } reg = readl (card->core.addr + DVBM_LPFD_TCSR) & ~DVBM_LPFD_TCSR_PAL; writel (reg | (val << 13), card->core.addr + DVBM_LPFD_TCSR); - spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -747,11 +750,9 @@ dvbm_lpfd_txinit (struct master_iface *iface) reg |= DVBM_LPFD_TCSR_RXCLK; break; } - spin_lock (&card->reg_lock); reg |= readl (card->core.addr + DVBM_LPFD_TCSR) & DVBM_LPFD_TCSR_PAL; writel (reg | DVBM_LPFD_TCSR_RST, card->core.addr + DVBM_LPFD_TCSR); writel (reg, card->core.addr + DVBM_LPFD_TCSR); - spin_unlock (&card->reg_lock); writel (DVBM_LPFD_TFSL << 16, card->core.addr + DVBM_LPFD_TFCR); /* There will be no races on IBSTR, IPSTR, and FTR * until this code returns, so we don't need to lock them */ @@ -772,10 +773,6 @@ dvbm_lpfd_txstart (struct master_iface *iface) struct master_dev *card = iface->card; unsigned int reg; - /* Enable DMA */ - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(0)); - /* Enable transmitter interrupts */ spin_lock_irq (&card->irq_lock); reg = readl (card->core.addr + DVBM_LPFD_ICSR) & @@ -785,10 +782,8 @@ dvbm_lpfd_txstart (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Enable the transmitter */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_TCSR); writel (reg | DVBM_LPFD_TCSR_EN, card->core.addr + DVBM_LPFD_TCSR); - spin_unlock (&card->reg_lock); return; } @@ -817,10 +812,8 @@ dvbm_lpfd_txstop (struct master_iface *iface) } /* Disable the transmitter */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_TCSR); writel (reg & ~DVBM_LPFD_TCSR_EN, card->core.addr + DVBM_LPFD_TCSR); - spin_unlock (&card->reg_lock); /* Disable transmitter interrupts */ spin_lock_irq (&card->irq_lock); @@ -831,8 +824,7 @@ dvbm_lpfd_txstop (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Disable DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(0)); return; @@ -849,10 +841,8 @@ dvbm_lpfd_txexit (struct master_iface *iface) unsigned int reg; /* Reset the transmitter */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_TCSR); writel (reg | DVBM_LPFD_TCSR_RST, card->core.addr + DVBM_LPFD_TCSR); - spin_unlock (&card->reg_lock); return; } @@ -870,13 +860,11 @@ dvbm_lpfd_start_tx_dma (struct master_iface *iface) writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(0)); - wmb (); writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC(0)); writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(0)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_ENABLE, @@ -965,15 +953,12 @@ dvbm_lpfd_txunlocked_ioctl (struct file *filp, /** * dvbm_lpfd_txfsync - DVB Master LP FD transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_lpfd_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_lpfd_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dma *dma = iface->dma; @@ -1047,7 +1032,6 @@ dvbm_lpfd_rxinit (struct master_iface *iface) /* There will be no races on RCSR * until this code returns, so we don't need to lock it */ writel (reg | DVBM_LPFD_RCSR_RST, card->core.addr + DVBM_LPFD_RCSR); - wmb (); writel (reg, card->core.addr + DVBM_LPFD_RCSR); /* Reset PID filter. @@ -1055,9 +1039,9 @@ dvbm_lpfd_rxinit (struct master_iface *iface) * until this code returns, so we don't need to lock it */ for (i = 0; i < 256; i++) { writel (i, card->core.addr + DVBM_LPFD_PFLUTAR); - wmb (); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_LPFD_PFLUTAR); writel (0xffffffff, card->core.addr + DVBM_LPFD_PFLUTR); - wmb (); } return; @@ -1080,7 +1064,6 @@ dvbm_lpfd_rxstart (struct master_iface *iface) writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(1)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(1)); @@ -1099,12 +1082,9 @@ dvbm_lpfd_rxstart (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Enable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_RCSR); writel (reg | DVBM_LPFD_RCSR_EN, card->core.addr + DVBM_LPFD_RCSR); - spin_unlock (&card->reg_lock); - return; } @@ -1119,10 +1099,8 @@ dvbm_lpfd_rxstop (struct master_iface *iface) unsigned int reg; /* Disable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_RCSR); writel (reg & ~DVBM_LPFD_RCSR_EN, card->core.addr + DVBM_LPFD_RCSR); - spin_unlock (&card->reg_lock); /* Disable receiver interrupts */ spin_lock_irq (&card->irq_lock); @@ -1135,18 +1113,17 @@ dvbm_lpfd_rxstop (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(1)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & - ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(1)); - /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(1)); @@ -1289,9 +1266,9 @@ dvbm_lpfd_rxunlocked_ioctl (struct file *filp, spin_lock (&card->reg_lock); for (i = 0; i < 256; i++) { writel (i, card->core.addr + DVBM_LPFD_PFLUTAR); - wmb (); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_LPFD_PFLUTAR); writel (pflut[i], card->core.addr + DVBM_LPFD_PFLUTR); - wmb (); } spin_unlock (&card->reg_lock); kfree (pflut); @@ -1314,15 +1291,12 @@ dvbm_lpfd_rxunlocked_ioctl (struct file *filp, /** * dvbm_lpfd_rxfsync - DVB Master LP FD receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_lpfd_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_lpfd_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -1337,7 +1311,6 @@ dvbm_lpfd_rxfsync (struct file *filp, spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_LPFD_RCSR); writel (reg | DVBM_LPFD_RCSR_RST, card->core.addr + DVBM_LPFD_RCSR); - wmb (); writel (reg, card->core.addr + DVBM_LPFD_RCSR); spin_unlock (&card->reg_lock); iface->events = 0; diff --git a/quad/src/dvbm_lpfd.h b/quad/src/dvbm_lpfd.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_lpqo.c b/quad/src/dvbm_lpqo.c new file mode 100644 index 000000000..38cb9479b --- /dev/null +++ b/quad/src/dvbm_lpqo.c @@ -0,0 +1,729 @@ +/* dvbm_lpqo.c + * + * Linux driver for Linear Systems Ltd. DVB Master Q/o LP PCIe. + * + * Copyright (C) 2006-2010 Linear Systems Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either Version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public Licence for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Linear Systems can be contacted at . + * + */ + +#include /* KERN_INFO */ +#include /* THIS_MODULE */ + +#include /* inode, file, file_operations */ +#include /* pt_regs */ +#include /* pci_resource_start () */ +#include /* kzalloc () */ +#include /* INIT_LIST_HEAD () */ +#include /* spin_lock_init () */ +#include /* __devinit */ +#include /* error codes */ +#include /* irqreturn_t */ +#include /* device_create file */ +#include /* mutex_init () */ + +#include /* put_user () */ +#include /* set_bit () */ + +#include "asicore.h" +#include "../include/master.h" +#include "mdev.h" +#include "dvbm.h" +#include "mdma.h" +#include "dvbm_lpqo.h" +#include "plx9080.h" +#include "lsdma.h" + +static const char dvbm_lpqoe_name[] = DVBM_NAME_LPQOE; +static const char dvbm_lpqoe_minibnc_name[] = DVBM_NAME_LPQOE_MINIBNC; + +/* Static function prototypes */ +static ssize_t dvbm_lpqo_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t dvbm_lpqo_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count); +static ssize_t dvbm_lpqo_show_uid (struct device *dev, + struct device_attribute *attr, + char *buf); +static irqreturn_t IRQ_HANDLER (dvbm_lpqo_irq_handler, irq, dev_id, regs); +static void dvbm_lpqo_init (struct master_iface *iface); +static void dvbm_lpqo_start (struct master_iface *iface); +static void dvbm_lpqo_stop (struct master_iface *iface); +static void dvbm_lpqo_exit (struct master_iface *iface); +static void dvbm_lpqo_start_tx_dma (struct master_iface *iface); +static long dvbm_lpqo_unlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg); +static int FSYNC_HANDLER(dvbm_lpqo_fsync,filp,datasync); + +static struct file_operations dvbm_lpqo_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = asi_write, + .poll = asi_txpoll, + .unlocked_ioctl = dvbm_lpqo_unlocked_ioctl, + .compat_ioctl = dvbm_lpqo_unlocked_ioctl, + .open = asi_open, + .release = asi_release, + .fsync = dvbm_lpqo_fsync, + .fasync = NULL +}; + +static struct master_iface_operations dvbm_lpqo_ops = { + .init = dvbm_lpqo_init, + .start = dvbm_lpqo_start, + .stop = dvbm_lpqo_stop, + .exit = dvbm_lpqo_exit, + .start_tx_dma = dvbm_lpqo_start_tx_dma +}; + +/** + * dvbm_lpqo_show_blackburst_type - interface attribute read handler + * @dev: device being read + * @attr: device_attribute + * @buf: output buffer + **/ +static ssize_t +dvbm_lpqo_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct master_dev *card = dev_get_drvdata(dev); + + return snprintf (buf, PAGE_SIZE, "%u\n", + (readl (card->core.addr + DVBM_LPQO_CSR) & DVBM_LPQO_CSR_PLLFS) >> 2); +} + +/** + * dvbm_lpqo_store_blackburst_type - interface attribute write handler + * @dev: device being written + * @attr: device attribute + * @buf: input buffer + * @count: + **/ +static ssize_t +dvbm_lpqo_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct master_dev *card = dev_get_drvdata(dev); + char *endp; + unsigned long val = simple_strtoul (buf, &endp, 0); + unsigned int reg; + const unsigned long max = MASTER_CTL_BLACKBURST_PAL; + int retcode = count; + struct list_head *p; + struct master_iface *iface; + unsigned int total_users = 0; + + if ((endp == buf) || (val > max)) { + return -EINVAL; + } + mutex_lock (&card->users_mutex); + list_for_each (p, &card->iface_list) { + iface = list_entry (p, struct master_iface, list); + total_users += iface->users; + } + if (total_users) { + retcode = -EBUSY; + goto OUT; + } + reg = readl (card->core.addr + DVBM_LPQO_CSR) & ~DVBM_LPQO_CSR_PLLFS; + writel (reg | (val << 2), card->core.addr + DVBM_LPQO_CSR); +OUT: + mutex_unlock (&card->users_mutex); + return retcode; +} + +/** + * dvbm_lpqo_show_uid - interface attribute read handler + * @dev: device being read + * @attr: device attribute + * @buf: output buffer + **/ +static ssize_t +dvbm_lpqo_show_uid (struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct master_dev *card = dev_get_drvdata(dev); + + return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", + readl (card->core.addr + DVBM_LPQO_SSN_HI), + readl (card->core.addr + DVBM_LPQO_SSN_LO)); +} + +static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, + dvbm_lpqo_show_blackburst_type,dvbm_lpqo_store_blackburst_type); +static DEVICE_ATTR(uid,S_IRUGO, dvbm_lpqo_show_uid,NULL); + +/** + * dvbm_lpqo_pci_probe - PCI insertion handler for a DVB Master Q/o LP PCIe + * @pdev: PCI device + * + * Handle the insertion of a DVB Master Q/o LP PCIe. + * Returns a negative error code on failure and 0 on success. + **/ +int __devinit +dvbm_lpqo_pci_probe (struct pci_dev *pdev) +{ + int err; + unsigned int i, cap; + struct master_dev *card; + + err = dvbm_pci_probe_generic (pdev); + if (err < 0) { + goto NO_PCI; + } + + /* Initialize the driver_data pointer so that dvbm_lpqo_pci_remove() + * doesn't try to free it if an error occurs */ + pci_set_drvdata (pdev, NULL); + + /* Allocate a board info structure */ + if ((card = (struct master_dev *) + kzalloc (sizeof (*card), GFP_KERNEL)) == NULL) { + err = -ENOMEM; + goto NO_MEM; + } + + /* Initialize the board info structure */ + card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 2), + pci_resource_len (pdev, 2)); + card->core.addr = ioremap_nocache (pci_resource_start (pdev, 0), + pci_resource_len (pdev, 0)); + switch (pdev->device) { + default: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: + card->name = dvbm_lpqoe_name; + break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: + card->name = dvbm_lpqoe_minibnc_name; + break; + } + card->version = readl(card->core.addr + DVBM_LPQO_FPGAID) & 0xffff; + card->id = pdev->device; + card->irq = pdev->irq; + card->irq_handler = dvbm_lpqo_irq_handler; + INIT_LIST_HEAD(&card->iface_list); + card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; + /* Lock for ICSR[] */ + spin_lock_init (&card->irq_lock); + spin_lock_init (&card->reg_lock); + mutex_init (&card->users_mutex); + card->parent = &pdev->dev; + + /* Print the firmware version */ + printk (KERN_INFO "%s: %s detected, firmware version %u.%u (0x%04X)\n", + dvbm_driver_name, card->name, + card->version >> 8, card->version & 0x00ff, card->version); + + /* Store the pointer to the board info structure + * in the PCI info structure */ + pci_set_drvdata (pdev, card); + + /* Reset the FPGA */ + for (i = 0; i < 4; i++) { + writel (DVBM_LPQO_TCSR_TXRST, + card->core.addr + DVBM_LPQO_TCSR(i)); + } + + /* Setup the LS DMA controller */ + writel (LSDMA_INTMSK_CH(0) | LSDMA_INTMSK_CH(1) | LSDMA_INTMSK_CH(2) + | LSDMA_INTMSK_CH(3), + card->bridge_addr + LSDMA_INTMSK); + + for (i = 0; i < 4; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(i)); + } + + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + + /* Register a DVB Master device */ + if ((err = dvbm_register (card)) < 0) { + goto NO_DEV; + } + + /* Add device attributes */ + if (card->capabilities & MASTER_CAP_BLACKBURST) { + if ((err = device_create_file (card->dev, + &dev_attr_blackburst_type)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'blackburst_type'\n", + dvbm_driver_name); + } + } + if (card->capabilities & MASTER_CAP_UID) { + if ((err = device_create_file (card->dev, + &dev_attr_uid)) < 0) { + printk (KERN_WARNING + "%s: Unable to create file 'uid'\n", + dvbm_driver_name); + } + } + + /* Register the transmit interfaces */ + cap = ASI_CAP_TX_SETCLKSRC | ASI_CAP_TX_FIFOUNDERRUN | ASI_CAP_TX_DATA | + ASI_CAP_TX_MAKE204 | + ASI_CAP_TX_FINETUNING | ASI_CAP_TX_BYTECOUNTER | + ASI_CAP_TX_LARGEIB | ASI_CAP_TX_INTERLEAVING | + ASI_CAP_TX_TIMESTAMPS | + ASI_CAP_TX_NULLPACKETS | + ASI_CAP_TX_PTIMESTAMPS; + if (pdev->device == DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC) { + if (card->version >= 0x0101) { + cap |= ASI_CAP_TX_27COUNTER; + } + } + for (i = 0; i < 4; i++) { + if ((err = asi_register_iface (card, + &lsdma_dma_ops, + 0, + MASTER_DIRECTION_TX, + &dvbm_lpqo_fops, + &dvbm_lpqo_ops, + cap, + 4, + ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { + goto NO_IFACE; + } + } + return 0; + +NO_IFACE: +NO_DEV: +NO_MEM: + dvbm_lpqo_pci_remove (pdev); +NO_PCI: + return err; +} + +/** + * dvbm_lpqo_pci_remove - PCI removal handler for DVB Master Q/o LP PCIe + * @pdev: PCI device + * + * Handle the removal of a DVB Master Q/o LP PCIe. + * This function may be called during PCI probe error handling, + * so don't mark it as __devexit. + **/ +void dvbm_lpqo_pci_remove (struct pci_dev *pdev) +{ + struct master_dev *card = pci_get_drvdata (pdev); + + if (card) { + unsigned int i; + + /* Unregister the device and all interfaces */ + dvbm_unregister_all (card); + + for (i = 0; i < 4; i++) { + writel(0, card->core.addr + DVBM_LPQO_ICSR(i)); + } + iounmap (card->core.addr); + iounmap (card->bridge_addr); + kfree (card); + } + dvbm_pci_remove_generic (pdev); + return; +} + +/** + * dvbm_lpqo_irq_handler - DVB Master Q/o LP PCIe interrupt service routine + * @irq: interrupt number + * @dev_id: pointer to the device data structure + * @regs: processor context + **/ +static irqreturn_t +IRQ_HANDLER (dvbm_lpqo_irq_handler, irq, dev_id, regs) +{ + struct master_dev *card = dev_id; + struct list_head *p = &card->iface_list; + struct master_iface *iface; + unsigned int status, interrupting_iface = 0, i; + unsigned int dmaintsrc = readl (card->bridge_addr + LSDMA_INTSRC); + + for (i = 0; i < 4; i++) { + p = p->next; + iface = list_entry(p, struct master_iface, list); + + if (dmaintsrc & LSDMA_INTSRC_CH(i)) { + /* Read the interrupt type and clear it */ + spin_lock(&card->irq_lock); + status = readl(card->bridge_addr + LSDMA_CSR(i)); + writel(status,card->bridge_addr + LSDMA_CSR(i)); + spin_unlock(&card->irq_lock); + + /* Increment the buffer pointer */ + if (status & LSDMA_CH_CSR_INTSRCBUFFER) { + mdma_advance(iface->dma); + } + + /* Flag end of chain */ + if (status & LSDMA_CH_CSR_INTSRCDONE) { + set_bit(ASI_EVENT_TX_BUFFER_ORDER, + &iface->events); + set_bit(0, &iface->dma_done); + } + + /* Flag DMA abort */ + if (status & LSDMA_CH_CSR_INTSRCSTOP) { + set_bit(0, &iface->dma_done); + } + + interrupting_iface |= (0x1 << i); + } + + /* Check and clear the source of the interrupts */ + spin_lock (&card->irq_lock); + status = readl (card->core.addr + DVBM_LPQO_ICSR(i)); + writel (status, card->core.addr + DVBM_LPQO_ICSR(i)); + spin_unlock (&card->irq_lock); + if (status & DVBM_LPQO_ICSR_TUIS) { + set_bit (ASI_EVENT_TX_FIFO_ORDER, + &iface->events); + interrupting_iface |= 0x1 << i; + } + if (status & DVBM_LPQO_ICSR_TXDIS) { + set_bit (ASI_EVENT_TX_DATA_ORDER, + &iface->events); + interrupting_iface |= 0x1 << i; + } + + if (interrupting_iface & (0x1 << i)) { + wake_up (&iface->queue); + } + } + + if (interrupting_iface) { + + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +/** + * dvbm_lpqo_init - Initialize the DVB Master Q/o LP PCIe transmitter + * @iface: interface + **/ +static void +dvbm_lpqo_init (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg = iface->null_packets ? DVBM_LPQO_TCSR_TNP : 0; + unsigned int clkreg = + readl(card->core.addr + DVBM_LPQO_CSR) & ~DVBM_LPQO_CSR_EXTCLK; + + switch (iface->timestamps) { + default: + case ASI_CTL_TSTAMP_NONE: + reg |= 0; + break; + case ASI_CTL_TSTAMP_APPEND: + reg |= DVBM_LPQO_TCSR_TTSS; + break; + case ASI_CTL_TSTAMP_PREPEND: + reg |= DVBM_LPQO_TCSR_TPRC; + break; + } + switch (iface->mode) { + default: + case ASI_CTL_TX_MODE_188: + reg |= DVBM_LPQO_TCSR_188; + break; + case ASI_CTL_TX_MODE_204: + reg |= DVBM_LPQO_TCSR_204; + break; + case ASI_CTL_TX_MODE_MAKE204: + reg |= DVBM_LPQO_TCSR_AUTO; + break; + } + switch (iface->clksrc) { + default: + case ASI_CTL_TX_CLKSRC_ONBOARD: + clkreg |= 0; + break; + case ASI_CTL_TX_CLKSRC_EXT: + clkreg |= DVBM_LPQO_CSR_EXTCLK; + break; + } + + /* There will be no races on CSR + * until this code returns, so we don't need to lock it */ + writel (reg | DVBM_LPQO_TCSR_TXRST, + card->core.addr + DVBM_LPQO_TCSR(channel)); + /* XXX Set the transmit clock source (shared by all 4 channels) + * This is broken because each channel can set a different clock source + * for all channels */ + writel (clkreg, card->core.addr + DVBM_LPQO_CSR); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_LPQO_FPGAID); + writel (reg, card->core.addr + DVBM_LPQO_TCSR(channel)); + writel (DVBM_LPQO_TFSL << 16, + card->core.addr + DVBM_LPQO_TFCR(channel)); + + /* Reset byte counter */ + readl (card->core.addr + DVBM_LPQO_TXBCOUNT(channel)); + + writel(0, card->core.addr + DVBM_LPQO_IBSTREG(channel)); + writel(0, card->core.addr + DVBM_LPQO_IPSTREG(channel)); + writel(0, card->core.addr + DVBM_LPQO_FTREG(channel)); + + return; +} + +/** + * dvbm_lpqo_start - Activate the DVB Master Q/o LP PCIe transmitter + * @iface: interface + **/ +static void +dvbm_lpqo_start (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg; + + /* Enable transmitter interrupts */ + spin_lock_irq (&card->irq_lock); + writel(DVBM_LPQO_ICSR_TUIE | DVBM_LPQO_ICSR_TXDIE, + card->core.addr + DVBM_LPQO_ICSR(channel)); + spin_unlock_irq(&card->irq_lock); + + /* Enable the transmitter */ + reg = readl(card->core.addr + DVBM_LPQO_TCSR(channel)); + writel(reg | DVBM_LPQO_TCSR_TXE, + card->core.addr + DVBM_LPQO_TCSR(channel)); + return; +} + +/** + * dvbm_lpqo_stop - Deactivate the DVB Master Q/o LP PCIe transmitter + * @iface: interface + **/ +static void +dvbm_lpqo_stop (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + struct master_dma *dma = iface->dma; + unsigned int reg; + + lsdma_tx_link_all (dma); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + lsdma_reset (dma); + + if (!iface->null_packets) { + /* Wait for the onboard FIFOs to empty */ + /* Atomic read of ICSR, so we don't need to lock */ + wait_event (iface->queue, + !(readl (card->core.addr + DVBM_LPQO_ICSR(channel)) & + DVBM_LPQO_ICSR_TXD)); + } + + /* Disable the Transmitter */ + reg = readl(card->core.addr + DVBM_LPQO_TCSR(channel)); + writel (reg & ~DVBM_LPQO_TCSR_TXE, + card->core.addr + DVBM_LPQO_TCSR(channel)); + + /* Disable Transmitter Interrupts */ + spin_lock_irq (&card->irq_lock); + writel (DVBM_LPQO_ICSR_TUIS | DVBM_LPQO_ICSR_TXDIS, + card->core.addr + DVBM_LPQO_ICSR(channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + spin_unlock_irq (&card->irq_lock); + + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(channel)); + return; +} + +/** + * dvbm_lpqo_exit - Clean up the DVB Master Q/o LP PCIe transmitter + * @iface: interface + **/ +static void +dvbm_lpqo_exit (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + + /* Reset the transmitter. + * There will be no races on CSR here, + * so we don't need to lock it */ + writel (DVBM_LPQO_TCSR_TXRST, + card->core.addr + DVBM_LPQO_TCSR(channel)); + + return; +} + +/** + * dvbm_lpqo_start_tx_dma - start transmit DMA + * @iface: interface + **/ +static void +dvbm_lpqo_start_tx_dma (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + struct master_dma *dma = iface->dma; + const unsigned int dma_channel = mdev_index (card, &iface->list); + + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(dma_channel)); + writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC(dma_channel)); + writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC_H(dma_channel)); + clear_bit (0, &iface->dma_done); + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_ENABLE, + card->bridge_addr + LSDMA_CSR(dma_channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + return; +} + +/** + * dvbm_lpqo_unlocked_ioctl - DVB Master Q/o LP PCIe unlocked_ioctl() method + * @filp: file + * @cmd: ioctl command + * @arg: ioctl argument + * + * Returns a negative error code on failure and 0 on success. + **/ +static long +dvbm_lpqo_unlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + struct asi_txstuffing stuffing; + const unsigned int channel = mdev_index (card, &iface->list); + + switch (cmd) { + case ASI_IOC_TXSETSTUFFING: + if (iface->transport != ASI_CTL_TRANSPORT_DVB_ASI) { + return -ENOTTY; + } + if (copy_from_user (&stuffing, + (struct asi_txstuffing __user *)arg, + sizeof (stuffing))) { + return -EFAULT; + } + if ((stuffing.ib > 0x00ff) || + (stuffing.ip > 0xffffff) || + (stuffing.normal_ip > 0xff) || + (stuffing.big_ip > 0xff) || + ((stuffing.il_normal + stuffing.il_big) > 0xf) || + (stuffing.il_normal > stuffing.normal_ip) || + (stuffing.il_big > stuffing.big_ip)) { + return -EINVAL; + } + + spin_lock (&card->reg_lock); + writel (stuffing.ib, + card->core.addr + DVBM_LPQO_IBSTREG(channel)); + writel (stuffing.ip, + card->core.addr + DVBM_LPQO_IPSTREG(channel)); + writel ((stuffing.il_big << DVBM_LPQO_FTR_ILBIG_SHIFT) | + (stuffing.big_ip << DVBM_LPQO_FTR_BIGIP_SHIFT) | + (stuffing.il_normal << DVBM_LPQO_FTR_ILNORMAL_SHIFT) | + stuffing.normal_ip, + card->core.addr + DVBM_LPQO_FTREG(channel)); + spin_unlock (&card->reg_lock); + break; + case ASI_IOC_TXGETBYTECOUNT: + if (!(iface->capabilities & ASI_CAP_TX_BYTECOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_LPQO_TXBCOUNT(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_TXGETTXD: + /* Atomic read of ICSR, so we don't need to lock */ + if (put_user ((readl (card->core.addr + DVBM_LPQO_ICSR(channel)) + & DVBM_LPQO_ICSR_TXD) ? 1 : 0, + (int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_TXGET27COUNT: + if (!(iface->capabilities & ASI_CAP_TX_27COUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_LPQO_27COUNTR), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + default: + return asi_txioctl (filp, cmd, arg); + } + + return 0; +} + +/** + * dvbm_lpqo_fsync - DVB Master Q/o LP PCIe fsync() method + * @filp: file to flush + * @datasync: used by filesystems + * + * Returns a negative error code on failure and 0 on success. + **/ +static int +FSYNC_HANDLER(dvbm_lpqo_fsync,filp,datasync) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + struct master_dma *dma = iface->dma; + const unsigned int channel = mdev_index (card, &iface->list); + + mutex_lock (&iface->buf_mutex); + + lsdma_tx_link_all(dma); + wait_event(iface->queue, test_bit(0, &iface->dma_done)); + lsdma_reset(dma); + + if (!iface->null_packets) { + /* Wait for the onboard FIFOs to empty */ + /* Atomic read of ICSR, so we don't need to lock */ + wait_event(iface->queue, + !(readl(card->core.addr + DVBM_LPQO_ICSR(channel)) + & DVBM_LPQO_ICSR_TXD)); + } + + mutex_unlock (&iface->buf_mutex); + + return 0; +} + diff --git a/quad/src/dvbm_lpqo.h b/quad/src/dvbm_lpqo.h new file mode 100644 index 000000000..becfe527d --- /dev/null +++ b/quad/src/dvbm_lpqo.h @@ -0,0 +1,104 @@ +/* dvbm_lpqo.h + * + * Header file for the Linear Systems Ltd. DVB Master Q/o LP PCIe. + * + * Copyright (C) 2006-2010 Linear Systems Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either Version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public Licence for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Linear Systems can be contacted at . + * + */ + +#ifndef _DVBM_LPQO_H +#define _DVBM_LPQO_H + +#include /* pci_dev */ +#include /* __devinit */ + +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE 0x0095 +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC 0x00AC + +#define DVBM_NAME_LPQOE "DVB Master Q/o LP PCIe" +#define DVBM_NAME_LPQOE_MINIBNC "DVB Master Q/o LP PCIe Mini BNC" + +#define DVBM_LPQO_TFSL 0x200 /* FIFO start level */ + +/* Register addresses */ +#define DVBM_LPQO_FIFO(c) ((c)*0x100+0x000) /* FIFO */ +#define DVBM_LPQO_DMATLR(c) ((c)*0x100+0x008) /* Receive FIFO control */ +#define DVBM_LPQO_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ +#define DVBM_LPQO_ICSR(c) ((c)*0x100+0x010) /* Int. Control/Status */ +#define DVBM_LPQO_FTREG(c) ((c)*0x100+0x084) /* Fine Tuning */ +#define DVBM_LPQO_TXBCOUNT(c) ((c)*0x100+0x088) /* Transmit Byte Counter */ +#define DVBM_LPQO_TCSR(c) ((c)*0x100+0x08c) /* Transmit Control/Status */ +#define DVBM_LPQO_IBSTREG(c) ((c)*0x100+0x090) /* Interbyte Stuffing */ +#define DVBM_LPQO_IPSTREG(c) ((c)*0x100+0x094) /* Interpacket stuffing */ +#define DVBM_LPQO_TFCR(c) ((c)*0x100+0x098) /* Transmit FIFO Control */ +#define DVBM_LPQO_TPIDR(c) ((c)*0x100+0x09c) /* Transmit PID */ +#define DVBM_LPQO_TPCRR_HI(c) ((c)*0x100+0x0a0) /* Transmit PCR, High Dword */ +#define DVBM_LPQO_TPCRR_LO(c) ((c)*0x100+0x0a4) /* Transmit PCR, Low Dword */ +#define DVBM_LPQO_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Dword */ +#define DVBM_LPQO_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Dword */ +#define DVBM_LPQO_FPGAID 0x400 /* FPGA ID */ +#define DVBM_LPQO_CSR 0x404 /* Control/Status */ +#define DVBM_LPQO_27COUNTR 0x408 /* 27 MHz Counter */ +#define DVBM_LPQO_SSN_HI 0x40c /* Silicon serial number, High */ +#define DVBM_LPQO_SSN_LO 0x410 /* Silicon serial number, low */ +#define DVBM_LPQO_JTAGR 0x414 /* JTAG */ + +/* Int. Control/Status Register bit locations */ +#define DVBM_LPQO_ICSR_TUIE 0x00000001 /* Transmit Underrun Interrupt Enable */ +#define DVBM_LPQO_ICSR_TXDIE 0x00000040 /* Transmit Data Interrupt Enable */ +#define DVBM_LPQO_ICSR_TU 0x00000100 /* Transmit Underrun Status */ +#define DVBM_LPQO_ICSR_TXD 0x00004000 /* Bit goes high when 1st byte of data is transmitted */ +#define DVBM_LPQO_ICSR_TUIS 0x00010000 /* Transmitter Underrun Interrupt Status */ +#define DVBM_LPQO_ICSR_TXDIS 0x00400000 /* Transmit Data Interrupt Status */ +#define DVBM_LPQO_ICSR_PMS 0x04000000 /* Packet Maturity Status */ +#define DVBM_LPQO_ICSR_NOSIG 0x08000000 /* No Signal */ + +/* Interrupt Control/Status Register bitmasks */ +#define DVBM_LPQO_ICSR_ISMASK 0x007f0000 /* Interrupt Status BitMask */ +#define DVBM_LPQO_ICSR_IEMASK 0x0000007f /* Interrupt Enable BitMask */ + +/* Transmit Control/Status Register (TCSR) bit locations */ +#define DVBM_LPQO_TCSR_TXMODE 0x00000003 /* Tx Mode */ +#define DVBM_LPQO_TCSR_TXE 0x00000010 /* Tx Enable */ +#define DVBM_LPQO_TCSR_TXRST 0x00000020 /* Tx Reset */ +#define DVBM_LPQO_TCSR_TTSS 0x00000100 /* Transmit Timestamp Strip */ +#define DVBM_LPQO_TCSR_TNP 0x00000200 /* Transmit Null Packet */ +#define DVBM_LPQO_TCSR_TPRC 0x00000400 /* Transmit Packet Release Control */ + +/* Transmit Control/Status Register bitmasks */ +#define DVBM_LPQO_TCSR_204MAKE188 0x00000005 /* Sync. 204 Make 188 */ +#define DVBM_LPQO_TCSR_AUTO 0x00000002 /* Sync. Auto */ +#define DVBM_LPQO_TCSR_204 0x00000001 /* Sync. 204 */ +#define DVBM_LPQO_TCSR_188 0x00000000 /* Sync. 188 */ + +/* Control/Status Register bit locations */ +#define DVBM_LPQO_CSR_PLLFS 0x00000004 /* PLL Frequency Select */ +#define DVBM_LPQO_CSR_EXTCLK 0x00000040 /* External Clock */ + +#define DVBM_LPQO_FTR_ILBIG_SHIFT 24 +#define DVBM_LPQO_FTR_BIGIP_SHIFT 16 +#define DVBM_LPQO_FTR_ILNORMAL_SHIFT 8 + +/* External function prototypes */ + +int dvbm_lpqo_pci_probe (struct pci_dev *pdev) __devinit; +void dvbm_lpqo_pci_remove (struct pci_dev *pdev); + +#endif + diff --git a/quad/src/dvbm_lprxe.c b/quad/src/dvbm_lprxe.c index b76d8602e..0126b02b4 100644 --- a/quad/src/dvbm_lprxe.c +++ b/quad/src/dvbm_lprxe.c @@ -51,8 +51,6 @@ static const char dvbm_lprxe_name[] = DVBM_NAME_LPRXE; /* Static function prototypes */ static irqreturn_t IRQ_HANDLER(dvbm_lprxe_irq_handler,irq,dev_id,regs); -static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, - dvbm_lpfd_show_blackburst_type,dvbm_lpfd_store_blackburst_type); static DEVICE_ATTR(uid,S_IRUGO, dvbm_lpfd_show_uid,NULL); @@ -99,7 +97,7 @@ dvbm_lprxe_pci_probe (struct pci_dev *pdev) card->irq = pdev->irq; card->irq_handler = dvbm_lprxe_irq_handler; INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; + card->capabilities = MASTER_CAP_UID; /* Lock for ICSR */ spin_lock_init (&card->irq_lock); /* Lock for IBSTR, IPSTR, FTR, PFLUT, TCSR, RCSR */ @@ -134,14 +132,6 @@ dvbm_lprxe_pci_probe (struct pci_dev *pdev) } /* Add device attributes */ - if (card->capabilities & MASTER_CAP_BLACKBURST) { - if ((err = device_create_file (card->dev, - &dev_attr_blackburst_type)) < 0) { - printk (KERN_WARNING - "%s: unable to create file 'blackburst_type'\n", - dvbm_driver_name); - } - } if (card->capabilities & MASTER_CAP_UID) { if ((err = device_create_file (card->dev, &dev_attr_uid)) < 0) { diff --git a/quad/src/dvbm_lptxe.c b/quad/src/dvbm_lptxe.c index e5d0a33b7..b6cfb41ce 100644 --- a/quad/src/dvbm_lptxe.c +++ b/quad/src/dvbm_lptxe.c @@ -159,6 +159,9 @@ dvbm_lptxe_pci_probe (struct pci_dev *pdev) ASI_CAP_TX_TIMESTAMPS | ASI_CAP_TX_NULLPACKETS | ASI_CAP_TX_PTIMESTAMPS; + if (card->version >= 0x0101) { + cap |= ASI_CAP_TX_27COUNTER; + } if ((err = asi_register_iface (card, &lsdma_dma_ops, DVBM_LPFD_FIFO, diff --git a/quad/src/dvbm_q3inoe.c b/quad/src/dvbm_q3inoe.c old mode 100755 new mode 100644 index 7aaacc926..574ca3d7b --- a/quad/src/dvbm_q3inoe.c +++ b/quad/src/dvbm_q3inoe.c @@ -35,10 +35,8 @@ #include /* error codes */ #include /* irqreturn_t */ #include /* device_create_file () */ -#include /* udelay () */ #include /* mutex_init () */ -#include /* put_user () */ #include /* set_bit () */ #include "asicore.h" @@ -46,100 +44,19 @@ #include "mdev.h" #include "dvbm.h" #include "mdma.h" -#include "dvbm_q3inoe.h" +#include "dvbm_qio.h" #include "plx9080.h" #include "lsdma.h" static const char dvbm_q3inoe_name[] = DVBM_NAME_Q3INOE; /* static function prototypes */ -static ssize_t dvbm_q3ino_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf); static irqreturn_t IRQ_HANDLER (dvbm_q3ino_irq_handler, irq, dev_id, regs); -static void dvbm_q3ino_txinit (struct master_iface *iface); -static void dvbm_q3ino_txstart (struct master_iface *iface); -static void dvbm_q3ino_txstop (struct master_iface *iface); -static void dvbm_q3ino_txexit (struct master_iface *iface); -static void dvbm_q3ino_start_tx_dma (struct master_iface *iface); -static long dvbm_q3ino_txunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int dvbm_q3ino_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); -static void dvbm_q3ino_rxinit (struct master_iface *iface); -static void dvbm_q3ino_rxstart (struct master_iface *iface); -static void dvbm_q3ino_rxstop (struct master_iface *iface); -static void dvbm_q3ino_rxexit (struct master_iface *iface); -static long dvbm_q3ino_rxunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int dvbm_q3ino_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); - -static struct file_operations dvbm_q3ino_txfops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = asi_write, - .poll = asi_txpoll, - .unlocked_ioctl = dvbm_q3ino_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, - .open = asi_open, - .release = asi_release, - .fsync = dvbm_q3ino_txfsync, - .fasync = NULL -}; - -static struct file_operations dvbm_q3ino_rxfops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = asi_read, - .poll = asi_rxpoll, - .unlocked_ioctl = dvbm_q3ino_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, - .open = asi_open, - .release = asi_release, - .fsync = dvbm_q3ino_rxfsync, - .fasync = NULL -}; - -static struct master_iface_operations dvbm_q3ino_txops = { - .init = dvbm_q3ino_txinit, - .start = dvbm_q3ino_txstart, - .stop = dvbm_q3ino_txstop, - .exit = dvbm_q3ino_txexit, - .start_tx_dma = dvbm_q3ino_start_tx_dma -}; - -static struct master_iface_operations dvbm_q3ino_rxops = { - .init = dvbm_q3ino_rxinit, - .start = dvbm_q3ino_rxstart, - .stop = dvbm_q3ino_rxstop, - .exit = dvbm_q3ino_rxexit -}; - -/** - * dvbm_q3ino_show_uid - interface attribute read handler - * @dev: device being read - * @attr: device attribute - * @buf: output buffer - **/ -static ssize_t -dvbm_q3ino_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct master_dev *card = dev_get_drvdata(dev); - - return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", - readl (card->core.addr + DVBM_Q3INO_SSN_HI), - readl (card->core.addr + DVBM_Q3INO_SSN_LO)); -} +static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, + dvbm_qio_show_blackburst_type,dvbm_qio_store_blackburst_type); static DEVICE_ATTR(uid,S_IRUGO, - dvbm_q3ino_show_uid,NULL); + dvbm_qio_show_uid,NULL); /** * dvbm_q3ino_pci_probe - PCI insertion handler for a DVB Master Quad-3in1out @@ -180,13 +97,13 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) /* ASI Core */ card->core.addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->version = readl(card->core.addr + DVBM_Q3INO_FPGAID) & 0xffff; + card->version = readl(card->core.addr + DVBM_QIO_FPGAID) & 0xffff; card->name = dvbm_q3inoe_name; card->id = pdev->device; card->irq = pdev->irq; card->irq_handler = dvbm_q3ino_irq_handler; INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_UID; + card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; /* Lock for ICSR */ spin_lock_init (&card->irq_lock); /* Lock for IBSTR, IPSTR, FTR, PFLUT, TCSR, RCSR */ @@ -222,12 +139,12 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) /* Reset the FPGA */ for (i = 0; i < 1; i++) { - writel (DVBM_Q3INO_TCSR_TXRST, - card->core.addr + DVBM_Q3INO_TCSR(i)); + writel (DVBM_QIO_TCSR_TXRST, + card->core.addr + DVBM_QIO_TCSR(i)); } for (i = 1; i < 4; i++) { - writel (DVBM_Q3INO_RCSR_RXRST, - card->core.addr + DVBM_Q3INO_RCSR(i)); + writel (DVBM_QIO_RCSR_RXRST, + card->core.addr + DVBM_QIO_RCSR(i)); } /* Setup the LS DMA Controller */ @@ -235,9 +152,15 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) | LSDMA_INTMSK_CH(3), card->bridge_addr + LSDMA_INTMSK); - for (i = 0; i< 4; i++) { - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE - | LSDMA_CH_CSR_DIRECTION, + for (i = 0; i < 1; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(i)); + } + for (i = 1; i < 4; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(i)); } /* Dummy read to flush PCI posted writes */ @@ -249,6 +172,14 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) } /* Add device attributes */ + if (card->capabilities & MASTER_CAP_BLACKBURST) { + if ((err = device_create_file (card->dev, + &dev_attr_blackburst_type)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'blackburst_type'\n", + dvbm_driver_name); + } + } if (card->capabilities & MASTER_CAP_UID) { if ((err = device_create_file (card->dev, &dev_attr_uid)) < 0) { @@ -273,8 +204,8 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) &lsdma_dma_ops, 0, MASTER_DIRECTION_TX, - &dvbm_q3ino_txfops, - &dvbm_q3ino_txops, + &dvbm_qio_txfops, + &dvbm_qio_txops, cap, 4, ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { @@ -296,8 +227,8 @@ dvbm_q3ino_pci_probe (struct pci_dev *pdev) &lsdma_dma_ops, 0, MASTER_DIRECTION_RX, - &dvbm_q3ino_rxfops, - &dvbm_q3ino_rxops, + &dvbm_qio_rxfops, + &dvbm_qio_rxops, cap, 4, ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { @@ -315,36 +246,6 @@ NO_PCI: return err; } -/** - * dvbm_q3ino_pci_remove - PCI removal handler for a DVB Master Quad-3in1out - * @pdev: PCI device - * - * Handle the removal of DVB Master Quad-3in1out. - * This function may be called during PCI probe error handling, - * so don't mark it as __devexit. - **/ -void -dvbm_q3ino_pci_remove (struct pci_dev *pdev) -{ - struct master_dev *card = pci_get_drvdata (pdev); - - if (card) { - int i; - - /* Unregister the device and all interfaces */ - dvbm_unregister_all (card); - - for (i = 0; i < 4; i++) { - writel (0, card->core.addr + DVBM_Q3INO_ICSR(i)); - } - iounmap (card->core.addr); - iounmap (card->bridge_addr); - kfree (card); - } - dvbm_pci_remove_generic (pdev); - return; -} - /** * dvbm_q3ino_irq_handler - DVB Master Quad-3in1out interrupt service routine * @irq: interrupt number @@ -391,15 +292,15 @@ IRQ_HANDLER (dvbm_q3ino_irq_handler, irq, dev_id, regs) } spin_lock (&card->irq_lock); - status = readl (card->core.addr + DVBM_Q3INO_ICSR(i)); - writel (status, card->core.addr + DVBM_Q3INO_ICSR(i)); + status = readl (card->core.addr + DVBM_QIO_ICSR(i)); + writel (status, card->core.addr + DVBM_QIO_ICSR(i)); - if (status & DVBM_Q3INO_ICSR_TXUIS) { + if (status & DVBM_QIO_ICSR_TXUIS) { set_bit (ASI_EVENT_TX_FIFO_ORDER, &iface->events); interrupting_iface |= 0x1 << i; } - if (status & DVBM_Q3INO_ICSR_TXDIS) { + if (status & DVBM_QIO_ICSR_TXDIS) { set_bit (ASI_EVENT_TX_DATA_ORDER, &iface->events); interrupting_iface |= 0x1 << i; @@ -447,30 +348,30 @@ IRQ_HANDLER (dvbm_q3ino_irq_handler, irq, dev_id, regs) } spin_lock (&card->irq_lock); - status = readl (card->core.addr + DVBM_Q3INO_ICSR(i)); - writel (status, card->core.addr + DVBM_Q3INO_ICSR(i)); + status = readl (card->core.addr + DVBM_QIO_ICSR(i)); + writel (status, card->core.addr + DVBM_QIO_ICSR(i)); - if (status & DVBM_Q3INO_ICSR_RXCDIS) { + if (status & DVBM_QIO_ICSR_RXCDIS) { set_bit (ASI_EVENT_RX_CARRIER_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3INO_ICSR_RXAOSIS) { + if (status & DVBM_QIO_ICSR_RXAOSIS) { set_bit (ASI_EVENT_RX_AOS_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3INO_ICSR_RXLOSIS) { + if (status & DVBM_QIO_ICSR_RXLOSIS) { set_bit (ASI_EVENT_RX_LOS_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3INO_ICSR_RXOIS) { + if (status & DVBM_QIO_ICSR_RXOIS) { set_bit (ASI_EVENT_RX_FIFO_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3INO_ICSR_RXDIS) { + if (status & DVBM_QIO_ICSR_RXDIS) { set_bit (ASI_EVENT_RX_DATA_ORDER, &iface->events); interrupting_iface |= 0x2; @@ -492,764 +393,3 @@ IRQ_HANDLER (dvbm_q3ino_irq_handler, irq, dev_id, regs) return IRQ_NONE; } -/** - * dvbm_q3ino_txinit - Initialize the DVB Master Quad-3in1out transmitter - * @iface: interface - **/ -static void -dvbm_q3ino_txinit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg = iface->null_packets ? DVBM_Q3INO_TCSR_TNP : 0; - - switch (iface->timestamps) { - default: - case ASI_CTL_TSTAMP_NONE: - reg |= 0; - break; - case ASI_CTL_TSTAMP_APPEND: - reg |= DVBM_Q3INO_TCSR_TTSS; - break; - case ASI_CTL_TSTAMP_PREPEND: - reg |= DVBM_Q3INO_TCSR_TPRC; - break; - } - switch (iface->mode) { - default: - case ASI_CTL_TX_MODE_188: - reg |= DVBM_Q3INO_TCSR_188; - break; - case ASI_CTL_TX_MODE_204: - reg |= DVBM_Q3INO_TCSR_204; - break; - case ASI_CTL_TX_MODE_MAKE204: - reg |= DVBM_Q3INO_TCSR_MAKE204; - break; - } - switch (iface->clksrc) { - default: - case ASI_CTL_TX_CLKSRC_ONBOARD: - reg |= 0; - break; - case ASI_CTL_TX_CLKSRC_EXT: - reg |= DVBM_Q3INO_TCSR_EXTCLK; - break; - } - - /* There will be no races on IBSTR, IPSTR, FTR, and TCSR - * until this code returns, so we don't need to lock them */ - writel (reg | DVBM_Q3INO_TCSR_TXRST, - card->core.addr + DVBM_Q3INO_TCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3INO_TCSR(channel)); - wmb (); - writel ((DVBM_Q3INO_TFL << 16) | DVBM_Q3INO_TDMATL, - card->core.addr + DVBM_Q3INO_TFCR(channel)); - writel (0, card->core.addr + DVBM_Q3INO_IBSTREG(channel)); - writel (0, card->core.addr + DVBM_Q3INO_IPSTREG(channel)); - writel (0, card->core.addr + DVBM_Q3INO_FTREG(channel)); - /* Reset byte counter */ - readl (card->core.addr + DVBM_Q3INO_TXBCOUNT (channel)); - return; -} - -/** - * dvbm_q3ino_txstart - Activate the DVB Master Quad-3in1out transmitter - * @iface: interface - **/ -static void -dvbm_q3ino_txstart (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - unsigned int reg; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Enable transmitter interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_RX_IE_MASK; - reg |= DVBM_Q3INO_ICSR_TXUIE | DVBM_Q3INO_ICSR_TXDIE; - writel (reg, card->core.addr + DVBM_Q3INO_ICSR(channel)); - spin_unlock_irq(&card->irq_lock); - - /* Enable the transmitter */ - spin_lock(&card->reg_lock); - reg = readl(card->core.addr + DVBM_Q3INO_TCSR(channel)); - writel(reg | DVBM_Q3INO_TCSR_TXE, - card->core.addr + DVBM_Q3INO_TCSR(channel)); - spin_unlock(&card->reg_lock); - - return; -} - -/** - * dvbm_q3ino_txstop - Deactivate the DVB Master Quad-3in1out transmitter - * @iface: interface - **/ -static void -dvbm_q3ino_txstop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Disable the transmitter. - * There will be no races on TCSR here, - * so we don't need to lock it */ - spin_lock(&card->reg_lock); - reg = readl(card->core.addr + DVBM_Q3INO_TCSR(channel)); - writel(reg & ~DVBM_Q3INO_TCSR_TXE, - card->core.addr + DVBM_Q3INO_TCSR(channel)); - spin_unlock(&card->reg_lock); - - /* Disable transmitter interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_RX_IE_MASK; - reg |= DVBM_Q3INO_ICSR_TXUIS | DVBM_Q3INO_ICSR_TXDIS; - writel (reg, card->core.addr + DVBM_Q3INO_ICSR(channel)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP), - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - udelay (10L); - - return; -} - -/** - * dvbm_q3ino_txexit - Clean up the DVB Master Quad-3in1out transmitter - * @iface: interface - **/ -static void -dvbm_q3ino_txexit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the transmitter */ - writel (DVBM_Q3INO_TCSR_TXRST, - card->core.addr + DVBM_Q3INO_TCSR(channel)); - - return; -} - -/** - * dvbm_q3ino_start_tx_dma - start transmit DMA - * @iface: interface - **/ -static void -dvbm_q3ino_start_tx_dma (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); - writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - return; -} - -/** - * dvbm_q3ino_txunlocked_ioctl - DVB Master Quad-3in1out transmitter unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -dvbm_q3ino_txunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct asi_txstuffing stuffing; - const unsigned int channel = mdev_index (card, &iface->list); - - switch (cmd) { - case ASI_IOC_TXSETSTUFFING: - if (iface->transport != ASI_CTL_TRANSPORT_DVB_ASI) { - return -ENOTTY; - } - if (copy_from_user (&stuffing, - (struct asi_txstuffing __user *)arg, - sizeof (stuffing))) { - return -EFAULT; - } - if ((stuffing.ib > 0xffff) || - (stuffing.ip > 0xffffff) || - (stuffing.normal_ip > 0xff) || - (stuffing.big_ip > 0xff) || - ((stuffing.il_normal + stuffing.il_big) > 0xf) || - (stuffing.il_normal > stuffing.normal_ip) || - (stuffing.il_big > stuffing.big_ip)) { - return -EINVAL; - } - spin_lock (&card->reg_lock); - writel (stuffing.ib, card->core.addr + DVBM_Q3INO_IBSTREG(channel)); - writel (stuffing.ip, card->core.addr + DVBM_Q3INO_IPSTREG(channel)); - writel ((stuffing.il_big << DVBM_Q3INO_FTR_ILBIG_SHIFT) | - (stuffing.big_ip << DVBM_Q3INO_FTR_BIGIP_SHIFT) | - (stuffing.il_normal << DVBM_Q3INO_FTR_ILNORMAL_SHIFT) | - stuffing.normal_ip, card->core.addr + DVBM_Q3INO_FTREG(channel)); - spin_unlock (&card->reg_lock); - break; - case ASI_IOC_TXGETBYTECOUNT: - if (!(iface->capabilities & ASI_CAP_TX_BYTECOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3INO_TXBCOUNT(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_TXGETTXD: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_TXD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - default: - return asi_txioctl (filp, cmd, arg); - } - return 0; -} - -/** - * dvbm_q3ino_txfsync - DVB Master Quad-3in1out transmitter fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -dvbm_q3ino_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - struct master_iface *txiface = list_entry (card->iface_list.next, - struct master_iface, list); - const unsigned int channel = mdev_index (card, &iface->list); - - mutex_lock (&iface->buf_mutex); - lsdma_tx_link_all (dma); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - lsdma_reset (dma); - - if (!txiface->null_packets) { - /* Wait for the onboard FIFOs to empty */ - /* Atomic read of ICSR, so we don't need to lock */ - wait_event (iface->queue, - !(readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_TXD)); - } - - mutex_unlock (&iface->buf_mutex); - return 0; -} - -/** - * dvbm_q3ino_rxinit - Initialize the DVB Master Quad-3in1out receiver - * @iface: interface - **/ -static void -dvbm_q3ino_rxinit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int i, reg = (iface->null_packets ? DVBM_Q3INO_RCSR_RNP : 0); - - switch (iface->timestamps) { - default: - case ASI_CTL_TSTAMP_NONE: - reg |= 0; - break; - case ASI_CTL_TSTAMP_APPEND: - reg |= DVBM_Q3INO_RCSR_APPEND; - break; - case ASI_CTL_TSTAMP_PREPEND: - reg |= DVBM_Q3INO_RCSR_PREPEND; - break; - } - switch (iface->mode) { - default: - case ASI_CTL_RX_MODE_RAW: - reg |= 0; - break; - case ASI_CTL_RX_MODE_188: - reg |= DVBM_Q3INO_RCSR_188 | DVBM_Q3INO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_204: - reg |= DVBM_Q3INO_RCSR_204 | DVBM_Q3INO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_AUTO: - reg |= DVBM_Q3INO_RCSR_AUTO | DVBM_Q3INO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_AUTOMAKE188: - reg |= DVBM_Q3INO_RCSR_AUTO | DVBM_Q3INO_RCSR_RSS | - DVBM_Q3INO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_204MAKE188: - reg |= DVBM_Q3INO_RCSR_204 | DVBM_Q3INO_RCSR_RSS | - DVBM_Q3INO_RCSR_PFE; - break; - } - - /* There will be no races on RCSR - * until this code returns, so we don't need to lock it */ - writel (reg | DVBM_Q3INO_RCSR_RXRST, card->core.addr + DVBM_Q3INO_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3INO_RCSR(channel)); - wmb (); - writel (DVBM_Q3INO_RDMATL, card->core.addr + DVBM_Q3INO_RDMATLR(channel)); - - /* Reset byte counter */ - readl (card->core.addr + DVBM_Q3INO_RXBCOUNT(channel)); - - /* Reset PID Filter. - * There will be no races on PFLUT - * until this code returns, so we don't need to lock it */ - for (i = 0; i < 256; i++) { - writel (i, card->core.addr + DVBM_Q3INO_PFLUTWA(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_Q3INO_FPGAID); - writel (0xffffffff, card->core.addr + DVBM_Q3INO_PFLUT(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_Q3INO_FPGAID); - } - - /* Clear PID registers */ - writel (0, card->core.addr + DVBM_Q3INO_PID0(channel)); - writel (0, card->core.addr + DVBM_Q3INO_PID1(channel)); - writel (0, card->core.addr + DVBM_Q3INO_PID2(channel)); - writel (0, card->core.addr + DVBM_Q3INO_PID3(channel)); - - /* Reset PID counters */ - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT0(channel)); - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT1(channel)); - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT2(channel)); - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT3(channel)); - - return; -} - -/** - * dvbm_q3ino_rxstart - Activate the DVB Master Quad-3in1out receiver - * @iface: interface - **/ -static void -dvbm_q3ino_rxstart (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Enable and start DMA */ - writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(channel)); - writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - - /* Enable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_TX_IEIS_MASK; - reg |= DVBM_Q3INO_ICSR_RXCDIE | DVBM_Q3INO_ICSR_RXAOSIE | - DVBM_Q3INO_ICSR_RXLOSIE | DVBM_Q3INO_ICSR_RXOIE | - DVBM_Q3INO_ICSR_RXDIE; - writel (reg, card->core.addr + DVBM_Q3INO_ICSR(channel)); - spin_unlock_irq (&card->irq_lock); - - /* Enable the receiver */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3INO_RCSR(channel)); - writel (reg | DVBM_Q3INO_RCSR_RXE, - card->core.addr + DVBM_Q3INO_RCSR(channel)); - spin_unlock (&card->reg_lock); - - return; -} - -/** - * dvbm_q3ino_rxstop - Deactivate the DVB Master Quad-3in1out receiver - * @iface: interface - **/ -static void -dvbm_q3ino_rxstop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Disable the receiver */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3INO_RCSR(channel)); - writel (reg & ~DVBM_Q3INO_RCSR_RXE, - card->core.addr + DVBM_Q3INO_RCSR(channel)); - spin_unlock (&card->reg_lock); - - /* Disable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_TX_IEIS_MASK; - reg |= DVBM_Q3INO_ICSR_RXCDIS | DVBM_Q3INO_ICSR_RXAOSIS | - DVBM_Q3INO_ICSR_RXLOSIS | DVBM_Q3INO_ICSR_RXOIS | - DVBM_Q3INO_ICSR_RXDIS; - writel (reg, card->core.addr + DVBM_Q3INO_ICSR(channel)); - spin_unlock_irq (&card->irq_lock); - - /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & - ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - return; -} - -/** - * dvbm_q3ino_rxexit - Clean up the DVB Master Quad-3in1out receiver - * @iface: interface - **/ -static void -dvbm_q3ino_rxexit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the receiver. - * There will be no races on RCSR here, - * so we don't need to lock it */ - writel (DVBM_Q3INO_RCSR_RXRST, card->core.addr + DVBM_Q3INO_RCSR(channel)); - - return; -} - -/** - * dvbm_q3ino_rxunlocked_ioctl - DVB Master Quad-3in1out receiver unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -dvbm_q3ino_rxunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - int val; - unsigned int reg = 0, *pflut, i; - - switch (cmd) { - case ASI_IOC_RXGETSTATUS: - /* Atomic reads of ICSR and RCSR, so we don't need to lock */ - reg = readl (card->core.addr + DVBM_Q3INO_ICSR(channel)); - switch (readl (card->core.addr + DVBM_Q3INO_RCSR(channel)) & DVBM_Q3INO_RCSR_SYNC_MASK) - { - case 0: - val = 1; - break; - case DVBM_Q3INO_RCSR_188: - val = (reg & DVBM_Q3INO_ICSR_RXPASSING) ? 188 : 0; - break; - case DVBM_Q3INO_RCSR_204: - val = (reg & DVBM_Q3INO_ICSR_RXPASSING) ? 204 : 0; - break; - case DVBM_Q3INO_RCSR_AUTO: - if (reg & DVBM_Q3INO_ICSR_RXPASSING) { - val = (reg & DVBM_Q3INO_ICSR_RX204) ? 204 : 188; - } else { - val = 0; - } - break; - default: - return -EIO; - } - if (put_user (val, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXGETBYTECOUNT: - if (!(iface->capabilities & ASI_CAP_RX_BYTECOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3INO_RXBCOUNT(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETINVSYNC: - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - switch (val) { - case 0: - reg |= 0; - break; - case 1: - reg |= DVBM_Q3INO_RCSR_INVSYNC; - break; - default: - return -EINVAL; - } - spin_lock (&card->reg_lock); - writel ((readl (card->core.addr + DVBM_Q3INO_RCSR(channel)) & - ~DVBM_Q3INO_RCSR_INVSYNC) | reg, - card->core.addr + DVBM_Q3INO_RCSR(channel)); - spin_unlock (&card->reg_lock); - break; - case ASI_IOC_RXGETCARRIER: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_RXCD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETDSYNC: - case ASI_IOC_RXSETINPUT_DEPRECATED: - case ASI_IOC_RXSETINPUT: - /* Dummy ioctl; only zero is valid */ - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if (val) { - return -EINVAL; - } - break; - case ASI_IOC_RXGETRXD: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3INO_ICSR(channel)) & - DVBM_Q3INO_ICSR_RXD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPF: - if (!(iface->capabilities & ASI_CAP_RX_PIDFILTER)) { - return -ENOTTY; - } - pflut = (unsigned int *) - kmalloc (sizeof (unsigned int [256]), GFP_KERNEL); - if (pflut == NULL) { - return -ENOMEM; - } - if (copy_from_user (pflut, (unsigned int __user *)arg, - sizeof (unsigned int [256]))) { - kfree (pflut); - return -EFAULT; - } - spin_lock (&card->reg_lock); - for (i = 0; i < 256; i++) { - writel (i, card->core.addr + DVBM_Q3INO_PFLUTWA(channel)); - wmb (); - writel (pflut[i], card->core.addr + DVBM_Q3INO_PFLUT(channel)); - wmb (); - } - spin_unlock (&card->reg_lock); - kfree (pflut); - break; - case ASI_IOC_RXSETPID0: - if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3INO_PID0(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT0(channel)); - break; - case ASI_IOC_RXGETPID0COUNT: - if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3INO_PIDCOUNT0(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID1: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3INO_PID1(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT1(channel)); - break; - case ASI_IOC_RXGETPID1COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3INO_PIDCOUNT1(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID2: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3INO_PID2(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT2(channel)); - break; - case ASI_IOC_RXGETPID2COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3INO_PIDCOUNT2(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID3: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3INO_PID3(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3INO_PIDCOUNT3(channel)); - break; - case ASI_IOC_RXGETPID3COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3INO_PIDCOUNT3(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXGET27COUNT: - if (!(iface->capabilities & ASI_CAP_RX_27COUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3INO_27COUNTR), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - default: - return asi_rxioctl (filp, cmd, arg); - } - return 0; -} - -/** - * dvbm_q3ino_rxfsync - DVB Master Quad-3in1out receiver fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -dvbm_q3ino_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - mutex_lock (&iface->buf_mutex); - - /* Stop the receiver */ - dvbm_q3ino_rxstop (iface); - - /* Reset the onboard FIFO and driver buffers */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3INO_RCSR(channel)); - writel (reg | DVBM_Q3INO_RCSR_RXRST, - card->core.addr + DVBM_Q3INO_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3INO_RCSR(channel)); - spin_unlock (&card->reg_lock); - iface->events = 0; - lsdma_reset (iface->dma); - - /* Start the receiver */ - dvbm_q3ino_rxstart (iface); - - mutex_unlock (&iface->buf_mutex); - return 0; -} - diff --git a/quad/src/dvbm_q3inoe.h b/quad/src/dvbm_q3inoe.h deleted file mode 100755 index 06537eb55..000000000 --- a/quad/src/dvbm_q3inoe.h +++ /dev/null @@ -1,169 +0,0 @@ -/* dvbm_q3inoe.h - * - * Header file for the Linear Systems Ltd. DVB Master Quad-3in1out. - * - * Copyright (C) 2008-2010 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _DVBM_Q3INOE_H -#define _DVBM_Q3INOE_H - -#include /* pci_dev */ -#include /* __devinit */ - -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQ3INOE 0x0088 - -#define DVBM_NAME_Q3INOE "DVB Master Quad-3in1out" - -/* DVB Master Quad-3in1out configuration */ -#define DVBM_Q3INO_TFL 0x200 /* Transmit FIFO Start Level */ -#define DVBM_Q3INO_RDMATL 0x020 /* Receiver DMA Trigger Level */ -#define DVBM_Q3INO_TDMATL 0xfdf /* Transmit DMA Trigger Level */ - -/* Register addresses */ -#define DVBM_Q3INO_FPGAID 0x400 /* FPGA ID */ -#define DVBM_Q3INO_HL2CSR 0x404 /* HOTLink II Control and status */ -#define DVBM_Q3INO_27COUNTR 0x408 /* 27 MHz Counter */ -#define DVBM_Q3INO_SSN_HI 0x40C /* Silicon serial number, High */ -#define DVBM_Q3INO_SSN_LO 0x410 /* Silicon serial number, low */ -#define DVBM_Q3INO_ASMIR 0x414 /* ASMI */ - -/* Receiver Registers */ -#define DVBM_Q3INO_RCSR(c) ((c)*0x100+0x004) /* Receive Control/Status */ -#define DVBM_Q3INO_RFCR(c) ((c)*0x100+0x008) /* Receive FIFO Control */ -#define DVBM_Q3INO_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ -#define DVBM_Q3INO_ICSR(c) ((c)*0x100+0x010) /* Interrupt Control and Status */ -#define DVBM_Q3INO_RXBCOUNT(c) ((c)*0x100+0x014) /* Receive Byte Counter */ -#define DVBM_Q3INO_PFLUTWA(c) ((c)*0x100+0x018) /* PID Filter LUT Address */ -#define DVBM_Q3INO_PFLUT(c) ((c)*0x100+0x01c) /* PID Filter LUT Data */ -#define DVBM_Q3INO_PID0(c) ((c)*0x100+0x020) /* PID Detector Value 0 */ -#define DVBM_Q3INO_PIDCOUNT0(c) ((c)*0x100+0x024) /* PID Count 0 */ -#define DVBM_Q3INO_PID1(c) ((c)*0x100+0x028) /* PID Detector Value 1 */ -#define DVBM_Q3INO_PIDCOUNT1(c) ((c)*0x100+0x02c) /* PID Count 1 */ -#define DVBM_Q3INO_PID2(c) ((c)*0x100+0x030) /* PID Detector Value 2 */ -#define DVBM_Q3INO_PIDCOUNT2(c) ((c)*0x100+0x034) /* PID Count 3 */ -#define DVBM_Q3INO_PID3(c) ((c)*0x100+0x038) /* PID Detector Value 3 */ -#define DVBM_Q3INO_PIDCOUNT3(c) ((c)*0x100+0x03c) /* PID Count 4 */ -#define DVBM_Q3INO_RDMATLR(c) ((c)*0x100+0x008) /* DMA Trigger Level */ - -/* Transmit Registers */ -#define DVBM_Q3INO_FTREG(c) ((c)*0x100+0x084) /* Finetuning */ -#define DVBM_Q3INO_TXBCOUNT(c) ((c)*0x100+0x088) /* Transmit Byte Counter */ -#define DVBM_Q3INO_TCSR(c) ((c)*0x100+0x08c) /* Transmit Control and Status */ -#define DVBM_Q3INO_IBSTREG(c) ((c)*0x100+0x090) /* Interbyte Stuffing */ -#define DVBM_Q3INO_IPSTREG(c) ((c)*0x100+0x094) /* Interpacket Stuffing */ -#define DVBM_Q3INO_TFCR(c) ((c)*0x100+0x098) /* Transmit FIFO Control */ -#define DVBM_Q3INO_TPIDR(c) ((c)*0x100+0x09c) /* Transmit PID */ -#define DVBM_Q3INO_TPCRR_HI(c) ((c)*0x100+0x0a0) /* Transmit PCR, High Word */ -#define DVBM_Q3INO_TPCRR_LO(c) ((c)*0x100+0x0a4) /* Transmit PCR, Low Word */ -#define DVBM_Q3INO_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Word */ -#define DVBM_Q3INO_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Word */ - -/* Receiver Control/Status Register (RCSR) bit locations */ - -#define DVM_Q3INO_RCSR_RXMODE 0x00000003 /* Rx Mode */ -#define DVBM_Q3INO_RCSR_RSS 0x00000008 /* Reed-Solomon Strip */ -#define DVBM_Q3INO_RCSR_RXE 0x00000010 /* Receiver Enable */ -#define DVBM_Q3INO_RCSR_RXRST 0x00000020 /* Receiver Reset */ -#define DVBM_Q3INO_RCSR_INVSYNC 0x00000080 /* Inverted Sync Byte Enable */ -#define DVBM_Q3INO_RCSR_RNP 0x00002000 /* Null Packet Replacement */ -#define DVBM_Q3INO_RCSR_PFE 0x00001000 /* PID Filter Enable */ -#define DVBM_Q3INO_RCSR_188 0x00000001 /* 188 Byte Packet */ -#define DVBM_Q3INO_RCSR_204 0x00000002 /* 204 Byte Packet */ -#define DVBM_Q3INO_RCSR_AUTO 0x00000003 /* Auto Byte Packet */ -#define DVBM_Q3INO_RCSR_APPEND 0x00000100 /* Appended Timestamp Mode */ -#define DVBM_Q3INO_RCSR_PREPEND 0x00000200 /* Prepended Timestamp Mode */ - -/* Interrupt Control/Status Register bit locations */ - -#define DVBM_Q3INO_ICSR_TXUIE 0x00000001 /* Tx FIFO Underrun Int. Enable */ -#define DVBM_Q3INO_ICSR_TXDIE 0x00000040 /* Tx Data Int. Enable */ -#define DVBM_Q3INO_ICSR_TXU 0x00000100 /* Tx FIFO Underrun Status */ -#define DVBM_Q3INO_ICSR_TXD 0x00004000 /* Tx Data */ -#define DVBM_Q3INO_ICSR_TXUIS 0x00010000 /* Tx FIFO Underrun Int. Status */ -#define DVBM_Q3INO_ICSR_TXDIS 0x00400000 /* Tx Data Interrupt Status */ -#define DVBM_Q3INO_ICSR_PMS 0x04000000 /* Packet Maturity Status */ -#define DVBM_Q3INO_ICSR_NOSIG 0x08000000 /* No Signal */ -#define DVBM_Q3INO_ICSR_RXOIE 0x00000001 /* Rx FIFO Overrun Int. Enable */ -#define DVBM_Q3INO_ICSR_RXLOSIE 0x00000002 /* Rx Loss of Sync. Int. Enable */ -#define DVBM_Q3INO_ICSR_RXAOSIE 0x00000004 /* Rx Acq. of Sync. Int. Enable */ -#define DVBM_Q3INO_ICSR_RXCDIE 0x00000008 /* Rx Carrier Detect Int. Enable */ -#define DVBM_Q3INO_ICSR_RXDIE 0x00000010 /* Rx Data Int. Enable */ -#define DVBM_Q3INO_ICSR_RXO 0x00000100 /* Rx FIFO Overrun Status */ -#define DVBM_Q3INO_ICSR_RXPASSING 0x00000200 /* Rx sync status same as SYNC */ -#define DVBM_Q3INO_ICSR_RXCD 0x00000800 /* Rx Carrier Detect Status */ -#define DVBM_Q3INO_ICSR_RXD 0x00001000 /* Rx Data */ -#define DVBM_Q3INO_ICSR_RXOIS 0x00010000 /* Rx FIFO Overrun Int. Status */ -#define DVBM_Q3INO_ICSR_RXLOSIS 0x00020000 /* Rx Loss of Sync. Int. Status */ -#define DVBM_Q3INO_ICSR_RXAOSIS 0x00040000 /* Rx Acq. of Sync. Int. Status */ -#define DVBM_Q3INO_ICSR_RXCDIS 0x00080000 /* Rx Carrier Detect Int. Status */ -#define DVBM_Q3INO_ICSR_RXDIS 0x00100000 /* Rx Data Int. Status */ -#define DVBM_Q3INO_ICSR_RX204 0x01000000 /* Rx 204-byte packets */ - -/* Transmit Control and Status (TCSR) */ - -#define DVBM_Q3INO_TCSR_188 0x0 /* 188 Byte Packet */ -#define DVBM_Q3INO_TCSR_204 0x1 /* 204 Byte Packet */ -#define DVBM_Q3INO_TCSR_MAKE204 0x2 /* Make 204 */ -#define DVBM_Q3INO_TCSR_TXE 0x00000010 /* Transmit Enable */ -#define DVBM_Q3INO_TCSR_TXRST 0x00000020 /* Transmit Reset */ -#define DVBM_Q3INO_TCSR_TXCS 0x000000c0 /* Transmit Clock Source add two more */ -#define DVBM_Q3INO_TCSR_EXTCLK 0x00000040 /* External clock Blackburst */ -#define DVBM_Q3INO_TCSR_TTSS 0x00000100 /* Transmit Timestamp Strip */ -#define DVBM_Q3INO_TCSR_TNP 0x00000200 /* Transmit Null Packet */ -#define DVBM_Q3INO_TCSR_TPRC 0x00000400 /* Transmit Packet Release */ - -/* Interrupt Control/Status Register bitmasks */ -#define DVBM_Q3INO_ICSR_TX_IEIS_MASK (DVBM_Q3INO_ICSR_TXUIE|DVBM_Q3INO_ICSR_TXDIE|DVBM_Q3INO_ICSR_TXU|DVBM_Q3INO_ICSR_TXD|DVBM_Q3INO_ICSR_TXUIS|DVBM_Q3INO_ICSR_TXDIS) -/* Interrupt status bits */ -#define DVBM_Q3INO_ICSR_TX_IS_MASK (DVBM_Q3INO_ICSR_TUIS|DVBM_Q3INO_ICSR_TXDIS) -/* Interrupt enable bits */ -#define DVBM_Q3INO_ICSR_TX_IE_MASK (DVBM_Q3INO_ICSR_TUIE|DVBM_Q3INO_ICSR_TXDIE) /* Interrupt Enable BitMask */ - -/* Finetuning Register bit locations */ -#define DVBM_Q3INO_FTR_ILBIG_MASK 0x0f000000 -#define DVBM_Q3INO_FTR_ILBIG_SHIFT 24 -#define DVBM_Q3INO_FTR_BIGIP_MASK 0x00ff0000 -#define DVBM_Q3INO_FTR_BIGIP_SHIFT 16 -#define DVBM_Q3INO_FTR_ILNORMAL_MASK 0x00000f00 -#define DVBM_Q3INO_FTR_ILNORMAL_SHIFT 8 -#define DVBM_Q3INO_FTR_NORMALIP_MASK 0x000000ff - -/* Control/Status Register bitmasks */ -#define DVBM_Q3INO_RCSR_SYNC_MASK 0x00000003 - -/* Transmit Control/Status Register bitmasks */ -#define DVBM_Q3INO_TCSR_CLK_MASK 0x000020c0 -#define DVBM_Q3INO_TCSR_MODE_MASK 0x00000003 - -/* Mask to reset all IE options in ICSR */ -#define DVBM_Q3INO_ICSR_RX_IE_MASK (DVBM_Q3INO_ICSR_RXOIE|DVBM_Q3INO_ICSR_RXLOSIE|DVBM_Q3INO_ICSR_RXAOSIE|DVBM_Q3INO_ICSR_RXCDIE|DVBM_Q3INO_ICSR_RXDIE) -/* The interrupts that are enabled */ -#define DVBM_Q3INO_ICSR_RX_IE (DVBM_Q3INO_ICSR_RXOIE|DVBM_Q3INO_ICSR_RXLOSIE|DVBM_Q3INO_ICSR_RXAOSIE|DVBM_Q3INO_ICSR_RXCDIE) -/* Interrupt Status bits in ICSR */ -#define DVBM_Q3INO_ICSR_RX_IS_BITS (DVBM_Q3INO_ICSR_ROIS|DVBM_Q3INO_ICSR_LOSIS|DVBM_Q3INO_ICSR_ASIS|DVBM_Q3INO_ICSR_CDIS|DVBM_Q3INO_ICSR_RXDIS) - -/* External function prototypes */ - -int dvbm_q3ino_pci_probe (struct pci_dev *pdev) __devinit; -void dvbm_q3ino_pci_remove (struct pci_dev *pdev); - -#endif - diff --git a/quad/src/dvbm_q3ioe.c b/quad/src/dvbm_q3ioe.c old mode 100755 new mode 100644 index 99c6e1525..25e7444ff --- a/quad/src/dvbm_q3ioe.c +++ b/quad/src/dvbm_q3ioe.c @@ -35,10 +35,8 @@ #include /* error codes */ #include /* irqreturn_t */ #include /* device_create_file () */ -#include /* udelay () */ #include /* mutex_init () */ -#include /* put_user () */ #include /* set_bit () */ #include "asicore.h" @@ -46,100 +44,19 @@ #include "mdev.h" #include "dvbm.h" #include "mdma.h" -#include "dvbm_q3ioe.h" +#include "dvbm_qio.h" #include "plx9080.h" #include "lsdma.h" static const char dvbm_q3ioe_name[] = DVBM_NAME_Q3IOE; /* static function prototypes */ -static ssize_t dvbm_q3io_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf); static irqreturn_t IRQ_HANDLER (dvbm_q3io_irq_handler, irq, dev_id, regs); -static void dvbm_q3io_txinit (struct master_iface *iface); -static void dvbm_q3io_txstart (struct master_iface *iface); -static void dvbm_q3io_txstop (struct master_iface *iface); -static void dvbm_q3io_txexit (struct master_iface *iface); -static void dvbm_q3io_start_tx_dma (struct master_iface *iface); -static long dvbm_q3io_txunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int dvbm_q3io_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); -static void dvbm_q3io_rxinit (struct master_iface *iface); -static void dvbm_q3io_rxstart (struct master_iface *iface); -static void dvbm_q3io_rxstop (struct master_iface *iface); -static void dvbm_q3io_rxexit (struct master_iface *iface); -static long dvbm_q3io_rxunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int dvbm_q3io_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); - -static struct file_operations dvbm_q3io_txfops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = asi_write, - .poll = asi_txpoll, - .unlocked_ioctl = dvbm_q3io_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, - .open = asi_open, - .release = asi_release, - .fsync = dvbm_q3io_txfsync, - .fasync = NULL -}; - -static struct file_operations dvbm_q3io_rxfops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = asi_read, - .poll = asi_rxpoll, - .unlocked_ioctl = dvbm_q3io_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, - .open = asi_open, - .release = asi_release, - .fsync = dvbm_q3io_rxfsync, - .fasync = NULL -}; - -static struct master_iface_operations dvbm_q3io_txops = { - .init = dvbm_q3io_txinit, - .start = dvbm_q3io_txstart, - .stop = dvbm_q3io_txstop, - .exit = dvbm_q3io_txexit, - .start_tx_dma = dvbm_q3io_start_tx_dma -}; - -static struct master_iface_operations dvbm_q3io_rxops = { - .init = dvbm_q3io_rxinit, - .start = dvbm_q3io_rxstart, - .stop = dvbm_q3io_rxstop, - .exit = dvbm_q3io_rxexit -}; - -/** - * dvbm_q3io_show_uid - interface attribute read handler - * @dev: device being read - * @attr: device attribute - * @buf: output buffer - **/ -static ssize_t -dvbm_q3io_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct master_dev *card = dev_get_drvdata(dev); - - return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", - readl (card->core.addr + DVBM_Q3IO_SSN_HI), - readl (card->core.addr + DVBM_Q3IO_SSN_LO)); -} +static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, + dvbm_qio_show_blackburst_type,dvbm_qio_store_blackburst_type); static DEVICE_ATTR(uid,S_IRUGO, - dvbm_q3io_show_uid,NULL); + dvbm_qio_show_uid,NULL); /** * dvbm_q3io_pci_probe - PCI insertion handler for a DVB Master Quad-1in3out @@ -180,13 +97,13 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) /* ASI Core */ card->core.addr = ioremap_nocache (pci_resource_start (pdev, 2), pci_resource_len (pdev, 2)); - card->version = readl(card->core.addr + DVBM_Q3IO_FPGAID) & 0xffff; + card->version = readl(card->core.addr + DVBM_QIO_FPGAID) & 0xffff; card->name = dvbm_q3ioe_name; card->id = pdev->device; card->irq = pdev->irq; card->irq_handler = dvbm_q3io_irq_handler; INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_UID; + card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; /* Lock for ICSR */ spin_lock_init (&card->irq_lock); /* Lock for IBSTR, IPSTR, FTR, PFLUT, TCSR, RCSR */ @@ -222,10 +139,12 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) /* Reset the FPGA */ for (i = 0; i < 3; i++) { - writel (DVBM_Q3IO_TCSR_TXRST, card->core.addr + DVBM_Q3IO_TCSR(i)); + writel (DVBM_QIO_TCSR_TXRST, + card->core.addr + DVBM_QIO_TCSR(i)); } for (i = 3; i < 4; i++) { - writel (DVBM_Q3IO_RCSR_RXRST, card->core.addr + DVBM_Q3IO_RCSR(i)); + writel (DVBM_QIO_RCSR_RXRST, + card->core.addr + DVBM_QIO_RCSR(i)); } /* Setup the LS DMA Controller */ @@ -233,9 +152,16 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) | LSDMA_INTMSK_CH(3), card->bridge_addr + LSDMA_INTMSK); - for (i = 0; i< 4; i++) { - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE - | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(i)); + for (i = 0; i < 3; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(i)); + } + for (i = 3; i < 4; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, + card->bridge_addr + LSDMA_CSR(i)); } /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); @@ -246,6 +172,14 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) } /* Add device attributes */ + if (card->capabilities & MASTER_CAP_BLACKBURST) { + if ((err = device_create_file (card->dev, + &dev_attr_blackburst_type)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'blackburst_type'\n", + dvbm_driver_name); + } + } if (card->capabilities & MASTER_CAP_UID) { if ((err = device_create_file (card->dev, &dev_attr_uid)) < 0) { @@ -270,8 +204,8 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) &lsdma_dma_ops, 0, MASTER_DIRECTION_TX, - &dvbm_q3io_txfops, - &dvbm_q3io_txops, + &dvbm_qio_txfops, + &dvbm_qio_txops, cap, 4, ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { @@ -293,8 +227,8 @@ dvbm_q3io_pci_probe (struct pci_dev *pdev) &lsdma_dma_ops, 0, MASTER_DIRECTION_RX, - &dvbm_q3io_rxfops, - &dvbm_q3io_rxops, + &dvbm_qio_rxfops, + &dvbm_qio_rxops, cap, 4, ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { @@ -312,36 +246,6 @@ NO_PCI: return err; } -/** - * dvbm_q3io_pci_remove - PCI removal handler for a DVB Master Quad-1in3out - * @pdev: PCI device - * - * Handle the removal of a DVB Master Quad-1in3out. - * This function may be called during PCI probe error handling, - * so don't mark it as __devexit. - **/ -void -dvbm_q3io_pci_remove (struct pci_dev *pdev) -{ - struct master_dev *card = pci_get_drvdata (pdev); - - if (card) { - int i; - - /* Unregister the device and all interfaces */ - dvbm_unregister_all (card); - - for (i = 0; i < 4; i++) { - writel (0, card->core.addr + DVBM_Q3IO_ICSR(i)); - } - iounmap (card->core.addr); - iounmap (card->bridge_addr); - kfree (card); - } - dvbm_pci_remove_generic (pdev); - return; -} - /** * dvbm_q3io_irq_handler - DVB Master Quad-1in3out interrupt service routine * @irq: interrupt number @@ -376,7 +280,8 @@ IRQ_HANDLER (dvbm_q3io_irq_handler, irq, dev_id, regs) /* Flag end-of-chain */ if (status & LSDMA_CH_CSR_INTSRCDONE) { - set_bit (ASI_EVENT_TX_BUFFER_ORDER, &iface->events); + set_bit (ASI_EVENT_TX_BUFFER_ORDER, + &iface->events); set_bit (0, &iface->dma_done); } /* Flag DMA abort */ @@ -388,15 +293,15 @@ IRQ_HANDLER (dvbm_q3io_irq_handler, irq, dev_id, regs) } spin_lock (&card->irq_lock); - status = readl (card->core.addr + DVBM_Q3IO_ICSR(i)); - writel (status, card->core.addr + DVBM_Q3IO_ICSR(i)); + status = readl (card->core.addr + DVBM_QIO_ICSR(i)); + writel (status, card->core.addr + DVBM_QIO_ICSR(i)); - if (status & DVBM_Q3IO_ICSR_TXUIS) { + if (status & DVBM_QIO_ICSR_TXUIS) { set_bit (ASI_EVENT_TX_FIFO_ORDER, &iface->events); interrupting_iface |= 0x1 << i; } - if (status & DVBM_Q3IO_ICSR_TXDIS) { + if (status & DVBM_QIO_ICSR_TXDIS) { set_bit (ASI_EVENT_TX_DATA_ORDER, &iface->events); interrupting_iface |= 0x1 << i; @@ -444,30 +349,30 @@ IRQ_HANDLER (dvbm_q3io_irq_handler, irq, dev_id, regs) } spin_lock (&card->irq_lock); - status = readl (card->core.addr + DVBM_Q3IO_ICSR(i)); - writel (status, card->core.addr + DVBM_Q3IO_ICSR(i)); + status = readl (card->core.addr + DVBM_QIO_ICSR(i)); + writel (status, card->core.addr + DVBM_QIO_ICSR(i)); - if (status & DVBM_Q3IO_ICSR_RXCDIS) { + if (status & DVBM_QIO_ICSR_RXCDIS) { set_bit (ASI_EVENT_RX_CARRIER_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3IO_ICSR_RXAOSIS) { + if (status & DVBM_QIO_ICSR_RXAOSIS) { set_bit (ASI_EVENT_RX_AOS_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3IO_ICSR_RXLOSIS) { + if (status & DVBM_QIO_ICSR_RXLOSIS) { set_bit (ASI_EVENT_RX_LOS_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3IO_ICSR_RXOIS) { + if (status & DVBM_QIO_ICSR_RXOIS) { set_bit (ASI_EVENT_RX_FIFO_ORDER, &iface->events); interrupting_iface |= 0x2; } - if (status & DVBM_Q3IO_ICSR_RXDIS) { + if (status & DVBM_QIO_ICSR_RXDIS) { set_bit (ASI_EVENT_RX_DATA_ORDER, &iface->events); interrupting_iface |= 0x2; @@ -489,766 +394,3 @@ IRQ_HANDLER (dvbm_q3io_irq_handler, irq, dev_id, regs) return IRQ_NONE; } -/** - * dvbm_q3io_txinit - Initialize the DVB Master Quad-1in3out transmitter - * @iface: interface - **/ -static void -dvbm_q3io_txinit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg = iface->null_packets ? DVBM_Q3IO_TCSR_TNP : 0; - - - switch (iface->timestamps) { - default: - case ASI_CTL_TSTAMP_NONE: - reg |= 0; - break; - case ASI_CTL_TSTAMP_APPEND: - reg |= DVBM_Q3IO_TCSR_TTSS; - break; - case ASI_CTL_TSTAMP_PREPEND: - reg |= DVBM_Q3IO_TCSR_TPRC; - break; - } - - switch (iface->mode) { - default: - case ASI_CTL_TX_MODE_188: - reg |= DVBM_Q3IO_TCSR_188; - break; - case ASI_CTL_TX_MODE_204: - reg |= DVBM_Q3IO_TCSR_204; - break; - case ASI_CTL_TX_MODE_MAKE204: - reg |= DVBM_Q3IO_TCSR_MAKE204; - break; - } - switch (iface->clksrc) { - default: - case ASI_CTL_TX_CLKSRC_ONBOARD: - reg |= 0; - break; - case ASI_CTL_TX_CLKSRC_EXT: - reg |= DVBM_Q3IO_TCSR_EXTCLK; - break; - } - - /* There will be no races on IBSTR, IPSTR, FTR, and TCSR - * until this code returns, so we don't need to lock them */ - writel (reg | DVBM_Q3IO_TCSR_TXRST, - card->core.addr + DVBM_Q3IO_TCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3IO_TCSR(channel)); - wmb (); - writel ((DVBM_Q3IO_TFL << 16) | DVBM_Q3IO_TDMATL, - card->core.addr + DVBM_Q3IO_TFCR(channel)); - writel (0, card->core.addr + DVBM_Q3IO_IBSTREG(channel)); - writel (0, card->core.addr + DVBM_Q3IO_IPSTREG(channel)); - writel (0, card->core.addr + DVBM_Q3IO_FTREG(channel)); - /* Reset byte counter */ - readl (card->core.addr + DVBM_Q3IO_TXBCOUNT (channel)); - return; -} - -/** - * dvbm_q3io_txstart - Activate the DVB Master Quad-1in3out transmitter - * @iface: interface - **/ -static void -dvbm_q3io_txstart (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - unsigned int reg; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Enable transmitter interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_RX_IE_MASK; - reg |= DVBM_Q3IO_ICSR_TXUIE | DVBM_Q3IO_ICSR_TXDIE; - writel (reg, card->core.addr + DVBM_Q3IO_ICSR(channel)); - spin_unlock_irq(&card->irq_lock); - - /* Enable the transmitter */ - spin_lock(&card->reg_lock); - reg = readl(card->core.addr + DVBM_Q3IO_TCSR(channel)); - writel(reg | DVBM_Q3IO_TCSR_TXE, - card->core.addr + DVBM_Q3IO_TCSR(channel)); - spin_unlock(&card->reg_lock); - - return; -} - -/** - * dvbm_q3io_txstop - Deactivate the DVB Master Quad-1in3out transmitter - * @iface: interface - **/ -static void -dvbm_q3io_txstop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Disable the transmitter. - * There will be no races on TCSR here, - * so we don't need to lock it */ - spin_lock(&card->reg_lock); - reg = readl(card->core.addr + DVBM_Q3IO_TCSR(channel)); - writel(reg & ~DVBM_Q3IO_TCSR_TXE, - card->core.addr + DVBM_Q3IO_TCSR(channel)); - spin_unlock(&card->reg_lock); - - /* Disable transmitter interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_RX_IE_MASK; - reg |= DVBM_Q3IO_ICSR_TXUIS | DVBM_Q3IO_ICSR_TXDIS; - writel (reg, card->core.addr + DVBM_Q3IO_ICSR(channel)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP), - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - udelay (10L); - - return; -} - -/** - * dvbm_q3io_txexit - Clean up the DVB Master Quad-1in3out transmitter - * @iface: interface - **/ -static void -dvbm_q3io_txexit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the transmitter */ - writel (DVBM_Q3IO_TCSR_TXRST, - card->core.addr + DVBM_Q3IO_TCSR(channel)); - - return; -} - -/** - * dvbm_q3io_start_tx_dma - start transmit DMA - * @iface: interface - **/ -static void -dvbm_q3io_start_tx_dma (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); - writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - return; -} - -/** - * dvbm_q3io_txunlocked_ioctl - DVB Master Quad-1in3out transmitter unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -dvbm_q3io_txunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct asi_txstuffing stuffing; - const unsigned int channel = mdev_index (card, &iface->list); - - switch (cmd) { - case ASI_IOC_TXSETSTUFFING: - if (iface->transport != ASI_CTL_TRANSPORT_DVB_ASI) { - return -ENOTTY; - } - if (copy_from_user (&stuffing, - (struct asi_txstuffing __user *)arg, - sizeof (stuffing))) { - return -EFAULT; - } - if ((stuffing.ib > 0xffff) || - (stuffing.ip > 0xffffff) || - (stuffing.normal_ip > 0xff) || - (stuffing.big_ip > 0xff) || - ((stuffing.il_normal + stuffing.il_big) > 0xf) || - (stuffing.il_normal > stuffing.normal_ip) || - (stuffing.il_big > stuffing.big_ip)) { - return -EINVAL; - } - spin_lock (&card->reg_lock); - writel (stuffing.ib, card->core.addr + DVBM_Q3IO_IBSTREG(channel)); - writel (stuffing.ip, card->core.addr + DVBM_Q3IO_IPSTREG(channel)); - writel ((stuffing.il_big << DVBM_Q3IO_FTR_ILBIG_SHIFT) | - (stuffing.big_ip << DVBM_Q3IO_FTR_BIGIP_SHIFT) | - (stuffing.il_normal << DVBM_Q3IO_FTR_ILNORMAL_SHIFT) | - stuffing.normal_ip, card->core.addr + DVBM_Q3IO_FTREG(channel)); - spin_unlock (&card->reg_lock); - break; - case ASI_IOC_TXGETBYTECOUNT: - if (!(iface->capabilities & ASI_CAP_TX_BYTECOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3IO_TXBCOUNT(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_TXGETTXD: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_TXD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - default: - return asi_txioctl (filp, cmd, arg); - } - return 0; -} - -/** - * dvbm_q3io_txfsync - DVB Master Quad-1in3out transmitter fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -dvbm_q3io_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - struct master_iface *txiface = list_entry (card->iface_list.next, - struct master_iface, list); - const unsigned int channel = mdev_index (card, &iface->list); - - mutex_lock (&iface->buf_mutex); - lsdma_tx_link_all (dma); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - lsdma_reset (dma); - - if (!txiface->null_packets) { - /* Wait for the onboard FIFOs to empty */ - /* Atomic read of ICSR, so we don't need to lock */ - wait_event (iface->queue, - !(readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_TXD)); - } - - mutex_unlock (&iface->buf_mutex); - return 0; -} - -/** - * dvbm_q3io_rxinit - Initialize the DVB Master Quad-1in3out receiver - * @iface: interface - **/ -static void -dvbm_q3io_rxinit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int i, reg = (iface->null_packets ? DVBM_Q3IO_RCSR_RNP : 0); - - switch (iface->timestamps) { - default: - case ASI_CTL_TSTAMP_NONE: - reg |= 0; - break; - case ASI_CTL_TSTAMP_APPEND: - reg |= DVBM_Q3IO_RCSR_APPEND; - break; - case ASI_CTL_TSTAMP_PREPEND: - reg |= DVBM_Q3IO_RCSR_PREPEND; - break; - } - - switch (iface->mode) { - default: - case ASI_CTL_RX_MODE_RAW: - reg |= 0; - break; - case ASI_CTL_RX_MODE_188: - reg |= DVBM_Q3IO_RCSR_188 | DVBM_Q3IO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_204: - reg |= DVBM_Q3IO_RCSR_204 | DVBM_Q3IO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_AUTO: - reg |= DVBM_Q3IO_RCSR_AUTO | DVBM_Q3IO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_AUTOMAKE188: - reg |= DVBM_Q3IO_RCSR_AUTO | DVBM_Q3IO_RCSR_RSS | - DVBM_Q3IO_RCSR_PFE; - break; - case ASI_CTL_RX_MODE_204MAKE188: - reg |= DVBM_Q3IO_RCSR_204 | DVBM_Q3IO_RCSR_RSS | - DVBM_Q3IO_RCSR_PFE; - break; - } - - /* There will be no races on RCSR - * until this code returns, so we don't need to lock it */ - writel (reg | DVBM_Q3IO_RCSR_RXRST, card->core.addr + DVBM_Q3IO_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3IO_RCSR(channel)); - wmb (); - writel (DVBM_Q3IO_RDMATL, card->core.addr + DVBM_Q3IO_RDMATLR(channel)); - - /* Reset byte counter */ - readl (card->core.addr + DVBM_Q3IO_RXBCOUNT(channel)); - - /* Reset PID Filter. - * There will be no races on PFLUT - * until this code returns, so we don't need to lock it */ - for (i = 0; i < 256; i++) { - writel (i, card->core.addr + DVBM_Q3IO_PFLUTWA(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_Q3IO_FPGAID); - writel (0xffffffff, card->core.addr + DVBM_Q3IO_PFLUT(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_Q3IO_FPGAID); - } - - /* Clear PID registers */ - writel (0, card->core.addr + DVBM_Q3IO_PID0(channel)); - writel (0, card->core.addr + DVBM_Q3IO_PID1(channel)); - writel (0, card->core.addr + DVBM_Q3IO_PID2(channel)); - writel (0, card->core.addr + DVBM_Q3IO_PID3(channel)); - - /* Reset PID counters */ - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT0(channel)); - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT1(channel)); - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT2(channel)); - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT3(channel)); - - return; -} - -/** - * dvbm_q3io_rxstart - Activate the DVB Master Quad-1in3out receiver - * @iface: interface - **/ -static void -dvbm_q3io_rxstart (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Enable and start DMA */ - writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(channel)); - writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - - /* Enable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_TX_IEIS_MASK; - reg |= DVBM_Q3IO_ICSR_RXCDIE | DVBM_Q3IO_ICSR_RXAOSIE | - DVBM_Q3IO_ICSR_RXLOSIE | DVBM_Q3IO_ICSR_RXOIE | - DVBM_Q3IO_ICSR_RXDIE; - writel (reg, card->core.addr + DVBM_Q3IO_ICSR(channel)); - spin_unlock_irq (&card->irq_lock); - - /* Enable the receiver */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3IO_RCSR(channel)); - writel (reg | DVBM_Q3IO_RCSR_RXE, card->core.addr + DVBM_Q3IO_RCSR(channel)); - spin_unlock (&card->reg_lock); - - return; -} - -/** - * dvbm_q3io_rxstop - Deactivate the DVB Master Quad-1in3out receiver - * @iface: interface - **/ -static void -dvbm_q3io_rxstop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Disable the receiver */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3IO_RCSR(channel)); - writel (reg & ~DVBM_Q3IO_RCSR_RXE, - card->core.addr + DVBM_Q3IO_RCSR(channel)); - spin_unlock (&card->reg_lock); - - /* Disable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_TX_IEIS_MASK; - reg |= DVBM_Q3IO_ICSR_RXCDIS | DVBM_Q3IO_ICSR_RXAOSIS | - DVBM_Q3IO_ICSR_RXLOSIS | DVBM_Q3IO_ICSR_RXOIS | - DVBM_Q3IO_ICSR_RXDIS; - writel (reg, card->core.addr + DVBM_Q3IO_ICSR(channel)); - spin_unlock_irq (&card->irq_lock); - - /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & - ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - return; -} - -/** - * dvbm_q3io_rxexit - Clean up the DVB Master Quad-1in3out receiver - * @iface: interface - **/ -static void -dvbm_q3io_rxexit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the receiver. - * There will be no races on RCSR here, - * so we don't need to lock it */ - writel (DVBM_Q3IO_RCSR_RXRST, card->core.addr + DVBM_Q3IO_RCSR(channel)); - - return; -} - -/** - * dvbm_q3io_rxunlocked_ioctl - DVB Master Quad-1in3out receiver unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -dvbm_q3io_rxunlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - int val; - unsigned int reg = 0, *pflut, i; - - switch (cmd) { - case ASI_IOC_RXGETSTATUS: - /* Atomic reads of ICSR and RCSR, so we don't need to lock */ - reg = readl (card->core.addr + DVBM_Q3IO_ICSR(channel)); - switch (readl (card->core.addr + DVBM_Q3IO_RCSR(channel)) & DVBM_Q3IO_RCSR_SYNC_MASK) { - case 0: - val = 1; - break; - case DVBM_Q3IO_RCSR_188: - val = (reg & DVBM_Q3IO_ICSR_RXPASSING) ? 188 : 0; - break; - case DVBM_Q3IO_RCSR_204: - val = (reg & DVBM_Q3IO_ICSR_RXPASSING) ? 204 : 0; - break; - case DVBM_Q3IO_RCSR_AUTO: - if (reg & DVBM_Q3IO_ICSR_RXPASSING) { - val = (reg & DVBM_Q3IO_ICSR_RX204) ? 204 : 188; - } else { - val = 0; - } - break; - - default: - return -EIO; - } - if (put_user (val, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXGETBYTECOUNT: - if (!(iface->capabilities & ASI_CAP_RX_BYTECOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3IO_RXBCOUNT(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETINVSYNC: - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - switch (val) { - case 0: - reg |= 0; - break; - case 1: - reg |= DVBM_Q3IO_RCSR_INVSYNC; - break; - default: - return -EINVAL; - } - spin_lock (&card->reg_lock); - writel ((readl (card->core.addr + DVBM_Q3IO_RCSR(channel)) & - ~DVBM_Q3IO_RCSR_INVSYNC) | reg, - card->core.addr + DVBM_Q3IO_RCSR(channel)); - spin_unlock (&card->reg_lock); - break; - case ASI_IOC_RXGETCARRIER: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_RXCD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETDSYNC: - case ASI_IOC_RXSETINPUT_DEPRECATED: - case ASI_IOC_RXSETINPUT: - /* Dummy ioctl; only zero is valid */ - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if (val) { - return -EINVAL; - } - break; - case ASI_IOC_RXGETRXD: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_Q3IO_ICSR(channel)) & - DVBM_Q3IO_ICSR_RXD) ? 1 : 0, (int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPF: - if (!(iface->capabilities & ASI_CAP_RX_PIDFILTER)) { - return -ENOTTY; - } - pflut = (unsigned int *) - kmalloc (sizeof (unsigned int [256]), GFP_KERNEL); - if (pflut == NULL) { - return -ENOMEM; - } - if (copy_from_user (pflut, (unsigned int __user *)arg, - sizeof (unsigned int [256]))) { - kfree (pflut); - return -EFAULT; - } - spin_lock (&card->reg_lock); - for (i = 0; i < 256; i++) { - writel (i, card->core.addr + DVBM_Q3IO_PFLUTWA(channel)); - wmb (); - writel (pflut[i], card->core.addr + DVBM_Q3IO_PFLUT(channel)); - wmb (); - } - spin_unlock (&card->reg_lock); - kfree (pflut); - break; - case ASI_IOC_RXSETPID0: - if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3IO_PID0(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT0(channel)); - break; - case ASI_IOC_RXGETPID0COUNT: - if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3IO_PIDCOUNT0(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID1: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3IO_PID1(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT1(channel)); - break; - case ASI_IOC_RXGETPID1COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3IO_PIDCOUNT1(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID2: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3IO_PID2(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT2(channel)); - break; - case ASI_IOC_RXGETPID2COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3IO_PIDCOUNT2(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXSETPID3: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (get_user (val, (int __user *)arg)) { - return -EFAULT; - } - if ((val < 0) || (val > 0x00001fff)) { - return -EINVAL; - } - writel (val, card->core.addr + DVBM_Q3IO_PID3(channel)); - /* Reset PID count */ - readl (card->core.addr + DVBM_Q3IO_PIDCOUNT3(channel)); - break; - case ASI_IOC_RXGETPID3COUNT: - if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + - DVBM_Q3IO_PIDCOUNT3(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_RXGET27COUNT: - if (!(iface->capabilities & ASI_CAP_RX_27COUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_Q3IO_27COUNTR), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - default: - return asi_rxioctl (filp, cmd, arg); - } - return 0; -} - -/** - * dvbm_q3io_rxfsync - DVB Master Quad-1in3out receiver fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -dvbm_q3io_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - mutex_lock (&iface->buf_mutex); - - /* Stop the receiver */ - dvbm_q3io_rxstop (iface); - - /* Reset the onboard FIFO and driver buffers */ - spin_lock (&card->reg_lock); - reg = readl (card->core.addr + DVBM_Q3IO_RCSR(channel)); - writel (reg | DVBM_Q3IO_RCSR_RXRST, - card->core.addr + DVBM_Q3IO_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + DVBM_Q3IO_RCSR(channel)); - spin_unlock (&card->reg_lock); - iface->events = 0; - lsdma_reset (iface->dma); - - /* Start the receiver */ - dvbm_q3io_rxstart (iface); - - mutex_unlock (&iface->buf_mutex); - return 0; -} - diff --git a/quad/src/dvbm_q3ioe.h b/quad/src/dvbm_q3ioe.h deleted file mode 100755 index e0a6869c1..000000000 --- a/quad/src/dvbm_q3ioe.h +++ /dev/null @@ -1,169 +0,0 @@ -/* dvbm_q3ioe.h - * - * Header file for the Linear Systems Ltd. DVB Master Quad-1in3out. - * - * Copyright (C) 2007-2010 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _DVBM_Q3IOE_H -#define _DVBM_Q3IOE_H - -#include /* pci_dev */ -#include /* __devinit */ - -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQ3IOE 0x0087 - -#define DVBM_NAME_Q3IOE "DVB Master Quad-1in3out" - -/* DVB Master Quad-1in3out configuration */ -#define DVBM_Q3IO_TFL 0x200 /* Transmit FIFO Start Level */ -#define DVBM_Q3IO_RDMATL 0x020 /* Receiver DMA Trigger Level */ -#define DVBM_Q3IO_TDMATL 0xfdf /* Transmit DMA Trigger Level */ - -/* Register addresses */ -#define DVBM_Q3IO_FPGAID 0x400 /* FPGA ID */ -#define DVBM_Q3IO_HL2CSR 0x404 /* HOTLink II Control and status */ -#define DVBM_Q3IO_27COUNTR 0x408 /* 27 MHz Counter */ -#define DVBM_Q3IO_SSN_HI 0x40C /* Silicon serial number, High */ -#define DVBM_Q3IO_SSN_LO 0x410 /* Silicon serial number, low */ -#define DVBM_Q3IO_ASMIR 0x414 /* ASMI */ - -/* Receiver Registers */ -#define DVBM_Q3IO_RCSR(c) ((c)*0x100+0x004) /* Receive Control/Status */ -#define DVBM_Q3IO_RFCR(c) ((c)*0x100+0x008) /* Receive FIFO Control */ -#define DVBM_Q3IO_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ -#define DVBM_Q3IO_ICSR(c) ((c)*0x100+0x010) /* Interrupt Control and Status */ -#define DVBM_Q3IO_RXBCOUNT(c) ((c)*0x100+0x014) /* Receive Byte Counter */ -#define DVBM_Q3IO_PFLUTWA(c) ((c)*0x100+0x018) /* PID Filter LUT Address */ -#define DVBM_Q3IO_PFLUT(c) ((c)*0x100+0x01c) /* PID Filter LUT Data */ -#define DVBM_Q3IO_PID0(c) ((c)*0x100+0x020) /* PID Detector Value 0 */ -#define DVBM_Q3IO_PIDCOUNT0(c) ((c)*0x100+0x024) /* PID Count 0 */ -#define DVBM_Q3IO_PID1(c) ((c)*0x100+0x028) /* PID Detector Value 1 */ -#define DVBM_Q3IO_PIDCOUNT1(c) ((c)*0x100+0x02c) /* PID Count 1 */ -#define DVBM_Q3IO_PID2(c) ((c)*0x100+0x030) /* PID Detector Value 2 */ -#define DVBM_Q3IO_PIDCOUNT2(c) ((c)*0x100+0x034) /* PID Count 3 */ -#define DVBM_Q3IO_PID3(c) ((c)*0x100+0x038) /* PID Detector Value 3 */ -#define DVBM_Q3IO_PIDCOUNT3(c) ((c)*0x100+0x03c) /* PID Count 4 */ -#define DVBM_Q3IO_RDMATLR(c) ((c)*0x100+0x008) /* DMA Trigger Level */ - -/* Transmit Registers */ -#define DVBM_Q3IO_FTREG(c) ((c)*0x100+0x084) /* Finetuning */ -#define DVBM_Q3IO_TXBCOUNT(c) ((c)*0x100+0x088) /* Transmit Byte Counter */ -#define DVBM_Q3IO_TCSR(c) ((c)*0x100+0x08c) /* Transmit Control and Status */ -#define DVBM_Q3IO_IBSTREG(c) ((c)*0x100+0x090) /* Interbyte Stuffing */ -#define DVBM_Q3IO_IPSTREG(c) ((c)*0x100+0x094) /* Interpacket Stuffing */ -#define DVBM_Q3IO_TFCR(c) ((c)*0x100+0x098) /* Transmit FIFO Control */ -#define DVBM_Q3IO_TPIDR(c) ((c)*0x100+0x09c) /* Transmit PID */ -#define DVBM_Q3IO_TPCRR_HI(c) ((c)*0x100+0x0a0) /* Transmit PCR, High Word */ -#define DVBM_Q3IO_TPCRR_LO(c) ((c)*0x100+0x0a4) /* Transmit PCR, Low Word */ -#define DVBM_Q3IO_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Word */ -#define DVBM_Q3IO_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Word */ - -/* Receiver Control/Status Register (RCSR) bit locations */ - -#define DVM_Q3IO_RCSR_RXMODE 0x00000003 /* Rx Mode */ -#define DVBM_Q3IO_RCSR_RSS 0x00000008 /* Reed-Solomon Strip */ -#define DVBM_Q3IO_RCSR_RXE 0x00000010 /* Receiver Enable */ -#define DVBM_Q3IO_RCSR_RXRST 0x00000020 /* Receiver Reset */ -#define DVBM_Q3IO_RCSR_INVSYNC 0x00000080 /* Inverted Sync Byte Enable */ -#define DVBM_Q3IO_RCSR_RNP 0x00002000 /* Null Packet Replacement */ -#define DVBM_Q3IO_RCSR_PFE 0x00001000 /* PID Filter Enable */ -#define DVBM_Q3IO_RCSR_188 0x00000001 /* 188 Byte Packet */ -#define DVBM_Q3IO_RCSR_204 0x00000002 /* 204 Byte Packet */ -#define DVBM_Q3IO_RCSR_AUTO 0x00000003 /* Auto Byte Packet */ -#define DVBM_Q3IO_RCSR_APPEND 0x00000100 /* Appended Timestamp Mode */ -#define DVBM_Q3IO_RCSR_PREPEND 0x00000200 /* Prepended Timestamp Mode */ - -/* Interrupt Control/Status Register bit locations */ - -#define DVBM_Q3IO_ICSR_TXUIE 0x00000001 /* Tx FIFO Underrun Int. Enable */ -#define DVBM_Q3IO_ICSR_TXDIE 0x00000040 /* Tx Data Int. Enable */ -#define DVBM_Q3IO_ICSR_TXU 0x00000100 /* Tx FIFO Underrun Status */ -#define DVBM_Q3IO_ICSR_TXD 0x00004000 /* Tx Data */ -#define DVBM_Q3IO_ICSR_TXUIS 0x00010000 /* Tx FIFO Underrun Int. Status */ -#define DVBM_Q3IO_ICSR_TXDIS 0x00400000 /* Tx Data Interrupt Status */ -#define DVBM_Q3IO_ICSR_PMS 0x04000000 /* Packet Maturity Status */ -#define DVBM_Q3IO_ICSR_NOSIG 0x08000000 /* No Signal */ -#define DVBM_Q3IO_ICSR_RXOIE 0x00000001 /* Rx FIFO Overrun Int. Enable */ -#define DVBM_Q3IO_ICSR_RXLOSIE 0x00000002 /* Rx Loss of Sync. Int. Enable */ -#define DVBM_Q3IO_ICSR_RXAOSIE 0x00000004 /* Rx Acq. of Sync. Int. Enable */ -#define DVBM_Q3IO_ICSR_RXCDIE 0x00000008 /* Rx Carrier Detect Int. Enable */ -#define DVBM_Q3IO_ICSR_RXDIE 0x00000010 /* Rx Data Int. Enable */ -#define DVBM_Q3IO_ICSR_RXO 0x00000100 /* Rx FIFO Overrun Status */ -#define DVBM_Q3IO_ICSR_RXPASSING 0x00000200 /* Rx sync status same as SYNC */ -#define DVBM_Q3IO_ICSR_RXCD 0x00000800 /* Rx Carrier Detect Status */ -#define DVBM_Q3IO_ICSR_RXD 0x00001000 /* Rx Data */ -#define DVBM_Q3IO_ICSR_RXOIS 0x00010000 /* Rx FIFO Overrun Int. Status */ -#define DVBM_Q3IO_ICSR_RXLOSIS 0x00020000 /* Rx Loss of Sync. Int. Status */ -#define DVBM_Q3IO_ICSR_RXAOSIS 0x00040000 /* Rx Acq. of Sync. Int. Status */ -#define DVBM_Q3IO_ICSR_RXCDIS 0x00080000 /* Rx Carrier Detect Int. Status */ -#define DVBM_Q3IO_ICSR_RXDIS 0x00100000 /* Rx Data Int. Status */ -#define DVBM_Q3IO_ICSR_RX204 0x01000000 /* Rx 204-byte packets */ - -/* Transmit Control and Status (TCSR) */ - -#define DVBM_Q3IO_TCSR_188 0x0 /* 188 Byte Packet */ -#define DVBM_Q3IO_TCSR_204 0x1 /* 204 Byte Packet */ -#define DVBM_Q3IO_TCSR_MAKE204 0x2 /* Make 204 */ -#define DVBM_Q3IO_TCSR_TXE 0x00000010 /* Transmit Enable */ -#define DVBM_Q3IO_TCSR_TXRST 0x00000020 /* Transmit Reset */ -#define DVBM_Q3IO_TCSR_TXCS 0x000000c0 /* Transmit Clock Source add two more */ -#define DVBM_Q3IO_TCSR_EXTCLK 0x00000040 /* External clock Blackburst */ -#define DVBM_Q3IO_TCSR_TTSS 0x00000100 /* Transmit Timestamp Strip */ -#define DVBM_Q3IO_TCSR_TNP 0x00000200 /* Transmit Null Packet */ -#define DVBM_Q3IO_TCSR_TPRC 0x00000400 /* Transmit Packet Release */ - -/* Interrupt Control/Status Register bitmasks */ -#define DVBM_Q3IO_ICSR_TX_IEIS_MASK (DVBM_Q3IO_ICSR_TXUIE|DVBM_Q3IO_ICSR_TXDIE|DVBM_Q3IO_ICSR_TXU|DVBM_Q3IO_ICSR_TXD|DVBM_Q3IO_ICSR_TXUIS|DVBM_Q3IO_ICSR_TXDIS) -/* Interrupt status bits */ -#define DVBM_Q3IO_ICSR_TX_IS_MASK (DVBM_Q3IO_ICSR_TUIS|DVBM_Q3IO_ICSR_TXDIS) -/* Interrupt enable bits */ -#define DVBM_Q3IO_ICSR_TX_IE_MASK (DVBM_Q3IO_ICSR_TUIE|DVBM_Q3IO_ICSR_TXDIE) /* Interrupt Enable BitMask */ - -/* Finetuning Register bit locations */ -#define DVBM_Q3IO_FTR_ILBIG_MASK 0x0f000000 -#define DVBM_Q3IO_FTR_ILBIG_SHIFT 24 -#define DVBM_Q3IO_FTR_BIGIP_MASK 0x00ff0000 -#define DVBM_Q3IO_FTR_BIGIP_SHIFT 16 -#define DVBM_Q3IO_FTR_ILNORMAL_MASK 0x00000f00 -#define DVBM_Q3IO_FTR_ILNORMAL_SHIFT 8 -#define DVBM_Q3IO_FTR_NORMALIP_MASK 0x000000ff - -/* Control/Status Register bitmasks */ -#define DVBM_Q3IO_RCSR_SYNC_MASK 0x00000003 - -/* Transmit Control/Status Register bitmasks */ -#define DVBM_Q3IO_TCSR_CLK_MASK 0x000020c0 -#define DVBM_Q3IO_TCSR_MODE_MASK 0x00000003 - -/* Mask to reset all IE options in ICSR */ -#define DVBM_Q3IO_ICSR_RX_IE_MASK (DVBM_Q3IO_ICSR_RXOIE|DVBM_Q3IO_ICSR_RXLOSIE|DVBM_Q3IO_ICSR_RXAOSIE|DVBM_Q3IO_ICSR_RXCDIE|DVBM_Q3IO_ICSR_RXDIE) -/* The interrupts that are enabled */ -#define DVBM_Q3IO_ICSR_RX_IE (DVBM_Q3IO_ICSR_RXOIE|DVBM_Q3IO_ICSR_RXLOSIE|DVBM_Q3IO_ICSR_RXAOSIE|DVBM_Q3IO_ICSR_RXCDIE) -/* Interrupt Status bits in ICSR */ -#define DVBM_Q3IO_ICSR_RX_IS_BITS (DVBM_Q3IO_ICSR_ROIS|DVBM_Q3IO_ICSR_LOSIS|DVBM_Q3IO_ICSR_ASIS|DVBM_Q3IO_ICSR_CDIS|DVBM_Q3IO_ICSR_RXDIS) - -/* External function prototypes */ - -int dvbm_q3io_pci_probe (struct pci_dev *pdev) __devinit; -void dvbm_q3io_pci_remove (struct pci_dev *pdev); - -#endif - diff --git a/quad/src/dvbm_qdual.c b/quad/src/dvbm_qdual.c old mode 100755 new mode 100644 index 11868460a..028e7ab23 --- a/quad/src/dvbm_qdual.c +++ b/quad/src/dvbm_qdual.c @@ -36,7 +36,6 @@ #include /* error codes */ #include /* irqreturn_t */ #include /* device_create_file () */ -#include /* udelay () */ #include /* mutex_init () */ #include /* put_user () */ @@ -57,6 +56,13 @@ static const char dvbm_lpqduale_name[] = DVBM_NAME_LPQDUALE; static const char dvbm_lpqduale_minibnc_name[] = DVBM_NAME_LPQDUALE_MINIBNC; /* static function prototypes */ +static ssize_t dvbm_qdual_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf); +static ssize_t dvbm_qdual_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count); static ssize_t dvbm_qdual_show_uid (struct device *dev, struct device_attribute *attr, char *buf); @@ -69,9 +75,7 @@ static void dvbm_qdual_start_tx_dma (struct master_iface *iface); static long dvbm_qdual_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_qdual_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_qdual_txfsync,filp,datasync); static void dvbm_qdual_rxinit (struct master_iface *iface); static void dvbm_qdual_rxstart (struct master_iface *iface); static void dvbm_qdual_rxstop (struct master_iface *iface); @@ -79,9 +83,7 @@ static void dvbm_qdual_rxexit (struct master_iface *iface); static long dvbm_qdual_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_qdual_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_qdual_rxfsync,filp,datasync); static struct file_operations dvbm_qdual_txfops = { .owner = THIS_MODULE, @@ -89,7 +91,7 @@ static struct file_operations dvbm_qdual_txfops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = dvbm_qdual_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_qdual_txunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_qdual_txfsync, @@ -102,7 +104,7 @@ static struct file_operations dvbm_qdual_rxfops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_qdual_rxunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_qdual_rxunlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_qdual_rxfsync, @@ -124,6 +126,67 @@ static struct master_iface_operations dvbm_qdual_rxops = { .exit = dvbm_qdual_rxexit }; +/** + * dvbm_qdual_show_blackburst_type - interface attribute read handler + * @dev: device being read + * @attr: device_attribute + * @buf: output buffer + **/ +static ssize_t +dvbm_qdual_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct master_dev *card = dev_get_drvdata(dev); + + return snprintf (buf, PAGE_SIZE, "%u\n", + (readl (card->core.addr + DVBM_QDUAL_HL2CSR) & DVBM_QDUAL_HL2CSR_PLLFS) >> 2); +} + +/** + * dvbm_qdual_store_blackburst_type - interface attribute write handler + * @dev: device being written + * @attr: device attribute + * @buf: input buffer + * @count: + **/ +static ssize_t +dvbm_qdual_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct master_dev *card = dev_get_drvdata(dev); + char *endp; + unsigned long val = simple_strtoul (buf, &endp, 0); + unsigned int reg; + const unsigned long max = MASTER_CTL_BLACKBURST_PAL; + int retcode = count; + struct list_head *p = &card->iface_list; + struct master_iface *iface; + unsigned int i; + unsigned int tx_users = 0; + + if ((endp == buf) || (val > max)) { + return -EINVAL; + } + mutex_lock (&card->users_mutex); + for (i = 0; i < 2; i++) { + p = p->next; + iface = list_entry (p, struct master_iface, list); + tx_users += iface->users; + } + if (tx_users) { + retcode = -EBUSY; + goto OUT; + } + reg = readl (card->core.addr + DVBM_QDUAL_HL2CSR) & ~DVBM_QDUAL_HL2CSR_PLLFS; + writel (reg | (val << 2), card->core.addr + DVBM_QDUAL_HL2CSR); +OUT: + mutex_unlock (&card->users_mutex); + return retcode; +} + /** * dvbm_qdual_show_uid - interface attribute read handler * @dev: device being read @@ -142,6 +205,8 @@ dvbm_qdual_show_uid (struct device *dev, readl (card->core.addr + DVBM_QDUAL_SSN_LO)); } +static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, + dvbm_qdual_show_blackburst_type,dvbm_qdual_store_blackburst_type); static DEVICE_ATTR(uid,S_IRUGO, dvbm_qdual_show_uid,NULL); @@ -226,7 +291,7 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) card->irq = pdev->irq; card->irq_handler = dvbm_qdual_irq_handler; INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_UID; + card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; /* Lock for ICSR */ spin_lock_init (&card->irq_lock); /* Lock for IBSTR, IPSTR, FTR, PFLUT, TCSR, RCSR */ @@ -286,7 +351,12 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) | LSDMA_INTMSK_CH(3), card->bridge_addr + LSDMA_INTMSK); - for (i = 0; i< 4; i++) { + for (i = 0; i < 2; i++) { + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(i)); + } + for (i = 2; i < 4; i++) { writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(i)); @@ -300,6 +370,14 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) } /* Add device attributes */ + if (card->capabilities & MASTER_CAP_BLACKBURST) { + if ((err = device_create_file (card->dev, + &dev_attr_blackburst_type)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'blackburst_type'\n", + dvbm_driver_name); + } + } if (card->capabilities & MASTER_CAP_UID) { if ((err = device_create_file (card->dev, &dev_attr_uid)) < 0) { @@ -322,6 +400,11 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) switch (pdev->device) { default: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUAL: + cap |= ASI_CAP_TX_RXCLKSRC | ASI_CAP_TX_27COUNTER; + if (card->version >= 0x0301) { + cap |= ASI_CAP_TX_EXTCLKSRC2; + } + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUALE: cap |= ASI_CAP_TX_RXCLKSRC; if (card->version >= 0x0301) { @@ -329,7 +412,11 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) } break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQDUALE: + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQDUALE_MINIBNC: + if (card->version >= 0x0102) { + cap |= ASI_CAP_TX_27COUNTER; + } break; } for (i = 0; i < 2; i++) { @@ -355,6 +442,20 @@ dvbm_qdual_pci_probe (struct pci_dev *pdev) ASI_CAP_RX_TIMESTAMPS | ASI_CAP_RX_PTIMESTAMPS | ASI_CAP_RX_NULLPACKETS; + switch (pdev->device) { + default: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUAL: + cap |= ASI_CAP_RX_27COUNTER; + break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUALE: + case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQDUALE: + break; + case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQDUALE_MINIBNC: + if (card->version >= 0x0102) { + cap |= ASI_CAP_RX_27COUNTER; + } + break; + } for (i = 2; i < 4; i++) { if ((err = asi_register_iface (card, &lsdma_dma_ops, @@ -580,7 +681,6 @@ dvbm_qdual_txinit (struct master_iface *iface) reg |= DVBM_QDUAL_TCSR_TPRC; break; } - switch (iface->mode) { default: case ASI_CTL_TX_MODE_188: @@ -613,9 +713,7 @@ dvbm_qdual_txinit (struct master_iface *iface) * until this code returns, so we don't need to lock them */ writel (reg | DVBM_QDUAL_TCSR_TXRST, card->core.addr + DVBM_QDUAL_TCSR(channel)); - wmb (); writel (reg, card->core.addr + DVBM_QDUAL_TCSR(channel)); - wmb (); writel ((DVBM_QDUAL_TFL << 16) | DVBM_QDUAL_TDMATL, card->core.addr + DVBM_QDUAL_TFCR(channel)); writel (0, card->core.addr + DVBM_QDUAL_IBSTREG(channel)); @@ -639,17 +737,14 @@ dvbm_qdual_txstart (struct master_iface *iface) /* Enable transmitter interrupts */ spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_QDUAL_ICSR(channel)); - reg |= DVBM_QDUAL_ICSR_TXUIE | DVBM_QDUAL_ICSR_TXDIE; - writel (reg, card->core.addr + DVBM_QDUAL_ICSR(channel)); + writel (DVBM_QDUAL_ICSR_TXUIE | DVBM_QDUAL_ICSR_TXDIE, + card->core.addr + DVBM_QDUAL_ICSR(channel)); spin_unlock_irq(&card->irq_lock); /* Enable the transmitter */ - spin_lock(&card->reg_lock); reg = readl(card->core.addr + DVBM_QDUAL_TCSR(channel)); writel(reg | DVBM_QDUAL_TCSR_TXE, card->core.addr + DVBM_QDUAL_TCSR(channel)); - spin_unlock(&card->reg_lock); return; } @@ -663,34 +758,38 @@ dvbm_qdual_txstop (struct master_iface *iface) { struct master_dev *card = iface->card; const unsigned int channel = mdev_index (card, &iface->list); + struct master_dma *dma = iface->dma; unsigned int reg; + lsdma_tx_link_all (dma); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + lsdma_reset (dma); + + if (!iface->null_packets) { + /* Wait for the onboard FIFOs to empty */ + /* Atomic read of ICSR, so we don't need to lock */ + wait_event (iface->queue, + !(readl (card->core.addr + DVBM_QDUAL_ICSR(channel)) & + DVBM_QDUAL_ICSR_TXD)); + } + /* Disable the transmitter. * There will be no races on TCSR here, * so we don't need to lock it */ - spin_lock(&card->reg_lock); reg = readl(card->core.addr + DVBM_QDUAL_TCSR(channel)); writel(reg & ~DVBM_QDUAL_TCSR_TXE, card->core.addr + DVBM_QDUAL_TCSR(channel)); - spin_unlock(&card->reg_lock); /* Disable transmitter interrupts */ spin_lock_irq (&card->irq_lock); writel (DVBM_QDUAL_ICSR_TXUIS | DVBM_QDUAL_ICSR_TXDIS, card->core.addr + DVBM_QDUAL_ICSR(channel)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP), - card->bridge_addr + LSDMA_CSR(channel)); - /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); spin_unlock_irq (&card->irq_lock); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(channel)); - udelay (10L); return; } @@ -726,13 +825,11 @@ dvbm_qdual_start_tx_dma (struct master_iface *iface) writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC(dma_channel)); writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(dma_channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_ENABLE, @@ -809,6 +906,15 @@ dvbm_qdual_txunlocked_ioctl (struct file *filp, return -EFAULT; } break; + case ASI_IOC_TXGET27COUNT: + if (!(iface->capabilities & ASI_CAP_TX_27COUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_QDUAL_27COUNTR), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; default: return asi_txioctl (filp, cmd, arg); } @@ -818,15 +924,12 @@ dvbm_qdual_txunlocked_ioctl (struct file *filp, /** * dvbm_qdual_txfsync - DVB Master Quad-2in2out transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_qdual_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_qdual_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -875,7 +978,6 @@ dvbm_qdual_rxinit (struct master_iface *iface) reg |= DVBM_QDUAL_RCSR_PTSE; break; } - switch (iface->mode) { default: case ASI_CTL_RX_MODE_RAW: @@ -904,9 +1006,7 @@ dvbm_qdual_rxinit (struct master_iface *iface) * until this code returns, so we don't need to lock it */ writel (reg | DVBM_QDUAL_RCSR_RXRST, card->core.addr + DVBM_QDUAL_RCSR(channel)); - wmb (); writel (reg, card->core.addr + DVBM_QDUAL_RCSR(channel)); - wmb (); writel (DVBM_QDUAL_RDMATL, card->core.addr + DVBM_QDUAL_RFCR(channel)); @@ -923,8 +1023,6 @@ dvbm_qdual_rxinit (struct master_iface *iface) readl (card->core.addr + DVBM_QDUAL_FPGAID); writel (0xffffffff, card->core.addr + DVBM_QDUAL_PFLUT(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_QDUAL_FPGAID); } /* Clear PID registers */ @@ -960,7 +1058,6 @@ dvbm_qdual_rxstart (struct master_iface *iface) writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(channel)); @@ -970,19 +1067,16 @@ dvbm_qdual_rxstart (struct master_iface *iface) /* Enable receiver interrupts */ spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_QDUAL_ICSR(channel)); - reg |= DVBM_QDUAL_ICSR_RXCDIE | DVBM_QDUAL_ICSR_RXAOSIE | + writel (DVBM_QDUAL_ICSR_RXCDIE | DVBM_QDUAL_ICSR_RXAOSIE | DVBM_QDUAL_ICSR_RXLOSIE | DVBM_QDUAL_ICSR_RXOIE | - DVBM_QDUAL_ICSR_RXDIE; - writel (reg, card->core.addr + DVBM_QDUAL_ICSR(channel)); + DVBM_QDUAL_ICSR_RXDIE, + card->core.addr + DVBM_QDUAL_ICSR(channel)); spin_unlock_irq (&card->irq_lock); /* Enable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_QDUAL_RCSR(channel)); writel (reg | DVBM_QDUAL_RCSR_RXE, card->core.addr + DVBM_QDUAL_RCSR(channel)); - spin_unlock (&card->reg_lock); return; } @@ -999,30 +1093,30 @@ dvbm_qdual_rxstop (struct master_iface *iface) unsigned int reg; /* Disable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_QDUAL_RCSR(channel)); writel (reg & ~DVBM_QDUAL_RCSR_RXE, card->core.addr + DVBM_QDUAL_RCSR(channel)); - spin_unlock (&card->reg_lock); /* Disable receiver interrupts */ spin_lock_irq (&card->irq_lock); writel (DVBM_QDUAL_ICSR_RXCDIS | DVBM_QDUAL_ICSR_RXAOSIS | DVBM_QDUAL_ICSR_RXLOSIS | DVBM_QDUAL_ICSR_RXOIS | - DVBM_QDUAL_ICSR_RXDIS, card->core.addr + DVBM_QDUAL_ICSR(channel)); + DVBM_QDUAL_ICSR_RXDIS, + card->core.addr + DVBM_QDUAL_ICSR(channel)); + spin_unlock_irq (&card->irq_lock); /* Disable and abort DMA */ writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(channel)); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(channel)); /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(channel)); @@ -1173,10 +1267,10 @@ dvbm_qdual_rxunlocked_ioctl (struct file *filp, for (i = 0; i < 256; i++) { writel (i, card->core.addr + DVBM_QDUAL_PFLUTWA(channel)); - wmb (); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_QDUAL_FPGAID); writel (pflut[i], card->core.addr + DVBM_QDUAL_PFLUT(channel)); - wmb (); } spin_unlock (&card->reg_lock); kfree (pflut); @@ -1295,15 +1389,12 @@ dvbm_qdual_rxunlocked_ioctl (struct file *filp, /** * dvbm_qdual_rxfsync - DVB Master Quad-2in2out receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_qdual_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_qdual_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -1320,7 +1411,6 @@ dvbm_qdual_rxfsync (struct file *filp, reg = readl (card->core.addr + DVBM_QDUAL_RCSR(channel)); writel (reg | DVBM_QDUAL_RCSR_RXRST, card->core.addr + DVBM_QDUAL_RCSR(channel)); - wmb (); writel (reg, card->core.addr + DVBM_QDUAL_RCSR(channel)); spin_unlock (&card->reg_lock); iface->events = 0; diff --git a/quad/src/dvbm_qdual.h b/quad/src/dvbm_qdual.h old mode 100755 new mode 100644 index f9c0cfe10..ef7522785 --- a/quad/src/dvbm_qdual.h +++ b/quad/src/dvbm_qdual.h @@ -82,6 +82,9 @@ #define DVBM_QDUAL_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Word */ #define DVBM_QDUAL_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Word */ +/* Control/Status Register bit locations */ +#define DVBM_QDUAL_HL2CSR_PLLFS 0x00000004 /* PLL Frequency Select */ + /* Receiver Control/Status Register (RCSR) bit locations */ #define DVBM_QDUAL_RCSR_188 0x00000001 /* 188 Byte Packet */ #define DVBM_QDUAL_RCSR_204 0x00000002 /* 204 Byte Packet */ diff --git a/quad/src/dvbm_qi.c b/quad/src/dvbm_qi.c old mode 100755 new mode 100644 index 6d502c4e9..5a4dc5ec1 --- a/quad/src/dvbm_qi.c +++ b/quad/src/dvbm_qi.c @@ -59,9 +59,7 @@ static void dvbm_qi_exit (struct master_iface *iface); static long dvbm_qi_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_qi_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_qi_fsync,filp,datasync); static struct file_operations dvbm_qi_fops = { .owner = THIS_MODULE, @@ -69,7 +67,7 @@ static struct file_operations dvbm_qi_fops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_qi_unlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_qi_unlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_qi_fsync, @@ -806,15 +804,12 @@ dvbm_qi_unlocked_ioctl (struct file *filp, /** * dvbm_qi_fsync - DVB Master Q/i fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_qi_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_qi_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/dvbm_qi.h b/quad/src/dvbm_qi.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_qio.c b/quad/src/dvbm_qio.c new file mode 100644 index 000000000..f845a578b --- /dev/null +++ b/quad/src/dvbm_qio.c @@ -0,0 +1,955 @@ +/* dvbm_qio.c + * + * Generic Linux driver functions for Linear Systems Ltd. DVB Master Q/io. + * + * Copyright (C) 2007-2010 Linear Systems Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either Version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public Licence for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Linear Systems can be contacted at . + * + */ + +#include /* KERN_INFO */ +#include /* THIS_MODULE */ + +#include /* inode, file, file_operations */ +#include /* pt_regs */ +#include /* pci_resource_start () */ +#include /* kzalloc () */ +#include /* INIT_LIST_HEAD () */ +#include /* spin_lock_init () */ +#include /* __devinit */ +#include /* error codes */ +#include /* irqreturn_t */ +#include /* mutex_lock () */ + +#include /* put_user () */ + +#include "asicore.h" +#include "../include/master.h" +#include "mdev.h" +#include "dvbm.h" +#include "mdma.h" +#include "dvbm_qio.h" +#include "plx9080.h" +#include "lsdma.h" + +/* static function prototypes */ +static void dvbm_qio_txinit (struct master_iface *iface); +static void dvbm_qio_txstart (struct master_iface *iface); +static void dvbm_qio_txstop (struct master_iface *iface); +static void dvbm_qio_txexit (struct master_iface *iface); +static void dvbm_qio_start_tx_dma (struct master_iface *iface); +static long dvbm_qio_txunlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg); +static int FSYNC_HANDLER(dvbm_qio_txfsync,filp,datasync); +static void dvbm_qio_rxinit (struct master_iface *iface); +static void dvbm_qio_rxstart (struct master_iface *iface); +static void dvbm_qio_rxstop (struct master_iface *iface); +static void dvbm_qio_rxexit (struct master_iface *iface); +static long dvbm_qio_rxunlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg); +static int FSYNC_HANDLER(dvbm_qio_rxfsync,filp,datasync); + +struct file_operations dvbm_qio_txfops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = asi_write, + .poll = asi_txpoll, + .unlocked_ioctl = dvbm_qio_txunlocked_ioctl, + .compat_ioctl = dvbm_qio_txunlocked_ioctl, + .open = asi_open, + .release = asi_release, + .fsync = dvbm_qio_txfsync, + .fasync = NULL +}; + +struct file_operations dvbm_qio_rxfops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = asi_read, + .poll = asi_rxpoll, + .unlocked_ioctl = dvbm_qio_rxunlocked_ioctl, + .compat_ioctl = dvbm_qio_rxunlocked_ioctl, + .open = asi_open, + .release = asi_release, + .fsync = dvbm_qio_rxfsync, + .fasync = NULL +}; + +struct master_iface_operations dvbm_qio_txops = { + .init = dvbm_qio_txinit, + .start = dvbm_qio_txstart, + .stop = dvbm_qio_txstop, + .exit = dvbm_qio_txexit, + .start_tx_dma = dvbm_qio_start_tx_dma +}; + +struct master_iface_operations dvbm_qio_rxops = { + .init = dvbm_qio_rxinit, + .start = dvbm_qio_rxstart, + .stop = dvbm_qio_rxstop, + .exit = dvbm_qio_rxexit +}; + +/** + * dvbm_qio_show_blackburst_type - interface attribute read handler + * @dev: device being read + * @attr: device_attribute + * @buf: output buffer + **/ +ssize_t +dvbm_qio_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct master_dev *card = dev_get_drvdata(dev); + + return snprintf (buf, PAGE_SIZE, "%u\n", + (readl (card->core.addr + DVBM_QIO_CSR) & DVBM_QIO_CSR_PLLFS) >> 2); +} + +/** + * dvbm_qio_store_blackburst_type - interface attribute write handler + * @dev: device being written + * @attr: device attribute + * @buf: input buffer + * @count: + **/ +ssize_t +dvbm_qio_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct master_dev *card = dev_get_drvdata(dev); + char *endp; + unsigned long val = simple_strtoul (buf, &endp, 0); + unsigned int reg; + const unsigned long max = MASTER_CTL_BLACKBURST_PAL; + int retcode = count; + struct list_head *p; + struct master_iface *iface; + unsigned int tx_users = 0; + + if ((endp == buf) || (val > max)) { + return -EINVAL; + } + mutex_lock (&card->users_mutex); + list_for_each (p, &card->iface_list) { + iface = list_entry (p, struct master_iface, list); + if (iface->direction == MASTER_DIRECTION_RX) { + break; + } + tx_users += iface->users; + } + if (tx_users) { + retcode = -EBUSY; + goto OUT; + } + reg = readl (card->core.addr + DVBM_QIO_CSR) & ~DVBM_QIO_CSR_PLLFS; + writel (reg | (val << 2), card->core.addr + DVBM_QIO_CSR); +OUT: + mutex_unlock (&card->users_mutex); + return retcode; +} + +/** + * dvbm_qio_show_uid - interface attribute read handler + * @dev: device being read + * @attr: device attribute + * @buf: output buffer + **/ +ssize_t +dvbm_qio_show_uid (struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct master_dev *card = dev_get_drvdata(dev); + + return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", + readl (card->core.addr + DVBM_QIO_SSN_HI), + readl (card->core.addr + DVBM_QIO_SSN_LO)); +} + +/** + * dvbm_qio_pci_remove - PCI removal handler for a DVB Master Q/io + * @pdev: PCI device + * + * Handle the removal of a DVB Master Q/io. + * This function may be called during PCI probe error handling, + * so don't mark it as __devexit. + **/ +void +dvbm_qio_pci_remove (struct pci_dev *pdev) +{ + struct master_dev *card = pci_get_drvdata (pdev); + + if (card) { + unsigned int i; + + /* Unregister the device and all interfaces */ + dvbm_unregister_all (card); + + for (i = 0; i < 4; i++) { + writel (0, card->core.addr + DVBM_QIO_ICSR(i)); + } + iounmap (card->core.addr); + iounmap (card->bridge_addr); + kfree (card); + } + dvbm_pci_remove_generic (pdev); + return; +} + +/** + * dvbm_qio_txinit - Initialize the DVB Master Q/io transmitter + * @iface: interface + **/ +static void +dvbm_qio_txinit (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg = iface->null_packets ? DVBM_QIO_TCSR_TNP : 0; + + switch (iface->timestamps) { + default: + case ASI_CTL_TSTAMP_NONE: + reg |= 0; + break; + case ASI_CTL_TSTAMP_APPEND: + reg |= DVBM_QIO_TCSR_TTSS; + break; + case ASI_CTL_TSTAMP_PREPEND: + reg |= DVBM_QIO_TCSR_TPRC; + break; + } + switch (iface->mode) { + default: + case ASI_CTL_TX_MODE_188: + reg |= DVBM_QIO_TCSR_188; + break; + case ASI_CTL_TX_MODE_204: + reg |= DVBM_QIO_TCSR_204; + break; + case ASI_CTL_TX_MODE_MAKE204: + reg |= DVBM_QIO_TCSR_MAKE204; + break; + } + switch (iface->clksrc) { + default: + case ASI_CTL_TX_CLKSRC_ONBOARD: + reg |= 0; + break; + case ASI_CTL_TX_CLKSRC_EXT: + reg |= DVBM_QIO_TCSR_EXTCLK; + break; + } + + /* There will be no races on IBSTR, IPSTR, FTR, and TCSR + * until this code returns, so we don't need to lock them */ + writel (reg | DVBM_QIO_TCSR_TXRST, + card->core.addr + DVBM_QIO_TCSR(channel)); + writel (reg, card->core.addr + DVBM_QIO_TCSR(channel)); + writel ((DVBM_QIO_TFSL << 16) | DVBM_QIO_TDMATL, + card->core.addr + DVBM_QIO_TFCR(channel)); + writel (0, card->core.addr + DVBM_QIO_IBSTREG(channel)); + writel (0, card->core.addr + DVBM_QIO_IPSTREG(channel)); + writel (0, card->core.addr + DVBM_QIO_FTREG(channel)); + /* Reset byte counter */ + readl (card->core.addr + DVBM_QIO_TXBCOUNT (channel)); + return; +} + +/** + * dvbm_qio_txstart - Activate the DVB Master Q/io transmitter + * @iface: interface + **/ +static void +dvbm_qio_txstart (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + unsigned int reg; + const unsigned int channel = mdev_index (card, &iface->list); + + /* Enable transmitter interrupts */ + spin_lock_irq (&card->irq_lock); + writel (DVBM_QIO_ICSR_TXUIE | DVBM_QIO_ICSR_TXDIE, + card->core.addr + DVBM_QIO_ICSR(channel)); + spin_unlock_irq(&card->irq_lock); + + /* Enable the transmitter */ + reg = readl(card->core.addr + DVBM_QIO_TCSR(channel)); + writel(reg | DVBM_QIO_TCSR_TXE, + card->core.addr + DVBM_QIO_TCSR(channel)); + + return; +} + +/** + * dvbm_qio_txstop - Deactivate the DVB Master Q/io transmitter + * @iface: interface + **/ +static void +dvbm_qio_txstop (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + struct master_dma *dma = iface->dma; + unsigned int reg; + + lsdma_tx_link_all (dma); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + lsdma_reset (dma); + + if (!iface->null_packets) { + /* Wait for the onboard FIFOs to empty */ + /* Atomic read of ICSR, so we don't need to lock */ + wait_event (iface->queue, + !(readl (card->core.addr + DVBM_QIO_ICSR(channel)) & + DVBM_QIO_ICSR_TXD)); + } + + /* Disable the transmitter. + * There will be no races on TCSR here, + * so we don't need to lock it */ + reg = readl(card->core.addr + DVBM_QIO_TCSR(channel)); + writel(reg & ~DVBM_QIO_TCSR_TXE, + card->core.addr + DVBM_QIO_TCSR(channel)); + + /* Disable transmitter interrupts */ + spin_lock_irq (&card->irq_lock); + writel (DVBM_QIO_ICSR_TXUIS | DVBM_QIO_ICSR_TXDIS, + card->core.addr + DVBM_QIO_ICSR(channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + spin_unlock_irq (&card->irq_lock); + + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(channel)); + + return; +} + +/** + * dvbm_qio_txexit - Clean up the DVB Master Q/io transmitter + * @iface: interface + **/ +static void +dvbm_qio_txexit (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + + /* Reset the transmitter */ + writel (DVBM_QIO_TCSR_TXRST, + card->core.addr + DVBM_QIO_TCSR(channel)); + + return; +} + +/** + * dvbm_qio_start_tx_dma - start transmit DMA + * @iface: interface + **/ +static void +dvbm_qio_start_tx_dma (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + struct master_dma *dma = iface->dma; + const unsigned int dma_channel = mdev_index (card, &iface->list); + + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(dma_channel)); + writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC(dma_channel)); + writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC_H(dma_channel)); + clear_bit (0, &iface->dma_done); + writel (LSDMA_CH_CSR_INTDONEENABLE | + LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_ENABLE, + card->bridge_addr + LSDMA_CSR(dma_channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + return; +} + +/** + * dvbm_qio_txunlocked_ioctl - DVB Master Q/io transmitter unlocked_ioctl() method + * @filp: file + * @cmd: ioctl command + * @arg: ioctl argument + * + * Returns a negative error code on failure and 0 on success. + **/ +static long +dvbm_qio_txunlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + struct asi_txstuffing stuffing; + const unsigned int channel = mdev_index (card, &iface->list); + + switch (cmd) { + case ASI_IOC_TXSETSTUFFING: + if (iface->transport != ASI_CTL_TRANSPORT_DVB_ASI) { + return -ENOTTY; + } + if (copy_from_user (&stuffing, + (struct asi_txstuffing __user *)arg, + sizeof (stuffing))) { + return -EFAULT; + } + if ((stuffing.ib > 0xffff) || + (stuffing.ip > 0xffffff) || + (stuffing.normal_ip > 0xff) || + (stuffing.big_ip > 0xff) || + ((stuffing.il_normal + stuffing.il_big) > 0xf) || + (stuffing.il_normal > stuffing.normal_ip) || + (stuffing.il_big > stuffing.big_ip)) { + return -EINVAL; + } + spin_lock (&card->reg_lock); + writel (stuffing.ib, card->core.addr + DVBM_QIO_IBSTREG(channel)); + writel (stuffing.ip, card->core.addr + DVBM_QIO_IPSTREG(channel)); + writel ((stuffing.il_big << DVBM_QIO_FTR_ILBIG_SHIFT) | + (stuffing.big_ip << DVBM_QIO_FTR_BIGIP_SHIFT) | + (stuffing.il_normal << DVBM_QIO_FTR_ILNORMAL_SHIFT) | + stuffing.normal_ip, card->core.addr + DVBM_QIO_FTREG(channel)); + spin_unlock (&card->reg_lock); + break; + case ASI_IOC_TXGETBYTECOUNT: + if (!(iface->capabilities & ASI_CAP_TX_BYTECOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_QIO_TXBCOUNT(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_TXGETTXD: + /* Atomic read of ICSR, so we don't need to lock */ + if (put_user ((readl (card->core.addr + DVBM_QIO_ICSR(channel)) & + DVBM_QIO_ICSR_TXD) ? 1 : 0, (int __user *)arg)) { + return -EFAULT; + } + break; + default: + return asi_txioctl (filp, cmd, arg); + } + return 0; +} + +/** + * dvbm_qio_txfsync - DVB Master Q/io transmitter fsync() method + * @filp: file to flush + * @datasync: used by filesystems + * + * Returns a negative error code on failure and 0 on success. + **/ +static int +FSYNC_HANDLER(dvbm_qio_txfsync,filp,datasync) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + struct master_dma *dma = iface->dma; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); + const unsigned int channel = mdev_index (card, &iface->list); + + mutex_lock (&iface->buf_mutex); + lsdma_tx_link_all (dma); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + lsdma_reset (dma); + + if (!txiface->null_packets) { + /* Wait for the onboard FIFOs to empty */ + /* Atomic read of ICSR, so we don't need to lock */ + wait_event (iface->queue, + !(readl (card->core.addr + DVBM_QIO_ICSR(channel)) & + DVBM_QIO_ICSR_TXD)); + } + + mutex_unlock (&iface->buf_mutex); + return 0; +} + +/** + * dvbm_qio_rxinit - Initialize the DVB Master Q/io receiver + * @iface: interface + **/ +static void +dvbm_qio_rxinit (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int i, reg = (iface->null_packets ? DVBM_QIO_RCSR_RNP : 0); + + switch (iface->timestamps) { + default: + case ASI_CTL_TSTAMP_NONE: + reg |= 0; + break; + case ASI_CTL_TSTAMP_APPEND: + reg |= DVBM_QIO_RCSR_APPEND; + break; + case ASI_CTL_TSTAMP_PREPEND: + reg |= DVBM_QIO_RCSR_PREPEND; + break; + } + switch (iface->mode) { + default: + case ASI_CTL_RX_MODE_RAW: + reg |= 0; + break; + case ASI_CTL_RX_MODE_188: + reg |= DVBM_QIO_RCSR_188 | DVBM_QIO_RCSR_PFE; + break; + case ASI_CTL_RX_MODE_204: + reg |= DVBM_QIO_RCSR_204 | DVBM_QIO_RCSR_PFE; + break; + case ASI_CTL_RX_MODE_AUTO: + reg |= DVBM_QIO_RCSR_AUTO | DVBM_QIO_RCSR_PFE; + break; + case ASI_CTL_RX_MODE_AUTOMAKE188: + reg |= DVBM_QIO_RCSR_AUTO | DVBM_QIO_RCSR_RSS | + DVBM_QIO_RCSR_PFE; + break; + case ASI_CTL_RX_MODE_204MAKE188: + reg |= DVBM_QIO_RCSR_204 | DVBM_QIO_RCSR_RSS | + DVBM_QIO_RCSR_PFE; + break; + } + + /* There will be no races on RCSR + * until this code returns, so we don't need to lock it */ + writel (reg | DVBM_QIO_RCSR_RXRST, + card->core.addr + DVBM_QIO_RCSR(channel)); + writel (reg, card->core.addr + DVBM_QIO_RCSR(channel)); + writel (DVBM_QIO_RDMATL, card->core.addr + DVBM_QIO_RFCR(channel)); + + /* Reset byte counter */ + readl (card->core.addr + DVBM_QIO_RXBCOUNT(channel)); + + /* Reset PID Filter. + * There will be no races on PFLUT + * until this code returns, so we don't need to lock it */ + for (i = 0; i < 256; i++) { + writel (i, card->core.addr + DVBM_QIO_PFLUTWA(channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_QIO_FPGAID); + writel (0xffffffff, card->core.addr + DVBM_QIO_PFLUT(channel)); + } + + /* Clear PID registers */ + writel (0, card->core.addr + DVBM_QIO_PID0(channel)); + writel (0, card->core.addr + DVBM_QIO_PID1(channel)); + writel (0, card->core.addr + DVBM_QIO_PID2(channel)); + writel (0, card->core.addr + DVBM_QIO_PID3(channel)); + + /* Reset PID counters */ + readl (card->core.addr + DVBM_QIO_PIDCOUNT0(channel)); + readl (card->core.addr + DVBM_QIO_PIDCOUNT1(channel)); + readl (card->core.addr + DVBM_QIO_PIDCOUNT2(channel)); + readl (card->core.addr + DVBM_QIO_PIDCOUNT3(channel)); + + return; +} + +/** + * dvbm_qio_rxstart - Activate the DVB Master Q/io receiver + * @iface: interface + **/ +static void +dvbm_qio_rxstart (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + struct master_dma *dma = iface->dma; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg; + + /* Enable and start DMA */ + writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC(channel)); + writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), + card->bridge_addr + LSDMA_DESC_H(channel)); + clear_bit (0, &iface->dma_done); + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, + card->bridge_addr + LSDMA_CSR(channel)); + + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + + /* Enable receiver interrupts */ + spin_lock_irq (&card->irq_lock); + writel (DVBM_QIO_ICSR_RXCDIE | DVBM_QIO_ICSR_RXAOSIE | + DVBM_QIO_ICSR_RXLOSIE | DVBM_QIO_ICSR_RXOIE | + DVBM_QIO_ICSR_RXDIE, + card->core.addr + DVBM_QIO_ICSR(channel)); + spin_unlock_irq (&card->irq_lock); + + /* Enable the receiver */ + reg = readl (card->core.addr + DVBM_QIO_RCSR(channel)); + writel (reg | DVBM_QIO_RCSR_RXE, + card->core.addr + DVBM_QIO_RCSR(channel)); + + return; +} + +/** + * dvbm_qio_rxstop - Deactivate the DVB Master Q/io receiver + * @iface: interface + **/ +static void +dvbm_qio_rxstop (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg; + + /* Disable the receiver */ + reg = readl (card->core.addr + DVBM_QIO_RCSR(channel)); + writel (reg & ~DVBM_QIO_RCSR_RXE, + card->core.addr + DVBM_QIO_RCSR(channel)); + + /* Disable receiver interrupts */ + spin_lock_irq (&card->irq_lock); + writel (DVBM_QIO_ICSR_RXCDIS | DVBM_QIO_ICSR_RXAOSIS | + DVBM_QIO_ICSR_RXLOSIS | DVBM_QIO_ICSR_RXOIS | + DVBM_QIO_ICSR_RXDIS, + card->core.addr + DVBM_QIO_ICSR(channel)); + spin_unlock_irq (&card->irq_lock); + + /* Disable and abort DMA */ + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, + card->bridge_addr + LSDMA_CSR(channel)); + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, + card->bridge_addr + LSDMA_CSR(channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->bridge_addr + LSDMA_INTMSK); + + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, + card->bridge_addr + LSDMA_CSR(channel)); + + return; +} + +/** + * dvbm_qio_rxexit - Clean up the DVB Master Q/io receiver + * @iface: interface + **/ +static void +dvbm_qio_rxexit (struct master_iface *iface) +{ + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + + /* Reset the receiver. + * There will be no races on RCSR here, + * so we don't need to lock it */ + writel (DVBM_QIO_RCSR_RXRST, + card->core.addr + DVBM_QIO_RCSR(channel)); + + return; +} + +/** + * dvbm_qio_rxunlocked_ioctl - DVB Master Q/io receiver unlocked_ioctl() method + * @filp: file + * @cmd: ioctl command + * @arg: ioctl argument + * + * Returns a negative error code on failure and 0 on success. + **/ +static long +dvbm_qio_rxunlocked_ioctl (struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + int val; + unsigned int reg = 0, *pflut, i; + + switch (cmd) { + case ASI_IOC_RXGETSTATUS: + /* Atomic reads of ICSR and RCSR, so we don't need to lock */ + reg = readl (card->core.addr + DVBM_QIO_ICSR(channel)); + switch (readl (card->core.addr + DVBM_QIO_RCSR(channel)) & DVBM_QIO_RCSR_SYNC_MASK) { + case 0: + val = 1; + break; + case DVBM_QIO_RCSR_188: + val = (reg & DVBM_QIO_ICSR_RXPASSING) ? 188 : 0; + break; + case DVBM_QIO_RCSR_204: + val = (reg & DVBM_QIO_ICSR_RXPASSING) ? 204 : 0; + break; + case DVBM_QIO_RCSR_AUTO: + if (reg & DVBM_QIO_ICSR_RXPASSING) { + val = (reg & DVBM_QIO_ICSR_RX204) ? 204 : 188; + } else { + val = 0; + } + break; + + default: + return -EIO; + } + if (put_user (val, (int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXGETBYTECOUNT: + if (!(iface->capabilities & ASI_CAP_RX_BYTECOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_QIO_RXBCOUNT(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETINVSYNC: + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + switch (val) { + case 0: + reg |= 0; + break; + case 1: + reg |= DVBM_QIO_RCSR_INVSYNC; + break; + default: + return -EINVAL; + } + spin_lock (&card->reg_lock); + writel ((readl (card->core.addr + DVBM_QIO_RCSR(channel)) & + ~DVBM_QIO_RCSR_INVSYNC) | reg, + card->core.addr + DVBM_QIO_RCSR(channel)); + spin_unlock (&card->reg_lock); + break; + case ASI_IOC_RXGETCARRIER: + /* Atomic read of ICSR, so we don't need to lock */ + if (put_user ((readl (card->core.addr + DVBM_QIO_ICSR(channel)) & + DVBM_QIO_ICSR_RXCD) ? 1 : 0, (int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETDSYNC: + case ASI_IOC_RXSETINPUT_DEPRECATED: + case ASI_IOC_RXSETINPUT: + /* Dummy ioctl; only zero is valid */ + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + if (val) { + return -EINVAL; + } + break; + case ASI_IOC_RXGETRXD: + /* Atomic read of ICSR, so we don't need to lock */ + if (put_user ((readl (card->core.addr + DVBM_QIO_ICSR(channel)) & + DVBM_QIO_ICSR_RXD) ? 1 : 0, (int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETPF: + if (!(iface->capabilities & ASI_CAP_RX_PIDFILTER)) { + return -ENOTTY; + } + pflut = (unsigned int *) + kmalloc (sizeof (unsigned int [256]), GFP_KERNEL); + if (pflut == NULL) { + return -ENOMEM; + } + if (copy_from_user (pflut, (unsigned int __user *)arg, + sizeof (unsigned int [256]))) { + kfree (pflut); + return -EFAULT; + } + spin_lock (&card->reg_lock); + for (i = 0; i < 256; i++) { + writel (i, card->core.addr + DVBM_QIO_PFLUTWA(channel)); + /* Dummy read to flush PCI posted writes */ + readl (card->core.addr + DVBM_QIO_FPGAID); + writel (pflut[i], card->core.addr + DVBM_QIO_PFLUT(channel)); + } + spin_unlock (&card->reg_lock); + kfree (pflut); + break; + case ASI_IOC_RXSETPID0: + if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { + return -ENOTTY; + } + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + if ((val < 0) || (val > 0x00001fff)) { + return -EINVAL; + } + writel (val, card->core.addr + DVBM_QIO_PID0(channel)); + /* Reset PID count */ + readl (card->core.addr + DVBM_QIO_PIDCOUNT0(channel)); + break; + case ASI_IOC_RXGETPID0COUNT: + if (!(iface->capabilities & ASI_CAP_RX_PIDCOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + + DVBM_QIO_PIDCOUNT0(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETPID1: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + if ((val < 0) || (val > 0x00001fff)) { + return -EINVAL; + } + writel (val, card->core.addr + DVBM_QIO_PID1(channel)); + /* Reset PID count */ + readl (card->core.addr + DVBM_QIO_PIDCOUNT1(channel)); + break; + case ASI_IOC_RXGETPID1COUNT: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + + DVBM_QIO_PIDCOUNT1(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETPID2: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + if ((val < 0) || (val > 0x00001fff)) { + return -EINVAL; + } + writel (val, card->core.addr + DVBM_QIO_PID2(channel)); + /* Reset PID count */ + readl (card->core.addr + DVBM_QIO_PIDCOUNT2(channel)); + break; + case ASI_IOC_RXGETPID2COUNT: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + + DVBM_QIO_PIDCOUNT2(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXSETPID3: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (get_user (val, (int __user *)arg)) { + return -EFAULT; + } + if ((val < 0) || (val > 0x00001fff)) { + return -EINVAL; + } + writel (val, card->core.addr + DVBM_QIO_PID3(channel)); + /* Reset PID count */ + readl (card->core.addr + DVBM_QIO_PIDCOUNT3(channel)); + break; + case ASI_IOC_RXGETPID3COUNT: + if (!(iface->capabilities & ASI_CAP_RX_4PIDCOUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + + DVBM_QIO_PIDCOUNT3(channel)), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + case ASI_IOC_RXGET27COUNT: + if (!(iface->capabilities & ASI_CAP_RX_27COUNTER)) { + return -ENOTTY; + } + if (put_user (readl (card->core.addr + DVBM_QIO_27COUNTR), + (unsigned int __user *)arg)) { + return -EFAULT; + } + break; + default: + return asi_rxioctl (filp, cmd, arg); + } + return 0; +} + +/** + * dvbm_qio_rxfsync - DVB Master Q/io receiver fsync() method + * @filp: file to flush + * @datasync: used by filesystems + * + * Returns a negative error code on failure and 0 on success. + **/ +static int +FSYNC_HANDLER(dvbm_qio_rxfsync,filp,datasync) +{ + struct master_iface *iface = filp->private_data; + struct master_dev *card = iface->card; + const unsigned int channel = mdev_index (card, &iface->list); + unsigned int reg; + + mutex_lock (&iface->buf_mutex); + + /* Stop the receiver */ + dvbm_qio_rxstop (iface); + + /* Reset the onboard FIFO and driver buffers */ + spin_lock (&card->reg_lock); + reg = readl (card->core.addr + DVBM_QIO_RCSR(channel)); + writel (reg | DVBM_QIO_RCSR_RXRST, + card->core.addr + DVBM_QIO_RCSR(channel)); + writel (reg, card->core.addr + DVBM_QIO_RCSR(channel)); + spin_unlock (&card->reg_lock); + iface->events = 0; + lsdma_reset (iface->dma); + + /* Start the receiver */ + dvbm_qio_rxstart (iface); + + mutex_unlock (&iface->buf_mutex); + return 0; +} + diff --git a/quad/src/dvbm_qio.h b/quad/src/dvbm_qio.h new file mode 100644 index 000000000..90a213706 --- /dev/null +++ b/quad/src/dvbm_qio.h @@ -0,0 +1,188 @@ +/* dvbm_qio.h + * + * Header file for the Linear Systems Ltd. DVB Master Q/io. + * + * Copyright (C) 2007-2010 Linear Systems Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either Version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public Licence for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Linear Systems can be contacted at . + * + */ + +#ifndef _DVBM_QIO_H +#define _DVBM_QIO_H + +#include /* file_operations */ +#include /* pci_dev */ +#include /* __devinit */ + +#include "miface.h" + +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQ3IOE 0x0087 +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQ3INOE 0x0088 +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQO 0x007C +#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE 0x0085 + +#define DVBM_NAME_Q3IOE "DVB Master Quad-1in3out" +#define DVBM_NAME_Q3INOE "DVB Master Quad-3in1out" +#define DVBM_NAME_QO "DVB Master Q/o" +#define DVBM_NAME_QOE "DVB Master Q/o PCIe" + +/* DVB Master Q/io configuration */ +#define DVBM_QIO_TFSL 0x200 /* Transmit FIFO Start Level */ +#define DVBM_QIO_RDMATL 0x020 /* Receiver DMA Trigger Level */ +#define DVBM_QIO_TDMATL 0xfdf /* Transmit DMA Trigger Level */ + +/* Register addresses */ +#define DVBM_QIO_FPGAID 0x400 /* FPGA ID */ +#define DVBM_QIO_CSR 0x404 /* Control/Status */ +#define DVBM_QIO_27COUNTR 0x408 /* 27 MHz Counter */ +#define DVBM_QIO_SSN_HI 0x40C /* Silicon serial number, High */ +#define DVBM_QIO_SSN_LO 0x410 /* Silicon serial number, low */ +#define DVBM_QIO_ASMIR 0x414 /* ASMI */ + +/* Common per-channel registers */ +#define DVBM_QIO_ICSR(c) ((c)*0x100+0x010) /* Interrupt Control/Status */ + +/* Receiver Registers */ +#define DVBM_QIO_RCSR(c) ((c)*0x100+0x004) /* Receive Control/Status */ +#define DVBM_QIO_RFCR(c) ((c)*0x100+0x008) /* Receive FIFO Control */ +#define DVBM_QIO_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ +#define DVBM_QIO_RXBCOUNT(c) ((c)*0x100+0x014) /* Receive Byte Counter */ +#define DVBM_QIO_PFLUTWA(c) ((c)*0x100+0x018) /* PID Filter LUT Address */ +#define DVBM_QIO_PFLUT(c) ((c)*0x100+0x01c) /* PID Filter LUT Data */ +#define DVBM_QIO_PID0(c) ((c)*0x100+0x020) /* PID Detector Value 0 */ +#define DVBM_QIO_PIDCOUNT0(c) ((c)*0x100+0x024) /* PID Count 0 */ +#define DVBM_QIO_PID1(c) ((c)*0x100+0x028) /* PID Detector Value 1 */ +#define DVBM_QIO_PIDCOUNT1(c) ((c)*0x100+0x02c) /* PID Count 1 */ +#define DVBM_QIO_PID2(c) ((c)*0x100+0x030) /* PID Detector Value 2 */ +#define DVBM_QIO_PIDCOUNT2(c) ((c)*0x100+0x034) /* PID Count 3 */ +#define DVBM_QIO_PID3(c) ((c)*0x100+0x038) /* PID Detector Value 3 */ +#define DVBM_QIO_PIDCOUNT3(c) ((c)*0x100+0x03c) /* PID Count 4 */ + +/* Transmit Registers */ +#define DVBM_QIO_FTREG(c) ((c)*0x100+0x084) /* Finetuning */ +#define DVBM_QIO_TXBCOUNT(c) ((c)*0x100+0x088) /* Transmit Byte Counter */ +#define DVBM_QIO_TCSR(c) ((c)*0x100+0x08c) /* Transmit Control/Status */ +#define DVBM_QIO_IBSTREG(c) ((c)*0x100+0x090) /* Interbyte Stuffing */ +#define DVBM_QIO_IPSTREG(c) ((c)*0x100+0x094) /* Interpacket Stuffing */ +#define DVBM_QIO_TFCR(c) ((c)*0x100+0x098) /* Transmit FIFO Control */ +#define DVBM_QIO_TPIDR(c) ((c)*0x100+0x09c) /* Transmit PID */ +#define DVBM_QIO_TPCRR_HI(c) ((c)*0x100+0x0a0) /* Transmit PCR, High Word */ +#define DVBM_QIO_TPCRR_LO(c) ((c)*0x100+0x0a4) /* Transmit PCR, Low Word */ +#define DVBM_QIO_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Word */ +#define DVBM_QIO_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Word */ + +/* Control/Status Register bit locations */ +#define DVBM_QIO_CSR_PLLFS 0x00000004 /* PLL Frequency Select */ + +/* Receiver Control/Status Register (RCSR) bit locations */ +#define DVBM_QIO_RCSR_RXMODE 0x00000003 /* Rx Mode */ +#define DVBM_QIO_RCSR_RSS 0x00000008 /* Reed-Solomon Strip */ +#define DVBM_QIO_RCSR_RXE 0x00000010 /* Receiver Enable */ +#define DVBM_QIO_RCSR_RXRST 0x00000020 /* Receiver Reset */ +#define DVBM_QIO_RCSR_INVSYNC 0x00000080 /* Inverted Sync Byte Enable */ +#define DVBM_QIO_RCSR_RNP 0x00002000 /* Null Packet Replacement */ +#define DVBM_QIO_RCSR_PFE 0x00001000 /* PID Filter Enable */ +#define DVBM_QIO_RCSR_188 0x00000001 /* 188 Byte Packet */ +#define DVBM_QIO_RCSR_204 0x00000002 /* 204 Byte Packet */ +#define DVBM_QIO_RCSR_AUTO 0x00000003 /* Auto Byte Packet */ +#define DVBM_QIO_RCSR_APPEND 0x00000100 /* Appended Timestamp Mode */ +#define DVBM_QIO_RCSR_PREPEND 0x00000200 /* Prepended Timestamp Mode */ + +/* Interrupt Control/Status Register bit locations */ +#define DVBM_QIO_ICSR_TXUIE 0x00000001 /* Tx FIFO Underrun Int. Enable */ +#define DVBM_QIO_ICSR_TXDIE 0x00000040 /* Tx Data Int. Enable */ +#define DVBM_QIO_ICSR_TXU 0x00000100 /* Tx FIFO Underrun Status */ +#define DVBM_QIO_ICSR_TXD 0x00004000 /* Tx Data */ +#define DVBM_QIO_ICSR_TXUIS 0x00010000 /* Tx FIFO Underrun Int. Status */ +#define DVBM_QIO_ICSR_TXDIS 0x00400000 /* Tx Data Interrupt Status */ +#define DVBM_QIO_ICSR_PMS 0x04000000 /* Packet Maturity Status */ +#define DVBM_QIO_ICSR_NOSIG 0x08000000 /* No Signal */ +#define DVBM_QIO_ICSR_RXOIE 0x00000001 /* Rx FIFO Overrun Int. Enable */ +#define DVBM_QIO_ICSR_RXLOSIE 0x00000002 /* Rx Loss of Sync. Int. Enable */ +#define DVBM_QIO_ICSR_RXAOSIE 0x00000004 /* Rx Acq. of Sync. Int. Enable */ +#define DVBM_QIO_ICSR_RXCDIE 0x00000008 /* Rx Carrier Detect Int. Enable */ +#define DVBM_QIO_ICSR_RXDIE 0x00000010 /* Rx Data Int. Enable */ +#define DVBM_QIO_ICSR_RXO 0x00000100 /* Rx FIFO Overrun Status */ +#define DVBM_QIO_ICSR_RXPASSING 0x00000200 /* Rx sync status same as SYNC */ +#define DVBM_QIO_ICSR_RXCD 0x00000800 /* Rx Carrier Detect Status */ +#define DVBM_QIO_ICSR_RXD 0x00001000 /* Rx Data */ +#define DVBM_QIO_ICSR_RXOIS 0x00010000 /* Rx FIFO Overrun Int. Status */ +#define DVBM_QIO_ICSR_RXLOSIS 0x00020000 /* Rx Loss of Sync. Int. Status */ +#define DVBM_QIO_ICSR_RXAOSIS 0x00040000 /* Rx Acq. of Sync. Int. Status */ +#define DVBM_QIO_ICSR_RXCDIS 0x00080000 /* Rx Carrier Detect Int. Status */ +#define DVBM_QIO_ICSR_RXDIS 0x00100000 /* Rx Data Int. Status */ +#define DVBM_QIO_ICSR_RX204 0x01000000 /* Rx 204-byte packets */ + +/* Transmit Control/Status Register (TCSR) bit locations */ +#define DVBM_QIO_TCSR_188 0x00000000 /* 188 Byte Packet */ +#define DVBM_QIO_TCSR_204 0x00000001 /* 204 Byte Packet */ +#define DVBM_QIO_TCSR_MAKE204 0x00000002 /* Make 204 */ +#define DVBM_QIO_TCSR_TXE 0x00000010 /* Transmit Enable */ +#define DVBM_QIO_TCSR_TXRST 0x00000020 /* Transmit Reset */ +#define DVBM_QIO_TCSR_TXCS 0x000000c0 /* Transmit Clock Source add two more */ +#define DVBM_QIO_TCSR_EXTCLK 0x00000040 /* External clock Blackburst */ +#define DVBM_QIO_TCSR_TTSS 0x00000100 /* Transmit Timestamp Strip */ +#define DVBM_QIO_TCSR_TNP 0x00000200 /* Transmit Null Packet */ +#define DVBM_QIO_TCSR_TPRC 0x00000400 /* Transmit Packet Release */ + +/* Finetuning Register bit locations */ +#define DVBM_QIO_FTR_ILBIG_MASK 0x0f000000 +#define DVBM_QIO_FTR_ILBIG_SHIFT 24 +#define DVBM_QIO_FTR_BIGIP_MASK 0x00ff0000 +#define DVBM_QIO_FTR_BIGIP_SHIFT 16 +#define DVBM_QIO_FTR_ILNORMAL_MASK 0x00000f00 +#define DVBM_QIO_FTR_ILNORMAL_SHIFT 8 +#define DVBM_QIO_FTR_NORMALIP_MASK 0x000000ff + +/* Control/Status Register bitmasks */ +#define DVBM_QIO_RCSR_SYNC_MASK 0x00000003 + +/* Transmit Control/Status Register bitmasks */ +#define DVBM_QIO_TCSR_CLK_MASK 0x000020c0 +#define DVBM_QIO_TCSR_MODE_MASK 0x00000003 + +/* External variables */ + +extern struct file_operations dvbm_qio_txfops; +extern struct file_operations dvbm_qio_rxfops; +extern struct master_iface_operations dvbm_qio_txops; +extern struct master_iface_operations dvbm_qio_rxops; + +/* External function prototypes */ + +ssize_t dvbm_qio_show_blackburst_type (struct device *dev, + struct device_attribute *attr, + char *buf); +ssize_t dvbm_qio_store_blackburst_type (struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count); +ssize_t dvbm_qio_show_uid (struct device *dev, + struct device_attribute *attr, + char *buf); +int dvbm_q3io_pci_probe (struct pci_dev *pdev) __devinit; +int dvbm_q3ino_pci_probe (struct pci_dev *pdev) __devinit; +int dvbm_qo_pci_probe (struct pci_dev *pdev) __devinit; +void dvbm_qio_pci_remove (struct pci_dev *pdev); + +#define dvbm_q3io_pci_remove(pdev) dvbm_qio_pci_remove(pdev) +#define dvbm_q3ino_pci_remove(pdev) dvbm_qio_pci_remove(pdev) +#define dvbm_qo_pci_remove(pdev) dvbm_qio_pci_remove(pdev) + +#endif + diff --git a/quad/src/dvbm_qlf.c b/quad/src/dvbm_qlf.c old mode 100755 new mode 100644 index 255a8d8e5..75e489d5a --- a/quad/src/dvbm_qlf.c +++ b/quad/src/dvbm_qlf.c @@ -65,9 +65,7 @@ static void dvbm_qlf_exit (struct master_iface *iface); static long dvbm_qlf_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_qlf_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_qlf_fsync,filp,datasync); static struct file_operations dvbm_qlf_fops = { .owner = THIS_MODULE, @@ -75,7 +73,7 @@ static struct file_operations dvbm_qlf_fops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_qlf_unlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_qlf_unlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_qlf_fsync, @@ -470,9 +468,7 @@ dvbm_qlf_init (struct master_iface *iface) * until this code returns, so we don't need to lock it */ writel (reg | DVBM_QLF_RCR_RST, card->core.addr + DVBM_QLF_RCR(channel)); - wmb (); writel (reg, card->core.addr + DVBM_QLF_RCR(channel)); - wmb (); writel (DVBM_QLF_RDMATL, card->core.addr + DVBM_QLF_RDMATLR(channel)); /* Reset the byte counter */ @@ -486,8 +482,6 @@ dvbm_qlf_init (struct master_iface *iface) /* Dummy read to flush PCI posted writes */ readl (card->core.addr + DVBM_QLF_FPGAID); writel (0xffffffff, card->core.addr + DVBM_QLF_PFLUTR(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_QLF_FPGAID); } /* Clear PID registers */ @@ -523,7 +517,6 @@ dvbm_qlf_start (struct master_iface *iface) writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(channel)); @@ -539,11 +532,9 @@ dvbm_qlf_start (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Enable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_QLF_RCR(channel)); writel (reg | DVBM_QLF_RCR_EN, card->core.addr + DVBM_QLF_RCR(channel)); - spin_unlock (&card->reg_lock); return; } @@ -560,11 +551,9 @@ dvbm_qlf_stop (struct master_iface *iface) unsigned int reg; /* Disable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + DVBM_QLF_RCR(channel)); writel (reg & ~DVBM_QLF_RCR_EN, card->core.addr + DVBM_QLF_RCR(channel)); - spin_unlock (&card->reg_lock); /* Disable receiver interrupts */ spin_lock_irq (&card->irq_lock); @@ -572,19 +561,20 @@ dvbm_qlf_stop (struct master_iface *iface) DVBM_QLF_ICSR_RXLOSIS | DVBM_QLF_ICSR_RXOIS | DVBM_QLF_ICSR_RXDIS, card->core.addr + DVBM_QLF_ICSR(channel)); + spin_unlock_irq (&card->irq_lock); /* Disable and abort DMA */ writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(channel)); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(channel)); /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(channel)); @@ -735,8 +725,6 @@ dvbm_qlf_unlocked_ioctl (struct file *filp, /* Dummy read to flush PCI posted writes */ readl (card->core.addr + DVBM_QLF_FPGAID); writel (pflut[i], card->core.addr + DVBM_QLF_PFLUTR(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + DVBM_QLF_FPGAID); } spin_unlock (&card->reg_lock); kfree (pflut); @@ -855,15 +843,12 @@ dvbm_qlf_unlocked_ioctl (struct file *filp, /** * dvbm_qlf_fsync - DVB Master Q/i RoHS receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_qlf_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_qlf_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -880,7 +865,6 @@ dvbm_qlf_fsync (struct file *filp, reg = readl (card->core.addr + DVBM_QLF_RCR(channel)); writel (reg | DVBM_QLF_RCR_RST, card->core.addr + DVBM_QLF_RCR(channel)); - wmb (); writel (reg, card->core.addr + DVBM_QLF_RCR(channel)); spin_unlock (&card->reg_lock); iface->events = 0; diff --git a/quad/src/dvbm_qlf.h b/quad/src/dvbm_qlf.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_qo.c b/quad/src/dvbm_qo.c old mode 100755 new mode 100644 index 5fb9487d3..162780bed --- a/quad/src/dvbm_qo.c +++ b/quad/src/dvbm_qo.c @@ -33,12 +33,10 @@ #include /* spin_lock_init () */ #include /* __devinit */ #include /* error codes */ -#include /* udelay () */ #include /* irqreturn_t */ #include /* device_create file */ #include /* mutex_init () */ -#include /* put_user () */ #include /* set_bit () */ #include "asicore.h" @@ -46,78 +44,25 @@ #include "mdev.h" #include "dvbm.h" #include "mdma.h" -#include "dvbm_qo.h" +#include "dvbm_qio.h" #include "plx9080.h" #include "lsdma.h" static const char dvbm_qo_name[] = DVBM_NAME_QO; static const char dvbm_qoe_name[] = DVBM_NAME_QOE; -static const char dvbm_lpqoe_name[] = DVBM_NAME_LPQOE; -static const char dvbm_lpqoe_minibnc_name[] = DVBM_NAME_LPQOE_MINIBNC; /* Static function prototypes */ -static ssize_t dvbm_qo_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf); static irqreturn_t IRQ_HANDLER (dvbm_qo_irq_handler, irq, dev_id, regs); -static void dvbm_qo_init (struct master_iface *iface); -static void dvbm_qo_start (struct master_iface *iface); -static void dvbm_qo_stop (struct master_iface *iface); -static void dvbm_qo_exit (struct master_iface *iface); -static void dvbm_qo_start_tx_dma (struct master_iface *iface); -static long dvbm_qo_unlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int dvbm_qo_fsync (struct file *filp, - struct dentry *dentry, - int datasync); -static struct file_operations dvbm_qo_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = asi_write, - .poll = asi_txpoll, - .unlocked_ioctl = dvbm_qo_unlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, - .open = asi_open, - .release = asi_release, - .fsync = dvbm_qo_fsync, - .fasync = NULL -}; - -static struct master_iface_operations dvbm_qo_ops = { - .init = dvbm_qo_init, - .start = dvbm_qo_start, - .stop = dvbm_qo_stop, - .exit = dvbm_qo_exit, - .start_tx_dma = dvbm_qo_start_tx_dma -}; +static DEVICE_ATTR(blackburst_type,S_IRUGO|S_IWUSR, + dvbm_qio_show_blackburst_type,dvbm_qio_store_blackburst_type); +static DEVICE_ATTR(uid,S_IRUGO, dvbm_qio_show_uid,NULL); /** - * dvbm_qlf_show_uid - interface attribute read handler - * @dev: device being read - * @attr: device attribute - * @buf: output buffer - **/ -static ssize_t -dvbm_qo_show_uid (struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct master_dev *card = dev_get_drvdata(dev); - - return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", - readl (card->core.addr + DVBM_QO_SSN_HI), - readl (card->core.addr + DVBM_QO_SSN_LO)); -} - -static DEVICE_ATTR(uid,S_IRUGO, dvbm_qo_show_uid,NULL); - -/** - * dvbm_qo_pci_probe - PCI insertion handler for a DVB Master Q/O + * dvbm_qo_pci_probe - PCI insertion handler for a DVB Master Q/o * @pdev: PCI device * - * Handle the insertion of a DVB Master Q/O. + * Handle the insertion of a DVB Master Q/o. * Returns a negative error code on failure and 0 on success. **/ int __devinit @@ -145,43 +90,25 @@ dvbm_qo_pci_probe (struct pci_dev *pdev) } /* Initialize the board info structure */ + card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 3), + pci_resource_len (pdev, 3)); + card->core.addr = ioremap_nocache (pci_resource_start (pdev, 2), + pci_resource_len (pdev, 2)); switch (pdev->device) { default: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQO: - card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 3), - pci_resource_len (pdev, 3)); - card->core.addr = ioremap_nocache (pci_resource_start (pdev, 2), - pci_resource_len (pdev, 2)); card->name = dvbm_qo_name; break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE: - card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 3), - pci_resource_len (pdev, 3)); - card->core.addr = ioremap_nocache (pci_resource_start (pdev, 2), - pci_resource_len (pdev, 2)); card->name = dvbm_qoe_name; break; - case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: - card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 2), - pci_resource_len (pdev, 2)); - card->core.addr = ioremap_nocache (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); - card->name = dvbm_lpqoe_name; - break; - case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: - card->bridge_addr = ioremap_nocache (pci_resource_start (pdev, 2), - pci_resource_len (pdev, 2)); - card->core.addr = ioremap_nocache (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); - card->name = dvbm_lpqoe_minibnc_name; - break; } - card->version = readl(card->core.addr + DVBM_QO_FPGAID) & 0xffff; + card->version = readl(card->core.addr + DVBM_QIO_FPGAID) & 0xffff; card->id = pdev->device; card->irq = pdev->irq; card->irq_handler = dvbm_qo_irq_handler; INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_UID; + card->capabilities = MASTER_CAP_BLACKBURST | MASTER_CAP_UID; /* Lock for ICSR[] */ spin_lock_init (&card->irq_lock); spin_lock_init (&card->reg_lock); @@ -197,36 +124,28 @@ dvbm_qo_pci_probe (struct pci_dev *pdev) * in the PCI info structure */ pci_set_drvdata (pdev, card); - switch (pdev->device) { - default: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBQO: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE: - /* PLX */ - p = ioremap_nocache (pci_resource_start (pdev, 0), - pci_resource_len (pdev, 0)); + /* PLX */ + p = ioremap_nocache (pci_resource_start (pdev, 0), + pci_resource_len (pdev, 0)); - /* Reset PCI 9056 */ - plx_reset_bridge(p); + /* Reset PCI 9056 */ + plx_reset_bridge(p); - /* Setup the PCI 9056 */ - writel(PLX_INTCSR_PCIINT_ENABLE | - PLX_INTCSR_PCILOCINT_ENABLE, - p + PLX_INTCSR); + /* Setup the PCI 9056 */ + writel(PLX_INTCSR_PCIINT_ENABLE | + PLX_INTCSR_PCILOCINT_ENABLE, + p + PLX_INTCSR); - /* Dummy read to flush PCI posted wires */ - readl(p + PLX_INTCSR); + /* Dummy read to flush PCI posted wires */ + readl(p + PLX_INTCSR); - /* Unmap PLX */ - iounmap (p); - break; - case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: - case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: - break; - } + /* Unmap PLX */ + iounmap (p); /* Reset the FPGA */ for (i = 0; i < 4; i++) { - writel (DVBM_QO_TCSR_TXRST, card->core.addr + DVBM_QO_TCSR(i)); + writel (DVBM_QIO_TCSR_TXRST, + card->core.addr + DVBM_QIO_TCSR(i)); } /* Setup the LS DMA controller */ @@ -236,8 +155,7 @@ dvbm_qo_pci_probe (struct pci_dev *pdev) for (i = 0; i < 4; i++) { writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION, + LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(i)); } @@ -250,6 +168,14 @@ dvbm_qo_pci_probe (struct pci_dev *pdev) } /* Add device attributes */ + if (card->capabilities & MASTER_CAP_BLACKBURST) { + if ((err = device_create_file (card->dev, + &dev_attr_blackburst_type)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'blackburst_type'\n", + dvbm_driver_name); + } + } if (card->capabilities & MASTER_CAP_UID) { if ((err = device_create_file (card->dev, &dev_attr_uid)) < 0) { @@ -272,8 +198,8 @@ dvbm_qo_pci_probe (struct pci_dev *pdev) &lsdma_dma_ops, 0, MASTER_DIRECTION_TX, - &dvbm_qo_fops, - &dvbm_qo_ops, + &dvbm_qio_txfops, + &dvbm_qio_txops, cap, 4, ASI_CTL_TRANSPORT_DVB_ASI)) < 0) { @@ -290,35 +216,6 @@ NO_PCI: return err; } -/** - * dvbm_qo_pci_remove - PCI removal handler for DVB Master Q/o - * @pdev: PCI device - * - * Handle the removal of a DVB Master Q/o. - * This function may be called during PCI probe error handling, - * so don't mark it as __devexit. - **/ -void dvbm_qo_pci_remove (struct pci_dev *pdev) -{ - struct master_dev *card = pci_get_drvdata (pdev); - - if (card) { - int i; - - /* Unregister the device and all interfaces */ - dvbm_unregister_all (card); - - for (i = 0; i < 4; i++) { - writel(0, card->core.addr + DVBM_QO_ICSR(i)); - } - iounmap (card->core.addr); - iounmap (card->bridge_addr); - kfree (card); - } - dvbm_pci_remove_generic (pdev); - return; -} - /** * dvbm_qo_irq_handler - DVB Master Q/o interrupt service routine * @irq: interrupt number @@ -367,20 +264,20 @@ IRQ_HANDLER (dvbm_qo_irq_handler, irq, dev_id, regs) /* Check and clear the source of the interrupts */ spin_lock (&card->irq_lock); - status = readl (card->core.addr + DVBM_QO_ICSR(i)); - writel (status, card->core.addr + DVBM_QO_ICSR(i)); + status = readl (card->core.addr + DVBM_QIO_ICSR(i)); + writel (status, card->core.addr + DVBM_QIO_ICSR(i)); + spin_unlock (&card->irq_lock); - if (status & DVBM_QO_ICSR_TUIS) { + if (status & DVBM_QIO_ICSR_TXUIS) { set_bit (ASI_EVENT_TX_FIFO_ORDER, &iface->events); interrupting_iface |= 0x1 << i; } - if (status & DVBM_QO_ICSR_TXDIS) { + if (status & DVBM_QIO_ICSR_TXDIS) { set_bit (ASI_EVENT_TX_DATA_ORDER, &iface->events); interrupting_iface |= 0x1 << i; } - spin_unlock (&card->irq_lock); if (interrupting_iface & (0x1 << i)) { wake_up (&iface->queue); @@ -397,312 +294,3 @@ IRQ_HANDLER (dvbm_qo_irq_handler, irq, dev_id, regs) return IRQ_NONE; } -/** - * dvbm_qo_init - Initialize the DVB Master Q/o Transmitter - * @iface: interface - **/ -static void -dvbm_qo_init (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg = iface->null_packets ? DVBM_QO_TCSR_TNP : 0; - - switch (iface->timestamps) { - default: - case ASI_CTL_TSTAMP_NONE: - reg |= 0; - break; - case ASI_CTL_TSTAMP_APPEND: - reg |= DVBM_QO_TCSR_TTSS; - break; - case ASI_CTL_TSTAMP_PREPEND: - reg |= DVBM_QO_TCSR_TPRC; - break; - } - - switch (iface->mode) { - default: - case ASI_CTL_TX_MODE_188: - reg |= DVBM_QO_TCSR_188; - break; - case ASI_CTL_TX_MODE_204: - reg |= DVBM_QO_TCSR_204; - break; - case ASI_CTL_TX_MODE_MAKE204: - reg |= DVBM_QO_TCSR_AUTO; - break; - } - - switch (iface->clksrc) { - default: - case ASI_CTL_TX_CLKSRC_ONBOARD: - reg |= 0; - break; - case ASI_CTL_TX_CLKSRC_EXT: - reg |= DVBM_QO_TCSR_EXTCLK; - break; - } - - /* There will be no races on CSR - * until this code returns, so we don't need to lock it */ - writel (reg | DVBM_QO_TCSR_TXRST, - card->core.addr + DVBM_QO_TCSR(channel)); - wmb(); - writel (reg, card->core.addr + DVBM_QO_TCSR(channel)); - readl (card->core.addr + DVBM_QO_FPGAID); - writel (DVBM_QO_TFSL << 16, card->core.addr + DVBM_QO_TFCR(channel)); - - /* Reset byte counter */ - readl (card->core.addr + DVBM_QO_TXBCOUNT(channel)); - - writel(0, card->core.addr + DVBM_QO_IBSTREG(channel)); - writel(0, card->core.addr + DVBM_QO_IPSTREG(channel)); - writel(0, card->core.addr + DVBM_QO_FTREG(channel)); - - return; -} - -/** - * dvbm_qo_start - Activate the DVB Master Q/o Transmitter - * @iface: interface - **/ -static void -dvbm_qo_start (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Enable DMA */ - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Enable transmitter interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_QO_ICSR(channel)); - reg |= DVBM_QO_ICSR_TUIE | DVBM_QO_ICSR_TXDIE; - writel(reg, card->core.addr + DVBM_QO_ICSR(channel)); - spin_unlock_irq(&card->irq_lock); - - /* Enable the transmitter */ - spin_lock(&card->reg_lock); - reg = readl(card->core.addr + DVBM_QO_TCSR(channel)); - writel(reg | DVBM_QO_TCSR_TXE, - card->core.addr + DVBM_QO_TCSR(channel)); - spin_unlock(&card->reg_lock); - return; -} - -/** - * dvbm_qo_stop - Deactivate the DVB Master Q/O transmitter - * @iface: interface - **/ -static void -dvbm_qo_stop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - struct master_dma *dma = iface->dma; - unsigned int reg; - - lsdma_tx_link_all (dma); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - lsdma_reset (dma); - - if (!iface->null_packets) { - /* Wait for the onboard FIFOs to empty */ - /* Atomic read of ICSR, so we don't need to lock */ - wait_event (iface->queue, - !(readl (card->core.addr + DVBM_QO_ICSR(channel)) & - DVBM_QO_ICSR_TXD)); - } - - /* Disable the Transmitter */ - spin_lock (&card->reg_lock); - reg = readl(card->core.addr + DVBM_QO_TCSR(channel)); - writel (reg & ~DVBM_QO_TCSR_TXE, - card->core.addr + DVBM_QO_TCSR(channel)); - spin_unlock (&card->reg_lock); - - /*Disable Transmitter Interrupts */ - spin_lock_irq (&card->irq_lock); - reg = readl (card->core.addr + DVBM_QO_ICSR(channel)); - reg |= DVBM_QO_ICSR_TUIS | DVBM_QO_ICSR_TXDIS; - writel (reg, card->core.addr + DVBM_QO_ICSR(channel)); - - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP), - card->bridge_addr + LSDMA_CSR(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - udelay (10L); - return; -} - -/** - * dvbm_qo_exit - Clean up the DVB Master Q/o transmitter - * @iface: interface - **/ -static void -dvbm_qo_exit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the transmitter. - * There will be no races on CSR here, - * so we don't need to lock it */ - writel (DVBM_QO_TCSR_TXRST, card->core.addr + DVBM_QO_TCSR(channel)); - - return; -} - -/** - * dvbm_qo_start_tx_dma - start transmit DMA - * @iface: interface - **/ -static void -dvbm_qo_start_tx_dma (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); - writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - return; -} - -/** - * dvbm_qo_unlocked_ioctl - DVB Master Q/o unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -dvbm_qo_unlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct asi_txstuffing stuffing; - const unsigned int channel = mdev_index (card, &iface->list); - - switch (cmd) { - case ASI_IOC_TXSETSTUFFING: - if (iface->transport != ASI_CTL_TRANSPORT_DVB_ASI) { - return -ENOTTY; - } - if (copy_from_user (&stuffing, - (struct asi_txstuffing __user *)arg, - sizeof (stuffing))) { - return -EFAULT; - } - if ((stuffing.ib > 0x00ff) || - (stuffing.ip > 0xffffff) || - (stuffing.normal_ip > 0xff) || - (stuffing.big_ip > 0xff) || - ((stuffing.il_normal + stuffing.il_big) > 0xf) || - (stuffing.il_normal > stuffing.normal_ip) || - (stuffing.il_big > stuffing.big_ip)) { - return -EINVAL; - } - - spin_lock (&card->reg_lock); - writel (stuffing.ib, - card->core.addr + DVBM_QO_IBSTREG(channel)); - writel (stuffing.ip, - card->core.addr + DVBM_QO_IPSTREG(channel)); - writel ((stuffing.il_big << DVBM_QO_FTR_ILBIG_SHIFT) | - (stuffing.big_ip << DVBM_QO_FTR_BIGIP_SHIFT) | - (stuffing.il_normal << DVBM_QO_FTR_ILNORMAL_SHIFT) | - stuffing.normal_ip, - card->core.addr + DVBM_QO_FTREG(channel)); - spin_unlock (&card->reg_lock); - break; - case ASI_IOC_TXGETBYTECOUNT: - if (!(iface->capabilities & ASI_CAP_TX_BYTECOUNTER)) { - return -ENOTTY; - } - if (put_user (readl (card->core.addr + DVBM_QO_TXBCOUNT(channel)), - (unsigned int __user *)arg)) { - return -EFAULT; - } - break; - case ASI_IOC_TXGETTXD: - /* Atomic read of ICSR, so we don't need to lock */ - if (put_user ((readl (card->core.addr + DVBM_QO_ICSR(channel)) - & DVBM_QO_ICSR_TXD) ? 1 : 0, - (int __user *)arg)) { - return -EFAULT; - } - break; - default: - return asi_txioctl (filp, cmd, arg); - } - - return 0; -} - -/** - * dvbm_qo_fsync - DVB Master Q/o fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -dvbm_qo_fsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - struct master_dma *dma = iface->dma; - const unsigned int channel = mdev_index (card, &iface->list); - - mutex_lock (&iface->buf_mutex); - - lsdma_tx_link_all(dma); - wait_event(iface->queue, test_bit(0, &iface->dma_done)); - lsdma_reset(dma); - - if (!iface->null_packets) - { - /* Wait for the onboard FIFOs to empty */ - /* Atomic read of ICSR, so we don't need to lock */ - wait_event(iface->queue, - !(readl(card->core.addr + DVBM_QO_ICSR(channel)) - & DVBM_QO_ICSR_TXD)); - } - - mutex_unlock (&iface->buf_mutex); - - return 0; -} - diff --git a/quad/src/dvbm_qo.h b/quad/src/dvbm_qo.h deleted file mode 100755 index c5ec68ea6..000000000 --- a/quad/src/dvbm_qo.h +++ /dev/null @@ -1,108 +0,0 @@ -/* dvbm_qo.h - * - * Header file for the Linear Systems Ltd. DVB Master Q/o. - * - * Copyright (C) 2006-2010 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _DVBM_QO_H -#define _DVBM_QO_H - -#include /* pci_dev */ -#include /* __devinit */ - -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQO 0x007C -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE 0x0085 -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE 0x0095 -#define DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC 0x00AC - -#define DVBM_NAME_QO "DVB Master Q/o" -#define DVBM_NAME_QOE "DVB Master Q/o PCIe" -#define DVBM_NAME_LPQOE "DVB Master Q/o LP PCIe" -#define DVBM_NAME_LPQOE_MINIBNC "DVB Master Q/o LP PCIe Mini BNC" - -#define DVBM_QO_TFSL 0x200 /* FIFO start level */ - -/* Register addresses */ -#define DVBM_QO_FIFO(c) ((c)*0x100+0x000) /* FIFO */ -#define DVBM_QO_CSR(c) ((c)*0x100+0x004) /* Control/Status */ -#define DVBM_QO_DMATLR(c) ((c)*0x100+0x008) /* Receive FIFO control */ -#define DVBM_QO_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ -#define DVBM_QO_ICSR(c) ((c)*0x100+0x010) /* Int. Control/Status */ -#define DVBM_QO_FTREG(c) ((c)*0x100+0x084) /* Fine Tuning */ -#define DVBM_QO_TXBCOUNT(c) ((c)*0x100+0x088) /* Transmit Byte Counter */ -#define DVBM_QO_TCSR(c) ((c)*0x100+0x08c) /* Transmit Control and Status */ -#define DVBM_QO_IBSTREG(c) ((c)*0x100+0x090) /* Interbyte Stuffing */ -#define DVBM_QO_IPSTREG(c) ((c)*0x100+0x094) /* Interpacket stuffing */ -#define DVBM_QO_TFCR(c) ((c)*0x100+0x098) /* Transmit FIFO Control */ -#define DVBM_QO_TPIDR(c) ((c)*0x100+0x09c) /* Transmit PID */ -#define DVBM_QO_TPCRR_HI(c) ((c)*0x100+0x0a0) /* Transmit PCR, High Dword */ -#define DVBM_QO_TPCRR_LO(c) ((c)*0x100+0x0a4) /* Transmit PCR, Low Dword */ -#define DVBM_QO_TSTAMPR_HI(c) ((c)*0x100+0x0a8) /* Transmit Timestamp, High Dword */ -#define DVBM_QO_TSTAMPR_LO(c) ((c)*0x100+0x0ac) /* Transmit Timestamp, Low Dword */ -#define DVBM_QO_FPGAID 0x400 /* FPGA ID */ -#define DVBM_QO_HL2CSR 0x404 /* HOTLink II Control and status */ -#define DVBM_QO_27COUNTR 0x408 /* 27 MHz Counter */ -#define DVBM_QO_SSN_HI 0x40c /* Silicon serial number, High */ -#define DVBM_QO_SSN_LO 0x410 /* Silicon serial number, low */ -#define DVBM_QO_ASMIR 0x414 /* ASMI */ -#define DVBM_QO_JTAGR 0x414 /* JTAG */ - -/* Int. Control/Status Register bit locations */ -#define DVBM_QO_ICSR_TUIE 0x00000001 /* Transmit Underrun Interrupt Enable */ -#define DVBM_QO_ICSR_TXDIE 0x00000040 /* Transmit Data Interrupt Enable */ -#define DVBM_QO_ICSR_TU 0x00000100 /* Transmit Underrun Status */ -#define DVBM_QO_ICSR_TXD 0x00004000 /* Bit goes high when 1st byte of data is transmitted */ -#define DVBM_QO_ICSR_TUIS 0x00010000 /* Transmitter Underrun Interrupt Status */ -#define DVBM_QO_ICSR_TXDIS 0x00400000 /* Transmit Data Interrupt Status */ -#define DVBM_QO_ICSR_PMS 0x04000000 /* Packet Maturity Status */ -#define DVBM_QO_ICSR_NOSIG 0x08000000 /* No Signal */ - -/* Interrupt Control/Status Register bitmasks */ -#define DVBM_QO_ICSR_ISMASK 0x007f0000 /* Interrupt Status BitMask */ -#define DVBM_QO_ICSR_IEMASK 0x0000007f /* Interrupt Enable BitMask */ - -/* Transmitter Control/Status Register (TCSR) bit locations */ -#define DVBM_QO_TCSR_TXMODE 0x00000003 /* Tx Mode */ -#define DVBM_QO_TCSR_TXE 0x00000010 /* Tx Enable */ -#define DVBM_QO_TCSR_TXRST 0x00000020 /* Tx Reset */ -#define DVBM_QO_TCSR_EXTCLK 0x00000040 /* External Clock */ -#define DVBM_QO_TCSR_TTSS 0x00000100 /* Transmit Timestamp Strip */ -#define DVBM_QO_TCSR_TNP 0x00000200 /* Transmit Null Packet */ -#define DVBM_QO_TCSR_TPRC 0x00000400 /* Transmit Packet Release Control */ -#define DVBM_QO_TCSR_PLLFS 0x00002000 /* PLL Frequency Select */ - -/* Control/Status Register bitmasks */ -#define DVBM_QO_TCSR_204MAKE188 0x00000005 /* Sync. 204 Make 188 */ -#define DVBM_QO_TCSR_AUTO 0x2 /* Sync. Auto */ -#define DVBM_QO_TCSR_204 0x1 /* Sync. 204 */ -#define DVBM_QO_TCSR_188 0x0 /* Sync. 188 */ - -#define DVBM_QO_FTR_ILBIG_SHIFT 24 -#define DVBM_QO_FTR_BIGIP_SHIFT 16 -#define DVBM_QO_FTR_ILNORMAL_SHIFT 8 - -/* External function prototypes */ - -int dvbm_qo_pci_probe (struct pci_dev *pdev) __devinit; -void dvbm_qo_pci_remove (struct pci_dev *pdev); - -#endif - diff --git a/quad/src/dvbm_rx.c b/quad/src/dvbm_rx.c old mode 100755 new mode 100644 index 000159a19..c2f375a3f --- a/quad/src/dvbm_rx.c +++ b/quad/src/dvbm_rx.c @@ -58,9 +58,7 @@ static void dvbm_rx_stop (struct master_iface *iface); static long dvbm_rx_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_rx_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_rx_fsync,filp,datasync); static struct file_operations dvbm_rx_fops = { .owner = THIS_MODULE, @@ -68,7 +66,7 @@ static struct file_operations dvbm_rx_fops = { .read = asi_read, .poll = asi_rxpoll, .unlocked_ioctl = dvbm_rx_unlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_rx_unlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_rx_fsync, @@ -615,15 +613,12 @@ dvbm_rx_unlocked_ioctl (struct file *filp, /** * dvbm_rx_fsync - DVB Master Receive fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_rx_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_rx_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/dvbm_rx.h b/quad/src/dvbm_rx.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_rxu.c b/quad/src/dvbm_rxu.c old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_tx.c b/quad/src/dvbm_tx.c old mode 100755 new mode 100644 index 4d4d2f871..5e0334d07 --- a/quad/src/dvbm_tx.c +++ b/quad/src/dvbm_tx.c @@ -60,9 +60,7 @@ static void dvbm_tx_start_tx_dma (struct master_iface *iface); static long dvbm_tx_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int dvbm_tx_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(dvbm_tx_fsync,filp,datasync); static struct file_operations dvbm_tx_fops = { .owner = THIS_MODULE, @@ -70,7 +68,7 @@ static struct file_operations dvbm_tx_fops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = dvbm_tx_unlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = dvbm_tx_unlocked_ioctl, .open = asi_open, .release = asi_release, .fsync = dvbm_tx_fsync, @@ -485,15 +483,12 @@ dvbm_tx_unlocked_ioctl (struct file *filp, /** * dvbm_tx_fsync - DVB Master Send fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -dvbm_tx_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(dvbm_tx_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dma *dma = iface->dma; diff --git a/quad/src/dvbm_tx.h b/quad/src/dvbm_tx.h old mode 100755 new mode 100644 diff --git a/quad/src/dvbm_txu.c b/quad/src/dvbm_txu.c old mode 100755 new mode 100644 diff --git a/quad/src/dvbmaster.c b/quad/src/dvbmaster.c old mode 100755 new mode 100644 index 802941e5f..4e5968db3 --- a/quad/src/dvbmaster.c +++ b/quad/src/dvbmaster.c @@ -44,10 +44,9 @@ #include "dvbm_lpfd.h" #include "dvbm_qlf.h" #include "dvbm_qi.h" -#include "dvbm_qo.h" +#include "dvbm_qio.h" +#include "dvbm_lpqo.h" #include "dvbm_qdual.h" -#include "dvbm_q3ioe.h" -#include "dvbm_q3inoe.h" #ifndef DEFINE_PCI_DEVICE_TABLE #define DEFINE_PCI_DEVICE_TABLE(_table) \ @@ -381,9 +380,10 @@ dvbm_pci_probe (struct pci_dev *pdev, return dvbm_qi_pci_probe (pdev); case DVBM_PCI_DEVICE_ID_LINSYS_DVBQO: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE: + return dvbm_qo_pci_probe (pdev); case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: - return dvbm_qo_pci_probe (pdev); + return dvbm_lpqo_pci_probe (pdev); case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUAL: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUALE: case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQDUALE: @@ -484,9 +484,11 @@ dvbm_pci_remove (struct pci_dev *pdev) break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBQO: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQOE: + dvbm_qo_pci_remove (pdev); + break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: - dvbm_qo_pci_remove (pdev); + dvbm_lpqo_pci_remove (pdev); break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUAL: case DVBM_PCI_DEVICE_ID_LINSYS_DVBQDUALE: diff --git a/quad/src/eeprom.c b/quad/src/eeprom.c old mode 100755 new mode 100644 diff --git a/quad/src/eeprom.h b/quad/src/eeprom.h old mode 100755 new mode 100644 diff --git a/quad/src/gt64131.c b/quad/src/gt64131.c old mode 100755 new mode 100644 diff --git a/quad/src/gt64131.h b/quad/src/gt64131.h old mode 100755 new mode 100644 diff --git a/quad/src/hdsdi_qie.c b/quad/src/hdsdi_qie.c deleted file mode 100755 index dd62a0a52..000000000 --- a/quad/src/hdsdi_qie.c +++ /dev/null @@ -1,783 +0,0 @@ -/* hdsdi_qi.c - * - * Linux driver functions for Linear Systems Ltd. SDI Master Q/i. - * - * Copyright (C) 2007-2008 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#include /* KERN_INFO */ -#include /* THIS_MODULE */ - -#include /* inode, file, file_operations */ -#include /* pt_regs */ -#include /* pci_dev */ -#include /* kmalloc () */ -#include /* INIT_LIST_HEAD () */ -#include /* spin_lock_init () */ -#include /* __devinit */ -#include /* error codes */ -#include /* irqreturn_t */ -#include /* class_device_create_file () */ - -#include /* sema_init () */ -#include /* put_user () */ -#include /* set_bit () */ - -#include "sdicore.h" -#include "sdim.h" -#include "../include/master.h" -#include "miface.h" -//Temporary fix for kernel 2.6.21 -#include "mdev.c" -//Temporary fix for kernel 2.6.21 -#include "lsdma.h" -//Temporary fix for kernel 2.6.21 -#include "masterlsdma.c" -#include "hdsdi_qie.h" - -#ifndef list_for_each_safe -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) -#endif - -static const char hdsdi_qi_name[] = HDSDI_NAME; - -/* Static function prototypes */ -static ssize_t hdsdi_qi_show_uid (struct class_device *cd, char *buf); -static int hdsdi_qi_pci_probe (struct pci_dev *dev, - const struct pci_device_id *id) __devinit; -static void hdsdi_qi_pci_remove (struct pci_dev *dev); -static irqreturn_t IRQ_HANDLER(hdsdi_qi_irq_handler,irq,dev_id,regs); -static void hdsdi_qi_init (struct master_iface *iface); -static void hdsdi_qi_start (struct master_iface *iface); -static void hdsdi_qi_stop (struct master_iface *iface); -static void hdsdi_qi_exit (struct master_iface *iface); -static int hdsdi_qi_open (struct inode *inode, struct file *filp); -static long hdsdi_qi_unlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); -static int hdsdi_qi_ioctl (struct inode *inode, - struct file *filp, - unsigned int cmd, - unsigned long arg); -static int hdsdi_qi_fsync (struct file *filp, - struct dentry *dentry, - int datasync); -static int hdsdi_qi_release (struct inode *inode, struct file *filp); -static int hdsdi_qi_init_module (void) __init; -static void hdsdi_qi_cleanup_module (void) __exit; - -MODULE_AUTHOR("Linear Systems Ltd."); -MODULE_DESCRIPTION("HD-SDI Q/i Driver"); -MODULE_LICENSE("GPL"); - -#ifdef MODULE_VERSION -MODULE_VERSION(MASTER_DRIVER_VERSION); -#endif - -static char hdsdi_driver_name[] = "hdsdiqi"; - -static struct pci_device_id hdsdi_pci_id_table[] = { - { - PCI_DEVICE(MASTER_PCI_VENDOR_ID_LINSYS, - HDSDI_PCI_DEVICE_ID_LINSYS) - }, - {0, } -}; - -static struct pci_driver hdsdi_pci_driver = { - .name = hdsdi_driver_name, - .id_table = hdsdi_pci_id_table, - .probe = hdsdi_qi_pci_probe, - .remove = hdsdi_qi_pci_remove -}; - -struct file_operations hdsdi_qi_rxfops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = masterlsdma_read, - .poll = masterlsdma_rxpoll, - .ioctl = hdsdi_qi_ioctl, -#ifdef HAVE_UNLOCKED_IOCTL - .unlocked_ioctl = hdsdi_qi_unlocked_ioctl, -#endif -#ifdef HAVE_COMPAT_IOCTL - .compat_ioctl = sdi_compat_ioctl, -#endif - .mmap = masterlsdma_mmap, - .open = hdsdi_qi_open, - .release = hdsdi_qi_release, - .fsync = hdsdi_qi_fsync, - .fasync = NULL -}; - -MODULE_DEVICE_TABLE(pci, hdsdi_pci_id_table); -static LIST_HEAD(hdsdi_card_list); - -static struct class hdsdi_class = { - .name = hdsdi_driver_name, - .release = mdev_class_device_release, - .class_release = NULL -}; - -/** - * hdsdi_qi_show_uid - interface attribute read handler - * @cd: class_device being read - * @buf: output buffer - **/ -static ssize_t -hdsdi_qi_show_uid (struct class_device *cd, - char *buf) -{ - struct master_dev *card = to_master_dev(cd); - - return snprintf (buf, PAGE_SIZE, "0x%08X%08X\n", - master_readl (card, HDSDI_QI_UIDR_HI), - master_readl (card, HDSDI_QI_UIDR_LO)); -} - -static CLASS_DEVICE_ATTR(uid,S_IRUGO, - hdsdi_qi_show_uid,NULL); - -/** - * hdsdi_pci_probe - PCI insertion handler for a SDI Master Q/i - * @dev: PCI device - * - * Handle the insertion of a SDI Master Q/i. - * Returns a negative error code on failure and 0 on success. - **/ -int __devinit -hdsdi_qi_pci_probe (struct pci_dev *dev, - const struct pci_device_id *id) -{ - - int err; - unsigned int i; - //unsigned int cap; - const char *name; - struct master_dev *card; - - switch (dev->device) { - case HDSDI_PCI_DEVICE_ID_LINSYS: - name = hdsdi_qi_name; - break; - default: - name = ""; - break; - } - - /* Store the pointer to the board info structure - * in the PCI info structure */ - pci_set_drvdata (dev, NULL); - - /* Wake a sleeping device */ - if ((err = pci_enable_device (dev)) < 0) { - printk (KERN_WARNING "%s: unable to enable device\n", - hdsdi_driver_name); - goto NO_PCI; - } - - /* Enable bus mastering */ - pci_set_master (dev); - - /* Request the PCI I/O resources */ - if ((err = pci_request_regions (dev, hdsdi_driver_name)) < 0) { - goto NO_PCI; - } - - /* Allocate a board info structure */ - if ((card = (struct master_dev *) - kmalloc (sizeof (*card), GFP_KERNEL)) == NULL) { - err = -ENOMEM; - goto NO_MEM; - } - - /* Initialize the board info structure */ - memset (card, 0, sizeof (*card)); - /* PLX 9056 */ - card->bridge_addr = ioremap_nocache (pci_resource_start (dev, 0), - pci_resource_len (dev, 0)); - /* SDI Core */ - card->core.addr = ioremap_nocache (pci_resource_start (dev, 0), - pci_resource_len (dev, 0)); - card->version = master_readl (card, HDSDI_QI_FPGAID) & 0xffff; - card->name = hdsdi_qi_name; - card->irq_handler = hdsdi_qi_irq_handler; - INIT_LIST_HEAD(&card->iface_list); - card->capabilities = MASTER_CAP_UID; - - - /* Lock for LSDMA_CSR, ICSR */ - spin_lock_init (&card->irq_lock); - /* Lock for PFLUT, RCR */ - spin_lock_init (&card->reg_lock); - sema_init (&card->users_sem, 1); - card->pdev = dev; - - /* Print the firmware version */ - printk (KERN_INFO "%s: %s detected, firmware version %u.%u (0x%04X)\n", - hdsdi_driver_name, name, - card->version >> 8, card->version & 0x00ff, card->version); - pci_set_drvdata (dev, card); - - /* Remap bridge address to the DMA controller */ - iounmap (card->bridge_addr); - /* LS DMA Controller */ - card->bridge_addr = ioremap_nocache (pci_resource_start (dev, 2), - pci_resource_len (dev, 2)); - /* Reset the FPGA */ - for (i = 0; i < 4; i++) { - master_writel (card, HDSDI_QI_RCSR(i), HDSDI_QI_RCSR_RST); - } - - /* Setup the LS DMA controller */ - writel (LSDMA_INTMSK_CH(0) | LSDMA_INTMSK_CH(1) | - LSDMA_INTMSK_CH(2) | LSDMA_INTMSK_CH(3), - card->bridge_addr + LSDMA_INTMSK); - for (i = 0; i < 4; i++) { - writel (LSDMA_CH_CSR_INTDONEENABLE | - LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION, - card->bridge_addr + LSDMA_CSR(i)); - } - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - - /* Register a Master device */ - if ((err = mdev_register (card, - &hdsdi_card_list, - hdsdi_driver_name, - &hdsdi_class)) < 0) { - goto NO_DEV; - } - - /* Add class_device attributes */ - if (card->capabilities & MASTER_CAP_UID) { - if ((err = class_device_create_file (&card->class_dev, - &class_device_attr_uid)) < 0) { - printk (KERN_WARNING - "%s: Unable to create file 'uid'\n", - hdsdi_driver_name); - } - } - - /* Register receiver interfaces */ - /* - if (card->version >= 0x0042) { //debug: double check this - cap = SDI_CAP_RX_27COUNTER | SDI_CAP_RX_TIMESTAMP ; //debug - } - */ - - for (i = 0; i < 4; i++) { - if ((err = sdi_register_iface (card, - MASTER_DIRECTION_RX, - &hdsdi_qi_rxfops, - 0, - 4)) < 0) { - goto NO_IFACE; - } - } - - return 0; - -NO_IFACE: - hdsdi_qi_pci_remove (dev); -NO_DEV: -NO_MEM: -NO_PCI: - return err; -} - -/** - * hdsdi_pci_remove - PCI removal handler for a SDI Master Q/i. - * @card: Master device - * - * Handle the removal of a SDI Master Q/i. - **/ -void -hdsdi_qi_pci_remove (struct pci_dev *dev) -{ - struct master_dev *card = pci_get_drvdata (dev); - - if (card) { - struct list_head *p, *n; - struct master_iface *iface; - - list_for_each_safe (p, n, &card->iface_list) { - iface = list_entry (p, struct master_iface, list); - sdi_unregister_iface (iface); - } - iounmap (card->core.addr); - iounmap (card->bridge_addr); - - list_for_each (p, &hdsdi_card_list) { - if (p == &card->list) { - mdev_unregister (card); - break; - } - } - pci_set_drvdata (dev, NULL); - } - pci_release_regions (dev); - pci_disable_device (dev); - - return; -} - -/** - * hdsdi_qi_irq_handler - SDI Master Q/i interrupt service routine - * @irq: interrupt number - * @dev_id: pointer to the device data structure - * @regs: processor context - **/ -static irqreturn_t -IRQ_HANDLER(hdsdi_qi_irq_handler,irq,dev_id,regs) -{ - struct master_dev *card = dev_id; - struct list_head *p = &card->iface_list; - struct master_iface *iface; - unsigned int dmaintsrc = readl (card->bridge_addr + LSDMA_INTSRC); - unsigned int status, interrupting_iface = 0, i; - - for (i = 0; i < 4; i++) { - p = p->next; - iface = list_entry (p, struct master_iface, list); - - /* Clear DMA interrupts */ - if (dmaintsrc & LSDMA_INTSRC_CH(i)) { - /* Read the interrupt type and clear it */ - spin_lock (&card->irq_lock); - status = readl (card->bridge_addr + LSDMA_CSR(i)); - writel (status, card->bridge_addr + LSDMA_CSR(i)); - spin_unlock (&card->irq_lock); - /* Increment the buffer pointer */ - if (status & LSDMA_CH_CSR_INTSRCBUFFER) { - lsdma_advance (iface->dma); - if (lsdma_rx_isempty (iface->dma)) { - set_bit (SDI_EVENT_RX_BUFFER_ORDER, - &iface->events); - } - } - - /* Flag end-of-chain */ - if (status & LSDMA_CH_CSR_INTSRCDONE) { - set_bit (0, &iface->dma_done); - } - - /* Flag DMA abort */ - if (status & LSDMA_CH_CSR_INTSRCSTOP) { - set_bit (0, &iface->dma_done); - } - - interrupting_iface |= (0x1 << i); - } - - /* Clear SDI interrupts */ - spin_lock (&card->irq_lock); - status = master_readl (card, HDSDI_QI_ICSR(i)); - writel (status, card->core.addr + HDSDI_QI_ICSR(i)); - spin_unlock (&card->irq_lock); - if (status & HDSDI_QI_ICSR_CDIS) { - set_bit (SDI_EVENT_RX_CARRIER_ORDER, - &iface->events); - interrupting_iface |= (0x1 << i); - } - if (status & HDSDI_QI_ICSR_ROIS) { - set_bit (SDI_EVENT_RX_FIFO_ORDER, - &iface->events); - interrupting_iface |= (0x1 << i); - } - if (interrupting_iface & (0x1 << i)) { - wake_up (&iface->queue); - } - } - - if (interrupting_iface) { - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/** - * hdsdi_qi_init - Initialize a SDI Master Q/i receiver - * @iface: interface - **/ -static void -hdsdi_qi_init (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg = 0; - - switch (iface->mode) { - default: - case HDSDI_QI_RCSR_MODE_RAW: - reg |= 0; - break; - case HDSDI_QI_RCSR_MODE_SYNC: - reg |= HDSDI_QI_RCSR_MODE_SYNC; - break; - case HDSDI_QI_RCSR_MODE_DEINTERLACE: - reg |= HDSDI_QI_RCSR_MODE_DEINTERLACE; - break; - } -/* - switch (iface->standard) { - default: - case HDSDI_QI_STD_260M_1035i: - reg |= 0; - printk ("Detected HDSDI_QI_STD_260M_1035i\n"); - break; - case HDSDI_QI_STD_295M_1080i: - reg |= HDSDI_QI_STD_295M_1080i; - printk ("Detected HDSDI_QI_STD_295M_1080i\n"); - break; - case HDSDI_QI_STD_274M_1080i: - reg |= HDSDI_QI_STD_274M_1080i; - printk ("Detected HDSDI_QI_STD_274M_1080i\n"); - break; - case HDSDI_QI_STD_274M_1080i_25HZ: - reg |= HDSDI_QI_STD_274M_1080i_25HZ; - printk ("Detected HDSDI_QI_STD_274M_1080i_25HZ\n"); - break; - case HDSDI_QI_STD_274M_1080p: - reg |= HDSDI_QI_STD_274M_1080p; - printk ("Detected HDSDI_QI_STD_274M_1080p\n"); - break; - case HDSDI_QI_STD_274M_1080p_25HZ: - reg |= HDSDI_QI_STD_274M_1080p_25HZ; - printk ("Detected HDSDI_QI_STD_274M_1080p_25HZ\n"); - break; - case HDSDI_QI_STD_274M_1080p_24HZ: - reg |= HDSDI_QI_STD_274M_1080p_24HZ; - printk ("Detected HDSDI_QI_STD_274M_1080p_24HZ\n"); - break; - case HDSDI_QI_STD_296M_720p: - reg |= HDSDI_QI_STD_296M_720p; - printk ("Detected HDSDI_QI_STD_296M_720p\n"); - break; - case HDSDI_QI_STD_274M_1080sf: - reg |= HDSDI_QI_STD_274M_1080sf; - printk ("Detected HDSDI_QI_STD_274M_1080sf\n"); - break; - case HDSDI_QI_STD_296M_720p_50HZ: - reg |= HDSDI_QI_STD_296M_720p_50HZ; - printk ("Detected HDSDI_QI_STD_296M_720p_50HZ\n"); - break; - } -*/ - - /* There will be no races on RCR - * until this code returns, so we don't need to lock it */ - writel (reg | HDSDI_QI_RCSR_RST, card->core.addr + HDSDI_QI_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + HDSDI_QI_RCSR(channel)); - wmb (); - writel(HDSDI_QI_RDMATL, card->core.addr + HDSDI_QI_RDMATLR(channel)); - - return; -} - -/** - * hdsdi_qi_start - Activate the SDI Master Q/i receiver - * @iface: interface - **/ -static void -hdsdi_qi_start (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Enable and start DMA */ - writel (lsdma_dma_to_desc_low (lsdma_head_desc_bus_addr (iface->dma)), - card->bridge_addr + LSDMA_DESC(channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - - /* Enable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - writel (HDSDI_QI_ICSR_CDIE | HDSDI_QI_ICSR_ROIE | - HDSDI_QI_ICSR_RXDIE, card->core.addr + HDSDI_QI_ICSR(channel)); - spin_unlock_irq (&card->irq_lock); - - /* Enable the receiver */ - spin_lock (&card->reg_lock); - reg = master_readl (card, HDSDI_QI_RCSR(channel)); - writel (reg | HDSDI_QI_RCSR_RXE | 0x10000000, card->core.addr + HDSDI_QI_RCSR(channel)); - spin_unlock (&card->reg_lock); - - return; -} - -/** - * hdsdi_qi_stop - Deactivate the SDI Master Q/i receiver - * @iface: interface - **/ -static void -hdsdi_qi_stop (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - /* Disable the receiver */ - spin_lock (&card->reg_lock); - reg = master_readl (card, HDSDI_QI_RCSR(channel)); - writel (reg & ~HDSDI_QI_RCSR_RXE, card->core.addr + HDSDI_QI_RCSR(channel)); - spin_unlock (&card->reg_lock); - - /* Disable receiver interrupts */ - spin_lock_irq (&card->irq_lock); - writel (HDSDI_QI_ICSR_CDIS | HDSDI_QI_ICSR_ROIS | - HDSDI_QI_ICSR_RXDIS, card->core.addr + HDSDI_QI_ICSR(channel)); - - /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); - wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - - return; -} - -/** - * hdsdi_qi_exit - Clean up the SDI Master Q/i receiver - * @iface: interface - **/ -static void -hdsdi_qi_exit (struct master_iface *iface) -{ - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - /* Reset the receiver. - * There will be no races on RCR here, - * so we don't need to lock it */ - writel (HDSDI_QI_RCSR_RST, card->core.addr + HDSDI_QI_RCSR(channel)); - - return; -} - -/** - * hdsdi_qi_open - SDI Master Q/i receiver open() method - * @inode: inode - * @filp: file - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -hdsdi_qi_open (struct inode *inode, struct file *filp) -{ - - return masterlsdma_open (inode, - filp, - hdsdi_qi_init, - hdsdi_qi_start, - 0, - LSDMA_MMAP); -} - -/** - * hdsdi_qi_unlocked_ioctl - SDI Master Q/i receiver unlocked_ioctl() method - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static long -hdsdi_qi_unlocked_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - - switch (cmd) { - case SDI_IOC_RXGETBUFLEVEL: - if (put_user (lsdma_rx_buflevel (iface->dma), - (unsigned int *)arg)) { - return -EFAULT; - } - break; - case SDI_IOC_RXGETSTATUS: - /* We don't lock since this should be an atomic read */ - if (put_user ((master_readl (card, HDSDI_QI_ICSR(channel)) & - HDSDI_QI_ICSR_RXPASSING) ? 1 : 0, (int *)arg)) { - return -EFAULT; - } - break; - case SDI_IOC_RXGETCARRIER: - /* We don't lock since this should be an atomic read */ - if (put_user ((master_readl (card, HDSDI_QI_ICSR(channel)) & - HDSDI_QI_ICSR_CD) ? 1 : 0, (int *)arg)) { - return -EFAULT; - } - break; - case SDI_IOC_QBUF: - return masterlsdma_rxqbuf (filp, arg); - case SDI_IOC_DQBUF: - return masterlsdma_rxdqbuf (filp, arg); - case SDI_IOC_RXGET27COUNT: - if (put_user (master_readl (card, HDSDI_QI_CNT27), - (unsigned int *)arg)) { - return -EFAULT; - } - break; - case SDI_IOC_RXGETTIMESTAMP: - if (put_user ((master_readl (card, HDSDI_QI_CFAT(channel))), - (unsigned int *)arg)) { - return -EFAULT; - } - break; - default: - return sdi_rxioctl (iface, cmd, arg); - } - - return 0; -} - -/** - * hdsdi_qi_ioctl - HD-SDI Master Q/i ioctl() method - * @inode: inode - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -hdsdi_qi_ioctl (struct inode *inode, - struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - return hdsdi_qi_unlocked_ioctl (filp, cmd, arg); -} - -/** - * hdsdi_qi_fsync - SDI Master Q/i receiver fsync() method - * @filp: file to flush - * @dentry: directory entry associated with the file - * @datasync: used by filesystems - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -hdsdi_qi_fsync (struct file *filp, - struct dentry *dentry, - int datasync) -{ - struct master_iface *iface = filp->private_data; - struct master_dev *card = iface->card; - const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - - /* Stop the receiver */ - hdsdi_qi_stop (iface); - - /* Reset the onboard FIFO and driver buffers */ - spin_lock (&card->reg_lock); - reg = master_readl (card, HDSDI_QI_RCSR(channel)); - writel (reg | HDSDI_QI_RCSR_RST, card->core.addr + HDSDI_QI_RCSR(channel)); - wmb (); - writel (reg, card->core.addr + HDSDI_QI_RCSR(channel)); - spin_unlock (&card->reg_lock); - iface->events = 0; - lsdma_reset (iface->dma); - - /* Start the receiver */ - hdsdi_qi_start (iface); - - up (&iface->buf_sem); - return 0; -} - -/** - * hdsdi_qi_release - SDI Master Q/i receiver release() method - * @inode: inode - * @filp: file - * - * Returns a negative error code on failure and 0 on success. - **/ -static int -hdsdi_qi_release (struct inode *inode, struct file *filp) -{ - struct master_iface *iface = filp->private_data; - - return masterlsdma_release (iface, hdsdi_qi_stop, hdsdi_qi_exit); -} - -/** - * hdsdi_qi_init_module - register the module as a PCI driver - * - * Returns a negative error code on failure and 0 on success. - **/ -static int __init -hdsdi_qi_init_module (void) -{ - printk (KERN_INFO "%s: Linear Systems Ltd. " - "HD-SDI Master driver from master-%s (%s)\n", - hdsdi_driver_name, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); - - return mdev_init_module (&hdsdi_pci_driver, - &hdsdi_class, - hdsdi_driver_name); -} - -/** - * hdsdi_qi_cleanup_module - unregister the module as a PCI driver - **/ -static void __exit -hdsdi_qi_cleanup_module (void) -{ - mdev_cleanup_module (&hdsdi_pci_driver, &hdsdi_class); - - return; -} - -module_init (hdsdi_qi_init_module); -module_exit (hdsdi_qi_cleanup_module); diff --git a/quad/src/hdsdi_qie.h b/quad/src/hdsdi_qie.h deleted file mode 100755 index 769cf4c06..000000000 --- a/quad/src/hdsdi_qie.h +++ /dev/null @@ -1,85 +0,0 @@ -/* hdsdi_qie.h - * - * Header file for the Linear Systems Ltd. SDI Master Q/i card. - * - * Copyright (C) 2007-2008 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _HDSDI_QI_H -#define _HDSDI_QI_H - -#define HDSDI_PCI_DEVICE_ID_LINSYS 0x00B6 -#define HDSDI_NAME "HD-SDI Q/i" - -/* HD-SDI configuration */ -#define HDSDI_QI_RCSR(c) ((c)*0x100+0x004) /* Receiver Control and Status Register */ -#define HDSDI_QI_RDMATLR(c) ((c)*0x100+0x008) /* Receiver FIFO Control */ -#define HDSDI_QI_FSR(c) ((c)*0x100+0x00c) /* FIFO Status */ -#define HDSDI_QI_ICSR(c) ((c)*0x100+0x010) /* Interrupt Control and Status */ -#define HDSDI_QI_CFAT(c) ((c)*0x100+0x028) /* Current Frame Arrival Timestamp */ - -#define HDSDI_QI_FPGAID 0x400 /* FPGA ID */ -#define HDSDI_QI_CSR 0x404 /* Channel CSR */ -#define HDSDI_QI_UIDR_HI 0x40c /* Unique ID, High Dword */ -#define HDSDI_QI_UIDR_LO 0x410 /* Unique ID, Low Dword */ -#define HDSDI_QI_ASMIR 0x414 /* ASMI */ -#define HDSDI_QI_JTAG 0x414 /* JTAG Control */ -#define HDSDI_QI_CNT27 0x408 /* 27 MHz Counter */ - -/* HD-SDI Receiver Control and Status */ -#define HDSDI_QI_RCSR_RXE 0x00000010 /* Receiver Enable */ -#define HDSDI_QI_RCSR_RST 0x00000020 /* Receiver Reset */ -#define HDSDI_QI_RCSR_STD 0xF0000000 /* Video Standard */ - -/* SMPTE Standard Formats */ -#define HDSDI_QI_STD_260M_1035i 0x00000000 /* SMPTE 260M 1035i 30 Hz */ -#define HDSDI_QI_STD_295M_1080i 0x10000000 /* SMPTE 295M 1080i 25 Hz */ -#define HDSDI_QI_STD_274M_1080i 0x20000000 /* SMPTE 274M 1080i or 1080sF 30 Hz*/ -#define HDSDI_QI_STD_274M_1080i_25HZ 0x30000000 /* SMPTE 274M 1080i or 1080sF 25 Hz */ -#define HDSDI_QI_STD_274M_1080p 0x40000000 /* SMPTE 274M 1080p 30 Hz*/ -#define HDSDI_QI_STD_274M_1080p_25HZ 0x50000000 /* SMPTE 274M 1080p 25 Hz */ -#define HDSDI_QI_STD_274M_1080p_24HZ 0x60000000 /* SMPTE 274M 1080p 24 Hz */ -#define HDSDI_QI_STD_296M_720p 0x70000000 /* SMPTE 296M 720p 60 Hz */ -#define HDSDI_QI_STD_274M_1080sf 0x80000000 /* SMPTE 274M 1080sF 24 Hz */ -#define HDSDI_QI_STD_296M_720p_50HZ 0x90000000 /* SMPTE 296M 720p 50 Hz */ - -/* HD-SDI RCSR Modes */ -#define HDSDI_QI_RCSR_MODE_RAW 0x00 /* WYSIWYG Transparent Mode (Raw mode) */ -#define HDSDI_QI_RCSR_MODE_SYNC 0x01 /* Synchronization Mode */ -#define HDSDI_QI_RCSR_MODE_DEINTERLACE 0x02 /* De-interlacing mode */ - -/* HD-SDI Receive FIFO Control */ -#define HDSDI_QI_RDMATL 0x080 /* Receiver DMA Trigger Level */ - -/* Interrupt Control and Status */ -#define HDSDI_QI_ICSR_ROIE 0x00000001 /* Receive Overrun Interrupt Enable */ -#define HDSDI_QI_ICSR_CDIE 0x00000008 /* Carrier Detect Interrupt Enable */ -#define HDSDI_QI_ICSR_RXDIE 0x00000010 /* Receive Data Interrupt Enable */ -#define HDSDI_QI_ICSR_RO 0x00000100 /* Receive Overrun Status */ -#define HDSDI_QI_ICSR_RXPASSING 0x00000200 /* Receive Sync Status */ -#define HDSDI_QI_ICSR_CD 0x00000800 /* Carrier Detect Status */ -#define HDSDI_QI_ICSR_RXD 0x00001000 /* Receive Data */ -#define HDSDI_QI_ICSR_ROIS 0x00010000 /* Receive Overrun Interrupt Status */ -#define HDSDI_QI_ICSR_CDIS 0x00080000 /* Receive Carrier Detect Interrupt Status */ -#define HDSDI_QI_ICSR_RXDIS 0x00100000 /* Receive Datat Interrupt Status */ -#define HDSDI_QI_ICSR_LKD 0x01000000 /* Autodetect Locked Status */ - -#endif - diff --git a/quad/src/hdsdim_qie.c b/quad/src/hdsdim_qie.c index 873e3c3f1..a8e9c518b 100644 --- a/quad/src/hdsdim_qie.c +++ b/quad/src/hdsdim_qie.c @@ -1,6 +1,6 @@ /* hdsdim_qie.c * - * Linux driver functions for Linear Systems Ltd. VidPort Q/i. + * Linux driver functions for Linear Systems Ltd. QuadPort H/i. * * Copyright (C) 2009-2010 Linear Systems Ltd. * @@ -66,9 +66,7 @@ static long hdsdim_qie_unlocked_ioctl (struct file *filp, static long hdsdim_qie_unlocked_audioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int hdsdim_qie_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(hdsdim_qie_fsync,filp,datasync); static struct file_operations hdsdim_qie_vidfops = { .owner = THIS_MODULE, @@ -76,7 +74,7 @@ static struct file_operations hdsdim_qie_vidfops = { .read = sdivideo_read, .poll = sdivideo_rxpoll, .unlocked_ioctl = hdsdim_qie_unlocked_ioctl, - .compat_ioctl = sdivideo_compat_ioctl, + .compat_ioctl = hdsdim_qie_unlocked_ioctl, .mmap = sdivideo_mmap, .open = sdivideo_open, .release = sdivideo_release, @@ -90,7 +88,7 @@ static struct file_operations hdsdim_qie_audfops = { .read = sdiaudio_read, .poll = sdiaudio_rxpoll, .unlocked_ioctl = hdsdim_qie_unlocked_audioctl, - .compat_ioctl = sdiaudio_compat_ioctl, + .compat_ioctl = hdsdim_qie_unlocked_audioctl, .mmap = sdiaudio_mmap, .open = sdiaudio_open, .release = sdiaudio_release, @@ -127,10 +125,10 @@ static DEVICE_ATTR(uid,S_IRUGO, hdsdim_qie_show_uid,NULL); /** - * hdsdim_qie_pci_probe - PCI insertion handler for a VidPort Q/i + * hdsdim_qie_pci_probe - PCI insertion handler for a QuadPort H/i * @pdev: PCI device * - * Handle the insertion of a VidPort Q/i. + * Handle the insertion of a QuadPort H/i. * Returns a negative error code on failure and 0 on success. **/ int __devinit @@ -271,10 +269,10 @@ NO_PCI: } /** - * hdsdim_qie_pci_remove - PCI removal handler for a VidPort Q/i. + * hdsdim_qie_pci_remove - PCI removal handler for a QuadPort H/i. * @pdev: PCI device * - * Handle the removal of a VidPort Q/i. + * Handle the removal of a QuadPort H/i. * This function may be called during PCI probe error handling, * so don't mark it as __devexit. **/ @@ -296,7 +294,7 @@ hdsdim_qie_pci_remove (struct pci_dev *pdev) } /** - * hdsdim_qie_irq_handler - VidPort Q/i interrupt service routine + * hdsdim_qie_irq_handler - QuadPort H/i interrupt service routine * @irq: interrupt number * @dev_id: pointer to the device data structure * @regs: processor context @@ -373,7 +371,7 @@ IRQ_HANDLER(hdsdim_qie_irq_handler,irq,dev_id,regs) } /** - * hdsdim_qie_init - Initialize a VidPort Q/i receiver + * hdsdim_qie_init - Initialize a QuadPort H/i receiver * @iface: interface **/ static void @@ -462,7 +460,7 @@ hdsdim_qie_init (struct master_iface *iface) } /** - * hdsdim_qie_start - Activate the VidPort Q/i receiver + * hdsdim_qie_start - Activate the QuadPort H/i receiver * @iface: interface **/ static void @@ -505,7 +503,7 @@ hdsdim_qie_start (struct master_iface *iface) } /** - * hdsdim_qie_stop - Deactivate the VidPort Q/i receiver + * hdsdim_qie_stop - Deactivate the QuadPort H/i receiver * @iface: interface **/ static void @@ -550,7 +548,7 @@ hdsdim_qie_stop (struct master_iface *iface) } /** - * hdsdim_qie_exit - Clean up the VidPort Q/i receiver + * hdsdim_qie_exit - Clean up the QuadPort H/i receiver * @iface: interface **/ static void @@ -569,7 +567,7 @@ hdsdim_qie_exit (struct master_iface *iface) } /** - * hdsdim_qie_unlocked_ioctl - VidPort Q/i receiver unlocked_ioctl() method + * hdsdim_qie_unlocked_ioctl - QuadPort H/i receiver unlocked_ioctl() method * @filp: file * @cmd: ioctl command * @arg: ioctl argument @@ -677,7 +675,7 @@ hdsdim_qie_unlocked_ioctl (struct file *filp, } /** - * hdsdim_qie_unlocked_audioctl - VidPort Q/i receiver audio unlocked_ioctl() method + * hdsdim_qie_unlocked_audioctl - QuadPort H/i receiver audio unlocked_ioctl() method * @filp: file * @cmd: ioctl command * @arg: ioctl argument @@ -737,17 +735,14 @@ hdsdim_qie_unlocked_audioctl (struct file *filp, } /** - * hdsdim_qie_fsync - VidPort Q/i receiver fsync() method + * hdsdim_qie_fsync - QuadPort H/i receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -hdsdim_qie_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(hdsdim_qie_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/hdsdim_qie.h b/quad/src/hdsdim_qie.h index fa70b2979..d6829c09c 100644 --- a/quad/src/hdsdim_qie.h +++ b/quad/src/hdsdim_qie.h @@ -1,6 +1,6 @@ /* hdsdim_qie.h * - * Header file for the Linear Systems Ltd. VidPort Q/i card. + * Header file for the Linear Systems Ltd. QuadPort H/i card. * * Copyright (C) 2009-2010 Linear Systems Ltd. * @@ -29,7 +29,7 @@ #include /* __devinit */ #define HDSDIM_PCI_DEVICE_ID_LINSYS_HDSDIQIE 0x00B6 -#define HDSDIM_NAME_QIE "VidPort Q/i" +#define HDSDIM_NAME_QIE "QuadPort H/i" /* HD-SDI configuration */ #define HDSDIM_QIE_RCSR(c) ((c)*0x100+0x004) /* Receiver Control and Status Register */ diff --git a/quad/src/hdsdim_rxe.c b/quad/src/hdsdim_rxe.c index dd8d4e7c8..b70f34d6a 100644 --- a/quad/src/hdsdim_rxe.c +++ b/quad/src/hdsdim_rxe.c @@ -69,9 +69,7 @@ static long hdsdim_rxe_unlocked_ioctl (struct file *filp, static long hdsdim_rxe_unlocked_audioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int hdsdim_rxe_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(hdsdim_rxe_fsync,filp,datasync); static struct file_operations hdsdim_rxe_vidfops = { .owner = THIS_MODULE, @@ -79,7 +77,7 @@ static struct file_operations hdsdim_rxe_vidfops = { .read = sdivideo_read, .poll = sdivideo_rxpoll, .unlocked_ioctl = hdsdim_rxe_unlocked_ioctl, - .compat_ioctl = sdivideo_compat_ioctl, + .compat_ioctl = hdsdim_rxe_unlocked_ioctl, .mmap = sdivideo_mmap, .open = sdivideo_open, .release = sdivideo_release, @@ -93,7 +91,7 @@ static struct file_operations hdsdim_rxe_audfops = { .read = sdiaudio_read, .poll = sdiaudio_rxpoll, .unlocked_ioctl = hdsdim_rxe_unlocked_audioctl, - .compat_ioctl = sdiaudio_compat_ioctl, + .compat_ioctl = hdsdim_rxe_unlocked_audioctl, .mmap = sdiaudio_mmap, .open = sdiaudio_open, .release = sdiaudio_release, @@ -147,7 +145,7 @@ int __devinit hdsdim_rxe_pci_probe (struct pci_dev *pdev) { int err; - unsigned int vidcap, audcap; + unsigned int cap; struct master_dev *card; err = hdsdim_pci_probe_generic (pdev); @@ -212,7 +210,10 @@ hdsdim_rxe_pci_probe (struct pci_dev *pdev) } } - vidcap = 0; + cap = 0; + if (card->version >= 0x0102) { + cap |= SDIVIDEO_CAP_RX_VANC; + } /* Register a video receive interface */ if ((err = sdivideo_register_iface (card, &lsdma_dma_ops, @@ -220,12 +221,12 @@ hdsdim_rxe_pci_probe (struct pci_dev *pdev) MASTER_DIRECTION_RX, &hdsdim_rxe_vidfops, &hdsdim_rxe_vidops, - vidcap, + cap, 4)) < 0) { //4 is the dma alignment, means dma transfer has to begin and end on 4 byte alignment goto NO_IFACE; } - audcap = SDIAUDIO_CAP_RX_NONAUDIO; + cap = SDIAUDIO_CAP_RX_NONAUDIO; /* Register an audio receive interface */ if ((err = sdiaudio_register_iface (card, &lsdma_dma_ops, @@ -233,7 +234,7 @@ hdsdim_rxe_pci_probe (struct pci_dev *pdev) MASTER_DIRECTION_RX, &hdsdim_rxe_audfops, &hdsdim_rxe_audops, - audcap, + cap, 4)) < 0) { //4 is the dma alignment, means dma transfer has to begin and end on 4 byte alignment goto NO_IFACE; } @@ -305,10 +306,13 @@ IRQ_HANDLER(hdsdim_rxe_irq_handler,irq,dev_id,regs) /* Increment the buffer pointer */ mdma_advance (vid_iface->dma); - /* Flag end-of-chain */ //stop also have to wait until the end of chain - if (dmacsr & LSDMA_CH_CSR_DONE) { + if (mdma_rx_isempty (vid_iface->dma)) { set_bit (SDIVIDEO_EVENT_RX_BUFFER_ORDER, &vid_iface->events); + } + + /* Flag end-of-chain */ //stop also have to wait until the end of chain + if (dmacsr & LSDMA_CH_CSR_DONE) { set_bit (0, &vid_iface->dma_done); } @@ -336,10 +340,13 @@ IRQ_HANDLER(hdsdim_rxe_irq_handler,irq,dev_id,regs) /* Increment the buffer pointer */ mdma_advance (aud_iface->dma); - /* Flag end-of-chain */ //stop also have to wait until the end of chain - if (dmacsr & LSDMA_CH_CSR_DONE) { + if (mdma_rx_isempty (aud_iface->dma)) { set_bit (SDIAUDIO_EVENT_RX_BUFFER_ORDER, &aud_iface->events); + } + + /* Flag end-of-chain */ //stop also have to wait until the end of chain + if (dmacsr & LSDMA_CH_CSR_DONE) { set_bit (0, &aud_iface->dma_done); } @@ -435,6 +442,9 @@ hdsdim_rxe_init (struct master_iface *iface) reg |= HDSDIM_RXE_CTRL_FOURCC_V210; break; } + if (iface->vanc) { + reg |= HDSDIM_RXE_CTRL_VANC; + } /* There will be no races on CSR * until this code returns, so we don't need to lock it @@ -532,6 +542,11 @@ hdsdim_rxe_stop (struct master_iface *iface) writel(reg | HDSDIM_RXE_CTRL_SWRST, card->core.addr + HDSDIM_RXE_CTRL); + /* Disable receiver non-DMA interrupts */ + writel (HDSDIM_RXE_INT_RVOI | + HDSDIM_RXE_INT_RVDI | HDSDIM_RXE_INT_RSTDI, + card->core.addr + HDSDIM_RXE_IMC); + /* Disable and abort DMA */ writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_64BIT | LSDMA_CH_CSR_DIRECTION, @@ -540,15 +555,14 @@ hdsdim_rxe_stop (struct master_iface *iface) LSDMA_CH_CSR_64BIT | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(3)); - - /* Disable receiver interrupts */ - writel (HDSDIM_RXE_INT_DMA3 | HDSDIM_RXE_INT_RVOI | - HDSDIM_RXE_INT_RVDI | HDSDIM_RXE_INT_RSTDI, - card->core.addr + HDSDIM_RXE_IMC); - /* Dummy read to flush PCI posted writes */ readl(card->core.addr + HDSDIM_RXE_FPGAID); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + + /* Disable receiver DMA interrupts */ + writel (HDSDIM_RXE_INT_DMA3, card->core.addr + HDSDIM_RXE_IMC); + return; } @@ -561,6 +575,10 @@ hdsdim_rxe_audstop (struct master_iface *iface) { struct master_dev *card = iface->card; + /* Disable receiver non-DMA interrupts */ + writel (HDSDIM_RXE_INT_RAOI | HDSDIM_RXE_INT_RADI, + card->core.addr + HDSDIM_RXE_IMC); + /* Disable and abort DMA */ writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_64BIT | LSDMA_CH_CSR_DIRECTION, @@ -569,15 +587,14 @@ hdsdim_rxe_audstop (struct master_iface *iface) LSDMA_CH_CSR_64BIT | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(4)); - - /* Disable receiver interrupts */ - writel (HDSDIM_RXE_INT_DMA4 | HDSDIM_RXE_INT_RAOI | - HDSDIM_RXE_INT_RADI, - card->core.addr + HDSDIM_RXE_IMC); - /* Dummy read to flush PCI posted writes */ readl(card->core.addr + HDSDIM_RXE_FPGAID); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); + + /* Disable receiver DMA interrupts */ + writel (HDSDIM_RXE_INT_DMA4, card->core.addr + HDSDIM_RXE_IMC); + return; } @@ -593,8 +610,7 @@ hdsdim_rxe_exit (struct master_iface *iface) /* Reset the receiver. * There will be no races on CSR here, * so we don't need to lock it */ - writel (HDSDIM_RXE_CTRL_SWRST, - card->core.addr + HDSDIM_RXE_CTRL); + writel (HDSDIM_RXE_CTRL_SWRST, card->core.addr + HDSDIM_RXE_CTRL); return; } @@ -777,15 +793,12 @@ hdsdim_rxe_unlocked_audioctl (struct file *filp, /** * hdsdim_rxe_fsync - VidPort SD/HD I Video fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -hdsdim_rxe_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(hdsdim_rxe_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -794,20 +807,19 @@ hdsdim_rxe_fsync (struct file *filp, mutex_lock (&iface->buf_mutex); /* Stop the receiver */ - hdsdim_rxe_stop (iface); + iface->ops->stop (iface); /* Reset the onboard FIFO and driver buffers */ spin_lock (&card->reg_lock); reg = readl (card->core.addr + HDSDIM_RXE_CTRL); writel (reg | HDSDIM_RXE_CTRL_SWRST, card->core.addr + HDSDIM_RXE_CTRL); - wmb (); writel (reg, card->core.addr + HDSDIM_RXE_CTRL); spin_unlock (&card->reg_lock); iface->events = 0; lsdma_reset (iface->dma); /* Start the receiver */ - hdsdim_rxe_start (iface); + iface->ops->start (iface); mutex_unlock (&iface->buf_mutex); return 0; diff --git a/quad/src/hdsdim_rxe.h b/quad/src/hdsdim_rxe.h index f8dae1866..16fa4bab7 100644 --- a/quad/src/hdsdim_rxe.h +++ b/quad/src/hdsdim_rxe.h @@ -64,6 +64,7 @@ #define HDSDIM_RXE_CTRL_SWRST 0x00000001 /* Reset */ #define HDSDIM_RXE_CTRL_CLKRST 0x00000008 /* Clock Reset */ #define HDSDIM_RXE_CTRL_FOURCC_V210 0x00010000 /* UYVY if not set */ +#define HDSDIM_RXE_CTRL_VANC 0x01000000 /* Vertical Ancillary Space */ /* Status Register (STATUS) bit locations */ #define HDSDIM_RXE_STATUS_RXSTD 0x000f0000 /* Receive Video Standard */ diff --git a/quad/src/hdsdim_txe.c b/quad/src/hdsdim_txe.c index 8b2b81f98..c0c2d4723 100644 --- a/quad/src/hdsdim_txe.c +++ b/quad/src/hdsdim_txe.c @@ -77,8 +77,7 @@ static long hdsdim_txe_unlocked_ioctl (struct file *filp, static long hdsdim_txe_unlocked_audioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int hdsdim_txe_fsync (struct file *filp, - struct dentry *dentry, int datasync); +static int FSYNC_HANDLER(hdsdim_txe_fsync,filp,datasync); static struct file_operations hdsdim_txe_vidfops = { .owner = THIS_MODULE, @@ -86,7 +85,7 @@ static struct file_operations hdsdim_txe_vidfops = { .write = sdivideo_write, .poll = sdivideo_txpoll, .unlocked_ioctl = hdsdim_txe_unlocked_ioctl, - .compat_ioctl = sdivideo_compat_ioctl, + .compat_ioctl = hdsdim_txe_unlocked_ioctl, .mmap = sdivideo_mmap, .open = sdivideo_open, .release = sdivideo_release, @@ -100,7 +99,7 @@ static struct file_operations hdsdim_txe_audfops = { .write = sdiaudio_write, .poll = sdiaudio_txpoll, .unlocked_ioctl = hdsdim_txe_unlocked_audioctl, - .compat_ioctl = sdivideo_compat_ioctl, + .compat_ioctl = hdsdim_txe_unlocked_audioctl, .mmap = sdiaudio_mmap, .open = sdiaudio_open, .release = sdiaudio_release, @@ -302,6 +301,7 @@ int __devinit hdsdim_txe_pci_probe (struct pci_dev *pdev) { int err; + unsigned int cap; struct master_dev *card; err = hdsdim_pci_probe_generic (pdev); @@ -369,13 +369,17 @@ hdsdim_txe_pci_probe (struct pci_dev *pdev) } /* Register a video transmit interface */ + cap = 0; + if (card->version >= 0x0202) { + cap |= SDIVIDEO_CAP_TX_VANC; + } if ((err = sdivideo_register_iface (card, &lsdma_dma_ops, 0, MASTER_DIRECTION_TX, &hdsdim_txe_vidfops, &hdsdim_txe_vidops, - 0, + cap, 4)) < 0) { //4 is the dma alignment, means dma transfer has to begin and end on 4 byte alignment goto NO_IFACE; } @@ -1008,7 +1012,6 @@ hdsdim_txe_init (struct master_iface *iface) tof_offset = 562; break; } - switch (iface->mode) { default: case SDIVIDEO_CTL_MODE_UYVY: @@ -1018,6 +1021,9 @@ hdsdim_txe_init (struct master_iface *iface) reg |= HDSDIM_TXE_CTRL_FOURCC_V210; break; } + if (iface->vanc) { + reg |= HDSDIM_TXE_CTRL_VANC; + } /* Enable the clock generator */ writel (reg | HDSDIM_TXE_CTRL_SWRST | HDSDIM_TXE_CTRL_HL2RST, @@ -1362,13 +1368,11 @@ hdsdim_txe_start_tx_dma (struct master_iface *iface) LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_64BIT, card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC(dma_channel)); writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(dma_channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_64BIT | @@ -1431,15 +1435,12 @@ hdsdim_txe_unlocked_audioctl (struct file *filp, /** * hdsdim_txe_fsync - VidPort SD/HD O fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -hdsdim_txe_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(hdsdim_txe_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dma *dma = iface->dma; diff --git a/quad/src/hdsdim_txe.h b/quad/src/hdsdim_txe.h index caff8bf44..1c9026091 100644 --- a/quad/src/hdsdim_txe.h +++ b/quad/src/hdsdim_txe.h @@ -84,6 +84,8 @@ #define HDSDIM_TXE_CTRL_TXSTD_296M_720p_24 0x00000c00 /* SMPTE 296M 720p24 */ #define HDSDIM_TXE_CTRL_TXSTD_125M_486i 0x00000000 /* SMPTE 125M 486i29.97 */ #define HDSDIM_TXE_CTRL_TXSTD_BT601_576i 0x00000400 /* ITU-R BT.601 720x576i25 */ +#define HDSDIM_TXE_CTRL_VPID 0x00100000 /* Video Payload Identifier */ +#define HDSDIM_TXE_CTRL_VANC 0x01000000 /* Vertical Ancillary Space */ /* Status Register (STATUS) bit locations */ #define HDSDIM_TXE_STATUS_REF_LOST 0x00000001 /* Reference Lost */ diff --git a/quad/src/jtag.c b/quad/src/jtag.c old mode 100755 new mode 100644 index 4dfceab70..432565051 --- a/quad/src/jtag.c +++ b/quad/src/jtag.c @@ -50,7 +50,7 @@ #include "mmsa.h" #include "sdim.h" #include "sdim_qoe.h" -#include "dvbm_qo.h" +#include "dvbm_lpqo.h" #include "dvbm_qlf.h" #include "dvbm_qdual.h" #include "eeprom.h" @@ -659,13 +659,13 @@ lsj_pci_probe (struct pci_dev *pdev, case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE: board_name = DVBM_NAME_LPQOE; core_bar = 0; - jtag_addr = DVBM_QO_JTAGR; + jtag_addr = DVBM_LPQO_JTAGR; bridge_bar = 2; break; case DVBM_PCI_DEVICE_ID_LINSYS_DVBLPQOE_MINIBNC: board_name = DVBM_NAME_LPQOE_MINIBNC; core_bar = 0; - jtag_addr = DVBM_QO_JTAGR; + jtag_addr = DVBM_LPQO_JTAGR; bridge_bar = 2; break; case SDIM_PCI_DEVICE_ID_LINSYS_SDIQOE: diff --git a/quad/src/lsdma.c b/quad/src/lsdma.c old mode 100755 new mode 100644 diff --git a/quad/src/lsdma.h b/quad/src/lsdma.h old mode 100755 new mode 100644 diff --git a/quad/src/masterlsdma.c b/quad/src/masterlsdma.c deleted file mode 100755 index c4d138d5f..000000000 --- a/quad/src/masterlsdma.c +++ /dev/null @@ -1,478 +0,0 @@ -/* masterlsdma.c - * - * Functions related to interfaces which use the Linear Systems DMA controller. - * - * Copyright (C) 2004-2007 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#include /* LINUX_VERSION_CODE */ - -#include /* file */ -#include /* poll_wait () */ -#include /* error codes */ -#include /* wait_event_interruptible () */ - -#include /* down_interruptible () */ -#include /* clear_bit () */ - -#include "mdev.h" -#include "miface.h" -// Temporary fix for Linux kernel 2.6.21 -#include "lsdma.c" -#include "masterlsdma.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) -static inline int -nonseekable_open (struct inode *inode, struct file *filp) -{ - return 0; -} -#endif - -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif - -/** - * masterlsdma_open - open() method - * @inode: inode - * @filp: file - * @init: interface initialization function - * @start: interface activation function - * @data_addr: local bus address of the data register - * @flags: allocation flags - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_open (struct inode *inode, - struct file *filp, - void (*init)(struct master_iface *iface), - void (*start)(struct master_iface *iface), - u32 data_addr, - unsigned int flags) -{ - struct master_iface *iface = - container_of(inode->i_cdev,struct master_iface,cdev); - struct master_dev *card = iface->card; - - filp->private_data = iface; - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users) { - if (((iface->owner != current->uid) && - (iface->owner != current->euid) && - !capable (CAP_DAC_OVERRIDE))) { - up (&card->users_sem); - return -EBUSY; - } - } else { - /* Reset flags */ - iface->events = 0; - __set_bit (0, &iface->dma_done); - - /* Create a DMA buffer management structure */ - if ((iface->dma = lsdma_alloc (card->pdev, - data_addr, - iface->buffers, - iface->bufsize, - (iface->direction == MASTER_DIRECTION_TX) ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE, - flags)) == NULL) { - up (&card->users_sem); - return -ENOMEM; - } - - /* Initialize the interface */ - if (init) { - init (iface); - } - - /* If we are the first user, install the interrupt handler */ - if (!mdev_users (card) && - (request_irq (card->pdev->irq, - card->irq_handler, - IRQF_SHARED, - card->name, - card) != 0)) { - lsdma_free (iface->dma); - up (&card->users_sem); - return -EBUSY; - } - - /* Activate the interface */ - if (start) { - start (iface); - } - - iface->owner = current->uid; - } - iface->users++; - up (&card->users_sem); - - return nonseekable_open (inode, filp); -} - -/** - * masterlsdma_write - write() method - * @filp: file - * @data: data - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes written on success. - **/ -ssize_t -masterlsdma_write (struct file *filp, - const char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = lsdma_write (dma, data, length); - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - lsdma_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); - writel (lsdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (lsdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - } - - up (&iface->buf_sem); - return ret; -} - -/** - * masterlsdma_read - read() method - * @filp: file - * @data: read buffer - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes read on success. - **/ -ssize_t -masterlsdma_read (struct file *filp, - char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = lsdma_read (dma, data, length); - - up (&iface->buf_sem); - return ret; -} - -/** - * masterlsdma_txpoll - transmitter poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterlsdma_txpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!lsdma_tx_isfull (iface->dma)) { - mask |= POLLOUT | POLLWRNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterlsdma_rxpoll - receiver poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterlsdma_rxpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!lsdma_rx_isempty (iface->dma)) { - mask |= POLLIN | POLLRDNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterlsdma_mmap - mmap() method - * @filp: file - * @vma: VMA - **/ -int -masterlsdma_mmap (struct file *filp, struct vm_area_struct *vma) -{ - struct master_iface *iface = filp->private_data; - - vma->vm_ops = &lsdma_vm_ops; - vma->vm_flags |= VM_RESERVED; - vma->vm_private_data = iface->dma; - return 0; -} - -/** - * masterlsdma_release - release() method - * @iface: interface - * @stop: interface deactivation function - * @exit: interface shutdown function - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_release (struct master_iface *iface, - void (*stop)(struct master_iface *iface), - void (*exit)(struct master_iface *iface)) -{ - struct master_dev *card = iface->card; - - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users == 1) { - if (stop) { - stop (iface); - } - if (exit) { - exit (iface); - } - /* If we are the last user, uninstall the interrupt handler */ - if (mdev_users (card) == 1) { - free_irq (card->pdev->irq, card); - } - /* Destroy the DMA buffer management structure */ - lsdma_free (iface->dma); - } - iface->users--; - up (&card->users_sem); - - return 0; -} - -/** - * masterlsdma_txdqbuf - transmitter dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_txdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (lsdma_txdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_txqbuf - transmitter qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_txqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (lsdma_txqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - lsdma_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (lsdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (lsdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - } - - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_rxdqbuf - receiver dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_rxdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (lsdma_rxdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_rxqbuf - receiver qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_rxqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (lsdma_rxqbuf (iface->dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - diff --git a/quad/src/masterlsdma.c.bkup b/quad/src/masterlsdma.c.bkup deleted file mode 100755 index c4d138d5f..000000000 --- a/quad/src/masterlsdma.c.bkup +++ /dev/null @@ -1,478 +0,0 @@ -/* masterlsdma.c - * - * Functions related to interfaces which use the Linear Systems DMA controller. - * - * Copyright (C) 2004-2007 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#include /* LINUX_VERSION_CODE */ - -#include /* file */ -#include /* poll_wait () */ -#include /* error codes */ -#include /* wait_event_interruptible () */ - -#include /* down_interruptible () */ -#include /* clear_bit () */ - -#include "mdev.h" -#include "miface.h" -// Temporary fix for Linux kernel 2.6.21 -#include "lsdma.c" -#include "masterlsdma.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) -static inline int -nonseekable_open (struct inode *inode, struct file *filp) -{ - return 0; -} -#endif - -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif - -/** - * masterlsdma_open - open() method - * @inode: inode - * @filp: file - * @init: interface initialization function - * @start: interface activation function - * @data_addr: local bus address of the data register - * @flags: allocation flags - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_open (struct inode *inode, - struct file *filp, - void (*init)(struct master_iface *iface), - void (*start)(struct master_iface *iface), - u32 data_addr, - unsigned int flags) -{ - struct master_iface *iface = - container_of(inode->i_cdev,struct master_iface,cdev); - struct master_dev *card = iface->card; - - filp->private_data = iface; - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users) { - if (((iface->owner != current->uid) && - (iface->owner != current->euid) && - !capable (CAP_DAC_OVERRIDE))) { - up (&card->users_sem); - return -EBUSY; - } - } else { - /* Reset flags */ - iface->events = 0; - __set_bit (0, &iface->dma_done); - - /* Create a DMA buffer management structure */ - if ((iface->dma = lsdma_alloc (card->pdev, - data_addr, - iface->buffers, - iface->bufsize, - (iface->direction == MASTER_DIRECTION_TX) ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE, - flags)) == NULL) { - up (&card->users_sem); - return -ENOMEM; - } - - /* Initialize the interface */ - if (init) { - init (iface); - } - - /* If we are the first user, install the interrupt handler */ - if (!mdev_users (card) && - (request_irq (card->pdev->irq, - card->irq_handler, - IRQF_SHARED, - card->name, - card) != 0)) { - lsdma_free (iface->dma); - up (&card->users_sem); - return -EBUSY; - } - - /* Activate the interface */ - if (start) { - start (iface); - } - - iface->owner = current->uid; - } - iface->users++; - up (&card->users_sem); - - return nonseekable_open (inode, filp); -} - -/** - * masterlsdma_write - write() method - * @filp: file - * @data: data - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes written on success. - **/ -ssize_t -masterlsdma_write (struct file *filp, - const char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = lsdma_write (dma, data, length); - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - lsdma_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); - writel (lsdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (lsdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - } - - up (&iface->buf_sem); - return ret; -} - -/** - * masterlsdma_read - read() method - * @filp: file - * @data: read buffer - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes read on success. - **/ -ssize_t -masterlsdma_read (struct file *filp, - char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = lsdma_read (dma, data, length); - - up (&iface->buf_sem); - return ret; -} - -/** - * masterlsdma_txpoll - transmitter poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterlsdma_txpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!lsdma_tx_isfull (iface->dma)) { - mask |= POLLOUT | POLLWRNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterlsdma_rxpoll - receiver poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterlsdma_rxpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!lsdma_rx_isempty (iface->dma)) { - mask |= POLLIN | POLLRDNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterlsdma_mmap - mmap() method - * @filp: file - * @vma: VMA - **/ -int -masterlsdma_mmap (struct file *filp, struct vm_area_struct *vma) -{ - struct master_iface *iface = filp->private_data; - - vma->vm_ops = &lsdma_vm_ops; - vma->vm_flags |= VM_RESERVED; - vma->vm_private_data = iface->dma; - return 0; -} - -/** - * masterlsdma_release - release() method - * @iface: interface - * @stop: interface deactivation function - * @exit: interface shutdown function - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_release (struct master_iface *iface, - void (*stop)(struct master_iface *iface), - void (*exit)(struct master_iface *iface)) -{ - struct master_dev *card = iface->card; - - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users == 1) { - if (stop) { - stop (iface); - } - if (exit) { - exit (iface); - } - /* If we are the last user, uninstall the interrupt handler */ - if (mdev_users (card) == 1) { - free_irq (card->pdev->irq, card); - } - /* Destroy the DMA buffer management structure */ - lsdma_free (iface->dma); - } - iface->users--; - up (&card->users_sem); - - return 0; -} - -/** - * masterlsdma_txdqbuf - transmitter dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_txdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (lsdma_txdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_txqbuf - transmitter qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_txqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (lsdma_txqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - lsdma_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - unsigned int dma_channel = mdev_index (card, &iface->list); - - writel (lsdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC(dma_channel)); - writel (lsdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), - card->bridge_addr + LSDMA_DESC_H(dma_channel)); - clear_bit (0, &iface->dma_done); - wmb (); - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(dma_channel)); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + LSDMA_INTMSK); - } - - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_rxdqbuf - receiver dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_rxdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct lsdma_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && lsdma_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !lsdma_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (lsdma_rxdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterlsdma_rxqbuf - receiver qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterlsdma_rxqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (lsdma_rxqbuf (iface->dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - diff --git a/quad/src/masterlsdma.h b/quad/src/masterlsdma.h deleted file mode 100755 index 09e177f49..000000000 --- a/quad/src/masterlsdma.h +++ /dev/null @@ -1,89 +0,0 @@ -/* masterlsdma.h - * - * Header file for masterlsdma.c. - * - * Copyright (C) 2004-2005 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _MASTERLSDMA_H -#define _MASTERLSDMA_H - -#include /* size_t, loff_t */ -#include /* file */ -#include /* poll_table */ -#include /* vm_area_struct */ - -#include "mdev.h" -#include "miface.h" - -/* External function prototypes */ -int masterlsdma_open (struct inode *inode, - struct file *filp, - void (*init)(struct master_iface *iface), - void (*start)(struct master_iface *iface), - u32 data_addr, - unsigned int flags); -ssize_t masterlsdma_write (struct file *filp, - const char __user *data, - size_t length, - loff_t *offset); -ssize_t masterlsdma_read (struct file *filp, - char __user *data, - size_t length, - loff_t *offset); -unsigned int masterlsdma_txpoll (struct file *filp, poll_table *wait); -unsigned int masterlsdma_rxpoll (struct file *filp, poll_table *wait); -int masterlsdma_mmap (struct file *filp, struct vm_area_struct *vma); -int masterlsdma_release (struct master_iface *iface, - void (*stop)(struct master_iface *iface), - void (*exit)(struct master_iface *iface)); -int masterlsdma_txdqbuf (struct file *filp, unsigned long arg); -int masterlsdma_txqbuf (struct file *filp, unsigned long arg); -int masterlsdma_rxdqbuf (struct file *filp, unsigned long arg); -int masterlsdma_rxqbuf (struct file *filp, unsigned long arg); - -/* Inline functions */ - -#ifndef wait_event_timeout -#define __wait_event_timeout(wq, condition, ret) \ -do { \ - DEFINE_WAIT(__wait); \ - \ - for (;;) { \ - prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ - if (condition) \ - break; \ - ret = schedule_timeout(ret); \ - if (!ret) \ - break; \ - } \ - finish_wait(&wq, &__wait); \ -} while (0) -#define wait_event_timeout(wq, condition, timeout) \ -({ \ - long __ret = timeout; \ - if (!(condition)) \ - __wait_event_timeout(wq, condition, __ret); \ - __ret; \ -}) -#endif - -#endif - diff --git a/quad/src/masterplx.c b/quad/src/masterplx.c deleted file mode 100755 index 5c9431067..000000000 --- a/quad/src/masterplx.c +++ /dev/null @@ -1,503 +0,0 @@ -/* masterplx.c - * - * Functions related to interfaces which use the PLX PCI 9080. - * - * Copyright (C) 2004-2007 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#include /* LINUX_VERSION_CODE */ - -#include /* file */ -#include /* poll_wait () */ -#include /* error codes */ -#include /* wait_event_interruptible () */ -#include /* udelay () */ - -#include /* down_interruptible () */ -#include /* clear_bit () */ - -#include "mdev.h" -// Temporary fix for Linux kernel 2.6.21 -#include "plx9080.c" -#include "masterplx.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) -static inline int -nonseekable_open (struct inode *inode, struct file *filp) -{ - return 0; -} -#endif - -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif - -/** - * masterplx_reset_bridge - reset the PCI 9080 - * @card: Master device containing the bridge - **/ -void -masterplx_reset_bridge (struct master_dev *card) -{ - unsigned int cntrl; - - /* Set the PCI Read Command to Memory Read Multiple */ - /* and pulse the PCI 9080 software reset bit */ - cntrl = (readl (card->bridge_addr + PLX_CNTRL) & - ~(PLX_CNTRL_PCIRCCDMA_MASK | PLX_CNTRL_PCIMRCCDM_MASK)) | 0xc0c; - writel (cntrl | PLX_CNTRL_RESET, card->bridge_addr + PLX_CNTRL); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + PLX_CNTRL); - udelay (100L); - writel (cntrl, card->bridge_addr + PLX_CNTRL); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + PLX_CNTRL); - udelay (100L); - - /* Reload the PCI 9080 local configuration registers from the EEPROM */ - writel (cntrl | PLX_CNTRL_RECONFIG, card->bridge_addr + PLX_CNTRL); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + PLX_CNTRL); - /* Sleep for at least 6 ms */ - set_current_state (TASK_UNINTERRUPTIBLE); - schedule_timeout (1 + HZ / 167); - writel (cntrl, card->bridge_addr + PLX_CNTRL); - /* Dummy read to flush PCI posted writes */ - readl (card->bridge_addr + PLX_CNTRL); -} - -/** - * masterplx_open - open() method - * @inode: inode - * @filp: file - * @init: interface initialization function - * @start: interface activation function - * @data_addr: local bus address of the data register - * @flags: allocation flags - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_open (struct inode *inode, - struct file *filp, - void (*init)(struct master_iface *iface), - void (*start)(struct master_iface *iface), - u32 data_addr, - unsigned int flags) -{ - struct master_iface *iface = - container_of(inode->i_cdev,struct master_iface,cdev); - struct master_dev *card = iface->card; - - filp->private_data = iface; - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users) { - if (((iface->owner != current->uid) && - (iface->owner != current->euid) && - !capable (CAP_DAC_OVERRIDE))) { - up (&card->users_sem); - return -EBUSY; - } - } else { - /* Reset flags */ - iface->events = 0; - __set_bit (0, &iface->dma_done); - - /* Create a DMA buffer management structure */ - if ((iface->dma = plx_alloc (card->pdev, - data_addr, - iface->buffers, - iface->bufsize, - (iface->direction == MASTER_DIRECTION_TX) ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE, - flags)) == NULL) { - up (&card->users_sem); - return -ENOMEM; - } - - /* Initialize the interface */ - if (init) { - init (iface); - } - - /* If we are the first user, install the interrupt handler */ - if (!mdev_users (card) && - (request_irq (card->pdev->irq, - card->irq_handler, - IRQF_SHARED, - card->name, - card) != 0)) { - plx_free (iface->dma); - up (&card->users_sem); - return -EBUSY; - } - - /* Activate the interface */ - if (start) { - start (iface); - } - - iface->owner = current->uid; - } - iface->users++; - up (&card->users_sem); - return nonseekable_open (inode, filp); -} - -/** - * masterplx_write - write() method - * @filp: file - * @data: data - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes written on success. - **/ -ssize_t -masterplx_write (struct file *filp, - const char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct plx_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && plx_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !plx_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = plx_write (dma, data, length); - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - plx_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - - writel (plx_head_desc_bus_addr (dma) | - PLX_DMADPR_DLOC_PCI, - card->bridge_addr + PLX_DMADPR0); - clear_bit (0, &iface->dma_done); - wmb (); - writeb (PLX_DMACSR_ENABLE | PLX_DMACSR_START, - card->bridge_addr + PLX_DMACSR0); - /* Dummy read to flush PCI posted writes */ - readb (card->bridge_addr + PLX_DMACSR0); - } - - up (&iface->buf_sem); - return ret; -} - -/** - * masterplx_read - read() method - * @filp: file - * @data: read buffer - * @length: size of data - * @offset: - * - * Returns a negative error code on failure and - * the number of bytes read on success. - **/ -ssize_t -masterplx_read (struct file *filp, - char __user *data, - size_t length, - loff_t *offset) -{ - struct master_iface *iface = filp->private_data; - struct plx_dma *dma = iface->dma; - ssize_t ret; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)) - if (offset != &filp->f_pos) { - return -ESPIPE; - } -#endif - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && plx_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !plx_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - - ret = plx_read (dma, data, length); - - up (&iface->buf_sem); - return ret; -} - -/** - * masterplx_txpoll - transmitter poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterplx_txpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!plx_tx_isfull (iface->dma)) { - mask |= POLLOUT | POLLWRNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterplx_rxpoll - receiver poll() method - * @filp: file - * @wait: - **/ -unsigned int -masterplx_rxpoll (struct file *filp, poll_table *wait) -{ - struct master_iface *iface = filp->private_data; - unsigned int mask = 0; - - poll_wait (filp, &iface->queue, wait); - if (!plx_rx_isempty (iface->dma)) { - mask |= POLLIN | POLLRDNORM; - } - if (iface->events) { - mask |= POLLPRI; - } - return mask; -} - -/** - * masterplx_mmap - mmap() method - * @filp: file - * @vma: VMA - **/ -int -masterplx_mmap (struct file *filp, struct vm_area_struct *vma) -{ - struct master_iface *iface = filp->private_data; - - vma->vm_ops = &plx_vm_ops; - vma->vm_flags |= VM_RESERVED; - vma->vm_private_data = iface->dma; - return 0; -} - -/** - * masterplx_release - release() method - * @iface: interface - * @stop: interface deactivation function - * @exit: interface shutdown function - * - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_release (struct master_iface *iface, - void (*stop)(struct master_iface *iface), - void (*exit)(struct master_iface *iface)) -{ - struct master_dev *card = iface->card; - - if (down_interruptible (&card->users_sem)) { - return -ERESTARTSYS; - } - if (iface->users == 1) { - if (stop) { - stop (iface); - } - if (exit) { - exit (iface); - } - - /* If we are the last user, uninstall the interrupt handler */ - if (mdev_users (card) == 1) { - free_irq (card->pdev->irq, card); - } - - /* Destroy the DMA buffer management structure */ - plx_free (iface->dma); - } - iface->users--; - up (&card->users_sem); - return 0; -} - -/** - * masterplx_txdqbuf - transmitter dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_txdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct plx_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && plx_tx_isfull (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !plx_tx_isfull (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (plx_txdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterplx_txqbuf - transmitter qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a transmitter buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_txqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct plx_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (plx_txqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - - /* If DMA is stopped and the buffer queue is half full, - * enable and start DMA */ - if (test_bit (0, &iface->dma_done) && - plx_tx_buflevel (dma) >= iface->buffers / 2) { - struct master_dev *card = iface->card; - - writel (plx_head_desc_bus_addr (dma) | - PLX_DMADPR_DLOC_PCI, - card->bridge_addr + PLX_DMADPR0); - clear_bit (0, &iface->dma_done); - wmb (); - writeb (PLX_DMACSR_ENABLE | PLX_DMACSR_START, - card->bridge_addr + PLX_DMACSR0); - /* Dummy read to flush PCI posted writes */ - readb (card->bridge_addr + PLX_DMACSR0); - } - - up (&iface->buf_sem); - return 0; -} - -/** - * masterplx_rxdqbuf - receiver dqbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Dequeue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_rxdqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - struct plx_dma *dma = iface->dma; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if ((filp->f_flags & O_NONBLOCK) && plx_rx_isempty (dma)) { - up (&iface->buf_sem); - return -EAGAIN; - } - if (wait_event_interruptible ( - iface->queue, !plx_rx_isempty (dma))) { - up (&iface->buf_sem); - return -ERESTARTSYS; - } - if (plx_rxdqbuf (dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - -/** - * masterplx_rxqbuf - receiver qbuf ioctl handler - * @filp: file - * @arg: ioctl argument - * - * Queue a receiver buffer. - * Returns a negative error code on failure and 0 on success. - **/ -int -masterplx_rxqbuf (struct file *filp, unsigned long arg) -{ - struct master_iface *iface = filp->private_data; - - if (down_interruptible (&iface->buf_sem)) { - return -ERESTARTSYS; - } - if (plx_rxqbuf (iface->dma, arg) < 0) { - up (&iface->buf_sem); - return -EINVAL; - } - up (&iface->buf_sem); - return 0; -} - diff --git a/quad/src/masterplx.h b/quad/src/masterplx.h deleted file mode 100755 index 25b6bac6a..000000000 --- a/quad/src/masterplx.h +++ /dev/null @@ -1,91 +0,0 @@ -/* masterplx.h - * - * Header file for masterplx.c. - * - * Copyright (C) 2004-2005 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _MASTERPLX_H -#define _MASTERPLX_H - -#include /* size_t, loff_t */ -#include /* file */ -#include /* poll_table */ -#include /* vm_area_struct */ - -#include "mdev.h" -#include "miface.h" - -/* External function prototypes */ - -void masterplx_reset_bridge (struct master_dev *card); -int masterplx_open (struct inode *inode, - struct file *filp, - void (*init)(struct master_iface *iface), - void (*start)(struct master_iface *iface), - u32 data_addr, - unsigned int flags); -ssize_t masterplx_write (struct file *filp, - const char __user *data, - size_t length, - loff_t *offset); -ssize_t masterplx_read (struct file *filp, - char __user *data, - size_t length, - loff_t *offset); -unsigned int masterplx_txpoll (struct file *filp, poll_table *wait); -unsigned int masterplx_rxpoll (struct file *filp, poll_table *wait); -int masterplx_mmap (struct file *filp, struct vm_area_struct *vma); -int masterplx_release (struct master_iface *iface, - void (*stop)(struct master_iface *iface), - void (*exit)(struct master_iface *iface)); -int masterplx_txdqbuf (struct file *filp, unsigned long arg); -int masterplx_txqbuf (struct file *filp, unsigned long arg); -int masterplx_rxdqbuf (struct file *filp, unsigned long arg); -int masterplx_rxqbuf (struct file *filp, unsigned long arg); - -/* Inline functions */ - -#ifndef wait_event_timeout -#define __wait_event_timeout(wq, condition, ret) \ -do { \ - DEFINE_WAIT(__wait); \ - \ - for (;;) { \ - prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ - if (condition) \ - break; \ - ret = schedule_timeout(ret); \ - if (!ret) \ - break; \ - } \ - finish_wait(&wq, &__wait); \ -} while (0) -#define wait_event_timeout(wq, condition, timeout) \ -({ \ - long __ret = timeout; \ - if (!(condition)) \ - __wait_event_timeout(wq, condition, __ret); \ - __ret; \ -}) -#endif - -#endif - diff --git a/quad/src/mdev.c b/quad/src/mdev.c old mode 100755 new mode 100644 index cabe62945..5ed5212b4 --- a/quad/src/mdev.c +++ b/quad/src/mdev.c @@ -50,7 +50,12 @@ dev_name(struct device *dev) static ssize_t mdev_show_fw_version (struct device *dev, struct device_attribute *attr, char *buf); -static ssize_t mdev_show_version (struct class *cls, char *buf); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) +#define mdev_show_version(cls,attr,buf) mdev_show_version(cls,buf) +#endif +static ssize_t mdev_show_version (struct class *cls, + struct class_attribute *attr, + char *buf); /** * mdev_index - return the index of an interface @@ -180,10 +185,13 @@ mdev_unregister (struct master_dev *card, struct class *cls) /** * mdev_show_version - class attribute read handler * @cls: class being read + * @attr: class attribute * @buf: output buffer **/ static ssize_t -mdev_show_version (struct class *cls, char *buf) +mdev_show_version (struct class *cls, + struct class_attribute *attr, + char *buf) { return snprintf (buf, PAGE_SIZE, "%s\n", MASTER_DRIVER_VERSION); } diff --git a/quad/src/mdev.h b/quad/src/mdev.h old mode 100755 new mode 100644 diff --git a/quad/src/mdev.h.bak b/quad/src/mdev.h.bak deleted file mode 100755 index fab26a0a6..000000000 --- a/quad/src/mdev.h.bak +++ /dev/null @@ -1,120 +0,0 @@ -/* mdev.h - * - * Definitions for Linear Systems Ltd. Master devices. - * - * Copyright (C) 2005-2006 Linear Systems Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either Version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public Licence for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Linear Systems can be contacted at . - * - */ - -#ifndef _MDEV_H -#define _MDEV_H - -#include /* container_of () */ -#include /* LINUX_VERSION_CODE */ - -#include /* __init */ -#include /* spinlock_t */ -#include /* pci_dev */ -#include /* list_head */ -#include /* irqreturn_t */ -#include /* class_device */ - -#include /* semaphore */ -#include /* inl () */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) -typedef unsigned long resource_size_t; -#endif - -#define to_master_dev(cd) container_of(cd,struct master_dev,class_dev) - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -#define IRQ_HANDLER(name,irq,dev_id,regs) \ - name (int irq, void *dev_id, struct pt_regs *regs) -typedef irqreturn_t (*irq_handler_t)(int, void *, struct pt_regs *); -#else -#define IRQ_HANDLER(name,irq,dev_id,regs) \ - name (int irq, void *dev_id) -#endif - -/** - * master_dev - generic Master device - * @list: handle for linked list of Master devices - * @bridge_addr: PCI bridge or DMA Controller base address - * @core: device core base address - * @name: marketing name of this device - * @version: firmware version - * @irq_handler: pointer to interrupt handler - * @iface_list: linked list of interfaces - * @capabilities: capabilities flags - * @class_dev: class device structure - * @irq_lock: lock for shared board registers accessed in interrupt context - * @reg_lock: lock for all other shared board registers - * @users_sem: lock for iface[].users - * @pdev: PCI device - **/ -struct master_dev { - struct list_head list; - void *bridge_addr; - union { - void *addr; - resource_size_t port; - } core; - const char *name; - unsigned int version; - irq_handler_t irq_handler; - struct list_head iface_list; - unsigned int capabilities; - struct class_device class_dev; - spinlock_t irq_lock; - spinlock_t reg_lock; - struct semaphore users_sem; - struct pci_dev *pdev; -}; - -/* External function prototypes */ - -unsigned int mdev_users (struct master_dev *card); -unsigned int mdev_index (struct master_dev *card, struct list_head *list); -void mdev_class_device_release (struct class_device *cd); -int mdev_register (struct master_dev *card, - struct list_head *devlist, - char *driver_name, - struct class *cls); -void mdev_unregister (struct master_dev *card); -int mdev_init_module (struct pci_driver *pci_drv, - struct class *cls, - char *name) __init; -void mdev_cleanup_module (struct pci_driver *pci_drv, - struct class *cls) __exit; - -/* Inline functions */ - -#define master_inl(card,offset) \ - inl((card)->core.port+(offset)) -#define master_outl(card,offset,val) \ - outl((val),(card)->core.port+(offset)) - -#define master_readl(card,offset) \ - readl((card)->core.addr+(offset)) -#define master_writel(card,offset,val) \ - writel((val),(card)->core.addr+(offset)) - -#endif - diff --git a/quad/src/miface.c b/quad/src/miface.c old mode 100755 new mode 100644 index 7903c53ad..bf14c8b6a --- a/quad/src/miface.c +++ b/quad/src/miface.c @@ -54,10 +54,13 @@ static const char fmt_x[] = "0x%04X\n"; /** * miface_show_version - class attribute read handler * @cls: class being read + * @attr: class attribute * @buf: output buffer **/ ssize_t -miface_show_version (struct class *cls, char *buf) +miface_show_version (struct class *cls, + struct class_attribute *attr, + char *buf) { return snprintf (buf, PAGE_SIZE, "%s\n", MASTER_DRIVER_VERSION); } @@ -82,6 +85,7 @@ MIFACE_SHOW(clksrc,fmt_u) MIFACE_SHOW(count27,fmt_u) MIFACE_SHOW(granularity,fmt_u) MIFACE_SHOW(mode,fmt_u) +MIFACE_SHOW(vanc,fmt_u) MIFACE_SHOW(null_packets,fmt_u) MIFACE_SHOW(timestamps,fmt_u) MIFACE_SHOW(transport,fmt_u) @@ -190,7 +194,7 @@ miface_open (struct inode *inode, struct file *filp) (request_irq (card->irq, card->irq_handler, IRQF_SHARED, - card->name, + filp->f_op->owner->name, card) != 0)) { mdma_free (iface->dma); mutex_unlock (&card->users_mutex); diff --git a/quad/src/miface.h b/quad/src/miface.h old mode 100755 new mode 100644 index 61a164943..25e8d5048 --- a/quad/src/miface.h +++ b/quad/src/miface.h @@ -25,6 +25,8 @@ #ifndef _MIFACE_H #define _MIFACE_H +#include /* LINUX_VERSION_CODE */ + #include /* uid_t */ #include /* list_head */ #include /* wait_queue_head_t */ @@ -38,6 +40,14 @@ #include "mdev.h" #include "mdma.h" +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)) +#define FSYNC_HANDLER(name,filp,datasync) \ + name (struct file *filp, struct dentry *dentry, int datasync) +#else +#define FSYNC_HANDLER(name,filp,datasync) \ + name (struct file *filp, int datasync) +#endif + #define MASTER_MINORBITS 8 #define MASTER_DIRECTION_TX 0 @@ -75,6 +85,7 @@ struct master_iface_operations { * @granularity: buffer size granularity in bytes * @mode: operating mode * @frmode: frame mode + * @vanc: vertical ancillary space * @sample_size: audio sample size * @sample_rate: audio sample rate * @channels: enable audio channel @@ -113,6 +124,7 @@ struct master_iface { unsigned int granularity; unsigned int mode; unsigned int frmode; + unsigned int vanc; unsigned int sample_size; unsigned int sample_rate; unsigned int channels; @@ -141,7 +153,12 @@ struct master_iface { /* External function prototypes */ -ssize_t miface_show_version (struct class *cls, char *buf); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34)) +#define miface_show_version(cls,attr,buf) miface_show_version(cls,buf) +#endif +ssize_t miface_show_version (struct class *cls, + struct class_attribute *attr, + char *buf); ssize_t miface_show_buffers (struct device *dev, struct device_attribute *attr, char *buf); @@ -160,6 +177,9 @@ ssize_t miface_show_granularity (struct device *dev, ssize_t miface_show_mode (struct device *dev, struct device_attribute *attr, char *buf); +ssize_t miface_show_vanc (struct device *dev, + struct device_attribute *attr, + char *buf); ssize_t miface_show_frmode (struct device *dev, struct device_attribute *attr, char *buf); diff --git a/quad/src/mmas.h b/quad/src/mmas.h old mode 100755 new mode 100644 diff --git a/quad/src/mmsa.h b/quad/src/mmsa.h old mode 100755 new mode 100644 diff --git a/quad/src/plx9080.c b/quad/src/plx9080.c old mode 100755 new mode 100644 diff --git a/quad/src/plx9080.h b/quad/src/plx9080.h old mode 100755 new mode 100644 diff --git a/quad/src/sa.c b/quad/src/sa.c old mode 100755 new mode 100644 index a5b32a319..42fbc2202 --- a/quad/src/sa.c +++ b/quad/src/sa.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* MODULE_LICENSE */ @@ -86,9 +85,7 @@ static void mmsa_start_tx_dma (struct master_iface *iface); static long mmsa_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int mmsa_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(mmsa_txfsync,filp,datasync); static void mmsa_rxinit (struct master_iface *iface); static void mmsa_rxstart (struct master_iface *iface); static void mmsa_rxstop (struct master_iface *iface); @@ -96,9 +93,7 @@ static void mmsa_rxexit (struct master_iface *iface); static long mmsa_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int mmsa_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(mmsa_rxfsync,filp,datasync); static int mmsa_init_module (void) __init; static void mmsa_cleanup_module (void) __exit; @@ -136,7 +131,7 @@ static struct file_operations mmsa_txfops = { .write = asi_write, .poll = asi_txpoll, .unlocked_ioctl = mmsa_txunlocked_ioctl, - .compat_ioctl = asi_compat_ioctl, + .compat_ioctl = mmsa_txunlocked_ioctl, .mmap = NULL, .open = asi_open, .release = asi_release, @@ -150,7 +145,7 @@ static struct file_operations mmsa_rxfops = { .read = sdi_read, .poll = sdi_rxpoll, .unlocked_ioctl = mmsa_rxunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = mmsa_rxunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -213,14 +208,23 @@ mmsa_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } spin_lock (&card->reg_lock); reg = master_inl (card, MMSA_TCSR) & ~MMSA_TCSR_PAL; master_outl (card, MMSA_TCSR, reg | (val << 13)); spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -396,7 +400,17 @@ mmsa_pci_probe (struct pci_dev *pdev, ASI_CAP_TX_27COUNTER | ASI_CAP_TX_TIMESTAMPS | ASI_CAP_TX_PTIMESTAMPS | ASI_CAP_TX_NULLPACKETS; - cap |= (card->version >= 0x0302) ? ASI_CAP_TX_RXCLKSRC : 0; + switch (pdev->device) { + default: + case MMSA_PCI_DEVICE_ID_LINSYS: + if (card->version >= 0x0302) { + cap |= ASI_CAP_TX_RXCLKSRC; + } + break; + case MMSAE_PCI_DEVICE_ID_LINSYS: + cap |= ASI_CAP_TX_RXCLKSRC; + break; + } if ((err = asi_register_iface (card, &plx_dma_ops, MMSA_FIFO, @@ -818,15 +832,12 @@ mmsa_txunlocked_ioctl (struct file *filp, /** * mmsa_txfsync - MultiMaster SDI-R transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -mmsa_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(mmsa_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dma *dma = iface->dma; @@ -1014,15 +1025,12 @@ mmsa_rxunlocked_ioctl (struct file *filp, /** * mmsa_rxfsync - MultiMaster SDI-R receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -mmsa_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(mmsa_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/sdiaudiocore.c b/quad/src/sdiaudiocore.c index 1a3c6587c..23883196b 100644 --- a/quad/src/sdiaudiocore.c +++ b/quad/src/sdiaudiocore.c @@ -1,6 +1,6 @@ /* sdiaudiocore.c * - * Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C Audio API. + * Linear Systems Ltd. SDI audio API. * * Copyright (C) 2009-2010 Linear Systems Ltd. * @@ -103,7 +103,6 @@ EXPORT_SYMBOL(sdiaudio_txpoll); EXPORT_SYMBOL(sdiaudio_rxpoll); EXPORT_SYMBOL(sdiaudio_txioctl); EXPORT_SYMBOL(sdiaudio_rxioctl); -EXPORT_SYMBOL(sdiaudio_compat_ioctl); EXPORT_SYMBOL(sdiaudio_mmap); EXPORT_SYMBOL(sdiaudio_release); EXPORT_SYMBOL(sdiaudio_register_iface); @@ -332,24 +331,6 @@ sdiaudio_rxioctl (struct file *filp, return 0; } -/** - * sdiaudio_compat_ioctl - 32-bit ioctl handler - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -long -sdiaudio_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = filp->f_dentry->d_inode; - - return filp->f_op->ioctl (inode, filp, cmd, arg); -} - /** * sdiaudio_mmap - SMPTE 292M and SMPTE 259M-C audio interface mmap() method * @filp: file diff --git a/quad/src/sdiaudiocore.h b/quad/src/sdiaudiocore.h index 844ee6e93..32a13c45e 100644 --- a/quad/src/sdiaudiocore.h +++ b/quad/src/sdiaudiocore.h @@ -1,9 +1,9 @@ /* sdiaudiocore.h * - * Header file for the Linux user-space API for - * Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C interface boards. + * Header file for the Linux user-space audio API for + * Linear Systems Ltd. SDI interface boards. * - * Copyright (C) 2009 Linear Systems Ltd. + * Copyright (C) 2009-2010 Linear Systems Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,9 +57,6 @@ long sdiaudio_txioctl (struct file *filp, long sdiaudio_rxioctl (struct file *filp, unsigned int cmd, unsigned long arg); -long sdiaudio_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); int sdiaudio_mmap (struct file *filp, struct vm_area_struct *vma); int sdiaudio_release (struct inode *inode, struct file *filp); int sdiaudio_register_iface (struct master_dev *card, diff --git a/quad/src/sdicore.c b/quad/src/sdicore.c old mode 100755 new mode 100644 index a8312fff3..e88cf9140 --- a/quad/src/sdicore.c +++ b/quad/src/sdicore.c @@ -93,7 +93,6 @@ EXPORT_SYMBOL(sdi_txpoll); EXPORT_SYMBOL(sdi_rxpoll); EXPORT_SYMBOL(sdi_txioctl); EXPORT_SYMBOL(sdi_rxioctl); -EXPORT_SYMBOL(sdi_compat_ioctl); EXPORT_SYMBOL(sdi_mmap); EXPORT_SYMBOL(sdi_release); EXPORT_SYMBOL(sdi_register_iface); @@ -326,24 +325,6 @@ sdi_rxioctl (struct file *filp, return 0; } -/** - * sdi_compat_ioctl - 32-bit ioctl handler - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -long -sdi_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = filp->f_dentry->d_inode; - - return filp->f_op->ioctl (inode, filp, cmd, arg); -} - /** * sdi_mmap - SDI interface mmap() method * @filp: file diff --git a/quad/src/sdicore.h b/quad/src/sdicore.h old mode 100755 new mode 100644 index 2af70333b..8864350e1 --- a/quad/src/sdicore.h +++ b/quad/src/sdicore.h @@ -3,7 +3,7 @@ * Header file for the Linux user-space API for * Linear Systems Ltd. SMPTE 259M-C interface boards. * - * Copyright (C) 2004-2009 Linear Systems Ltd. + * Copyright (C) 2004-2010 Linear Systems Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,9 +57,6 @@ long sdi_txioctl (struct file *filp, long sdi_rxioctl (struct file *filp, unsigned int cmd, unsigned long arg); -long sdi_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); int sdi_mmap (struct file *filp, struct vm_area_struct *vma); int sdi_release (struct inode *inode, struct file *filp); int sdi_register_iface (struct master_dev *card, diff --git a/quad/src/sdim.h b/quad/src/sdim.h old mode 100755 new mode 100644 diff --git a/quad/src/sdim_lpfd.c b/quad/src/sdim_lpfd.c old mode 100755 new mode 100644 index 644daa146..9721223bf --- a/quad/src/sdim_lpfd.c +++ b/quad/src/sdim_lpfd.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* MODULE_LICENSE */ @@ -84,9 +83,7 @@ static void sdim_start_tx_dma (struct master_iface *iface); static long sdim_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(sdim_txfsync,filp,datasync); static void sdim_rxinit (struct master_iface *iface); static void sdim_rxstart (struct master_iface *iface); static void sdim_rxstop (struct master_iface *iface); @@ -94,9 +91,7 @@ static void sdim_rxexit (struct master_iface *iface); static long sdim_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(sdim_rxfsync,filp,datasync); static int sdim_init_module (void) __init; static void sdim_cleanup_module (void) __exit; @@ -134,7 +129,7 @@ static struct file_operations sdim_txfops = { .write = sdi_write, .poll = sdi_txpoll, .unlocked_ioctl = sdim_txunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = sdim_txunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -148,7 +143,7 @@ static struct file_operations sdim_rxfops = { .read = sdi_read, .poll = sdi_rxpoll, .unlocked_ioctl = sdim_rxunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = sdim_rxunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -211,14 +206,21 @@ sdim_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } - spin_lock (&card->reg_lock); + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } reg = readl (card->core.addr + SDIM_TCSR) & ~SDIM_TCSR_PAL; writel (reg | (val << 9), card->core.addr + SDIM_TCSR); - spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -594,11 +596,9 @@ sdim_txinit (struct master_iface *iface) reg |= SDIM_TCSR_RXCLK; break; } - spin_lock (&card->reg_lock); reg |= readl (card->core.addr + SDIM_TCSR) & SDIM_TCSR_PAL; writel (reg | SDIM_TCSR_RST, card->core.addr + SDIM_TCSR); writel (reg, card->core.addr + SDIM_TCSR); - spin_unlock (&card->reg_lock); writel ((SDIM_TFSL << 16) | SDIM_TDMATL, card->core.addr + SDIM_TFCR); return; @@ -614,10 +614,6 @@ sdim_txstart (struct master_iface *iface) struct master_dev *card = iface->card; unsigned int reg; - /* Enable DMA */ - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(0)); - /* Enable transmitter interrupts */ spin_lock_irq (&card->irq_lock); reg = readl (card->core.addr + SDIM_ICSR) & @@ -627,10 +623,9 @@ sdim_txstart (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Disable RP178 pattern generation and enable the transmitter */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_TCSR); - writel (reg | SDIM_TCSR_EN | SDIM_TCSR_RP178, card->core.addr + SDIM_TCSR); - spin_unlock (&card->reg_lock); + writel (reg | SDIM_TCSR_EN | SDIM_TCSR_RP178, + card->core.addr + SDIM_TCSR); return; } @@ -656,10 +651,9 @@ sdim_txstop (struct master_iface *iface) !(readl (card->core.addr + SDIM_ICSR) & SDIM_ICSR_TXD)); /* Disable the transmitter and enable RP178 pattern generation */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_TCSR); - writel (reg & ~SDIM_TCSR_EN & ~SDIM_TCSR_RP178, card->core.addr + SDIM_TCSR); - spin_unlock (&card->reg_lock); + writel (reg & ~SDIM_TCSR_EN & ~SDIM_TCSR_RP178, + card->core.addr + SDIM_TCSR); /* Disable transmitter interrupts */ spin_lock_irq (&card->irq_lock); @@ -670,8 +664,7 @@ sdim_txstop (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Disable DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE) & - ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(0)); return; @@ -688,10 +681,8 @@ sdim_txexit (struct master_iface *iface) unsigned int reg; /* Reset the transmitter */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_TCSR); writel (reg | SDIM_TCSR_RST, card->core.addr + SDIM_TCSR); - spin_unlock (&card->reg_lock); return; } @@ -709,13 +700,11 @@ sdim_start_tx_dma (struct master_iface *iface) writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(0)); - wmb (); writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC(0)); writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(0)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_ENABLE, @@ -758,15 +747,12 @@ sdim_txunlocked_ioctl (struct file *filp, /** * sdim_txfsync - SDI Master transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -810,9 +796,7 @@ sdim_rxinit (struct master_iface *iface) /* There will be no races on RCSR * until this code returns, so we don't need to lock it */ writel (reg | SDIM_RCSR_RST, card->core.addr + SDIM_RCSR); - wmb (); writel (reg, card->core.addr + SDIM_RCSR); - wmb (); writel (SDIM_RDMATL, card->core.addr + SDIM_RFCR); return; @@ -835,7 +819,6 @@ sdim_rxstart (struct master_iface *iface) writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(1)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(1)); @@ -852,10 +835,8 @@ sdim_rxstart (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Enable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_RCSR); writel (reg | SDIM_RCSR_EN, card->core.addr + SDIM_RCSR); - spin_unlock (&card->reg_lock); return; } @@ -871,10 +852,8 @@ sdim_rxstop (struct master_iface *iface) unsigned int reg; /* Disable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_RCSR); writel (reg & ~SDIM_RCSR_EN, card->core.addr + SDIM_RCSR); - spin_unlock (&card->reg_lock); /* Disable receiver interrupts */ spin_lock_irq (&card->irq_lock); @@ -886,20 +865,19 @@ sdim_rxstop (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(1)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & - ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(1)); - /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION) & ~LSDMA_CH_CSR_ENABLE, + + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION, card->bridge_addr + LSDMA_CSR(1)); return; @@ -962,15 +940,12 @@ sdim_rxunlocked_ioctl (struct file *filp, /** * sdim_rxfsync - SDI Master receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -985,7 +960,6 @@ sdim_rxfsync (struct file *filp, spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_RCSR); writel (reg | SDIM_RCSR_RST, card->core.addr + SDIM_RCSR); - wmb (); writel (reg, card->core.addr + SDIM_RCSR); spin_unlock (&card->reg_lock); iface->events = 0; diff --git a/quad/src/sdim_qie.c b/quad/src/sdim_qie.c old mode 100755 new mode 100644 index 9a8420c86..e038cd7be --- a/quad/src/sdim_qie.c +++ b/quad/src/sdim_qie.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* THIS_MODULE */ @@ -78,9 +77,7 @@ static void sdim_qie_exit (struct master_iface *iface); static long sdim_qie_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_qie_fsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(sdim_qie_fsync,filp,datasync); static int sdim_qie_init_module (void) __init; static void sdim_qie_cleanup_module (void) __exit; @@ -118,7 +115,7 @@ static struct file_operations sdim_qie_fops = { .read = sdi_read, .poll = sdi_rxpoll, .unlocked_ioctl = sdim_qie_unlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = sdim_qie_unlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -464,9 +461,7 @@ sdim_qie_init (struct master_iface *iface) /* There will be no races on RCR * until this code returns, so we don't need to lock it */ writel (reg | SDIM_QIE_RCSR_RST, card->core.addr + SDIM_QIE_RCR(channel)); - wmb (); writel (reg, card->core.addr + SDIM_QIE_RCR(channel)); - wmb (); writel(SDIM_QIE_RDMATL, card->core.addr + SDIM_QIE_RDMATLR(channel)); return; @@ -490,7 +485,6 @@ sdim_qie_start (struct master_iface *iface) writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_ENABLE, card->bridge_addr + LSDMA_CSR(channel)); @@ -504,10 +498,9 @@ sdim_qie_start (struct master_iface *iface) spin_unlock_irq (&card->irq_lock); /* Enable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_QIE_RCR(channel)); - writel (reg | SDIM_QIE_RCSR_EN, card->core.addr + SDIM_QIE_RCR(channel)); - spin_unlock (&card->reg_lock); + writel (reg | SDIM_QIE_RCSR_EN, + card->core.addr + SDIM_QIE_RCR(channel)); return; } @@ -524,31 +517,30 @@ sdim_qie_stop (struct master_iface *iface) unsigned int reg; /* Disable the receiver */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_QIE_RCR(channel)); - writel (reg & ~SDIM_QIE_RCSR_EN, card->core.addr + SDIM_QIE_RCR(channel)); - spin_unlock (&card->reg_lock); + writel (reg & ~SDIM_QIE_RCSR_EN, + card->core.addr + SDIM_QIE_RCR(channel)); /* Disable receiver interrupts */ spin_lock_irq (&card->irq_lock); writel (SDIM_QIE_ICSR_RXCDIS | SDIM_QIE_ICSR_RXOIS | SDIM_QIE_ICSR_RXDIS, card->core.addr + SDIM_QIE_ICSR(channel)); + spin_unlock_irq (&card->irq_lock); /* Disable and abort DMA */ - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(channel)); - wmb (); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(channel)); - /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); - spin_unlock_irq (&card->irq_lock); + wait_event (iface->queue, test_bit (0, &iface->dma_done)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, + + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | + LSDMA_CH_CSR_DIRECTION | LSDMA_CH_CSR_STOP, card->bridge_addr + LSDMA_CSR(channel)); return; @@ -614,15 +606,12 @@ sdim_qie_unlocked_ioctl (struct file *filp, /** * sdim_qie_fsync - SDI Master Q/i receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_qie_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_qie_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -635,12 +624,9 @@ sdim_qie_fsync (struct file *filp, sdim_qie_stop (iface); /* Reset the onboard FIFO and driver buffers */ - spin_lock (&card->reg_lock); reg = readl (card->core.addr + SDIM_QIE_RCR(channel)); writel (reg | SDIM_QIE_RCSR_RST, card->core.addr + SDIM_QIE_RCR(channel)); - wmb (); writel (reg, card->core.addr + SDIM_QIE_RCR(channel)); - spin_unlock (&card->reg_lock); iface->events = 0; lsdma_reset (iface->dma); diff --git a/quad/src/sdim_qie.h b/quad/src/sdim_qie.h old mode 100755 new mode 100644 diff --git a/quad/src/sdim_qoe.c b/quad/src/sdim_qoe.c old mode 100755 new mode 100644 index f790fb52f..1f41efb5c --- a/quad/src/sdim_qoe.c +++ b/quad/src/sdim_qoe.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* THIS_MODULE */ @@ -35,7 +34,6 @@ #include /* spin_lock_init () */ #include /* __devinit */ #include /* error codes */ -#include /* udelay () */ #include /* irqreturn_t */ #include /* device_create_file */ #include /* mutex_init () */ @@ -85,8 +83,7 @@ static void sdim_qoe_start_tx_dma (struct master_iface *iface); static long sdim_qoe_unlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_qoe_fsync (struct file *filp, - struct dentry *dentry, int datasync); +static int FSYNC_HANDLER(sdim_qoe_fsync,filp,datasync); static int sdim_qoe_init_module (void) __init; static void sdim_qoe_cleanup_module (void) __exit; @@ -119,8 +116,8 @@ static struct file_operations sdim_qoe_fops = { .llseek = no_llseek, .write = sdi_write, .poll = sdi_txpoll, - .unlocked_ioctl=sdim_qoe_unlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .unlocked_ioctl = sdim_qoe_unlocked_ioctl, + .compat_ioctl = sdim_qoe_unlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -176,14 +173,26 @@ sdim_qoe_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct list_head *p; + struct master_iface *iface; + unsigned int total_users = 0; if ((endp == buf) || (val > max)) { return -EINVAL; } - spin_lock (&card->reg_lock); + mutex_lock (&card->users_mutex); + list_for_each (p, &card->iface_list) { + iface = list_entry (p, struct master_iface, list); + total_users += iface->users; + } + if (total_users) { + retcode = -EBUSY; + goto OUT; + } reg = readl (card->core.addr + SDIM_QOE_CSR) & ~SDIM_QOE_CSR_PAL; writel (reg | (val << 2), card->core.addr + SDIM_QOE_CSR); - spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -433,11 +442,11 @@ IRQ_HANDLER (sdim_qoe_irq_handler, irq, dev_id, regs) } /* Flag DMA abort */ - if (status &LSDMA_CH_CSR_INTSRCSTOP) { + if (status & LSDMA_CH_CSR_INTSRCSTOP) { set_bit(0, &iface->dma_done); } - interrupting_iface |= (0x1 << i ); + interrupting_iface |= 0x1 << i; } /* Check and clear the source of the interrupts */ @@ -478,7 +487,9 @@ sdim_qoe_init (struct master_iface *iface) { struct master_dev *card = iface->card; const unsigned int channel = mdev_index (card, &iface->list); - unsigned int reg = 0, clkreg = readl (card->core.addr + SDIM_QOE_CSR); + unsigned int reg = 0; + unsigned int clkreg = + readl (card->core.addr + SDIM_QOE_CSR) & ~SDIM_QOE_CSR_EXTCLK; switch (iface->mode) { default: @@ -489,7 +500,6 @@ sdim_qoe_init (struct master_iface *iface) reg |= SDIM_TCSR_10BIT; break; } - switch (iface->clksrc) { default: case SDI_CTL_TX_CLKSRC_ONBOARD: @@ -505,15 +515,14 @@ sdim_qoe_init (struct master_iface *iface) */ writel (reg | SDIM_QOE_TCSR_TXRST, card->core.addr + SDIM_QOE_TCSR(channel)); - wmb(); - /* Set the transmit clock source (shared by all 4 channels) */ + /* XXX Set the transmit clock source (shared by all 4 channels) + * This is broken because each channel can set a different clock source + * for all channels */ writel (clkreg, card->core.addr + SDIM_QOE_CSR); - wmb(); - writel (reg, card->core.addr + SDIM_QOE_TCSR(channel)); - wmb(); - /* Dummy read to flush PCI posted writes */ - readl (card->core.addr + SDIM_QOE_ICSR(channel)); + readl (card->core.addr + SDIM_QOE_FPGAID); + writel (reg, card->core.addr + SDIM_QOE_TCSR(channel)); + writel (SDIM_QOE_TFSL << 16, card->core.addr + SDIM_QOE_TFCR(channel)); /* Disable RP178 pattern generation. @@ -536,15 +545,10 @@ sdim_qoe_start (struct master_iface *iface) const unsigned int channel = mdev_index (card, &iface->list); unsigned int reg = 0; - /* Enabling Channel DMA Explicitly */ - writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, - card->bridge_addr + LSDMA_CSR(channel)); - /* Enable transmitter interrupts */ spin_lock_irq (&card->irq_lock); - reg |= SDIM_QOE_ICSR_TUIE | SDIM_QOE_ICSR_TXDIE; - writel(reg, card->core.addr + SDIM_QOE_ICSR(channel)); - readl(card->core.addr + SDIM_QOE_FPGAID); + writel(SDIM_QOE_ICSR_TUIE | SDIM_QOE_ICSR_TXDIE, + card->core.addr + SDIM_QOE_ICSR(channel)); spin_unlock_irq(&card->irq_lock); /* Enable the transmitter @@ -580,7 +584,6 @@ sdim_qoe_stop (struct master_iface *iface) SDIM_QOE_ICSR_TXD)); /* Disable the Transmitter */ - /* Races will be taken care of here */ reg = readl(card->core.addr + SDIM_QOE_TCSR(channel)); writel(reg & ~SDIM_QOE_TCSR_TXE, card->core.addr + SDIM_QOE_TCSR(channel)); @@ -589,14 +592,12 @@ sdim_qoe_stop (struct master_iface *iface) spin_lock_irq (&card->irq_lock); reg = SDIM_QOE_ICSR_TUIS | SDIM_QOE_ICSR_TXDIS; writel (reg, card->core.addr + SDIM_QOE_ICSR(channel)); - writel ((LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | - LSDMA_CH_CSR_STOP) & ~LSDMA_CH_CSR_ENABLE, - card->bridge_addr + LSDMA_CSR(channel)); /* Dummy read to flush PCI posted writes */ readl (card->bridge_addr + LSDMA_INTMSK); spin_unlock_irq (&card->irq_lock); - udelay (10L); + writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, + card->bridge_addr + LSDMA_CSR(channel)); return; } @@ -633,13 +634,11 @@ sdim_qoe_start_tx_dma (struct master_iface *iface) writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE, card->bridge_addr + LSDMA_CSR(dma_channel)); - wmb (); writel (mdma_dma_to_desc_low (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC(dma_channel)); writel (mdma_dma_to_desc_high (lsdma_head_desc_bus_addr (dma)), card->bridge_addr + LSDMA_DESC_H(dma_channel)); clear_bit (0, &iface->dma_done); - wmb (); writel (LSDMA_CH_CSR_INTDONEENABLE | LSDMA_CH_CSR_INTSTOPENABLE | LSDMA_CH_CSR_ENABLE, @@ -686,15 +685,12 @@ sdim_qoe_unlocked_ioctl (struct file *filp, /** * sdim_qoe_fsync - SDI Master Q/o fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_qoe_fsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_qoe_fsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/sdim_qoe.h b/quad/src/sdim_qoe.h old mode 100755 new mode 100644 diff --git a/quad/src/sdimaster.c b/quad/src/sdimaster.c old mode 100755 new mode 100644 index 9a3338f9f..c687a0720 --- a/quad/src/sdimaster.c +++ b/quad/src/sdimaster.c @@ -22,7 +22,6 @@ * */ -#include /* LINUX_VERSION_CODE */ #include /* KERN_INFO */ #include /* MODULE_LICENSE */ @@ -84,9 +83,7 @@ static void sdim_start_tx_dma (struct master_iface *iface); static long sdim_txunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_txfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(sdim_txfsync,filp,datasync); static void sdim_rxinit (struct master_iface *iface); static void sdim_rxstart (struct master_iface *iface); static void sdim_rxstop (struct master_iface *iface); @@ -94,9 +91,7 @@ static void sdim_rxexit (struct master_iface *iface); static long sdim_rxunlocked_ioctl (struct file *filp, unsigned int cmd, unsigned long arg); -static int sdim_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync); +static int FSYNC_HANDLER(sdim_rxfsync,filp,datasync); static int sdim_init_module (void) __init; static void sdim_cleanup_module (void) __exit; @@ -134,7 +129,7 @@ static struct file_operations sdim_txfops = { .write = sdi_write, .poll = sdi_txpoll, .unlocked_ioctl = sdim_txunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = sdim_txunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -148,7 +143,7 @@ static struct file_operations sdim_rxfops = { .read = sdi_read, .poll = sdi_rxpoll, .unlocked_ioctl = sdim_rxunlocked_ioctl, - .compat_ioctl = sdi_compat_ioctl, + .compat_ioctl = sdim_rxunlocked_ioctl, .mmap = sdi_mmap, .open = sdi_open, .release = sdi_release, @@ -211,14 +206,23 @@ sdim_store_blackburst_type (struct device *dev, unsigned int reg; const unsigned long max = MASTER_CTL_BLACKBURST_PAL; int retcode = count; + struct master_iface *txiface = list_entry (card->iface_list.next, + struct master_iface, list); if ((endp == buf) || (val > max)) { return -EINVAL; } + mutex_lock (&card->users_mutex); + if (txiface->users) { + retcode = -EBUSY; + goto OUT; + } spin_lock (&card->reg_lock); reg = master_inl (card, SDIM_TCSR) & ~SDIM_TCSR_PAL; master_outl (card, SDIM_TCSR, reg | (val << 9)); spin_unlock (&card->reg_lock); +OUT: + mutex_unlock (&card->users_mutex); return retcode; } @@ -752,15 +756,12 @@ sdim_txunlocked_ioctl (struct file *filp, /** * sdim_txfsync - SDI Master transmitter fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_txfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_txfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; @@ -945,15 +946,12 @@ sdim_rxunlocked_ioctl (struct file *filp, /** * sdim_rxfsync - SDI Master receiver fsync() method * @filp: file to flush - * @dentry: directory entry associated with the file * @datasync: used by filesystems * * Returns a negative error code on failure and 0 on success. **/ static int -sdim_rxfsync (struct file *filp, - struct dentry *dentry, - int datasync) +FSYNC_HANDLER(sdim_rxfsync,filp,datasync) { struct master_iface *iface = filp->private_data; struct master_dev *card = iface->card; diff --git a/quad/src/sdivideocore.c b/quad/src/sdivideocore.c index ef9a4c002..a0ab3e396 100644 --- a/quad/src/sdivideocore.c +++ b/quad/src/sdivideocore.c @@ -1,6 +1,6 @@ /* sdivideocore.c * - * Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C API + * Linear Systems Ltd. SDI video API * * Copyright (C) 2009-2010 Linear Systems Ltd. * @@ -83,6 +83,9 @@ static ssize_t sdivideo_store_frmode (struct device *dev, static ssize_t sdivideo_store_mode (struct device *dev, struct device_attribute *attr, const char *buf, size_t count); +static ssize_t sdivideo_store_vanc (struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); static ssize_t sdivideo_store_vb1cnt (struct device *dev, struct device_attribute *attr, const char *buf, size_t count); @@ -118,7 +121,6 @@ EXPORT_SYMBOL(sdivideo_txpoll); EXPORT_SYMBOL(sdivideo_rxpoll); EXPORT_SYMBOL(sdivideo_txioctl); EXPORT_SYMBOL(sdivideo_rxioctl); -EXPORT_SYMBOL(sdivideo_compat_ioctl); EXPORT_SYMBOL(sdivideo_mmap); EXPORT_SYMBOL(sdivideo_release); EXPORT_SYMBOL(sdivideo_register_iface); @@ -347,24 +349,6 @@ sdivideo_rxioctl (struct file *filp, return 0; } -/** - * sdivideo_compat_ioctl - 32-bit ioctl handler - * @filp: file - * @cmd: ioctl command - * @arg: ioctl argument - * - * Returns a negative error code on failure and 0 on success. - **/ -long -sdivideo_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg) -{ - struct inode *inode = filp->f_dentry->d_inode; - - return filp->f_op->ioctl (inode, filp, cmd, arg); -} - /** * sdivideo_mmap - SMPTE 292M and SMPTE 259M-C video interface mmap() method * @filp: file @@ -515,6 +499,8 @@ sdivideo_validate_mode (struct master_iface *iface, return 0; } +#define sdivideo_validate_vanc(iface,val) (0) + /** * sdivideo_validate_vb1cnt - validate a vb1cnt attribute value * @iface: interface being written @@ -619,6 +605,7 @@ SDIVIDEO_STORE(bufsize) SDIVIDEO_STORE(clksrc) SDIVIDEO_STORE(frmode) SDIVIDEO_STORE(mode) +SDIVIDEO_STORE(vanc) SDIVIDEO_STORE(vb1cnt) SDIVIDEO_STORE(vb1ln1) SDIVIDEO_STORE(vb2cnt) @@ -634,6 +621,8 @@ static DEVICE_ATTR(frame_mode,S_IRUGO|S_IWUSR, miface_show_frmode,sdivideo_store_frmode); static DEVICE_ATTR(mode,S_IRUGO|S_IWUSR, miface_show_mode,sdivideo_store_mode); +static DEVICE_ATTR(vanc,S_IRUGO|S_IWUSR, + miface_show_vanc,sdivideo_store_vanc); static DEVICE_ATTR(vb1_cnt,S_IRUGO|S_IWUSR, miface_show_vb1cnt,sdivideo_store_vb1cnt); static DEVICE_ATTR(vb1_ln1,S_IRUGO|S_IWUSR, @@ -704,6 +693,7 @@ sdivideo_register_iface (struct master_dev *card, } iface->granularity = granularity; iface->mode = SDIVIDEO_CTL_MODE_UYVY; + iface->vanc = 0; iface->ops = iface_ops; iface->dma_ops = dma_ops; iface->data_addr = data_addr; @@ -798,8 +788,24 @@ sdivideo_register_iface (struct master_dev *card, "%s: unable to create file 'frame_mode'\n", sdivideo_driver_name); } + if (iface->capabilities & SDIVIDEO_CAP_TX_VANC) { + if ((err = device_create_file (iface->dev, + &dev_attr_vanc)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'vanc'\n", + sdivideo_driver_name); + } + } } if (iface->direction == MASTER_DIRECTION_RX) { + if (iface->capabilities & SDIVIDEO_CAP_RX_VANC) { + if ((err = device_create_file (iface->dev, + &dev_attr_vanc)) < 0) { + printk (KERN_WARNING + "%s: unable to create file 'vanc'\n", + sdivideo_driver_name); + } + } if (iface->capabilities & SDIVIDEO_CAP_RX_VBI) { if ((err = device_create_file (iface->dev, &dev_attr_vb1_cnt)) < 0) { diff --git a/quad/src/sdivideocore.h b/quad/src/sdivideocore.h index da9fe83c8..d0289489f 100644 --- a/quad/src/sdivideocore.h +++ b/quad/src/sdivideocore.h @@ -1,9 +1,9 @@ /* sdivideocore.h * - * Header file for the Linux user-space API for - * Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C interface boards. + * Header file for the Linux user-space video API for + * Linear Systems Ltd. SDI interface boards. * - * Copyright (C) 2009 Linear Systems Ltd. + * Copyright (C) 2009-2010 Linear Systems Ltd. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,9 +57,6 @@ long sdivideo_txioctl (struct file *filp, long sdivideo_rxioctl (struct file *filp, unsigned int cmd, unsigned long arg); -long sdivideo_compat_ioctl (struct file *filp, - unsigned int cmd, - unsigned long arg); int sdivideo_mmap (struct file *filp, struct vm_area_struct *vma); int sdivideo_release (struct inode *inode, struct file *filp); int sdivideo_register_iface (struct master_dev *card, diff --git a/ultragrid/src/video_capture/quad.c b/ultragrid/src/video_capture/quad.c index 0fa3c5fee..0a8722221 100644 --- a/ultragrid/src/video_capture/quad.c +++ b/ultragrid/src/video_capture/quad.c @@ -189,8 +189,10 @@ struct vidcap_quad_state { struct video_frame frame; }; -int frames = 0; -struct timeval t, t0; +static int frames = 0; +static struct timeval t, t0; + +static void print_output_modes(); static void get_carrier (int fd) @@ -220,8 +222,8 @@ static const struct frame_mode * get_video_standard (int fd) "detected."); return NULL; } else { - if(val >= sizeof(frame_modes)/sizeof(struct frame_mode) - || frame_modes[val].magic != FMODE_MAGIC) { + if(val < sizeof(frame_modes)/sizeof(struct frame_mode) + && frame_modes[val].magic == FMODE_MAGIC) { printf("\t%s video mode detected.\n", frame_modes[val].name); return &frame_modes[val]; @@ -247,7 +249,7 @@ vidcap_quad_probe(void) } void * -vidcap_quad_init(void) +vidcap_quad_init(char *init_fmt) { struct vidcap_quad_state *s; @@ -264,6 +266,7 @@ vidcap_quad_init(void) unsigned long int mode; const struct codec_info_t *c_info; const struct frame_mode *frame_mode; + int frame_mode_number; printf("vidcap_quad_init\n"); @@ -428,11 +431,19 @@ vidcap_quad_init(void) } /*Get video standard*/ - frame_mode = get_video_standard (s->fd); - if(frame_mode == NULL) { + //frame_mode = get_video_standard (s->fd); + if(strcmp(init_fmt, "help") == 0) { + print_output_modes(); + return NULL; + } + frame_mode_number = atoi(init_fmt); + if(frame_mode_number < 0 || + frame_mode_number >= + sizeof(frame_modes)/sizeof(struct frame_mode)) { close(s->fd); return NULL; } + frame_mode = &frame_modes[frame_mode_number]; if(frame_mode == &frame_modes[SDIVIDEO_CTL_UNLOCKED]) { fprintf(stderr, "Please setup correct video mode " "via sysfs."); @@ -497,11 +508,13 @@ vidcap_quad_grab(void *state) struct vidcap_quad_state *s = (struct vidcap_quad_state *) state; unsigned int val; - ssize_t read_ret; + ssize_t read_ret = 0ul; ssize_t bytes; /* Receive the data and check for errors */ + while(read_ret < s->frame.data_len) + { if(poll (&(s->pfd), 1, 1000) < 0) { fprintf (stderr, "%s: ", device); perror ("unable to poll device file"); @@ -509,17 +522,11 @@ vidcap_quad_grab(void *state) } if(s->pfd.revents & POLLIN) { - bytes = 0; - while(bytes < s->frame.data_len) { - if ((read_ret = read (s->fd, &s->frame.data[bytes], - s->bufsize)) < 0) { - fprintf (stderr, "%s: ", device); - perror ("unable to read from device file"); - return NULL; - } - bytes += read_ret; - } - + if ((read_ret += read (s->fd, s->frame.data + read_ret, s->frame.data_len - read_ret)) < 0) { + fprintf (stderr, "%s: ", device); + perror ("unable to read from device file"); + return NULL; + } } if(s->pfd.revents & POLLPRI) { @@ -554,6 +561,7 @@ vidcap_quad_grab(void *state) } } + } frames++; @@ -569,6 +577,17 @@ vidcap_quad_grab(void *state) return &s->frame; } +static void print_output_modes() +{ + int i; + printf("usage: -g \n\twhere mode is one of following.\n"); + printf("Available output modes:\n"); + for(i = 0; i < sizeof(frame_modes)/sizeof(struct frame_mode); ++i) { + if(frame_modes[i].magic == FMODE_MAGIC) + printf("\t%2u: %s\n", i, frame_modes[i].name); + } +} + #endif /* HAVE_QUAD */ #endif /* HAVE_MACOSX */ diff --git a/ultragrid/src/video_capture/quad.h b/ultragrid/src/video_capture/quad.h index 799b23ef0..dd896cd35 100644 --- a/ultragrid/src/video_capture/quad.h +++ b/ultragrid/src/video_capture/quad.h @@ -47,6 +47,6 @@ #define VIDCAP_QUAD_ID 0x10203044 struct vidcap_type *vidcap_quad_probe(void); -void *vidcap_quad_init(void); +void *vidcap_quad_init(char *fmt); void vidcap_quad_done(void *state); struct video_frame *vidcap_quad_grab(void *state);