⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx88-core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			return 0;		}		dprintk(1,"pll not locked yet, waiting ...\n");		msleep(10);	}	dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);	return -1;}int cx88_start_audio_dma(struct cx88_core *core){	/* setup fifo + format */	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);	cx_write(MO_AUDD_LNGTH,    128); /* fifo bpl size */	cx_write(MO_AUDR_LNGTH,    128); /* fifo bpl size */	/* start dma */	cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */	return 0;}int cx88_stop_audio_dma(struct cx88_core *core){	/* stop dma */	cx_write(MO_AUD_DMACNTRL, 0x0000);	return 0;}static int set_tvaudio(struct cx88_core *core){	struct cx88_tvnorm *norm = core->tvnorm;	if (CX88_VMUX_TELEVISION != INPUT(core->input)->type)		return 0;	if (V4L2_STD_PAL_BG & norm->id) {		core->tvaudio = WW_BG;	} else if (V4L2_STD_PAL_DK & norm->id) {		core->tvaudio = WW_DK;	} else if (V4L2_STD_PAL_I & norm->id) {		core->tvaudio = WW_I;	} else if (V4L2_STD_SECAM_L & norm->id) {		core->tvaudio = WW_L;	} else if (V4L2_STD_SECAM_DK & norm->id) {		core->tvaudio = WW_DK;	} else if ((V4L2_STD_NTSC_M & norm->id) ||		   (V4L2_STD_PAL_M  & norm->id)) {		core->tvaudio = WW_BTSC;	} else if (V4L2_STD_NTSC_M_JP & norm->id) {		core->tvaudio = WW_EIAJ;	} else {		printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",		       core->name, norm->name);		core->tvaudio = 0;		return 0;	}	cx_andor(MO_AFECFG_IO, 0x1f, 0x0);	cx88_set_tvaudio(core);	/* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); *//*   This should be needed only on cx88-alsa. It seems that some cx88 chips have   bugs and does require DMA enabled for it to work. */	cx88_start_audio_dma(core);	return 0;}int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm){	u32 fsc8;	u32 adc_clock;	u32 vdec_clock;	u32 step_db,step_dr;	u64 tmp64;	u32 bdelay,agcdelay,htotal;	core->tvnorm = norm;	fsc8       = norm_fsc8(norm);	adc_clock  = xtal;	vdec_clock = fsc8;	step_db    = fsc8;	step_dr    = fsc8;	if (norm->id & V4L2_STD_SECAM) {		step_db = 4250000 * 8;		step_dr = 4406250 * 8;	}	dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",		norm->name, fsc8, adc_clock, vdec_clock, step_db, step_dr);	set_pll(core,2,vdec_clock);	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",		norm->cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);	cx_andor(MO_INPUT_FORMAT, 0xf, norm->cxiformat);	// FIXME: as-is from DScaler	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",		norm->cxoformat, cx_read(MO_OUTPUT_FORMAT));	cx_write(MO_OUTPUT_FORMAT, norm->cxoformat);	// MO_SCONV_REG = adc clock / video dec clock * 2^17	tmp64  = adc_clock * (u64)(1 << 17);	do_div(tmp64, vdec_clock);	dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",		(u32)tmp64, cx_read(MO_SCONV_REG));	cx_write(MO_SCONV_REG, (u32)tmp64);	// MO_SUB_STEP = 8 * fsc / video dec clock * 2^22	tmp64  = step_db * (u64)(1 << 22);	do_div(tmp64, vdec_clock);	dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",		(u32)tmp64, cx_read(MO_SUB_STEP));	cx_write(MO_SUB_STEP, (u32)tmp64);	// MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22	tmp64  = step_dr * (u64)(1 << 22);	do_div(tmp64, vdec_clock);	dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",		(u32)tmp64, cx_read(MO_SUB_STEP_DR));	cx_write(MO_SUB_STEP_DR, (u32)tmp64);	// bdelay + agcdelay	bdelay   = vdec_clock * 65 / 20000000 + 21;	agcdelay = vdec_clock * 68 / 20000000 + 15;	dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",		(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);	cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);	// htotal	tmp64 = norm_htotal(norm) * (u64)vdec_clock;	do_div(tmp64, fsc8);	htotal = (u32)tmp64 | (norm_notchfilter(norm) << 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)));	// this is needed as well to set all tvnorm parameter	cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);	// audio	set_tvaudio(core);	// tell i2c chips	cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);	// done	return 0;}/* ------------------------------------------------------------------ */static int cx88_pci_quirks(char *name, struct pci_dev *pci){	unsigned int lat = UNSET;	u8 ctrl = 0;	u8 value;	/* check pci quirks */	if (pci_pci_problems & PCIPCI_TRITON) {		printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",		       name);		ctrl |= CX88X_EN_TBFX;	}	if (pci_pci_problems & PCIPCI_NATOMA) {		printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",		       name);		ctrl |= CX88X_EN_TBFX;	}	if (pci_pci_problems & PCIPCI_VIAETBF) {		printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",		       name);		ctrl |= CX88X_EN_TBFX;	}	if (pci_pci_problems & PCIPCI_VSFX) {		printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",		       name);		ctrl |= CX88X_EN_VSFX;	}#ifdef PCIPCI_ALIMAGIK	if (pci_pci_problems & PCIPCI_ALIMAGIK) {		printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",		       name);		lat = 0x0A;	}#endif	/* check insmod options */	if (UNSET != latency)		lat = latency;	/* apply stuff */	if (ctrl) {		pci_read_config_byte(pci, CX88X_DEVCTRL, &value);		value |= ctrl;		pci_write_config_byte(pci, CX88X_DEVCTRL, value);	}	if (UNSET != lat) {		printk(KERN_INFO "%s: setting pci latency timer to %d\n",		       name, latency);		pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);	}	return 0;}/* ------------------------------------------------------------------ */struct video_device *cx88_vdev_init(struct cx88_core *core,				    struct pci_dev *pci,				    struct video_device *template,				    char *type){	struct video_device *vfd;	vfd = video_device_alloc();	if (NULL == vfd)		return NULL;	*vfd = *template;	vfd->minor   = -1;	vfd->dev     = &pci->dev;	vfd->release = video_device_release;	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",		 core->name, type, cx88_boards[core->board].name);	return vfd;}static int get_ressources(struct cx88_core *core, struct pci_dev *pci){	if (request_mem_region(pci_resource_start(pci,0),			       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));	return -EBUSY;}struct cx88_core* cx88_core_get(struct pci_dev *pci){	struct cx88_core *core;	struct list_head *item;	int i;	down(&devlist);	list_for_each(item,&cx88_devlist) {		core = list_entry(item, struct cx88_core, devlist);		if (pci->bus->number != core->pci_bus)			continue;		if (PCI_SLOT(pci->devfn) != core->pci_slot)			continue;		if (0 != get_ressources(core,pci))			goto fail_unlock;		atomic_inc(&core->refcount);		up(&devlist);		return core;	}	core = kmalloc(sizeof(*core),GFP_KERNEL);	if (NULL == core)		goto fail_unlock;	memset(core,0,sizeof(*core));	atomic_inc(&core->refcount);	core->pci_bus  = pci->bus->number;	core->pci_slot = PCI_SLOT(pci->devfn);	core->pci_irqmask = 0x00fc00;	init_MUTEX(&core->lock);	core->nr = cx88_devcount++;	sprintf(core->name,"cx88[%d]",core->nr);	if (0 != get_ressources(core,pci)) {		printk(KERN_ERR "CORE %s No more PCI ressources for "			"subsystem: %04x:%04x, board: %s\n",			core->name,pci->subsystem_vendor,			pci->subsystem_device,			cx88_boards[core->board].name);		cx88_devcount--;		goto fail_free;	}	list_add_tail(&core->devlist,&cx88_devlist);	/* PCI stuff */	cx88_pci_quirks(core->name, pci);	core->lmmio = ioremap(pci_resource_start(pci,0),			      pci_resource_len(pci,0));	core->bmmio = (u8 __iomem *)core->lmmio;	/* board config */	core->board = UNSET;	if (card[core->nr] < cx88_bcount)		core->board = card[core->nr];	for (i = 0; UNSET == core->board  &&  i < cx88_idcount; i++)		if (pci->subsystem_vendor == cx88_subids[i].subvendor &&		    pci->subsystem_device == cx88_subids[i].subdevice)			core->board = cx88_subids[i].card;	if (UNSET == core->board) {		core->board = CX88_BOARD_UNKNOWN;		cx88_card_list(core,pci);	}	printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",		core->name,pci->subsystem_vendor,		pci->subsystem_device,cx88_boards[core->board].name,		core->board, card[core->nr] == core->board ?		"insmod option" : "autodetected");	core->tuner_type = tuner[core->nr];	core->radio_type = radio[core->nr];	if (UNSET == core->tuner_type)		core->tuner_type = cx88_boards[core->board].tuner_type;	if (UNSET == core->radio_type)		core->radio_type = cx88_boards[core->board].radio_type;	if (!core->tuner_addr)		core->tuner_addr = cx88_boards[core->board].tuner_addr;	if (!core->radio_addr)		core->radio_addr = cx88_boards[core->board].radio_addr;	printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",		core->tuner_type, core->tuner_addr<<1,		core->radio_type, core->radio_addr<<1);	core->tda9887_conf = cx88_boards[core->board].tda9887_conf;	/* init hardware */	cx88_reset(core);	cx88_i2c_init(core,pci);	cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);	cx88_card_setup(core);	cx88_ir_init(core,pci);	up(&devlist);	return core;fail_free:	kfree(core);fail_unlock:	up(&devlist);	return NULL;}void cx88_core_put(struct cx88_core *core, struct pci_dev *pci){	release_mem_region(pci_resource_start(pci,0),			   pci_resource_len(pci,0));	if (!atomic_dec_and_test(&core->refcount))		return;	down(&devlist);	cx88_ir_fini(core);	if (0 == core->i2c_rc)		i2c_bit_del_bus(&core->i2c_adap);	list_del(&core->devlist);	iounmap(core->lmmio);	cx88_devcount--;	up(&devlist);	kfree(core);}/* ------------------------------------------------------------------ */EXPORT_SYMBOL(cx88_print_ioctl);EXPORT_SYMBOL(cx88_print_irqbits);EXPORT_SYMBOL(cx88_core_irq);EXPORT_SYMBOL(cx88_wakeup);EXPORT_SYMBOL(cx88_reset);EXPORT_SYMBOL(cx88_shutdown);EXPORT_SYMBOL(cx88_risc_buffer);EXPORT_SYMBOL(cx88_risc_databuffer);EXPORT_SYMBOL(cx88_risc_stopper);EXPORT_SYMBOL(cx88_free_buffer);EXPORT_SYMBOL(cx88_sram_channels);EXPORT_SYMBOL(cx88_sram_channel_setup);EXPORT_SYMBOL(cx88_sram_channel_dump);EXPORT_SYMBOL(cx88_set_tvnorm);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: * c-basic-offset: 8 * End: * 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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -