drivers/media/pci/cx18/cx18-dvb.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/cx18/cx18-dvb.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/cx18/cx18-dvb.c
Extension
.c
Size
16312 bytes
Lines
594
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (sz < 2 || sz > 64 || (sz % 2) != 0) {
			CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
				 fn, (unsigned long) sz);
			ret = -EILSEQ;
			release_firmware(*fw);
			*fw = NULL;
		}
	}

	if (ret) {
		CX18_ERR("The MPC718 board variant with the MT352 DVB-T demodulator will not work without it\n");
		CX18_ERR("Run 'linux/scripts/get_dvb_firmware mpc718' if you need the firmware\n");
	}
	return ret;
}

static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
{
	struct cx18_dvb *dvb = container_of(fe->dvb,
					    struct cx18_dvb, dvb_adapter);
	struct cx18_stream *stream = dvb->stream;
	const struct firmware *fw = NULL;
	int ret;
	int i;
	u8 buf[3];

	ret = yuan_mpc718_mt352_reqfw(stream, &fw);
	if (ret)
		return ret;

	/* Loop through all the register-value pairs in the firmware file */
	for (i = 0; i < fw->size; i += 2) {
		buf[0] = fw->data[i];
		/* Intercept a few registers we want to set ourselves */
		switch (buf[0]) {
		case TRL_NOMINAL_RATE_0:
			/* Set our custom OFDM bandwidth in the case below */
			break;
		case TRL_NOMINAL_RATE_1:
			/* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
			/* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
			/* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
			buf[1] = 0x72;
			buf[2] = 0x49;
			mt352_write(fe, buf, 3);
			break;
		case INPUT_FREQ_0:
			/* Set our custom IF in the case below */
			break;
		case INPUT_FREQ_1:
			/* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
			buf[1] = 0x31;
			buf[2] = 0xc0;
			mt352_write(fe, buf, 3);
			break;
		default:
			/* Pass through the register-value pair from the fw */
			buf[1] = fw->data[i+1];
			mt352_write(fe, buf, 2);
			break;
		}
	}

	buf[0] = (u8) TUNER_GO;
	buf[1] = 0x01; /* Go */
	mt352_write(fe, buf, 2);
	release_firmware(fw);
	return 0;
}

static struct mt352_config yuan_mpc718_mt352_demod = {
	.demod_address = 0x1e >> 1,
	.adc_clock     = 20480,     /* 20.480 MHz */
	.if2           =  4560,     /*  4.560 MHz */
	.no_tuner      = 1,         /* XC3028 is not behind the gate */
	.demod_init    = yuan_mpc718_mt352_init,
};

static struct zl10353_config yuan_mpc718_zl10353_demod = {
	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
	.parallel_ts           = 1,         /* Not a serial TS */
	.no_tuner              = 1,         /* XC3028 is not behind the gate */
	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
};

static struct zl10353_config gotview_dvd3_zl10353_demod = {
	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
	.parallel_ts           = 1,         /* Not a serial TS */

Annotation

Implementation Notes