*(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));
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;
/* 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;
}
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;
/* 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;
}
}
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;
}
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)
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,
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);
{
/* 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);
/* 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);
// 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);
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;
}
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);
/* 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);
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--;
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: