Пример #1
0
static void
bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch, void *buf, uint32_t count)
{
	struct bcm2835_audio_info *sc = ch->parent;
	VC_AUDIO_MSG_T m;
	int ret;

	if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) {
		return;
	}

	m.type = VC_AUDIO_MSG_TYPE_WRITE;
	m.u.write.count = count;
	m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE;
	m.u.write.callback = NULL;
	m.u.write.cookie = ch;
	m.u.write.silence = 0;

	ret = vchi_msg_queue(sc->vchi_handle,
	    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (ret != 0)
		printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);

	while (count > 0) {
		int bytes = MIN((int)m.u.write.max_packet, (int)count);
		ret = vchi_msg_queue(sc->vchi_handle,
		    buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
		if (ret != 0)
			printf("%s: vchi_msg_queue failed: %d\n",
			    __func__, ret);
		buf = (char *)buf + bytes;
		count -= bytes;
	}
}
Пример #2
0
static void
bcm2835_audio_update_params(struct bcm2835_audio_info *sc, struct bcm2835_audio_chinfo *ch)
{
	VC_AUDIO_MSG_T m;
	int ret;

	VCHIQ_VCHI_LOCK(sc);
	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		vchi_service_use(sc->vchi_handle);

		sc->msg_result = -1;

		m.type = VC_AUDIO_MSG_TYPE_CONFIG;
		m.u.config.channels = AFMT_CHANNEL(ch->fmt);
		m.u.config.samplerate = ch->spd;
		m.u.config.bps = AFMT_BIT(ch->fmt);

		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);

		mtx_lock(&sc->msg_avail_lock);
		cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock);
		if (sc->msg_result)
			printf("%s failed: %d\n", __func__, sc->msg_result);
		mtx_unlock(&sc->msg_avail_lock);

		vchi_service_release(sc->vchi_handle);
	}
	VCHIQ_VCHI_UNLOCK(sc);
}
Пример #3
0
/******************************************************************************
NAME
   vc_gencmd_send

SYNOPSIS
   int vc_gencmd_send( const char *format, ... )

FUNCTION
   Send a string to general command service.

RETURNS
   int
******************************************************************************/
int vc_gencmd_send_list ( const char *format, va_list a )
{
   int success = -1;

   // Obtain the lock and keep it so no one else can butt in while we await the response.
   if(lock_obtain() == 0)
   {
      int length = vsnprintf( gencmd_client.command_buffer, GENCMD_MAX_LENGTH, format, a );
      
      if (length >= 0 && length < GENCMD_MAX_LENGTH)
      {
         int i;
         use_gencmd_service();
         for( i=0; i<gencmd_client.num_connections; i++ ) {
            success = vchi_msg_queue( gencmd_client.open_handle[i],
                                           gencmd_client.command_buffer,
                                           length+1,
                                           VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );

            if(success == 0)
            { // only want to send on one connection, so break on success
               break;
            }
         }
         release_gencmd_service();
      }

      lock_release();
   }

   return success;
}
Пример #4
0
static void
bcm2835_audio_update_controls(struct bcm2835_audio_info *sc)
{
	VC_AUDIO_MSG_T m;
	int ret, db;

	VCHIQ_VCHI_LOCK(sc);
	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		vchi_service_use(sc->vchi_handle);

		sc->msg_result = -1;

		m.type = VC_AUDIO_MSG_TYPE_CONTROL;
		m.u.control.dest = sc->dest;
		if (sc->volume > 99)
			sc->volume = 99;
		db = db_levels[sc->volume/5];
		m.u.control.volume = VCHIQ_AUDIO_VOLUME(db);

		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);

		mtx_lock(&sc->msg_avail_lock);
		cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock);
		if (sc->msg_result)
			printf("%s failed: %d\n", __func__, sc->msg_result);
		mtx_unlock(&sc->msg_avail_lock);

		vchi_service_release(sc->vchi_handle);
	}
	VCHIQ_VCHI_UNLOCK(sc);
}
Пример #5
0
static void
bcm2835_audio_start(struct bcm2835_audio_chinfo *ch)
{
	VC_AUDIO_MSG_T m;
	int ret;
	struct bcm2835_audio_info *sc = ch->parent;

	VCHIQ_VCHI_LOCK(sc);
	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		vchi_service_use(sc->vchi_handle);

		bcm2835_audio_reset_channel(ch);

		m.type = VC_AUDIO_MSG_TYPE_START;
		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);

		vchi_service_release(sc->vchi_handle);
	}
	VCHIQ_VCHI_UNLOCK(sc);

}
Пример #6
0
int
vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle,
			  void *data,
			  unsigned int size)
{
	return vchi_msg_queue(handle,
			      vchi_queue_kernel_message_callback,
			      data,
			      size);
}
Пример #7
0
int
vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle,
			void __user *data,
			unsigned int size)
{
	struct vchi_queue_user_message_context copycontext = {
		.data = data
	};

	return vchi_msg_queue(handle,
			      vchi_queue_user_message_callback,
			      &copycontext,
			      size);
}
Пример #8
0
int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream)
{
	AUDIO_INSTANCE_T *instance;
	VC_AUDIO_MSG_T m;
	int32_t success;
	int ret;
	LOG_DBG(" .. IN\n");

	my_workqueue_init(alsa_stream);

	ret = bcm2835_audio_open_connection(alsa_stream);
	if (ret != 0) {
		ret = -1;
		goto exit;
	}
	instance = alsa_stream->instance;
	LOG_DBG(" instance (%p)\n", instance);

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	m.type = VC_AUDIO_MSG_TYPE_OPEN;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);
exit:
	LOG_DBG(" .. OUT\n");
	return ret;
}
static int vc_gencmd_send_string(char *command)
{
   int success = 0, i;
   for( i=0; i<gencmd_client.num_connections; i++ ) {
      success += vchi_msg_queue( gencmd_client.open_handle[i],
                                 command,
                                 strlen(command)+1,
                                 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
      assert(!success);
      if(success != 0)
         break;
   }
   lock_release();
   return success;
}
Пример #10
0
static void
bcm2835_audio_open(struct bcm2835_audio_info *sc)
{
	VC_AUDIO_MSG_T m;
	int ret;

	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		m.type = VC_AUDIO_MSG_TYPE_OPEN;
		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
	}
}
Пример #11
0
static void
bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch)
{
	VC_AUDIO_MSG_T m;
	int ret;
	struct bcm2835_audio_info *sc = ch->parent;

	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		m.type = VC_AUDIO_MSG_TYPE_STOP;
		m.u.stop.draining = 0;

		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
	}
}
Пример #12
0
static void
bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed)
{
	VC_AUDIO_MSG_T m;
	int ret;

	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		m.type = VC_AUDIO_MSG_TYPE_CONFIG;
		m.u.config.channels = AFMT_CHANNEL(fmt);
		m.u.config.samplerate = speed;
		m.u.config.bps = AFMT_BIT(fmt);

		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
	}
}
Пример #13
0
static void
bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest)
{
	VC_AUDIO_MSG_T m;
	int ret, db;

	if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) {
		m.type = VC_AUDIO_MSG_TYPE_CONTROL;
		m.u.control.dest = dest;
		if (volume > 99)
			volume = 99;
		db = db_levels[volume/5];
		m.u.control.volume = VCHIQ_AUDIO_VOLUME(db);

		ret = vchi_msg_queue(sc->vchi_handle,
		    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

		if (ret != 0)
			printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);
	}
}
Пример #14
0
int32_t vc_vchi_fb_read(VC_VCHI_FB_HANDLE_T handle, uint32_t res_handle,
			void *buf, int32_t size)
{
	int32_t ret, success = 0;
	FB_INSTANCE_T *instance = handle;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_READ_T *fb_read;
	VC_FB_RESULT_T result;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle", __func__);

		ret = -1;
		goto out;
	}

	if (buf == NULL) {
		LOG_ERR("%s: invalid buffer pointer", __func__);

		ret = -1;
		goto out;
	}

	if (size <= 0) {
		LOG_ERR("%s: invalid buffer size %d", __func__, size);

		ret = -1;
		goto out;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	LOG_INFO("%s: enter", __func__);

	msg_len = sizeof(*msg_hdr) + sizeof(*fb_read);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_READ;

	fb_read = (VC_FB_READ_T *) msg_hdr->body;
	fb_read->res_handle = res_handle;
	fb_read->size = size;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	LOG_INFO("%s: done sending msg", __func__);
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   &result, sizeof(result),
				   &msg_len, VCHI_FLAGS_NONE);

	LOG_INFO("%s: got reply message %x", __func__, result.success);

	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(result));

		ret = -1;
		goto unlock;
	}

	LOG_INFO("%s: all good do bulk_receive %x", __func__, result.success);
	success = vchi_bulk_queue_receive(instance->vchi_handle[0],
					  buf,
					  size,
					  VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
					  0);

	if (success != 0)
		LOG_ERR("%s: vchi_bulk_queue_receive failed", __func__);

unlock:

	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	ret = success;
	LOG_INFO("%s: exit", __func__);
out:
	return ret;
}
Пример #15
0
int32_t vc_vchi_fb_cfg(VC_VCHI_FB_HANDLE_T handle,
		       VC_FB_CFG_T * cfg, VC_FB_CFG_RESULT_T * cfg_result)
{
	int32_t ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle", __func__);

		ret = -1;
		goto out;
	}

	if (cfg == NULL) {
		LOG_ERR("%s: invalid cfg pointer", __func__);

		ret = -1;
		goto out;
	}

	if (cfg_result == NULL) {
		LOG_ERR("%s: invalid cfg_result pointer", __func__);

		ret = -1;
		goto out;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*cfg);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_CFG;

	/* Copy the user buffer into the message buffer */
	memcpy(msg_hdr->body, cfg, sizeof(*cfg));

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   cfg_result, sizeof(*cfg_result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(*cfg_result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*cfg_result));

		ret = -1;
		goto unlock;
	}

	ret = cfg_result->success ? -1 : 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

out:
	return ret;
}
Пример #16
0
int32_t vc_vchi_fb_swap(VC_VCHI_FB_HANDLE_T handle,
			uint32_t res_handle, uint32_t active_frame)
{
	int ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_SWAP_T *swap;
	VC_FB_RESULT_T result;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*swap);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_SWAP;

	swap = (VC_FB_SWAP_T *) msg_hdr->body;
	swap->res_handle = res_handle;
	swap->active_frame = active_frame;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   &result, sizeof(result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(result));

		ret = -1;
		goto unlock;
	}

	ret = result.success ? -1 : 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}
Пример #17
0
int32_t vc_vchi_fb_alloc(VC_VCHI_FB_HANDLE_T handle,
			 VC_FB_ALLOC_T * alloc,
			 VC_FB_ALLOC_RESULT_T * alloc_result)
{
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	int32_t ret = -1;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	if (alloc == NULL) {
		LOG_ERR("%s: invalid alloc pointer %p", __func__, alloc);

		return -1;
	}
	/* TODO check individual alloc member values */

	if (alloc_result == NULL) {
		LOG_ERR("%s: invalid alloc_result pointer 0x%p", __func__,
			alloc_result);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*alloc);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_ALLOC;

	/* Copy the user buffer into the message buffer */
	memcpy(msg_hdr->body, alloc, sizeof(*alloc));

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		goto unlock;
	}
	/*  We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   alloc_result, sizeof(*alloc_result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		goto unlock;
	} else if (msg_len != sizeof(*alloc_result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*alloc_result));

		goto unlock;
	}
	/* success if we got to here */
	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}
Пример #18
0
int32_t vc_vchi_fb_get_scrn_info(VC_VCHI_FB_HANDLE_T handle,
				 VC_FB_SCRN scrn, VC_FB_SCRN_INFO_T * info)
{
	int ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_GET_SCRN_INFO_T *get_scrn_info;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	if (scrn >= VC_FB_SCRN_MAX) {
		LOG_ERR("%s: invalid screen %u", __func__, scrn);

		return -1;
	}

	if (info == NULL) {
		LOG_ERR("%s: invalid info pointer %p", __func__, info);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*get_scrn_info);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_GET_SCRN_INFO;

	get_scrn_info = (VC_FB_GET_SCRN_INFO_T *) msg_hdr->body;
	get_scrn_info->scrn = scrn;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   info, sizeof(*info),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(*info)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*info));

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}
Пример #19
0
static void
bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch)
{
	struct bcm2835_audio_info *sc = ch->parent;
	VC_AUDIO_MSG_T m;
	void *buf;
	uint32_t count, size;
	int ret;

	VCHIQ_VCHI_LOCK(sc);
	if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) {
		VCHIQ_VCHI_UNLOCK(sc);
		return;
	}

	vchi_service_use(sc->vchi_handle);

	size = sndbuf_getsize(ch->buffer);
	count = vchiq_unbuffered_bytes(ch);
	buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + ch->buffered_ptr;

	if (ch->buffered_ptr + count > size)
		count = size - ch->buffered_ptr;

	if (count < VCHIQ_AUDIO_PACKET_SIZE)
		goto done;

	count = min(count, ch->free_buffer);
	count -= count % VCHIQ_AUDIO_PACKET_SIZE;

	m.type = VC_AUDIO_MSG_TYPE_WRITE;
	m.u.write.count = count;
	m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE;
	m.u.write.callback = NULL;
	m.u.write.cookie = ch;
	if (buf)
		m.u.write.silence = 0;
	else
		m.u.write.silence = 1;

	ret = vchi_msg_queue(sc->vchi_handle,
	    &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (ret != 0)
		printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret);

	if (buf) {
		while (count > 0) {
			int bytes = MIN((int)m.u.write.max_packet, (int)count);
			ch->free_buffer -= bytes;
			ch->buffered_ptr += bytes;
			ch->buffered_ptr = ch->buffered_ptr % size;
			ret = vchi_msg_queue(sc->vchi_handle,
			    buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
			if (ret != 0)
				printf("%s: vchi_msg_queue failed: %d\n",
				    __func__, ret);
			buf = (char *)buf + bytes;
			count -= bytes;
		}
	}
done:

	vchi_service_release(sc->vchi_handle);
	VCHIQ_VCHI_UNLOCK(sc);
}
Пример #20
0
int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,
			       uint32_t count, void *src)
{
	VC_AUDIO_MSG_T m;
	AUDIO_INSTANCE_T *instance = alsa_stream->instance;
	int32_t success;
	int ret;

	LOG_DBG(" .. IN\n");

	LOG_INFO(" Writing %d bytes from %p\n", count, src);

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	if ( instance->peer_version==0 && vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0 ) {
		LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
	}
	m.type = VC_AUDIO_MSG_TYPE_WRITE;
	m.u.write.count = count;
	// old version uses bulk, new version uses control
	m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000;
	m.u.write.callback = alsa_stream->fifo_irq_handler;
	m.u.write.cookie = alsa_stream;
	m.u.write.silence = src == NULL;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	if (!m.u.write.silence) {
		if (m.u.write.max_packet == 0) {
			/* Send the message to the videocore */
			success = vchi_bulk_queue_transmit(instance->vchi_handle[0],
							   src, count,
							   0 *
							   VCHI_FLAGS_BLOCK_UNTIL_QUEUED
							   +
							   1 *
							   VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
							   NULL);
		} else {
			while (count > 0) {
				int bytes = min((int)m.u.write.max_packet, (int)count);
				success = vchi_msg_queue(instance->vchi_handle[0],
							 src, bytes,
							 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
				src = (char *)src + bytes;
				count -= bytes;
			}
		}
		if (success != 0) {
			LOG_ERR
			    ("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
			     __func__, success);

			ret = -1;
			goto unlock;
		}
	}
	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);
	LOG_DBG(" .. OUT\n");
	return ret;
}
Пример #21
0
int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)
{
	VC_AUDIO_MSG_T m;
	AUDIO_INSTANCE_T *instance = alsa_stream->instance;
	int32_t success;
	int ret;
	LOG_DBG(" .. IN\n");

	my_workqueue_quit(alsa_stream);

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	m.type = VC_AUDIO_MSG_TYPE_CLOSE;

	/* Create the message available completion */
	init_completion(&instance->msg_avail_comp);

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);
		ret = -1;
		goto unlock;
	}

	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
	if (ret) {
		LOG_DBG("%s: failed on waiting for event (status=%d)\n",
			__func__, success);
		goto unlock;
	}
	if (instance->result != 0) {
		LOG_ERR("%s: failed result (status=%d)\n",
			__func__, instance->result);

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	/* Stop the audio service */
	if (instance) {
		vc_vchi_audio_deinit(instance);
		alsa_stream->instance = NULL;
	}
	LOG_DBG(" .. OUT\n");
	return ret;
}
Пример #22
0
int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,
			     uint32_t channels, uint32_t samplerate,
			     uint32_t bps)
{
	VC_AUDIO_MSG_T m;
	AUDIO_INSTANCE_T *instance = alsa_stream->instance;
	int32_t success;
	int ret;
	LOG_DBG(" .. IN\n");

	LOG_INFO
	    (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
	     channels, samplerate, bps);

	/* resend ctls - alsa_stream may not have been open when first send */
	ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
	if (ret != 0) {
		LOG_ERR(" Alsa controls not supported\n");
		return -EINVAL;
	}

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	instance->result = -1;

	m.type = VC_AUDIO_MSG_TYPE_CONFIG;
	m.u.config.channels = channels;
	m.u.config.samplerate = samplerate;
	m.u.config.bps = bps;

	/* Create the message available completion */
	init_completion(&instance->msg_avail_comp);

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);

		ret = -1;
		goto unlock;
	}

	/* We are expecting a reply from the videocore */
	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
	if (ret) {
		LOG_DBG("%s: failed on waiting for event (status=%d)\n",
			__func__, success);
		goto unlock;
	}

	if (instance->result != 0) {
		LOG_ERR("%s: result=%d", __func__, instance->result);

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	LOG_DBG(" .. OUT\n");
	return ret;
}
Пример #23
0
static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream,
				       bcm2835_chip_t * chip)
{
	VC_AUDIO_MSG_T m;
	AUDIO_INSTANCE_T *instance = alsa_stream->instance;
	int32_t success;
	int ret;
	LOG_DBG(" .. IN\n");

	LOG_INFO
	    (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	instance->result = -1;

	m.type = VC_AUDIO_MSG_TYPE_CONTROL;
	m.u.control.dest = chip->dest;
	m.u.control.volume = chip->volume;

	/* Create the message available completion */
	init_completion(&instance->msg_avail_comp);

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);

		ret = -1;
		goto unlock;
	}

	/* We are expecting a reply from the videocore */
	ret = wait_for_completion_interruptible(&instance->msg_avail_comp);
	if (ret) {
		LOG_DBG("%s: failed on waiting for event (status=%d)\n",
			__func__, success);
		goto unlock;
	}

	if (instance->result != 0) {
		LOG_ERR("%s: result=%d\n", __func__, instance->result);

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	LOG_DBG(" .. OUT\n");
	return ret;
}