drivers/media/usb/go7007/go7007-driver.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/go7007/go7007-driver.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/go7007/go7007-driver.c
Extension
.c
Size
18809 bytes
Lines
741
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (request_firmware(&fw_entry, fw_name, go->dev)) {
			v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
			return -1;
		}
		if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
			v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
			release_firmware(fw_entry);
			return -1;
		}
		fw_len = fw_entry->size - 16;
		bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
		if (bounce == NULL) {
			v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
			release_firmware(fw_entry);
			return -1;
		}
		release_firmware(fw_entry);
		go->boot_fw_len = fw_len;
		go->boot_fw = bounce;
	}
	if (go7007_interface_reset(go) < 0 ||
	    go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
			(intr_val & ~0x1) != 0x5a5a) {
		v4l2_err(go, "error transferring firmware\n");
		kfree(go->boot_fw);
		go->boot_fw = NULL;
		return -1;
	}
	return 0;
}

MODULE_FIRMWARE("go7007/go7007fw.bin");

/*
 * Boot the encoder and register the I2C adapter if requested.  Do the
 * minimum initialization necessary, since the board-specific code may
 * still need to probe the board ID.
 *
 * Must NOT be called with the hw_lock held.
 */
int go7007_boot_encoder(struct go7007 *go, int init_i2c)
{
	int ret;

	mutex_lock(&go->hw_lock);
	ret = go7007_load_encoder(go);
	mutex_unlock(&go->hw_lock);
	if (ret < 0)
		return -1;
	if (!init_i2c)
		return 0;
	if (go7007_i2c_init(go) < 0)
		return -1;
	go->i2c_adapter_online = 1;
	return 0;
}
EXPORT_SYMBOL(go7007_boot_encoder);

/*
 * Configure any hardware-related registers in the GO7007, such as GPIO
 * pins and bus parameters, which are board-specific.  This assumes
 * the boot firmware has already been downloaded.
 *
 * Must be called with the hw_lock held.
 */
static int go7007_init_encoder(struct go7007 *go)
{
	if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
		go7007_write_addr(go, 0x1000, 0x0811);
		go7007_write_addr(go, 0x1000, 0x0c11);
	}
	switch (go->board_id) {
	case GO7007_BOARDID_MATRIX_REV:
		/* Set GPIO pin 0 to be an output (audio clock control) */
		go7007_write_addr(go, 0x3c82, 0x0001);
		go7007_write_addr(go, 0x3c80, 0x00fe);
		break;
	case GO7007_BOARDID_ADLINK_MPG24:
		/* set GPIO5 to be an output, currently low */
		go7007_write_addr(go, 0x3c82, 0x0000);
		go7007_write_addr(go, 0x3c80, 0x00df);
		break;
	case GO7007_BOARDID_ADS_USBAV_709:
		/* GPIO pin 0: audio clock control */
		/*      pin 2: TW9906 reset */
		/*      pin 3: capture LED */
		go7007_write_addr(go, 0x3c82, 0x000d);
		go7007_write_addr(go, 0x3c80, 0x00f2);
		break;

Annotation

Implementation Notes