drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c

Source file repositories/reference/linux-study-clean/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
Extension
.c
Size
9967 bytes
Lines
384
Domain
Driver Families
Bucket
drivers/staging
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

struct bcm2835_audio_instance {
	struct device *dev;
	unsigned int service_handle;
	struct completion msg_avail_comp;
	struct mutex vchi_mutex; /* Serialize vchiq access */
	struct bcm2835_alsa_stream *alsa_stream;
	int result;
	unsigned int max_packet;
	short peer_version;
};

static bool force_bulk;
module_param(force_bulk, bool, 0444);
MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");

static void bcm2835_audio_lock(struct bcm2835_audio_instance *instance)
{
	mutex_lock(&instance->vchi_mutex);
	vchiq_use_service(instance->alsa_stream->chip->vchi_ctx->instance,
			  instance->service_handle);
}

static void bcm2835_audio_unlock(struct bcm2835_audio_instance *instance)
{
	vchiq_release_service(instance->alsa_stream->chip->vchi_ctx->instance,
			      instance->service_handle);
	mutex_unlock(&instance->vchi_mutex);
}

static int bcm2835_audio_send_msg_locked(struct bcm2835_audio_instance *instance,
					 struct vc_audio_msg *m, bool wait)
{
	int status;

	if (wait) {
		instance->result = -1;
		init_completion(&instance->msg_avail_comp);
	}

	status = vchiq_queue_kernel_message(instance->alsa_stream->chip->vchi_ctx->instance,
					    instance->service_handle, m, sizeof(*m));
	if (status) {
		dev_err(instance->dev,
			"vchi message queue failed: %d, msg=%d\n",
			status, m->type);
		return -EIO;
	}

	if (wait) {
		if (!wait_for_completion_timeout(&instance->msg_avail_comp,
						 secs_to_jiffies(10))) {
			dev_err(instance->dev,
				"vchi message timeout, msg=%d\n", m->type);
			return -ETIMEDOUT;
		} else if (instance->result) {
			dev_err(instance->dev,
				"vchi message response error:%d, msg=%d\n",
				instance->result, m->type);
			return -EIO;
		}
	}

	return 0;
}

static int bcm2835_audio_send_msg(struct bcm2835_audio_instance *instance,
				  struct vc_audio_msg *m, bool wait)
{
	int err;

	bcm2835_audio_lock(instance);
	err = bcm2835_audio_send_msg_locked(instance, m, wait);
	bcm2835_audio_unlock(instance);
	return err;
}

static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
				     int type, bool wait)
{
	struct vc_audio_msg m = { .type = type };

	return bcm2835_audio_send_msg(instance, &m, wait);
}

static int audio_vchi_callback(struct vchiq_instance *vchiq_instance,
			       enum vchiq_reason reason,
			       struct vchiq_header *header,
			       unsigned int handle,
			       void *cb_data, void __user *cb_userdata)
{

Annotation

Implementation Notes