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 enougth 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 *    TOTAL                     = 29.0k
 245 *
 246 * Every channel has 160 bytes control data (64 bytes instruction
 247 * queue and 6 CDT entries), which is close to 2k total.
 248 *
 249 * Address layout:
 250 *    0x0000 - 0x03ff    CMDs / reserved
 251 *    0x0400 - 0x0bff    instruction queues + CDs
 252 *    0x0c00 -           FIFOs
 253 */
 254
 255struct sram_channel cx88_sram_channels[] = {
 256        [SRAM_CH21] = {
 257                .name       = "video y / packed",
 258                .cmds_start = 0x180040,
 259                .ctrl_start = 0x180400,
 260                .cdt        = 0x180400 + 64,
 261                .fifo_start = 0x180c00,
 262                .fifo_size  = 0x002800,
 263                .ptr1_reg   = MO_DMA21_PTR1,
 264                .ptr2_reg   = MO_DMA21_PTR2,
 265                .cnt1_reg   = MO_DMA21_CNT1,
 266                .cnt2_reg   = MO_DMA21_CNT2,
 267        },
 268        [SRAM_CH22] = {
 269                .name       = "video u",
 270                .cmds_start = 0x180080,
 271                .ctrl_start = 0x1804a0,
 272                .cdt        = 0x1804a0 + 64,
 273                .fifo_start = 0x183400,
 274                .fifo_size  = 0x000800,
 275                .ptr1_reg   = MO_DMA22_PTR1,
 276                .ptr2_reg   = MO_DMA22_PTR2,
 277                .cnt1_reg   = MO_DMA22_CNT1,
 278                .cnt2_reg   = MO_DMA22_CNT2,
 279        },
 280        [SRAM_CH23] = {
 281                .name       = "video v",
 282                .cmds_start = 0x1800c0,
 283                .ctrl_start = 0x180540,
 284                .cdt        = 0x180540 + 64,
 285                .fifo_start = 0x183c00,
 286                .fifo_size  = 0x000800,
 287                .ptr1_reg   = MO_DMA23_PTR1,
 288                .ptr2_reg   = MO_DMA23_PTR2,
 289                .cnt1_reg   = MO_DMA23_CNT1,
 290                .cnt2_reg   = MO_DMA23_CNT2,
 291        },
 292        [SRAM_CH24] = {
 293                .name       = "vbi",
 294                .cmds_start = 0x180100,
 295                .ctrl_start = 0x1805e0,
 296                .cdt        = 0x1805e0 + 64,
 297                .fifo_start = 0x184400,
 298                .fifo_size  = 0x001000,
 299                .ptr1_reg   = MO_DMA24_PTR1,
 300                .ptr2_reg   = MO_DMA24_PTR2,
 301                .cnt1_reg   = MO_DMA24_CNT1,
 302                .cnt2_reg   = MO_DMA24_CNT2,
 303        },
 304        [SRAM_CH25] = {
 305                .name       = "audio from",
 306                .cmds_start = 0x180140,
 307                .ctrl_start = 0x180680,
 308                .cdt        = 0x180680 + 64,
 309                .fifo_start = 0x185400,
 310                .fifo_size  = 0x001000,
 311                .ptr1_reg   = MO_DMA25_PTR1,
 312                .ptr2_reg   = MO_DMA25_PTR2,
 313                .cnt1_reg   = MO_DMA25_CNT1,
 314                .cnt2_reg   = MO_DMA25_CNT2,
 315        },
 316        [SRAM_CH26] = {
 317                .name       = "audio to",
 318                .cmds_start = 0x180180,
 319                .ctrl_start = 0x180720,
 320                .cdt        = 0x180680 + 64,  /* same as audio IN */
 321                .fifo_start = 0x185400,       /* same as audio IN */
 322                .fifo_size  = 0x001000,       /* same as audio IN */
 323                .ptr1_reg   = MO_DMA26_PTR1,
 324                .ptr2_reg   = MO_DMA26_PTR2,
 325                .cnt1_reg   = MO_DMA26_CNT1,
 326                .cnt2_reg   = MO_DMA26_CNT2,
 327        },
 328        [SRAM_CH28] = {
 329                .name       = "mpeg",
 330                .cmds_start = 0x180200,
 331                .ctrl_start = 0x1807C0,
 332                .cdt        = 0x1807C0 + 64,
 333                .fifo_start = 0x186400,
 334                .fifo_size  = 0x001000,
 335                .ptr1_reg   = MO_DMA28_PTR1,
 336                .ptr2_reg   = MO_DMA28_PTR2,
 337                .cnt1_reg   = MO_DMA28_CNT1,
 338                .cnt2_reg   = MO_DMA28_CNT2,
 339        },
 340};
 341
 342int cx88_sram_channel_setup(struct cx88_core *core,
 343                            struct sram_channel *ch,
 344                            unsigned int bpl, u32 risc)
 345{
 346        unsigned int i,lines;
 347        u32 cdt;
 348
 349        bpl   = (bpl + 7) & ~7; /* alignment */
 350        cdt   = ch->cdt;
 351        lines = ch->fifo_size / bpl;
 352        if (lines > 6)
 353                lines = 6;
 354        BUG_ON(lines < 2);
 355
 356        /* write CDT */
 357        for (i = 0; i < lines; i++)
 358                cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
 359
 360        /* write CMDS */
 361        cx_write(ch->cmds_start +  0, risc);
 362        cx_write(ch->cmds_start +  4, cdt);
 363        cx_write(ch->cmds_start +  8, (lines*16) >> 3);
 364        cx_write(ch->cmds_start + 12, ch->ctrl_start);
 365        cx_write(ch->cmds_start + 16, 64 >> 2);
 366        for (i = 20; i < 64; i += 4)
 367                cx_write(ch->cmds_start + i, 0);
 368
 369        /* fill registers */
 370        cx_write(ch->ptr1_reg, ch->fifo_start);
 371        cx_write(ch->ptr2_reg, cdt);
 372        cx_write(ch->cnt1_reg, (bpl >> 3) -1);
 373        cx_write(ch->cnt2_reg, (lines*16) >> 3);
 374
 375        dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
 376        return 0;
 377}
 378
 379/* ------------------------------------------------------------------ */
 380/* debug helper code                                                  */
 381
 382static int cx88_risc_decode(u32 risc)
 383{
 384        static char *instr[16] = {
 385                [ RISC_SYNC    >> 28 ] = "sync",
 386                [ RISC_WRITE   >> 28 ] = "write",
 387                [ RISC_WRITEC  >> 28 ] = "writec",
 388                [ RISC_READ    >> 28 ] = "read",
 389                [ RISC_READC   >> 28 ] = "readc",
 390                [ RISC_JUMP    >> 28 ] = "jump",
 391                [ RISC_SKIP    >> 28 ] = "skip",
 392                [ RISC_WRITERM >> 28 ] = "writerm",
 393                [ RISC_WRITECM >> 28 ] = "writecm",
 394                [ RISC_WRITECR >> 28 ] = "writecr",
 395        };
 396        static int incr[16] = {
 397                [ RISC_WRITE   >> 28 ] = 2,
 398                [ RISC_JUMP    >> 28 ] = 2,
 399                [ RISC_WRITERM >> 28 ] = 3,
 400                [ RISC_WRITECM >> 28 ] = 3,
 401                [ RISC_WRITECR >> 28 ] = 4,
 402        };
 403        static char *bits[] = {
 404                "12",   "13",   "14",   "resync",
 405                "cnt0", "cnt1", "18",   "19",
 406                "20",   "21",   "22",   "23",
 407                "irq1", "irq2", "eol",  "sol",
 408        };
 409        int i;
 410
 411        printk("0x%08x [ %s", risc,
 412               instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
 413        for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
 414                if (risc & (1 << (i + 12)))
 415                        printk(" %s",bits[i]);
 416        printk(" count=%d ]\n", risc & 0xfff);
 417        return incr[risc >> 28] ? incr[risc >> 28] : 1;
 418}
 419
 420
 421void cx88_sram_channel_dump(struct cx88_core *core,
 422                            struct sram_channel *ch)
 423{
 424        static char *name[] = {
 425                "initial risc",
 426                "cdt base",
 427                "cdt size",
 428                "iq base",
 429                "iq size",
 430                "risc pc",
 431                "iq wr ptr",
 432                "iq rd ptr",
 433                "cdt current",
 434                "pci target",
 435                "line / byte",
 436        };
 437        u32 risc;
 438        unsigned int i,j,n;
 439
 440        printk("%s: %s - dma channel status dump\n",
 441               core->name,ch->name);
 442        for (i = 0; i < ARRAY_SIZE(name); i++)
 443                printk("%s:   cmds: %-12s: 0x%08x\n",
 444                       core->name,name[i],
 445                       cx_read(ch->cmds_start + 4*i));
 446        for (n = 1, i = 0; i < 4; i++) {
 447                risc = cx_read(ch->cmds_start + 4 * (i+11));
 448                printk("%s:   risc%d: ", core->name, i);
 449                if (--n)
 450                        printk("0x%08x [ arg #%d ]\n", risc, n);
 451                else
 452                        n = cx88_risc_decode(risc);
 453        }
 454        for (i = 0; i < 16; i += n) {
 455                risc = cx_read(ch->ctrl_start + 4 * i);
 456                printk("%s:   iq %x: ", core->name, i);
 457                n = cx88_risc_decode(risc);
 458                for (j = 1; j < n; j++) {
 459                        risc = cx_read(ch->ctrl_start + 4 * (i+j));
 460                        printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
 461                               core->name, i+j, risc, j);
 462                }
 463        }
 464
 465        printk("%s: fifo: 0x%08x -> 0x%x\n",
 466               core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
 467        printk("%s: ctrl: 0x%08x -> 0x%x\n",
 468               core->name, ch->ctrl_start, ch->ctrl_start+6*16);
 469        printk("%s:   ptr1_reg: 0x%08x\n",
 470               core->name,cx_read(ch->ptr1_reg));
 471        printk("%s:   ptr2_reg: 0x%08x\n",
 472               core->name,cx_read(ch->ptr2_reg));
 473        printk("%s:   cnt1_reg: 0x%08x\n",
 474               core->name,cx_read(ch->cnt1_reg));
 475        printk("%s:   cnt2_reg: 0x%08x\n",
 476               core->name,cx_read(ch->cnt2_reg));
 477}
 478
 479static char *cx88_pci_irqs[32] = {
 480        "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
 481        "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
 482        "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
 483        "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
 484};
 485
 486void cx88_print_irqbits(char *name, char *tag, char **strings,
 487                        int len, u32 bits, u32 mask)
 488{
 489        unsigned int i;
 490
 491        printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
 492        for (i = 0; i < len; i++) {
 493                if (!(bits & (1 << i)))
 494                        continue;
 495                if (strings[i])
 496                        printk(" %s", strings[i]);
 497                else
 498                        printk(" %d", i);
 499                if (!(mask & (1 << i)))
 500                        continue;
 501                printk("*");
 502        }
 503        printk("\n");
 504}
 505
 506/* ------------------------------------------------------------------ */
 507
 508int cx88_core_irq(struct cx88_core *core, u32 status)
 509{
 510        int handled = 0;
 511
 512        if (status & PCI_INT_IR_SMPINT) {
 513                cx88_ir_irq(core);
 514                handled++;
 515        }
 516        if (!handled)
 517                cx88_print_irqbits(core->name, "irq pci",
 518                                   cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
 519                                   status, core->pci_irqmask);
 520        return handled;
 521}
 522
 523void cx88_wakeup(struct cx88_core *core,
 524                 struct cx88_dmaqueue *q, u32 count)
 525{
 526        struct cx88_buffer *buf;
 527        int bc;
 528
 529        for (bc = 0;; bc++) {
 530                if (list_empty(&q->active))
 531                        break;
 532                buf = list_entry(q->active.next,
 533                                 struct cx88_buffer, vb.queue);
 534                /* count comes from the hw and is is 16bit wide --
 535                 * this trick handles wrap-arounds correctly for
 536                 * up to 32767 buffers in flight... */
 537                if ((s16) (count - buf->count) < 0)
 538                        break;
 539                do_gettimeofday(&buf->vb.ts);
 540                dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
 541                        count, buf->count);
 542                buf->vb.state = VIDEOBUF_DONE;
 543                list_del(&buf->vb.queue);
 544                wake_up(&buf->vb.done);
 545        }
 546        if (list_empty(&q->active)) {
 547                del_timer(&q->timeout);
 548        } else {
 549                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
 550        }
 551        if (bc != 1)
 552                printk("%s: %d buffers handled (should be 1)\n",__func__,bc);
 553}
 554
 555void cx88_shutdown(struct cx88_core *core)
 556{
 557        /* disable RISC controller + IRQs */
 558        cx_write(MO_DEV_CNTRL2, 0);
 559
 560        /* stop dma transfers */
 561        cx_write(MO_VID_DMACNTRL, 0x0);
 562        cx_write(MO_AUD_DMACNTRL, 0x0);
 563        cx_write(MO_TS_DMACNTRL, 0x0);
 564        cx_write(MO_VIP_DMACNTRL, 0x0);
 565        cx_write(MO_GPHST_DMACNTRL, 0x0);
 566
 567        /* stop interrupts */
 568        cx_write(MO_PCI_INTMSK, 0x0);
 569        cx_write(MO_VID_INTMSK, 0x0);
 570        cx_write(MO_AUD_INTMSK, 0x0);
 571        cx_write(MO_TS_INTMSK, 0x0);
 572        cx_write(MO_VIP_INTMSK, 0x0);
 573        cx_write(MO_GPHST_INTMSK, 0x0);
 574
 575        /* stop capturing */
 576        cx_write(VID_CAPTURE_CONTROL, 0);
 577}
 578
 579int cx88_reset(struct cx88_core *core)
 580{
 581        dprintk(1,"%s\n",__func__);
 582        cx88_shutdown(core);
 583
 584        /* clear irq status */
 585        cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
 586        cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
 587        cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
 588
 589        /* wait a bit */
 590        msleep(100);
 591
 592        /* init sram */
 593        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
 594        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
 595        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
 596        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
 597        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
 598        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
 599        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
 600
 601        /* misc init ... */
 602        cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
 603                                   (1 << 12) |   // agc gain
 604                                   (1 << 11) |   // adaptibe agc
 605                                   (0 << 10) |   // chroma agc
 606                                   (0 <<  9) |   // ckillen
 607                                   (7)));
 608
 609        /* setup image format */
 610        cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
 611
 612        /* setup FIFO Threshholds */
 613        cx_write(MO_PDMA_STHRSH,   0x0807);
 614        cx_write(MO_PDMA_DTHRSH,   0x0807);
 615
 616        /* fixes flashing of image */
 617        cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
 618        cx_write(MO_AGC_BACK_VBI,  0x00E00555);
 619
 620        cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
 621        cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
 622        cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
 623
 624        /* Reset on-board parts */
 625        cx_write(MO_SRST_IO, 0);
 626        msleep(10);
 627        cx_write(MO_SRST_IO, 1);
 628
 629        return 0;
 630}
 631
 632/* ------------------------------------------------------------------ */
 633
 634static unsigned int inline norm_swidth(v4l2_std_id norm)
 635{
 636        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 637}
 638
 639static unsigned int inline norm_hdelay(v4l2_std_id norm)
 640{
 641        return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 642}
 643
 644static unsigned int inline norm_vdelay(v4l2_std_id norm)
 645{
 646        return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
 647}
 648
 649static unsigned int inline norm_fsc8(v4l2_std_id norm)
 650{
 651        if (norm & V4L2_STD_PAL_M)
 652                return 28604892;      // 3.575611 MHz
 653
 654        if (norm & (V4L2_STD_PAL_Nc))
 655                return 28656448;      // 3.582056 MHz
 656
 657        if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
 658                return 28636360;      // 3.57954545 MHz +/- 10 Hz
 659
 660        /* SECAM have also different sub carrier for chroma,
 661           but step_db and step_dr, at cx88_set_tvnorm already handles that.
 662
 663           The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
 664         */
 665
 666        return 35468950;      // 4.43361875 MHz +/- 5 Hz
 667}
 668
 669static unsigned int inline norm_htotal(v4l2_std_id norm)
 670{
 671
 672        unsigned int fsc4=norm_fsc8(norm)/2;
 673
 674        /* returns 4*FSC / vtotal / frames per seconds */
 675        return (norm & V4L2_STD_625_50) ?
 676                                ((fsc4+312)/625+12)/25 :
 677                                ((fsc4+262)/525*1001+15000)/30000;
 678}
 679
 680static unsigned int inline norm_vbipack(v4l2_std_id norm)
 681{
 682        return (norm & V4L2_STD_625_50) ? 511 : 400;
 683}
 684
 685int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
 686                   enum v4l2_field field)
 687{
 688        unsigned int swidth  = norm_swidth(core->tvnorm);
 689        unsigned int sheight = norm_maxh(core->tvnorm);
 690        u32 value;
 691
 692        dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
 693                V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
 694                V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
 695                v4l2_norm_to_name(core->tvnorm));
 696        if (!V4L2_FIELD_HAS_BOTH(field))
 697                height *= 2;
 698
 699        // recalc H delay and scale registers
 700        value = (width * norm_hdelay(core->tvnorm)) / swidth;
 701        value &= 0x3fe;
 702        cx_write(MO_HDELAY_EVEN,  value);
 703        cx_write(MO_HDELAY_ODD,   value);
 704        dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
 705
 706        value = (swidth * 4096 / width) - 4096;
 707        cx_write(MO_HSCALE_EVEN,  value);
 708        cx_write(MO_HSCALE_ODD,   value);
 709        dprintk(1,"set_scale: hscale  0x%04x\n", value);
 710
 711        cx_write(MO_HACTIVE_EVEN, width);
 712        cx_write(MO_HACTIVE_ODD,  width);
 713        dprintk(1,"set_scale: hactive 0x%04x\n", width);
 714
 715        // recalc V scale Register (delay is constant)
 716        cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
 717        cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
 718        dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
 719
 720        value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
 721        cx_write(MO_VSCALE_EVEN,  value);
 722        cx_write(MO_VSCALE_ODD,   value);
 723        dprintk(1,"set_scale: vscale  0x%04x\n", value);
 724
 725        cx_write(MO_VACTIVE_EVEN, sheight);
 726        cx_write(MO_VACTIVE_ODD,  sheight);
 727        dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
 728
 729        // setup filters
 730        value = 0;
 731        value |= (1 << 19);        // CFILT (default)
 732        if (core->tvnorm & V4L2_STD_SECAM) {
 733                value |= (1 << 15);
 734                value |= (1 << 16);
 735        }
 736        if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
 737                value |= (1 << 13) | (1 << 5);
 738        if (V4L2_FIELD_INTERLACED == field)
 739                value |= (1 << 3); // VINT (interlaced vertical scaling)
 740        if (width < 385)
 741                value |= (1 << 0); // 3-tap interpolation
 742        if (width < 193)
 743                value |= (1 << 1); // 5-tap interpolation
 744        if (nocomb)
 745                value |= (3 << 5); // disable comb filter
 746
 747        cx_write(MO_FILTER_EVEN,  value);
 748        cx_write(MO_FILTER_ODD,   value);
 749        dprintk(1,"set_scale: filter  0x%04x\n", value);
 750
 751        return 0;
 752}
 753
 754static const u32 xtal = 28636363;
 755
 756static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
 757{
 758        static u32 pre[] = { 0, 0, 0, 3, 2, 1 };
 759        u64 pll;
 760        u32 reg;
 761        int i;
 762
 763        if (prescale < 2)
 764                prescale = 2;
 765        if (prescale > 5)
 766                prescale = 5;
 767
 768        pll = ofreq * 8 * prescale * (u64)(1 << 20);
 769        do_div(pll,xtal);
 770        reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
 771        if (((reg >> 20) & 0x3f) < 14) {
 772                printk("%s/0: pll out of range\n",core->name);
 773                return -1;
 774        }
 775
 776        dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
 777                reg, cx_read(MO_PLL_REG), ofreq);
 778        cx_write(MO_PLL_REG, reg);
 779        for (i = 0; i < 100; i++) {
 780                reg = cx_read(MO_DEVICE_STATUS);
 781                if (reg & (1<<2)) {
 782                        dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
 783                                prescale,ofreq);
 784                        return 0;
 785                }
 786                dprintk(1,"pll not locked yet, waiting ...\n");
 787                msleep(10);
 788        }
 789        dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
 790        return -1;
 791}
 792
 793int cx88_start_audio_dma(struct cx88_core *core)
 794{
 795        /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
 796        int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
 797
 798        /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 799        if (cx_read(MO_AUD_DMACNTRL) & 0x10)
 800                return 0;
 801
 802        /* setup fifo + format */
 803        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
 804        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
 805
 806        cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
 807        cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
 808
 809        /* start dma */
 810        cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
 811
 812        return 0;
 813}
 814
 815int cx88_stop_audio_dma(struct cx88_core *core)
 816{
 817        /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 818        if (cx_read(MO_AUD_DMACNTRL) & 0x10)
 819                return 0;
 820
 821        /* stop dma */
 822        cx_write(MO_AUD_DMACNTRL, 0x0000);
 823
 824        return 0;
 825}
 826
 827static int set_tvaudio(struct cx88_core *core)
 828{
 829        v4l2_std_id norm = core->tvnorm;
 830
 831        if (CX88_VMUX_TELEVISION != INPUT(core->input).type)
 832                return 0;
 833
 834        if (V4L2_STD_PAL_BG & norm) {
 835                core->tvaudio = WW_BG;
 836
 837        } else if (V4L2_STD_PAL_DK & norm) {
 838                core->tvaudio = WW_DK;
 839
 840        } else if (V4L2_STD_PAL_I & norm) {
 841                core->tvaudio = WW_I;
 842
 843        } else if (V4L2_STD_SECAM_L & norm) {
 844                core->tvaudio = WW_L;
 845
 846        } else if (V4L2_STD_SECAM_DK & norm) {
 847                core->tvaudio = WW_DK;
 848
 849        } else if ((V4L2_STD_NTSC_M & norm) ||
 850                   (V4L2_STD_PAL_M  & norm)) {
 851                core->tvaudio = WW_BTSC;
 852
 853        } else if (V4L2_STD_NTSC_M_JP & norm) {
 854                core->tvaudio = WW_EIAJ;
 855
 856        } else {
 857                printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
 858                       core->name, v4l2_norm_to_name(core->tvnorm));
 859                core->tvaudio = 0;
 860                return 0;
 861        }
 862
 863        cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
 864        cx88_set_tvaudio(core);
 865        /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
 866
 867/*
 868   This should be needed only on cx88-alsa. It seems that some cx88 chips have
 869   bugs and does require DMA enabled for it to work.
 870 */
 871        cx88_start_audio_dma(core);
 872        return 0;
 873}
 874
 875
 876
 877int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 878{
 879        u32 fsc8;
 880        u32 adc_clock;
 881        u32 vdec_clock;
 882        u32 step_db,step_dr;
 883        u64 tmp64;
 884        u32 bdelay,agcdelay,htotal;
 885        u32 cxiformat, cxoformat;
 886
 887        core->tvnorm = norm;
 888        fsc8       = norm_fsc8(norm);
 889        adc_clock  = xtal;
 890        vdec_clock = fsc8;
 891        step_db    = fsc8;
 892        step_dr    = fsc8;
 893
 894        if (norm & V4L2_STD_NTSC_M_JP) {
 895                cxiformat = VideoFormatNTSCJapan;
 896                cxoformat = 0x181f0008;
 897        } else if (norm & V4L2_STD_NTSC_443) {
 898                cxiformat = VideoFormatNTSC443;
 899                cxoformat = 0x181f0008;
 900        } else if (norm & V4L2_STD_PAL_M) {
 901                cxiformat = VideoFormatPALM;
 902                cxoformat = 0x1c1f0008;
 903        } else if (norm & V4L2_STD_PAL_N) {
 904                cxiformat = VideoFormatPALN;
 905                cxoformat = 0x1c1f0008;
 906        } else if (norm & V4L2_STD_PAL_Nc) {
 907                cxiformat = VideoFormatPALNC;
 908                cxoformat = 0x1c1f0008;
 909        } else if (norm & V4L2_STD_PAL_60) {
 910                cxiformat = VideoFormatPAL60;
 911                cxoformat = 0x181f0008;
 912        } else if (norm & V4L2_STD_NTSC) {
 913                cxiformat = VideoFormatNTSC;
 914                cxoformat = 0x181f0008;
 915        } else if (norm & V4L2_STD_SECAM) {
 916                step_db = 4250000 * 8;
 917                step_dr = 4406250 * 8;
 918
 919                cxiformat = VideoFormatSECAM;
 920                cxoformat = 0x181f0008;
 921        } else { /* PAL */
 922                cxiformat = VideoFormatPAL;
 923                cxoformat = 0x181f0008;
 924        }
 925
 926        dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
 927                v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
 928                step_db, step_dr);
 929        set_pll(core,2,vdec_clock);
 930
 931        dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
 932                cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
 933        /* Chroma AGC must be disabled if SECAM is used, we enable it
 934           by default on PAL and NTSC */
 935        cx_andor(MO_INPUT_FORMAT, 0x40f,
 936                 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
 937
 938        // FIXME: as-is from DScaler
 939        dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
 940                cxoformat, cx_read(MO_OUTPUT_FORMAT));
 941        cx_write(MO_OUTPUT_FORMAT, cxoformat);
 942
 943        // MO_SCONV_REG = adc clock / video dec clock * 2^17
 944        tmp64  = adc_clock * (u64)(1 << 17);
 945        do_div(tmp64, vdec_clock);
 946        dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
 947                (u32)tmp64, cx_read(MO_SCONV_REG));
 948        cx_write(MO_SCONV_REG, (u32)tmp64);
 949
 950        // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
 951        tmp64  = step_db * (u64)(1 << 22);
 952        do_div(tmp64, vdec_clock);
 953        dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
 954                (u32)tmp64, cx_read(MO_SUB_STEP));
 955        cx_write(MO_SUB_STEP, (u32)tmp64);
 956
 957        // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
 958        tmp64  = step_dr * (u64)(1 << 22);
 959        do_div(tmp64, vdec_clock);
 960        dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
 961                (u32)tmp64, cx_read(MO_SUB_STEP_DR));
 962        cx_write(MO_SUB_STEP_DR, (u32)tmp64);
 963
 964        // bdelay + agcdelay
 965        bdelay   = vdec_clock * 65 / 20000000 + 21;
 966        agcdelay = vdec_clock * 68 / 20000000 + 15;
 967        dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
 968                (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
 969        cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
 970
 971        // htotal
 972        tmp64 = norm_htotal(norm) * (u64)vdec_clock;
 973        do_div(tmp64, fsc8);
 974        htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
 975        dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
 976                htotal, cx_read(MO_HTOTAL), (u32)tmp64);
 977        cx_write(MO_HTOTAL, htotal);
 978
 979        // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
 980        // the effective vbi offset ~244 samples, the same as the Bt8x8
 981        cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
 982
 983        // this is needed as well to set all tvnorm parameter
 984        cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
 985
 986        // audio
 987        set_tvaudio(core);
 988
 989        // tell i2c chips
 990        cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm);
 991
 992        // done
 993        return 0;
 994}
 995
 996/* ------------------------------------------------------------------ */
 997
 998struct video_device *cx88_vdev_init(struct cx88_core *core,
 999                                    struct pci_dev *pci,
1000                                    struct video_device *template,
1001                                    char *type)
1002{
1003        struct video_device *vfd;
1004
1005        vfd = video_device_alloc();
1006        if (NULL == vfd)
1007                return NULL;
1008        *vfd = *template;
1009        vfd->minor   = -1;
1010        vfd->parent  = &pci->dev;
1011        vfd->release = video_device_release;
1012        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
1013                 core->name, type, core->board.name);
1014        return vfd;
1015}
1016
1017struct cx88_core* cx88_core_get(struct pci_dev *pci)
1018{
1019        struct cx88_core *core;
1020
1021        mutex_lock(&devlist);
1022        list_for_each_entry(core, &cx88_devlist, devlist) {
1023                if (pci->bus->number != core->pci_bus)
1024                        continue;
1025                if (PCI_SLOT(pci->devfn) != core->pci_slot)
1026                        continue;
1027
1028                if (0 != cx88_get_resources(core, pci)) {
1029                        mutex_unlock(&devlist);
1030                        return NULL;
1031                }
1032                atomic_inc(&core->refcount);
1033                mutex_unlock(&devlist);
1034                return core;
1035        }
1036
1037        core = cx88_core_create(pci, cx88_devcount);
1038        if (NULL != core) {
1039                cx88_devcount++;
1040                list_add_tail(&core->devlist, &cx88_devlist);
1041        }
1042
1043        mutex_unlock(&devlist);
1044        return core;
1045}
1046
1047void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
1048{
1049        release_mem_region(pci_resource_start(pci,0),
1050                           pci_resource_len(pci,0));
1051
1052        if (!atomic_dec_and_test(&core->refcount))
1053                return;
1054
1055        mutex_lock(&devlist);
1056        cx88_ir_fini(core);
1057        if (0 == core->i2c_rc)
1058                i2c_del_adapter(&core->i2c_adap);
1059        list_del(&core->devlist);
1060        iounmap(core->lmmio);
1061        cx88_devcount--;
1062        mutex_unlock(&devlist);
1063        kfree(core);
1064}
1065
1066/* ------------------------------------------------------------------ */
1067
1068EXPORT_SYMBOL(cx88_print_irqbits);
1069
1070EXPORT_SYMBOL(cx88_core_irq);
1071EXPORT_SYMBOL(cx88_wakeup);
1072EXPORT_SYMBOL(cx88_reset);
1073EXPORT_SYMBOL(cx88_shutdown);
1074
1075EXPORT_SYMBOL(cx88_risc_buffer);
1076EXPORT_SYMBOL(cx88_risc_databuffer);
1077EXPORT_SYMBOL(cx88_risc_stopper);
1078EXPORT_SYMBOL(cx88_free_buffer);
1079
1080EXPORT_SYMBOL(cx88_sram_channels);
1081EXPORT_SYMBOL(cx88_sram_channel_setup);
1082EXPORT_SYMBOL(cx88_sram_channel_dump);
1083
1084EXPORT_SYMBOL(cx88_set_tvnorm);
1085EXPORT_SYMBOL(cx88_set_scale);
1086
1087EXPORT_SYMBOL(cx88_vdev_init);
1088EXPORT_SYMBOL(cx88_core_get);
1089EXPORT_SYMBOL(cx88_core_put);
1090
1091EXPORT_SYMBOL(cx88_ir_start);
1092EXPORT_SYMBOL(cx88_ir_stop);
1093
1094/*
1095 * Local variables:
1096 * c-basic-offset: 8
1097 * End:
1098 * 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
1099 */
1100
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.