drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c
Extension
.c
Size
10657 bytes
Lines
373
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 (!(buf->ctx->msg_queue.status & CONTEXT_LIST_QUEUED)) {
			queue_work(buf->ctx->dev->core_workqueue, &buf->ctx->msg_queue.core_work);
			buf->ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
		}
	}

	mtk_v4l2_vdec_dbg(3, buf->ctx, "enqueue buf type: %d addr: 0x%p num: %d",
			  msg_ctx->hardware_index, buf, msg_ctx->ready_num);
	spin_unlock(&msg_ctx->ready_lock);

	return 0;
}

static bool vdec_msg_queue_wait_event(struct vdec_msg_queue_ctx *msg_ctx)
{
	int ret;

	ret = wait_event_timeout(msg_ctx->ready_to_use,
				 !list_empty(&msg_ctx->ready_queue),
				 msecs_to_jiffies(VDEC_MSG_QUEUE_TIMEOUT_MS));
	if (!ret)
		return false;

	return true;
}

struct vdec_lat_buf *vdec_msg_queue_dqbuf(struct vdec_msg_queue_ctx *msg_ctx)
{
	struct vdec_lat_buf *buf;
	struct list_head *head;
	int ret;

	spin_lock(&msg_ctx->ready_lock);
	if (list_empty(&msg_ctx->ready_queue)) {
		spin_unlock(&msg_ctx->ready_lock);

		if (msg_ctx->hardware_index == MTK_VDEC_CORE)
			return NULL;

		ret = vdec_msg_queue_wait_event(msg_ctx);
		if (!ret)
			return NULL;
		spin_lock(&msg_ctx->ready_lock);
	}

	if (msg_ctx->hardware_index == MTK_VDEC_CORE)
		buf = list_first_entry(&msg_ctx->ready_queue,
				       struct vdec_lat_buf, core_list);
	else
		buf = list_first_entry(&msg_ctx->ready_queue,
				       struct vdec_lat_buf, lat_list);

	head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
	if (!head) {
		spin_unlock(&msg_ctx->ready_lock);
		mtk_v4l2_vdec_err(buf->ctx, "fail to dqbuf: %d", msg_ctx->hardware_index);
		return NULL;
	}
	list_del(head);
	vdec_msg_queue_dec(&buf->ctx->msg_queue, msg_ctx->hardware_index);

	msg_ctx->ready_num--;
	mtk_v4l2_vdec_dbg(3, buf->ctx, "dqueue buf type:%d addr: 0x%p num: %d",
			  msg_ctx->hardware_index, buf, msg_ctx->ready_num);
	spin_unlock(&msg_ctx->ready_lock);

	return buf;
}

void vdec_msg_queue_update_ube_rptr(struct vdec_msg_queue *msg_queue, uint64_t ube_rptr)
{
	spin_lock(&msg_queue->lat_ctx.ready_lock);
	msg_queue->wdma_rptr_addr = ube_rptr;
	mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "update ube rprt (0x%llx)", ube_rptr);
	spin_unlock(&msg_queue->lat_ctx.ready_lock);
}

void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t ube_wptr)
{
	spin_lock(&msg_queue->lat_ctx.ready_lock);
	msg_queue->wdma_wptr_addr = ube_wptr;
	mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "update ube wprt: (0x%llx 0x%llx) offset: 0x%llx",
			  msg_queue->wdma_rptr_addr, msg_queue->wdma_wptr_addr,
			  ube_wptr);
	spin_unlock(&msg_queue->lat_ctx.ready_lock);
}

bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
{
	if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {

Annotation

Implementation Notes