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

📄 budget-ci.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
			dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);		}	} else {		// trigger on rising edge if a CAM is not present - when a CAM is inserted, we		// only want to get the IRQ when it sets READY. If we trigger on the falling edge,		// the CAM might not actually be ready yet.		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);		// generate a CAM removal IRQ if we haven't already		if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {			// CAM removal IRQ			budget_ci->slot_status = SLOTSTATUS_NONE;			dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,						     DVB_CA_EN50221_CAMCHANGE_REMOVED);		}	}}static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open){	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;	unsigned int flags;	// ensure we don't get spurious IRQs during initialisation	if (!budget_ci->budget.ci_present)		return -EINVAL;	// read the CAM status	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);	if (flags & CICONTROL_CAMDETECT) {		// mark it as present if it wasn't before		if (budget_ci->slot_status & SLOTSTATUS_NONE) {			budget_ci->slot_status = SLOTSTATUS_PRESENT;		}		// during a RESET, we check if we can read from IO memory to see when CAM is ready		if (budget_ci->slot_status & SLOTSTATUS_RESET) {			if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {				budget_ci->slot_status = SLOTSTATUS_READY;			}		}	} else {		budget_ci->slot_status = SLOTSTATUS_NONE;	}	if (budget_ci->slot_status != SLOTSTATUS_NONE) {		if (budget_ci->slot_status & SLOTSTATUS_READY) {			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;		}		return DVB_CA_EN50221_POLL_CAM_PRESENT;	}	return 0;}static int ciintf_init(struct budget_ci *budget_ci){	struct saa7146_dev *saa = budget_ci->budget.dev;	int flags;	int result;	int ci_version;	int ca_flags;	memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));	// enable DEBI pins	saa7146_write(saa, MC1, MASK_27 | MASK_11);	// test if it is there	ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);	if ((ci_version & 0xa0) != 0xa0) {		result = -ENODEV;		goto error;	}	// determine whether a CAM is present or not	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);	budget_ci->slot_status = SLOTSTATUS_NONE;	if (flags & CICONTROL_CAMDETECT)		budget_ci->slot_status = SLOTSTATUS_PRESENT;	// version 0xa2 of the CI firmware doesn't generate interrupts	if (ci_version == 0xa2) {		ca_flags = 0;		budget_ci->ci_irq = 0;	} else {		ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |				DVB_CA_EN50221_FLAG_IRQ_FR |				DVB_CA_EN50221_FLAG_IRQ_DA;		budget_ci->ci_irq = 1;	}	// register CI interface	budget_ci->ca.owner = THIS_MODULE;	budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;	budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;	budget_ci->ca.read_cam_control = ciintf_read_cam_control;	budget_ci->ca.write_cam_control = ciintf_write_cam_control;	budget_ci->ca.slot_reset = ciintf_slot_reset;	budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;	budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;	budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;	budget_ci->ca.data = budget_ci;	if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,					  &budget_ci->ca,					  ca_flags, 1)) != 0) {		printk("budget_ci: CI interface detected, but initialisation failed.\n");		goto error;	}	// Setup CI slot IRQ	if (budget_ci->ci_irq) {		tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);		if (budget_ci->slot_status != SLOTSTATUS_NONE) {			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);		} else {			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);		}		SAA7146_IER_ENABLE(saa, MASK_03);	}	// enable interface	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,			       CICONTROL_RESET, 1, 0);	// success!	printk("budget_ci: CI interface initialised\n");	budget_ci->budget.ci_present = 1;	// forge a fake CI IRQ so the CAM state is setup correctly	if (budget_ci->ci_irq) {		flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;		if (budget_ci->slot_status != SLOTSTATUS_NONE)			flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;		dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);	}	return 0;error:	saa7146_write(saa, MC1, MASK_27);	return result;}static void ciintf_deinit(struct budget_ci *budget_ci){	struct saa7146_dev *saa = budget_ci->budget.dev;	// disable CI interrupts	if (budget_ci->ci_irq) {		SAA7146_IER_DISABLE(saa, MASK_03);		saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);		tasklet_kill(&budget_ci->ciintf_irq_tasklet);	}	// reset interface	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);	msleep(1);	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,			       CICONTROL_RESET, 1, 0);	// disable TS data stream to CI interface	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);	// release the CA device	dvb_ca_en50221_release(&budget_ci->ca);	// disable DEBI pins	saa7146_write(saa, MC1, MASK_27);}static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr){	struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;	dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);	if (*isr & MASK_06)		tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);	if (*isr & MASK_10)		ttpci_budget_irq10_handler(dev, isr);	if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))		tasklet_schedule(&budget_ci->ciintf_irq_tasklet);}static u8 philips_su1278_tt_inittab[] = {	0x01, 0x0f,	0x02, 0x30,	0x03, 0x00,	0x04, 0x5b,	0x05, 0x85,	0x06, 0x02,	0x07, 0x00,	0x08, 0x02,	0x09, 0x00,	0x0C, 0x01,	0x0D, 0x81,	0x0E, 0x44,	0x0f, 0x14,	0x10, 0x3c,	0x11, 0x84,	0x12, 0xda,	0x13, 0x97,	0x14, 0x95,	0x15, 0xc9,	0x16, 0x19,	0x17, 0x8c,	0x18, 0x59,	0x19, 0xf8,	0x1a, 0xfe,	0x1c, 0x7f,	0x1d, 0x00,	0x1e, 0x00,	0x1f, 0x50,	0x20, 0x00,	0x21, 0x00,	0x22, 0x00,	0x23, 0x00,	0x28, 0x00,	0x29, 0x28,	0x2a, 0x14,	0x2b, 0x0f,	0x2c, 0x09,	0x2d, 0x09,	0x31, 0x1f,	0x32, 0x19,	0x33, 0xfc,	0x34, 0x93,	0xff, 0xff};static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio){	stv0299_writereg(fe, 0x0e, 0x44);	if (srate >= 10000000) {		stv0299_writereg(fe, 0x13, 0x97);		stv0299_writereg(fe, 0x14, 0x95);		stv0299_writereg(fe, 0x15, 0xc9);		stv0299_writereg(fe, 0x17, 0x8c);		stv0299_writereg(fe, 0x1a, 0xfe);		stv0299_writereg(fe, 0x1c, 0x7f);		stv0299_writereg(fe, 0x2d, 0x09);	} else {		stv0299_writereg(fe, 0x13, 0x99);		stv0299_writereg(fe, 0x14, 0x8d);		stv0299_writereg(fe, 0x15, 0xce);		stv0299_writereg(fe, 0x17, 0x43);		stv0299_writereg(fe, 0x1a, 0x1d);		stv0299_writereg(fe, 0x1c, 0x12);		stv0299_writereg(fe, 0x2d, 0x05);	}	stv0299_writereg(fe, 0x0e, 0x23);	stv0299_writereg(fe, 0x0f, 0x94);	stv0299_writereg(fe, 0x10, 0x39);	stv0299_writereg(fe, 0x15, 0xc9);	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);	return 0;}static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,					   struct dvb_frontend_parameters *params){	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;	u32 div;	u8 buf[4];	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };	if ((params->frequency < 950000) || (params->frequency > 2150000))		return -EINVAL;	div = (params->frequency + (500 - 1)) / 500;	// round correctly	buf[0] = (div >> 8) & 0x7f;	buf[1] = div & 0xff;	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;	buf[3] = 0x20;	if (params->u.qpsk.symbol_rate < 4000000)		buf[3] |= 1;	if (params->frequency < 1250000)		buf[3] |= 0;	else if (params->frequency < 1550000)		buf[3] |= 0x40;	else if (params->frequency < 2050000)		buf[3] |= 0x80;	else if (params->frequency < 2150000)		buf[3] |= 0xC0;	if (fe->ops.i2c_gate_ctrl)		fe->ops.i2c_gate_ctrl(fe, 1);	if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)		return -EIO;	return 0;}static struct stv0299_config philips_su1278_tt_config = {	.demod_address = 0x68,	.inittab = philips_su1278_tt_inittab,	.mclk = 64000000UL,	.invert = 0,	.skip_reinit = 1,	.lock_output = STV0299_LOCKOUTPUT_1,	.volt13_op0_op1 = STV0299_VOLT13_OP1,	.min_delay_ms = 50,	.set_symbol_rate = philips_su1278_tt_set_symbol_rate,};static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe){	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =			sizeof(td1316_init) };	// setup PLL configuration	if (fe->ops.i2c_gate_ctrl)		fe->ops.i2c_gate_ctrl(fe, 1);	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)		return -EIO;	msleep(1);	// disable the mc44BC374c (do not check for errors)	tuner_msg.addr = 0x65;	tuner_msg.buf = disable_mc44BC374c;	tuner_msg.len = sizeof(disable_mc44BC374c);	if (fe->ops.i2c_gate_ctrl)		fe->ops.i2c_gate_ctrl(fe, 1);	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {		if (fe->ops.i2c_gate_ctrl)			fe->ops.i2c_gate_ctrl(fe, 1);		i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);	}	return 0;}static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params){	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;	u8 tuner_buf[4];	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };	int tuner_frequency = 0;	u8 band, cp, filter;	// determine charge pump	tuner_frequency = params->frequency + 36130000;	if (tuner_frequency < 87000000)		return -EINVAL;	else if (tuner_frequency < 130000000)		cp = 3;	else if (tuner_frequency < 160000000)		cp = 5;	else if (tuner_frequency < 200000000)		cp = 6;	else if (tuner_frequency < 290000000)		cp = 3;	else if (tuner_frequency < 420000000)		cp = 5;	else if (tuner_frequency < 480000000)		cp = 6;	else if (tuner_frequency < 620000000)		cp = 3;	else if (tuner_frequency < 830000000)		cp = 5;	else if (tuner_frequency < 895000000)		cp = 7;	else		return -EINVAL;	// determine band	if (params->frequency < 49000000)		return -EINVAL;	else if (params->frequency < 159000000)		band = 1;	else if (params->frequency < 444000000)		band = 2;	else if (params->frequency < 861000000)		band = 4;	else		return -EINVAL;	// setup PLL filter and TDA9889	switch (params->u.ofdm.bandwidth) {	case BANDWIDTH_6_MHZ:		tda1004x_writereg(fe, 0x0C, 0x14);		filter = 0;		break;	case BANDWIDTH_7_MHZ:		tda1004x_writereg(fe, 0x0C, 0x80);		filter = 0;		break;	case BANDWIDTH_8_MHZ:		tda1004x_writereg(fe, 0x0C, 0x14);		filter = 1;		break;	default:		return -EINVAL;	}	// calculate divisor	// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)	tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;	// setup tuner buffer	tuner_buf[0] = tuner_frequency >> 8;	tuner_buf[1] = tuner_frequency & 0xff;	tuner_buf[2] = 0xca;	tuner_buf[3] = (cp << 5) | (filter << 3) | band;	if (fe->ops.i2c_gate_ctrl)		fe->ops.i2c_gate_ctrl(fe, 1);	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)		return -EIO;	msleep(1);	return 0;}static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,					     const struct firmware **fw, char *name)

⌨️ 快捷键说明

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