drivers/media/pci/hws/hws_video.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/hws/hws_video.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/hws/hws_video.c
Extension
.c
Size
42250 bytes
Lines
1491
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 (err) {
			dev_err(&pdev->pdev->dev,
				"v4l2 ctrl init failed on ch%d: %d\n", ch, err);
			return err;
		}
	}

	return 0;
}

static void hws_video_drain_queue_locked(struct hws_video *vid)
{
	/* Return in-flight first */
	if (vid->active) {
		vb2_buffer_done(&vid->active->vb.vb2_buf, VB2_BUF_STATE_ERROR);
		vid->active = NULL;
	}

	/* Then everything queued */
	while (!list_empty(&vid->capture_queue)) {
		struct hwsvideo_buffer *b =
		    list_first_entry(&vid->capture_queue,
				     struct hwsvideo_buffer,
				     list);
		list_del_init(&b->list);
		vb2_buffer_done(&b->vb.vb2_buf, VB2_BUF_STATE_ERROR);
	}
}

static void hws_video_release_registration(struct hws_video *vid)
{
	if (vid->buffer_queue.ops) {
		vb2_queue_release(&vid->buffer_queue);
		vid->buffer_queue.ops = NULL;
	}

	if (!vid->video_device)
		return;

	if (video_is_registered(vid->video_device))
		vb2_video_unregister_device(vid->video_device);
	else
		video_device_release(vid->video_device);
	vid->video_device = NULL;
}

static void hws_video_collect_done_locked(struct hws_video *vid,
					  struct list_head *done)
{
	struct hwsvideo_buffer *b;

	if (vid->active) {
		if (!list_node_unlinked(&vid->active->list)) {
			list_move_tail(&vid->active->list, done);
		} else {
			INIT_LIST_HEAD(&vid->active->list);
			list_add_tail(&vid->active->list, done);
		}
		vid->active = NULL;
	}

	if (vid->next_prepared) {
		if (!list_node_unlinked(&vid->next_prepared->list)) {
			list_move_tail(&vid->next_prepared->list, done);
		} else {
			INIT_LIST_HEAD(&vid->next_prepared->list);
			list_add_tail(&vid->next_prepared->list, done);
		}
		vid->next_prepared = NULL;
	}

	while (!list_empty(&vid->capture_queue)) {
		b = list_first_entry(&vid->capture_queue, struct hwsvideo_buffer,
				     list);
		list_move_tail(&b->list, done);
	}

	vid->queued_count = 0;
}

void hws_video_cleanup_channel(struct hws_pcie_dev *pdev, int ch)
{
	struct hws_video *vid;
	unsigned long flags;

	if (!pdev || ch < 0 || ch >= pdev->max_channels)
		return;

	vid = &pdev->video[ch];

Annotation

Implementation Notes