fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / media / video / cx88 / cx88-core.c
index 3720f24..1899736 100644 (file)
@@ -105,7 +105,7 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
                        offset+=bpl;
                } else {
-                       /* scanline needs to be splitted */
+                       /* scanline needs to be split */
                        todo = bpl;
                        *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|
                                            (sg_dma_len(sg)-offset));
@@ -146,9 +146,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
                fields++;
 
        /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords) */
-       instructions  = (bpl * lines * fields) / PAGE_SIZE + lines * fields;
-       instructions += 3 + 4;
+          one write per scan line + syncs + jump (all 2 dwords).  Padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+       instructions += 2;
        if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
                return rc;
 
@@ -163,7 +165,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
        return 0;
 }
 
@@ -176,9 +178,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
        int rc;
 
        /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords) */
-       instructions  = (bpl * lines) / PAGE_SIZE + lines;
-       instructions += 3 + 4;
+          one write per scan line + syncs + jump (all 2 dwords).  Here
+          there is no padding and no sync.  First DMA region may be smaller
+          than PAGE_SIZE */
+       instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+       instructions += 1;
        if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
                return rc;
 
@@ -188,7 +192,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
        return 0;
 }
 
@@ -213,14 +217,13 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
 }
 
 void
-cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
 {
-       if (in_interrupt())
-               BUG();
+       BUG_ON(in_interrupt());
        videobuf_waiton(&buf->vb,0,0);
-       videobuf_dma_pci_unmap(pci, &buf->vb.dma);
+       videobuf_dma_unmap(q, &buf->vb.dma);
        videobuf_dma_free(&buf->vb.dma);
-       btcx_riscmem_free(pci, &buf->risc);
+       btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc);
        buf->vb.state = STATE_NEEDS_INIT;
 }
 
@@ -630,12 +633,12 @@ int cx88_reset(struct cx88_core *core)
 
 static unsigned int inline norm_swidth(struct cx88_tvnorm *norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 922 : 754;
+       return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
 }
 
 static unsigned int inline norm_hdelay(struct cx88_tvnorm *norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 186 : 135;
+       return (norm->id & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
 }
 
 static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
@@ -645,36 +648,38 @@ static unsigned int inline norm_vdelay(struct cx88_tvnorm *norm)
 
 static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
 {
-       static const unsigned int ntsc = 28636360;
-       static const unsigned int pal  = 35468950;
-       static const unsigned int palm  = 28604892;
-
        if (norm->id & V4L2_STD_PAL_M)
-               return palm;
+               return 28604892;      // 3.575611 MHz
 
-       return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
-}
+       if (norm->id & (V4L2_STD_PAL_Nc))
+               return 28656448;      // 3.582056 MHz
 
-static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
-{
-       return (norm->id & V4L2_STD_625_50)
-               ? HLNotchFilter135PAL
-               : HLNotchFilter135NTSC;
+       if (norm->id & V4L2_STD_NTSC) // All NTSC/M and variants
+               return 28636360;      // 3.57954545 MHz +/- 10 Hz
+
+       /* SECAM have also different sub carrier for chroma,
+          but step_db and step_dr, at cx88_set_tvnorm already handles that.
+
+          The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
+        */
+
+       return 35468950;      // 4.43361875 MHz +/- 5 Hz
 }
 
 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
 {
-       /* Should always be Line Draw Time / (4*FSC) */
 
-       if (norm->id & V4L2_STD_PAL_M)
-               return 909;
+       unsigned int fsc4=norm_fsc8(norm)/2;
 
-       return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
+       /* returns 4*FSC / vtotal / frames per seconds */
+       return (norm->id & V4L2_STD_625_50) ?
+                               ((fsc4+312)/625+12)/25 :
+                               ((fsc4+262)/525*1001+15000)/30000;
 }
 
 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 511 : 288;
+       return (norm->id & V4L2_STD_625_50) ? 511 : 400;
 }
 
 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
@@ -696,7 +701,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
        value &= 0x3fe;
        cx_write(MO_HDELAY_EVEN,  value);
        cx_write(MO_HDELAY_ODD,   value);
-       dprintk(1,"set_scale: hdelay  0x%04x\n", value);
+       dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
 
        value = (swidth * 4096 / width) - 4096;
        cx_write(MO_HSCALE_EVEN,  value);
@@ -789,6 +794,11 @@ int cx88_start_audio_dma(struct cx88_core *core)
 {
        /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
        int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
        /* setup fifo + format */
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
@@ -798,11 +808,16 @@ int cx88_start_audio_dma(struct cx88_core *core)
 
        /* start dma */
        cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
+
        return 0;
 }
 
 int cx88_stop_audio_dma(struct cx88_core *core)
 {
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
        /* stop dma */
        cx_write(MO_AUD_DMACNTRL, 0x0000);
 
@@ -924,14 +939,14 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
        // htotal
        tmp64 = norm_htotal(norm) * (u64)vdec_clock;
        do_div(tmp64, fsc8);
-       htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
+       htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
        dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
                htotal, cx_read(MO_HTOTAL), (u32)tmp64);
        cx_write(MO_HTOTAL, htotal);
 
-       // vbi stuff
-       cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm)   << 11) | */
-                                norm_vbipack(norm)));
+       // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
+       // the effective vbi offset ~244 samples, the same as the Bt8x8
+       cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
 
        // this is needed as well to set all tvnorm parameter
        cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
@@ -1028,8 +1043,8 @@ static int get_ressources(struct cx88_core *core, struct pci_dev *pci)
                               pci_resource_len(pci,0),
                               core->name))
                return 0;
-       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
-              core->name,pci_resource_start(pci,0));
+       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+              core->name,(unsigned long long)pci_resource_start(pci,0));
        return -EBUSY;
 }
 
@@ -1061,7 +1076,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
        core->pci_bus  = pci->bus->number;
        core->pci_slot = PCI_SLOT(pci->devfn);
        core->pci_irqmask = 0x00fc00;
-       init_MUTEX(&core->lock);
+       mutex_init(&core->lock);
 
        core->nr = cx88_devcount++;
        sprintf(core->name,"cx88[%d]",core->nr);
@@ -1120,6 +1135,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
 
        /* init hardware */
        cx88_reset(core);
+       cx88_card_setup_pre_i2c(core);
        cx88_i2c_init(core,pci);
        cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
        cx88_card_setup(core);
@@ -1146,7 +1162,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
        mutex_lock(&devlist);
        cx88_ir_fini(core);
        if (0 == core->i2c_rc)
-               i2c_bit_del_bus(&core->i2c_adap);
+               i2c_del_adapter(&core->i2c_adap);
        list_del(&core->devlist);
        iounmap(core->lmmio);
        cx88_devcount--;
@@ -1178,8 +1194,6 @@ EXPORT_SYMBOL(cx88_set_scale);
 EXPORT_SYMBOL(cx88_vdev_init);
 EXPORT_SYMBOL(cx88_core_get);
 EXPORT_SYMBOL(cx88_core_put);
-EXPORT_SYMBOL(cx88_start_audio_dma);
-EXPORT_SYMBOL(cx88_stop_audio_dma);
 
 /*
  * Local variables: