linux/drivers/media/video/cx88/cx88-core.c
<<
>>
Prefs
   1/*
   2 *
   3 * device driver for Conexant 2388x based TV cards
   4 * driver core
   5 *
   6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
   7 *
   8 * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
   9 *     - Multituner support
  10 *     - video_ioctl2 conversion
  11 *     - PAL/M fixes
  12 *
  13 *  This program is free software; you can redistribute it and/or modify
  14 *  it under the terms of the GNU General Public License as published by
  15 *  the Free Software Foundation; either version 2 of the License, or
  16 *  (at your option) any later version.
  17 *
  18 *  This program is distributed in the hope that it will be useful,
  19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 *  GNU General Public License for more details.
  22 *
  23 *  You should have received a copy of the GNU General Public License
  24 *  along with this program; if not, write to the Free Software
  25 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#include <linux/init.h>
  29#include <linux/list.h>
  30#include <linux/module.h>
  31#include <linux/kernel.h>
  32#include <linux/slab.h>
  33#include <linux/kmod.h>
  34#include <linux/sound.h>
  35#include <linux/interrupt.h>
  36#include <linux/pci.h>
  37#include <linux/delay.h>
  38#include <linux/videodev2.h>
  39#include <linux/mutex.h>
  40
  41#include "cx88.h"
  42#include <media/v4l2-common.h>
  43#include <media/v4l2-ioctl.h>
  44
  45MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
  46MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  47MODULE_LICENSE("GPL");
  48
  49/* ------------------------------------------------------------------ */
  50
  51static unsigned int core_debug;
  52module_param(core_debug,int,0644);
  53MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
  54
  55static unsigned int nicam;
  56module_param(nicam,int,0644);
  57MODULE_PARM_DESC(nicam,"tv audio is nicam");
  58
  59static unsigned int nocomb;
  60module_param(nocomb,int,0644);
  61MODULE_PARM_DESC(nocomb,"disable comb filter");
  62
  63#define dprintk(level,fmt, arg...)      if (core_debug >= level)        \
  64        printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
  65
  66static unsigned int cx88_devcount;
  67static LIST_HEAD(cx88_devlist);
  68static DEFINE_MUTEX(devlist);
  69
  70#define NO_SYNC_LINE (-1U)
  71
  72/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
  73         generated _after_ lpi lines are transferred. */
  74static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
  75                            unsigned int offset, u32 sync_line,
  76                            unsigned int bpl, unsigned int padding,
  77                            unsigned int lines, unsigned int lpi)
  78{
  79        struct scatterlist *sg;
  80        unsigned int line,todo,sol;
  81
  82        /* sync instruction */
  83        if (sync_line != NO_SYNC_LINE)
  84                *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
  85
  86        /* scan lines */
  87        sg = sglist;
  88        for (line = 0; line < lines; line++) {
  89                while (offset && offset >= sg_dma_len(sg)) {
  90                        offset -= sg_dma_len(sg);
  91                        sg++;
  92                }
  93                if (lpi && line>0 && !(line % lpi))
  94                        sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
  95                else
  96                        sol = RISC_SOL;
  97                if (bpl <= sg_dma_len(sg)-offset) {
  98                        /* fits into current chunk */
  99                        *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
 100                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
 101                        offset+=bpl;
 102                } else {
 103                        /* scanline needs to be split */
 104                        todo = bpl;
 105                        *(rp++)=cpu_to_le32(RISC_WRITE|sol|
 106                                            (sg_dma_len(sg)-offset));
 107                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
 108                        todo -= (sg_dma_len(sg)-offset);
 109                        offset = 0;
 110                        sg++;
 111                        while (todo > sg_dma_len(sg)) {
 112                                *(rp++)=cpu_to_le32(RISC_WRITE|
 113                                                    sg_dma_len(sg));
 114                                *(rp++)=cpu_to_le32(sg_dma_address(sg));
 115                                todo -= sg_dma_len(sg);
 116                                sg++;
 117                        }
 118                        *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
 119                        *(rp++)=cpu_to_le32(sg_dma_address(sg));
 120                        offset += todo;
 121                }
 122                offset += padding;
 123        }
 124
 125        return rp;
 126}
 127
 128int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 129                     struct scatterlist *sglist,
 130                     unsigned int top_offset, unsigned int bottom_offset,
 131                     unsigned int bpl, unsigned int padding, unsigned int lines)
 132{
 133        u32 instructions,fields;
 134        __le32 *rp;
 135        int rc;
 136
 137        fields = 0;
 138        if (UNSET != top_offset)
 139                fields++;
 140        if (UNSET != bottom_offset)
 141                fields++;
 142
 143        /* estimate risc mem: worst case is one write per page border +
 144           one write per scan line + syncs + jump (all 2 dwords).  Padding
 145           can cause next bpl to start close to a page border.  First DMA
 146           region may be smaller than PAGE_SIZE */
 147        instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
 148        instructions += 2;
 149        if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
 150                return rc;
 151
 152        /* write risc instructions */
 153        rp = risc->cpu;
 154        if (UNSET != top_offset)
 155                rp = cx88_risc_field(rp, sglist, top_offset, 0,
 156                                     bpl, padding, lines, 0);
 157        if (UNSET != bottom_offset)
 158                rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
 159                                     bpl, padding, lines, 0);
 160
 161        /* save pointer to jmp instruction address */
 162        risc->jmp = rp;
 163        BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
 164        return 0;
 165}
 166
 167int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 168                         struct scatterlist *sglist, unsigned int bpl,
 169                         unsigned int lines, unsigned int lpi)
 170{
 171        u32 instructions;
 172        __le32 *rp;
 173        int rc;
 174
 175        /* estimate risc mem: worst case is one write per page border +
 176           one write per scan line + syncs + jump (all 2 dwords).  Here
 177           there is no padding and no sync.  First DMA region may be smaller
 178           than PAGE_SIZE */
 179        instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
 180        instructions += 1;
 181        if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
 182                return rc;
 183
 184        /* write risc instructions */
 185        rp = risc->cpu;
 186        rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
 187
 188        /* save pointer to jmp instruction address */
 189        risc->jmp = rp;
 190        BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
 191        return 0;
 192}
 193
 194int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 195                      u32 reg, u32 mask, u32 value)
 196{
 197        __le32 *rp;
 198        int rc;
 199
 200        if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
 201                return rc;
 202
 203        /* write risc instructions */
 204        rp = risc->cpu;
 205        *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
 206        *(rp++) = cpu_to_le32(reg);
 207        *(rp++) = cpu_to_le32(value);
 208        *(rp++) = cpu_to_le32(mask);
 209        *(rp++) = cpu_to_le32(RISC_JUMP);
 210        *(rp++) = cpu_to_le32(risc->dma);
 211        return 0;
 212}
 213
 214void
 215cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
 216{
 217        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 218
 219        BUG_ON(in_interrupt());
 220        videobuf_waiton(&buf->vb,0,0);
 221        videobuf_dma_unmap(q, dma);
 222        videobuf_dma_free(dma);
 223        btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
 224        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 225}
 226
 227/* ------------------------------------------------------------------ */
 228/* our SRAM memory layout                                             */
 229
 230/* we are going to put all thr risc programs into host memory, so we
 231 * can use the whole SDRAM for the DMA fifos.  To simplify things, we
 232 * use a static memory layout.  That surely will waste memory in case
 233 * we don't use all DMA channels at the same time (which will be the
 234 * case most of the time).  But that still gives us enough FIFO space
 235 * to be able to deal with insane long pci latencies ...
 236 *
 237 * FIFO space allocations:
 238 *    channel  21    (y video)  - 10.0k
 239 *    channel  22    (u video)  -  2.0k
 240 *    channel  23    (v video)  -  2.0k
 241 *    channel  24    (vbi)      -  4.0k
 242 *    channels 25+26 (audio)    -  4.0k
 243 *    channel  28    (mpeg)     -  4.0k
 244 *    channel  27    (audio rds)-  3.0k
 245 *    TOTAL                     = 29.0k
 246 *
 247 * Every channel has 160 bytes control data (64 bytes instruction
 248 * queue and 6 CDT entries), which is close to 2k total.
 249 *
 250 * Address layout:
 251 *    0x0000 - 0x03ff    CMDs / reserved
 252 *    0x0400 - 0x0bff    instruction queues + CDs
 253 *    0x0c00 -           FIFOs
 254 */
 255
 256struct sram_channel cx88_sram_channels[] = {
 257        [SRAM_CH21] = {
 258                .name       = "video y / packed",
 259                .cmds_start = 0x180040,
 260                .ctrl_start = 0x180400,
 261                .cdt        = 0x180400 + 64,
 262                .fifo_start = 0x180c00,
 263                .fifo_size  = 0x002800,
 264                .ptr1_reg   = MO_DMA21_PTR1,
 265                .ptr2_reg   = MO_DMA21_PTR2,
 266                .cnt1_reg   = MO_DMA21_CNT1,
 267                .cnt2_reg   = MO_DMA21_CNT2,
 268        },
 269        [SRAM_CH22] = {
 270                .name       = "video u",
 271                .cmds_start = 0x180080,
 272                .ctrl_start = 0x1804a0,
 273                .cdt        = 0x1804a0 + 64,
 274                .fifo_start = 0x183400,
 275                .fifo_size  = 0x000800,
 276                .ptr1_reg   = MO_DMA22_PTR1,
 277                .ptr2_reg   = MO_DMA22_PTR2,
 278                .cnt1_reg   = MO_DMA22_CNT1,
 279                .cnt2_reg   = MO_DMA22_CNT2,
 280        },
 281        [SRAM_CH23] = {
 282                .name       = "video v",
 283                .cmds_start = 0x1800c0,
 284                .ctrl_start = 0x180540,
 285                .cdt        = 0x180540 + 64,
 286                .fifo_start = 0x183c00,
 287                .fifo_size  = 0x000800,
 288                .ptr1_reg   = MO_DMA23_PTR1,
 289                .ptr2_reg   = MO_DMA23_PTR2,
 290                .cnt1_reg   = MO_DMA23_CNT1,
 291                .cnt2_reg   = MO_DMA23_CNT2,
 292        },
 293        [SRAM_CH24] = {
 294                .name       = "vbi",
 295                .cmds_start = 0x180100,
 296                .ctrl_start = 0x1805e0,
 297                .cdt        = 0x1805e0 + 64,
 298                .fifo_start = 0x184400,
 299                .fifo_size  = 0x001000,
 300                .ptr1_reg   = MO_DMA24_PTR1,
 301                .ptr2_reg   = MO_DMA24_PTR2,
 302                .cnt1_reg   = MO_DMA24_CNT1,
 303                .cnt2_reg   = MO_DMA24_CNT2,
 304        },
 305        [SRAM_CH25] = {
 306                .name       = "audio from",
 307                .cmds_start = 0x180140,
 308                .ctrl_start = 0x180680,
 309                .cdt        = 0x180680 + 64,
 310                .fifo_start = 0x185400,
 311                .fifo_size  = 0x001000,
 312                .ptr1_reg   = MO_DMA25_PTR1,
 313                .ptr2_reg   = MO_DMA25_PTR2,
 314                .cnt1_reg   = MO_DMA25_CNT1,
 315                .cnt2_reg   = MO_DMA25_CNT2,
 316        },
 317        [SRAM_CH26] = {
 318                .name       = "audio to",
 319                .cmds_start = 0x180180,
 320                .ctrl_start = 0x180720,
 321                .cdt        = 0x180680 + 64,  /* same as audio IN */
 322                .fifo_start = 0x185400,       /* same as audio IN */
 323                .fifo_size  = 0x001000,       /* same as audio IN */
 324                .ptr1_reg   = MO_DMA26_PTR1,
 325                .ptr2_reg   = MO_DMA26_PTR2,
 326                .cnt1_reg   = MO_DMA26_CNT1,
 327                .cnt2_reg   = MO_DMA26_CNT2,
 328        },
 329        [SRAM_CH28] = {
 330                .name       = "mpeg",
 331                .cmds_start = 0x180200,
 332                .ctrl_start = 0x1807C0,
 333                .cdt        = 0x1807C0 + 64,
 334                .fifo_start = 0x186400,
 335                .fifo_size  = 0x001000,
 336                .ptr1_reg   = MO_DMA28_PTR1,
 337                .ptr2_reg   = MO_DMA28_PTR2,
 338                .cnt1_reg   = MO_DMA28_CNT1,
 339                .cnt2_reg   = MO_DMA28_CNT2,
 340        },
 341        [SRAM_CH27] = {
 342                .name       = "audio rds",
 343                .cmds_start = 0x1801C0,
 344                .ctrl_start = 0x180860,
 345                .cdt        = 0x180860 + 64,
 346                .fifo_start = 0x187400,
 347                .fifo_size  = 0x000C00,
 348                .ptr1_reg   = MO_DMA27_PTR1,
 349                .ptr2_reg   = MO_DMA27_PTR2,
 350                .cnt1_reg   = MO_DMA27_CNT1,
 351                .cnt2_reg   = MO_DMA27_CNT2,
 352        },
 353};
 354
 355int cx88_sram_channel_setup(struct cx88_core *core,
 356                            struct sram_channel *ch,
 357                            unsigned int bpl, u32 risc)
 358{
 359        unsigned int i,lines;
 360        u32 cdt;
 361
 362        bpl   = (bpl + 7) & ~7; /* alignment */
 363        cdt   = ch->cdt;
 364        lines = ch->fifo_size / bpl;
 365        if (lines > 6)
 366                lines = 6;
 367        BUG_ON(lines < 2);
 368
 369        /* write CDT */
 370        for (i = 0; i < lines; i++)
 371                cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
 372
 373        /* write CMDS */
 374        cx_write(ch->cmds_start +  0, risc);
 375        cx_write(ch->cmds_start +  4, cdt);
 376        cx_write(ch->cmds_start +  8, (lines*16) >> 3);
 377        cx_write(ch->cmds_start + 12, ch->ctrl_start);
 378        cx_write(ch->cmds_start + 16, 64 >> 2);
 379        for (i = 20; i < 64; i += 4)
 380                cx_write(ch->cmds_start + i, 0);
 381
 382        /* fill registers */
 383        cx_write(ch->ptr1_reg, ch->fifo_start);
 384        cx_write(ch->ptr2_reg, cdt);
 385        cx_write(ch->cnt1_reg, (bpl >> 3) -1);
 386        cx_write(ch->cnt2_reg, (lines*16) >> 3);
 387
 388        dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
 389        return 0;
 390}
 391
 392/* ------------------------------------------------------------------ */
 393/* debug helper code                                                  */
 394
 395static int cx88_risc_decode(u32 risc)
 396{
 397        static char *instr[16] = {
 398                [ RISC_SYNC    >> 28 ] = "sync",
 399                [ RISC_WRITE   >> 28 ] = "write",
 400                [ RISC_WRITEC  >> 28 ] = "writec",
 401                [ RISC_READ    >> 28 ] = "read",
 402                [ RISC_READC   >> 28 ] = "readc",
 403                [ RISC_JUMP    >> 28 ] = "jump",
 404                [ RISC_SKIP    >> 28 ] = "skip",
 405                [ RISC_WRITERM >> 28 ] = "writerm",
 406                [ RISC_WRITECM >> 28 ] = "writecm",
 407                [ RISC_WRITECR >> 28 ] = "writecr",
 408        };
 409        static int incr[16] = {
 410                [ RISC_WRITE   >> 28 ] = 2,
 411                [ RISC_JUMP    >> 28 ] = 2,
 412                [ RISC_WRITERM >> 28 ] = 3,
 413                [ RISC_WRITECM >> 28 ] = 3,
 414                [ RISC_WRITECR >> 28 ] = 4,
 415        };
 416        static char *bits[] = {
 417                "12",   "13",   "14",   "resync",
 418                "cnt0", "cnt1", "18",   "19",
 419                "20",   "21",   "22",   "23",
 420                "irq1", "irq2", "eol",  "sol",
 421        };
 422        int i;
 423
 424        printk("0x%08x [ %s", risc,
 425               instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
 426        for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
 427                if (risc & (1 << (i + 12)))
 428                        printk(" %s",bits[i]);
 429        printk(" count=%d ]\n", risc & 0xfff);
 430        return incr[risc >> 28] ? incr[risc >> 28] : 1;
 431}
 432
 433
 434void cx88_sram_channel_dump(struct cx88_core *core,
 435                            struct sram_channel *ch)
 436{
 437        static char *name[] = {
 438                "initial risc",
 439                "cdt base",
 440                "cdt size",
 441                "iq base",
 442                "iq size",
 443                "risc pc",
 444                "iq wr ptr",
 445                "iq rd ptr",
 446                "cdt current",
 447                "pci target",
 448                "line / byte",
 449        };
 450        u32 risc;
 451        unsigned int i,j,n;
 452
 453        printk("%s: %s - dma channel status dump\n",
 454               core->name,ch->name);
 455        for (i = 0; i < ARRAY_SIZE(name); i++)
 456                printk("%s:   cmds: %-12s: 0x%08x\n",
 457                       core->name,name[i],
 458                       cx_read(ch->cmds_start + 4*i));
 459        for (n = 1, i = 0; i < 4; i++) {
 460                risc = cx_read(ch->cmds_start + 4 * (i+11));
 461                printk("%s:   risc%d: ", core->name, i);
 462                if (--n)
 463                        printk("0x%08x [ arg #%d ]\n", risc, n);
 464                else
 465                        n = cx88_risc_decode(risc);
 466        }
 467        for (i = 0; i < 16; i += n) {
 468                risc = cx_read(ch->ctrl_start + 4 * i);
 469                printk("%s:   iq %x: ", core->name, i);
 470                n = cx88_risc_decode(risc);
 471                for (j = 1; j < n; j++) {
 472                        risc = cx_read(ch->ctrl_start + 4 * (i+j));
 473                        printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
 474                               core->name, i+j, risc, j);
 475                }
 476        }
 477
 478        printk("%s: fifo: 0x%08x -> 0x%x\n",
 479               core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
 480        printk("%s: ctrl: 0x%08x -> 0x%x\n",
 481               core->name, ch->ctrl_start, ch->ctrl_start+6*16);
 482        printk("%s:   ptr1_reg: 0x%08x\n",
 483               core->name,cx_read(ch->ptr1_reg));
 484        printk("%s:   ptr2_reg: 0x%08x\n",
 485               core->name,cx_read(ch->ptr2_reg));
 486        printk("%s:   cnt1_reg: 0x%08x\n",
 487               core->name,cx_read(ch->cnt1_reg));
 488        printk("%s:   cnt2_reg: 0x%08x\n",
 489               core->name,cx_read(ch->cnt2_reg));
 490}
 491
 492static char *cx88_pci_irqs[32] = {
 493        "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
 494        "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
 495        "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
 496        "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
 497};
 498
 499void cx88_print_irqbits(char *name, char *tag, char **strings,
 500                        int len, u32 bits, u32 mask)
 501{
 502        unsigned int i;
 503
 504        printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
 505        for (i = 0; i < len; i++) {
 506                if (!(bits & (1 << i)))
 507                        continue;
 508                if (strings[i])
 509                        printk(" %s", strings[i]);
 510                else
 511                        printk(" %d", i);
 512                if (!(mask & (1 << i)))
 513                        continue;
 514                printk("*");
 515        }
 516        printk("\n");
 517}
 518
 519/* ------------------------------------------------------------------ */
 520
 521int cx88_core_irq(struct cx88_core *core, u32 status)
 522{
 523        int handled = 0;
 524
 525        if (status & PCI_INT_IR_SMPINT) {
 526                cx88_ir_irq(core);
 527                handled++;
 528        }
 529        if (!handled)
 530                cx88_print_irqbits(core->name, "irq pci",
 531                                   cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
 532                                   status, core->pci_irqmask);
 533        return handled;
 534}
 535
 536void cx88_wakeup(struct cx88_core *core,
 537                 struct cx88_dmaqueue *q, u32 count)
 538{
 539        struct cx88_buffer *buf;
 540        int bc;
 541
 542        for (bc = 0;; bc++) {
 543                if (list_empty(&q->active))
 544                        break;
 545                buf = list_entry(q->active.next,
 546                                 struct cx88_buffer, vb.queue);
 547                /* count comes from the hw and is is 16bit wide --
 548                 * this trick handles wrap-arounds correctly for
 549                 * up to 32767 buffers in flight... */
 550                if ((s16) (count - buf->count) < 0)
 551                        break;
 552                do_gettimeofday(&buf->vb.ts);
 553                dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
 554                        count, buf->count);
 555                buf->vb.state = VIDEOBUF_DONE;
 556                list_del(&buf->vb.queue);
 557                wake_up(&buf->vb.done);
 558        }
 559        if (list_empty(&q->active)) {
 560                del_timer(&q->timeout);
 561        } else {
 562                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 563        }
 564        if (bc != 1)
 565                dprintk(2, "%s: %d buffers handled (should be 1)\n",
 566                        __func__, bc);
 567}
 568
 569void cx88_shutdown(struct cx88_core *core)
 570{
 571        /* disable RISC controller + IRQs */
 572        cx_write(MO_DEV_CNTRL2, 0);
 573
 574        /* stop dma transfers */
 575        cx_write(MO_VID_DMACNTRL, 0x0);
 576        cx_write(MO_AUD_DMACNTRL, 0x0);
 577        cx_write(MO_TS_DMACNTRL, 0x0);
 578        cx_write(MO_VIP_DMACNTRL, 0x0);
 579        cx_write(MO_GPHST_DMACNTRL, 0x0);
 580
 581        /* stop interrupts */
 582        cx_write(MO_PCI_INTMSK, 0x0);
 583        cx_write(MO_VID_INTMSK, 0x0);
 584        cx_write(MO_AUD_INTMSK, 0x0);
 585        cx_write(MO_TS_INTMSK, 0x0);
 586        cx_write(MO_VIP_INTMSK, 0x0);
 587        cx_write(MO_GPHST_INTMSK, 0x0);
 588
 589        /* stop capturing */
 590        cx_write(VID_CAPTURE_CONTROL, 0);
 591}
 592
 593int cx88_reset(struct cx88_core *core)
 594{
 595        dprintk(1,"%s\n",__func__);
 596        cx88_shutdown(core);
 597
 598        /* clear irq status */
 599        cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
 600        cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
 601        cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
 602
 603        /* wait a bit */
 604        msleep(100);
 605
 606        /* init sram */
 607        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
 608        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
 609        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
 610        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
 611        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
 612        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
 613        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
 614        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
 615
 616        /* misc init ... */
 617        cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
 618                                   (1 << 12) |   // agc gain
 619                                   (1 << 11) |   // adaptibe agc
 620                                   (0 << 10) |   // chroma agc
 621                                   (0 <<  9) |   // ckillen
 622                                   (7)));
 623
 624        /* setup image format */
 625        cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
 626
 627        /* setup FIFO Threshholds */
 628        cx_write(MO_PDMA_STHRSH,   0x0807);
 629        cx_write(MO_PDMA_DTHRSH,   0x0807);
 630
 631        /* fixes flashing of image */
 632        cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
 633        cx_write(MO_AGC_BACK_VBI,  0x00E00555);
 634
 635        cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
 636        cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
 637        cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
 638
 639        /* Reset on-board parts */
 640        cx_write(MO_SRST_IO, 0);
 641        msleep(10);
 642        cx_write(MO_SRST_IO, 1);
 643
 644        return 0;
 645}
 646
 647/* ------------------------------------------------------------------ */
 648
 649static unsigned int inline norm_swidth(v4l2_std_id norm)
 650{
 651        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 652}
 653
 654static unsigned int inline norm_hdelay(v4l2_std_id norm)
 655{
 656        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 657}
 658
 659static unsigned int inline norm_vdelay(v4l2_std_id norm)
 660{
 661        return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 662}
 663
 664static unsigned int inline norm_fsc8(v4l2_std_id norm)
 665{
 666        if (norm & V4L2_STD_PAL_M)
 667                return 28604892;      // 3.575611 MHz
 668
 669        if (norm & (V4L2_STD_PAL_Nc))
 670                return 28656448;      // 3.582056 MHz
 671
 672        if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
 673                return 28636360;      // 3.57954545 MHz +/- 10 Hz
 674
 675        /* SECAM have also different sub carrier for chroma,
 676           but step_db and step_dr, at cx88_set_tvnorm already handles that.
 677
 678           The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
 679         */
 680
 681        return 35468950;      // 4.43361875 MHz +/- 5 Hz
 682}
 683
 684static unsigned int inline norm_htotal(v4l2_std_id norm)
 685{
 686
 687        unsigned int fsc4=norm_fsc8(norm)/2;
 688
 689        /* returns 4*FSC / vtotal / frames per seconds */
 690        return (norm & V4L2_STD_625_50) ?
 691                                ((fsc4+312)/625+12)/25 :
 692                                ((fsc4+262)/525*1001+15000)/30000;
 693}
 694
 695static unsigned int inline norm_vbipack(v4l2_std_id norm)
 696{
 697        return (norm & V4L2_STD_625_50) ? 511 : 400;
 698}
 699
 700int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
 701                   enum v4l2_field field)
 702{
 703        unsigned int swidth  = norm_swidth(core->tvnorm);
 704        unsigned int sheight = norm_maxh(core->tvnorm);
 705        u32 value;
 706
 707        dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
 708                V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
 709                V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
 710                v4l2_norm_to_name(core->tvnorm));
 711        if (!V4L2_FIELD_HAS_BOTH(field))
 712                height *= 2;
 713
 714        // recalc H delay and scale registers
 715        value = (width * norm_hdelay(core->tvnorm)) / swidth;
 716        value &= 0x3fe;
 717        cx_write(MO_HDELAY_EVEN,  value);
 718        cx_write(MO_HDELAY_ODD,   value);
 719        dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
 720
 721        value = (swidth * 4096 / width) - 4096;
 722        cx_write(MO_HSCALE_EVEN,  value);
 723        cx_write(MO_HSCALE_ODD,   value);
 724        dprintk(1,"set_scale: hscale  0x%04x\n", value);
 725
 726        cx_write(MO_HACTIVE_EVEN, width);
 727        cx_write(MO_HACTIVE_ODD,  width);
 728        dprintk(1,"set_scale: hactive 0x%04x\n", width);
 729
 730        // recalc V scale Register (delay is constant)
 731        cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
 732        cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
 733        dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
 734
 735        value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
 736        cx_write(MO_VSCALE_EVEN,  value);
 737        cx_write(MO_VSCALE_ODD,   value);
 738        dprintk(1,"set_scale: vscale  0x%04x\n", value);
 739
 740        cx_write(MO_VACTIVE_EVEN, sheight);
 741        cx_write(MO_VACTIVE_ODD,  sheight);
 742        dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
 743
 744        // setup filters
 745        value = 0;
 746        value |= (1 << 19);        // CFILT (default)
 747        if (core->tvnorm & V4L2_STD_SECAM) {
 748                value |= (1 << 15);
 749                value |= (1 << 16);
 750        }
 751        if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
 752                value |= (1 << 13) | (1 << 5);
 753        if (V4L2_FIELD_INTERLACED == field)
 754                value |= (1 << 3); // VINT (interlaced vertical scaling)
 755        if (width < 385)
 756                value |= (1 << 0); // 3-tap interpolation
 757        if (width < 193)
 758                value |= (1 << 1); // 5-tap interpolation
 759        if (nocomb)
 760                value |= (3 << 5); // disable comb filter
 761
 762        cx_write(MO_FILTER_EVEN,  value);
 763        cx_write(MO_FILTER_ODD,   value);
 764        dprintk(1,"set_scale: filter  0x%04x\n", value);
 765
 766        return 0;
 767}
 768
 769static const u32 xtal = 28636363;
 770
 771static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
 772{
 773        static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
 774        u64 pll;
 775        u32 reg;
 776        int i;
 777
 778        if (prescale < 2)
 779                prescale = 2;
 780        if (prescale > 5)
 781                prescale = 5;
 782
 783        pll = ofreq * 8 * prescale * (u64)(1 << 20);
 784        do_div(pll,xtal);
 785        reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
 786        if (((reg >> 20) & 0x3f) < 14) {
 787                printk("%s/0: pll out of range\n",core->name);
 788                return -1;
 789        }
 790
 791        dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
 792                reg, cx_read(MO_PLL_REG), ofreq);
 793        cx_write(MO_PLL_REG, reg);
 794        for (i = 0; i < 100; i++) {
 795                reg = cx_read(MO_DEVICE_STATUS);
 796                if (reg & (1<<2)) {
 797                        dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
 798                                prescale,ofreq);
 799                        return 0;
 800                }
 801                dprintk(1,"pll not locked yet, waiting ...\n");
 802                msleep(10);
 803        }
 804        dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
 805        return -1;
 806}
 807
 808int cx88_start_audio_dma(struct cx88_core *core)
 809{
 810        /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
 811        int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
 812
 813        int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
 814
 815        /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 816        if (cx_read(MO_AUD_DMACNTRL) & 0x10)
 817                return 0;
 818
 819        /* setup fifo + format */
 820        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
 821        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
 822        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
 823                                rds_bpl, 0);
 824
 825        cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
 826        cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
 827
 828        /* enable Up, Down and Audio RDS fifo */
 829        cx_write(MO_AUD_DMACNTRL, 0x0007);
 830
 831        return 0;
 832}
 833
 834int cx88_stop_audio_dma(struct cx88_core *core)
 835{
 836        /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 837        if (cx_read(MO_AUD_DMACNTRL) & 0x10)
 838                return 0;
 839
 840        /* stop dma */
 841        cx_write(MO_AUD_DMACNTRL, 0x0000);
 842
 843        return 0;
 844}
 845
 846static int set_tvaudio(struct cx88_core *core)
 847{
 848        v4l2_std_id norm = core->tvnorm;
 849
 850        if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
 851                return 0;
 852
 853        if (V4L2_STD_PAL_BG & norm) {
 854                core->tvaudio = WW_BG;
 855
 856        } else if (V4L2_STD_PAL_DK & norm) {
 857                core->tvaudio = WW_DK;
 858
 859        } else if (V4L2_STD_PAL_I & norm) {
 860                core->tvaudio = WW_I;
 861
 862        } else if (V4L2_STD_SECAM_L & norm) {
 863                core->tvaudio = WW_L;
 864
 865        } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
 866                core->tvaudio = WW_BG;
 867
 868        } else if (V4L2_STD_SECAM_DK & norm) {
 869                core->tvaudio = WW_DK;
 870
 871        } else if ((V4L2_STD_NTSC_M & norm) ||
 872                   (V4L2_STD_PAL_M  & norm)) {
 873                core->tvaudio = WW_BTSC;
 874
 875        } else if (V4L2_STD_NTSC_M_JP & norm) {
 876                core->tvaudio = WW_EIAJ;
 877
 878        } else {
 879                printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
 880                       core->name, v4l2_norm_to_name(core->tvnorm));
 881                core->tvaudio = 0;
 882                return 0;
 883        }
 884
 885        cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
 886        cx88_set_tvaudio(core);
 887        /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
 888
 889/*
 890   This should be needed only on cx88-alsa. It seems that some cx88 chips have
 891   bugs and does require DMA enabled for it to work.
 892 */
 893        cx88_start_audio_dma(core);
 894        return 0;
 895}
 896
 897
 898
 899int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 900{
 901        u32 fsc8;
 902        u32 adc_clock;
 903        u32 vdec_clock;
 904        u32 step_db,step_dr;
 905        u64 tmp64;
 906        u32 bdelay,agcdelay,htotal;
 907        u32 cxiformat, cxoformat;
 908
 909        core->tvnorm = norm;
 910        fsc8       = norm_fsc8(norm);
 911        adc_clock  = xtal;
 912        vdec_clock = fsc8;
 913        step_db    = fsc8;
 914        step_dr    = fsc8;
 915
 916        if (norm & V4L2_STD_NTSC_M_JP) {
 917                cxiformat = VideoFormatNTSCJapan;
 918                cxoformat = 0x181f0008;
 919        } else if (norm & V4L2_STD_NTSC_443) {
 920                cxiformat = VideoFormatNTSC443;
 921                cxoformat = 0x181f0008;
 922        } else if (norm & V4L2_STD_PAL_M) {
 923                cxiformat = VideoFormatPALM;
 924                cxoformat = 0x1c1f0008;
 925        } else if (norm & V4L2_STD_PAL_N) {
 926                cxiformat = VideoFormatPALN;
 927                cxoformat = 0x1c1f0008;
 928        } else if (norm & V4L2_STD_PAL_Nc) {
 929                cxiformat = VideoFormatPALNC;
 930                cxoformat = 0x1c1f0008;
 931        } else if (norm & V4L2_STD_PAL_60) {
 932                cxiformat = VideoFormatPAL60;
 933                cxoformat = 0x181f0008;
 934        } else if (norm & V4L2_STD_NTSC) {
 935                cxiformat = VideoFormatNTSC;
 936                cxoformat = 0x181f0008;
 937        } else if (norm & V4L2_STD_SECAM) {
 938                step_db = 4250000 * 8;
 939                step_dr = 4406250 * 8;
 940
 941                cxiformat = VideoFormatSECAM;
 942                cxoformat = 0x181f0008;
 943        } else { /* PAL */
 944                cxiformat = VideoFormatPAL;
 945                cxoformat = 0x181f0008;
 946        }
 947
 948        dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
 949                v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
 950                step_db, step_dr);
 951        set_pll(core,2,vdec_clock);
 952
 953        dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
 954                cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
 955        /* Chroma AGC must be disabled if SECAM is used, we enable it
 956           by default on PAL and NTSC */
 957        cx_andor(MO_INPUT_FORMAT, 0x40f,
 958                 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
 959
 960        // FIXME: as-is from DScaler
 961        dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
 962                cxoformat, cx_read(MO_OUTPUT_FORMAT));
 963        cx_write(MO_OUTPUT_FORMAT, cxoformat);
 964
 965        // MO_SCONV_REG = adc clock / video dec clock * 2^17
 966        tmp64  = adc_clock * (u64)(1 << 17);
 967        do_div(tmp64, vdec_clock);
 968        dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
 969                (u32)tmp64, cx_read(MO_SCONV_REG));
 970        cx_write(MO_SCONV_REG, (u32)tmp64);
 971
 972        // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
 973        tmp64  = step_db * (u64)(1 << 22);
 974        do_div(tmp64, vdec_clock);
 975        dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
 976                (u32)tmp64, cx_read(MO_SUB_STEP));
 977        cx_write(MO_SUB_STEP, (u32)tmp64);
 978
 979        // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
 980        tmp64  = step_dr * (u64)(1 << 22);
 981        do_div(tmp64, vdec_clock);
 982        dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
 983                (u32)tmp64, cx_read(MO_SUB_STEP_DR));
 984        cx_write(MO_SUB_STEP_DR, (u32)tmp64);
 985
 986        // bdelay + agcdelay
 987        bdelay   = vdec_clock * 65 / 20000000 + 21;
 988        agcdelay = vdec_clock * 68 / 20000000 + 15;
 989        dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
 990                (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
 991        cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
 992
 993        // htotal
 994        tmp64 = norm_htotal(norm) * (u64)vdec_clock;
 995        do_div(tmp64, fsc8);
 996        htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
 997        dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
 998                htotal, cx_read(MO_HTOTAL), (u32)tmp64);
 999        cx_write(MO_HTOTAL, htotal);
1000
1001        // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
1002        // the effective vbi offset ~244 samples, the same as the Bt8x8
1003        cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
1004
1005        // this is needed as well to set all tvnorm parameter
1006        cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
1007
1008        // audio
1009        set_tvaudio(core);
1010
1011        // tell i2c chips
1012        call_all(core, core, s_std, norm);
1013
1014        // done
1015        return 0;
1016}
1017
1018/* ------------------------------------------------------------------ */
1019
1020struct video_device *cx88_vdev_init(struct cx88_core *core,
1021                                    struct pci_dev *pci,
1022                                    struct video_device *template,
1023                                    char *type)
1024{
1025        struct video_device *vfd;
1026
1027        vfd = video_device_alloc();
1028        if (NULL == vfd)
1029                return NULL;
1030        *vfd = *template;
1031        vfd->v4l2_dev = &core->v4l2_dev;
1032        vfd->parent = &pci->dev;
1033        vfd->release = video_device_release;
1034        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1035                 core->name, type, core->board.name);
1036        return vfd;
1037}
1038
1039struct cx88_core* cx88_core_get(struct pci_dev *pci)
1040{
1041        struct cx88_core *core;
1042
1043        mutex_lock(&devlist);
1044        list_for_each_entry(core, &cx88_devlist, devlist) {
1045                if (pci->bus->number != core->pci_bus)
1046                        continue;
1047                if (PCI_SLOT(pci->devfn) != core->pci_slot)
1048                        continue;
1049
1050                if (0 != cx88_get_resources(core, pci)) {
1051                        mutex_unlock(&devlist);
1052                        return NULL;
1053                }
1054                atomic_inc(&core->refcount);
1055                mutex_unlock(&devlist);
1056                return core;
1057        }
1058
1059        core = cx88_core_create(pci, cx88_devcount);
1060        if (NULL != core) {
1061                cx88_devcount++;
1062                list_add_tail(&core->devlist, &cx88_devlist);
1063        }
1064
1065        mutex_unlock(&devlist);
1066        return core;
1067}
1068
1069void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1070{
1071        release_mem_region(pci_resource_start(pci,0),
1072                           pci_resource_len(pci,0));
1073
1074        if (!atomic_dec_and_test(&core->refcount))
1075                return;
1076
1077        mutex_lock(&devlist);
1078        cx88_ir_fini(core);
1079        if (0 == core->i2c_rc) {
1080                if (core->i2c_rtc)
1081                        i2c_unregister_device(core->i2c_rtc);
1082                i2c_del_adapter(&core->i2c_adap);
1083        }
1084        list_del(&core->devlist);
1085        iounmap(core->lmmio);
1086        cx88_devcount--;
1087        mutex_unlock(&devlist);
1088        v4l2_device_unregister(&core->v4l2_dev);
1089        kfree(core);
1090}
1091
1092/* ------------------------------------------------------------------ */
1093
1094EXPORT_SYMBOL(cx88_print_irqbits);
1095
1096EXPORT_SYMBOL(cx88_core_irq);
1097EXPORT_SYMBOL(cx88_wakeup);
1098EXPORT_SYMBOL(cx88_reset);
1099EXPORT_SYMBOL(cx88_shutdown);
1100
1101EXPORT_SYMBOL(cx88_risc_buffer);
1102EXPORT_SYMBOL(cx88_risc_databuffer);
1103EXPORT_SYMBOL(cx88_risc_stopper);
1104EXPORT_SYMBOL(cx88_free_buffer);
1105
1106EXPORT_SYMBOL(cx88_sram_channels);
1107EXPORT_SYMBOL(cx88_sram_channel_setup);
1108EXPORT_SYMBOL(cx88_sram_channel_dump);
1109
1110EXPORT_SYMBOL(cx88_set_tvnorm);
1111EXPORT_SYMBOL(cx88_set_scale);
1112
1113EXPORT_SYMBOL(cx88_vdev_init);
1114EXPORT_SYMBOL(cx88_core_get);
1115EXPORT_SYMBOL(cx88_core_put);
1116
1117EXPORT_SYMBOL(cx88_ir_start);
1118EXPORT_SYMBOL(cx88_ir_stop);
1119
1120/*
1121 * Local variables:
1122 * c-basic-offset: 8
1123 * End:
1124 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
1125 */
1126