static int audio_close(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct audio_upperhalf_s *upper = inode->i_private; int ret; audvdbg("crefs: %d\n", upper->crefs); /* Get exclusive access to the device structures */ ret = sem_wait(&upper->exclsem); if (ret < 0) { ret = -errno; goto errout; } /* Decrement the references to the driver. If the reference count will * decrement to 0, then uninitialize the driver. */ if (upper->crefs > 1) { upper->crefs--; } else { FAR struct audio_lowerhalf_s *lower = upper->dev; /* There are no more references to the port */ upper->crefs = 0; /* Disable the Audio device */ DEBUGASSERT(lower->ops->shutdown != NULL); audvdbg("calling shutdown: %d\n"); lower->ops->shutdown(lower); } ret = OK; //errout_with_sem: sem_post(&upper->exclsem); errout: return ret; }
alc_i2c_t *alc5658_i2c_initialize(void) { alc_i2c_t *i2c; int i; int ret; i2c_dev = up_i2cinitialize(CONFIG_ALC5658_I2C_PORT); if (i2c_dev == NULL) { i2cerr("ALC5658 up_i2cinitialize(port: %d) failed\n", CONFIG_ALC5658_I2C_PORT); return NULL; } configs.frequency = CONFIG_ALC5658_I2C_FREQ; configs.address = ALC5658_ADDR; configs.addrlen = CONFIG_ALC5658_I2C_ADDRLEN; i2c = &alc5658_i2c; for (i = 0; i < sizeof(codec_init_script) / sizeof(t_codec_init_script_entry); i++) { ret = i2c->modify(codec_init_script[i].addr, codec_init_script[i].val, 0xFFFF); audvdbg("ALC %x <- %x\n", codec_init_script[i].addr, ret); delay(codec_init_script[i].delay); } return i2c; }
void apb_free(FAR struct ap_buffer_s *apb) { int refcount; /* Perform a reference count decrement and possibly release the memory */ apb_semtake(apb); refcount = apb->crefs--; apb_semgive(apb); if (refcount <= 1) { audvdbg("Freeing %p\n", apb); lib_ufree(apb); } }
static int audio_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; FAR struct audio_upperhalf_s *upper = inode->i_private; uint8_t tmp; int ret; audvdbg("crefs: %d\n", upper->crefs); /* Get exclusive access to the device structures */ ret = sem_wait(&upper->exclsem); if (ret < 0) { ret = -errno; goto errout; } /* Increment the count of references to the device. If this the first * time that the driver has been opened for this device, then initialize * the device. */ tmp = upper->crefs + 1; if (tmp == 0) { /* More than 255 opens; uint8_t overflows to zero */ ret = -EMFILE; goto errout_with_sem; } /* Save the new open count on success */ upper->crefs = tmp; upper->usermq = NULL; ret = OK; errout_with_sem: sem_post(&upper->exclsem); errout: return ret; }
int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) { FAR struct audio_upperhalf_s *upper; char path[AUDIO_MAX_DEVICE_PATH]; static bool dev_audio_created = false; #ifndef CONFIG_AUDIO_CUSTOM_DEV_PATH const char* devname = "/dev/audio"; #elif !defined(CONFIG_AUDIO_DEV_ROOT) const char* devname = CONFIG_AUDIO_DEV_PATH; const char* ptr; char* pathptr; #endif /* Allocate the upper-half data structure */ upper = (FAR struct audio_upperhalf_s *)kzalloc(sizeof(struct audio_upperhalf_s)); if (!upper) { auddbg("Allocation failed\n"); return -ENOMEM; } /* Initialize the Audio device structure (it was already zeroed by kzalloc()) */ sem_init(&upper->exclsem, 0, 1); upper->dev = dev; #ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH #ifdef CONFIG_AUDIO_DEV_ROOT /* This is the simple case ... No need to make a directory */ strcpy(path, "/dev/"); strcat(path, name); #else /* Ensure the path begins with "/dev" as we don't support placing device * anywhere but in the /dev directory */ DEBUGASSERT(strncmp(devname, "/dev", 4) == 0); /* Create a /dev/audio directory. */ if (!dev_audio_created) { /* Get path name after "/dev" */ ptr = &devname[4]; if (*ptr == '/') { ptr++; } strcpy(path, "/dev/"); pathptr = &path[5]; /* Do mkdir for each segment of the path */ while (*ptr != '\0') { /* Build next path segment into path variable */ while (*ptr != '/' && *ptr != '\0') { *pathptr++ = *ptr++; } *pathptr = '\0'; /* Make this level of directory */ mkdir(path, 0644); /* Check for another level */ *pathptr++ = '/'; if (*ptr == '/') { ptr++; } } /* Indicate we have created the audio dev path */ dev_audio_created = true; } /* Now build the path for registration */ strcpy(path, devname); if (devname[sizeof(devname)-1] != '/') { strcat(path, "/"); } strcat(path, name); #endif /* CONFIG_AUDIO_DEV_PATH=="/dev" */ #else /* CONFIG_AUDIO_CUSTOM_DEV_PATH */ /* Create a /dev/audio directory. */ if (!dev_audio_created) { /* We don't check for error here because even if it fails, then * the register_driver call below will return an error condition * for us. */ mkdir(devname, 0644); dev_audio_created = true; } /* Register the Audio device */ memset(path, 0, AUDIO_MAX_DEVICE_PATH); strcpy(path, devname); strcat(path, "/"); strncat(path, name, AUDIO_MAX_DEVICE_PATH - 11); #endif audvdbg("Registering %s\n", path); return register_driver(path, &g_audioops, 0666, upper); }
static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct inode *inode = filep->f_inode; FAR struct audio_upperhalf_s *upper = inode->i_private; FAR struct audio_lowerhalf_s *lower = upper->dev; int ret; audvdbg("cmd: %d arg: %ld\n", cmd, arg); /* Get exclusive access to the device structures */ ret = sem_wait(&upper->exclsem); if (ret < 0) { return ret; } /* Handle built-in ioctl commands */ switch (cmd) { /* AUDIOIOC_GETCAPS - Get the audio device capabilities. * * ioctl argument: A pointer to the audio_caps_s structure. */ case AUDIOIOC_GETCAPS: { FAR struct audio_caps_s *caps = (FAR struct audio_caps_s*)((uintptr_t)arg); DEBUGASSERT(lower->ops->getcaps != NULL); audvdbg("AUDIOIOC_GETCAPS: Device=%d", caps->ac_type); /* Call the lower-half driver capabilities handler */ ret = lower->ops->getcaps(lower, caps->ac_type, caps); } break; case AUDIOIOC_CONFIGURE: { FAR const struct audio_caps_s *caps = (FAR const struct audio_caps_s*)((uintptr_t)arg); DEBUGASSERT(lower->ops->configure != NULL); audvdbg("AUDIOIOC_INITIALIZE: Device=%d", caps->ac_type); /* Call the lower-half driver configure handler */ ret = lower->ops->configure(lower, caps, &audio_callback, upper); } break; case AUDIOIOC_SHUTDOWN: { DEBUGASSERT(lower->ops->shutdown != NULL); audvdbg("AUDIOIOC_SHUTDOWN\n"); /* Call the lower-half driver initialize handler */ ret = lower->ops->shutdown(lower); } break; /* AUDIOIOC_START - Start the pulsed output. The AUDIOIOC_SETCHARACTERISTICS * command must have previously been sent. * * ioctl argument: None */ case AUDIOIOC_START: { audvdbg("AUDIOIOC_START\n"); DEBUGASSERT(lower->ops->start != NULL); /* Start the pulse train */ ret = audio_start(upper, filep->f_oflags); } break; /* AUDIOIOC_STOP - Stop the pulsed output. * * ioctl argument: None */ case AUDIOIOC_STOP: { audvdbg("AUDIOIOC_STOP\n"); DEBUGASSERT(lower->ops->stop != NULL); if (upper->started) { ret = lower->ops->stop(lower); upper->started = false; } } break; /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ default: { audvdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); DEBUGASSERT(lower->ops->ioctl != NULL); ret = lower->ops->ioctl(lower, cmd, arg); } break; } sem_post(&upper->exclsem); return ret; }
static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { FAR struct inode *inode = filep->f_inode; FAR struct audio_upperhalf_s *upper = inode->i_private; FAR struct audio_lowerhalf_s *lower = upper->dev; FAR struct audio_buf_desc_s *bufdesc; #ifdef CONFIG_AUDIO_MULTI_SESSION FAR void *session; #endif int ret; audvdbg("cmd: %d arg: %ld\n", cmd, arg); /* Get exclusive access to the device structures */ ret = sem_wait(&upper->exclsem); if (ret < 0) { return ret; } /* Handle built-in ioctl commands */ switch (cmd) { /* AUDIOIOC_GETCAPS - Get the audio device capabilities. * * ioctl argument: A pointer to the audio_caps_s structure. */ case AUDIOIOC_GETCAPS: { FAR struct audio_caps_s *caps = (FAR struct audio_caps_s*)((uintptr_t)arg); DEBUGASSERT(lower->ops->getcaps != NULL); audvdbg("AUDIOIOC_GETCAPS: Device=%d\n", caps->ac_type); /* Call the lower-half driver capabilities handler */ ret = lower->ops->getcaps(lower, caps->ac_type, caps); } break; case AUDIOIOC_CONFIGURE: { FAR const struct audio_caps_desc_s *caps = (FAR const struct audio_caps_desc_s*)((uintptr_t)arg); DEBUGASSERT(lower->ops->configure != NULL); audvdbg("AUDIOIOC_INITIALIZE: Device=%d\n", caps->caps.ac_type); /* Call the lower-half driver configure handler */ #ifdef CONFIG_AUDIO_MULTI_SESSION ret = lower->ops->configure(lower, caps->session, &caps->caps); #else ret = lower->ops->configure(lower, &caps->caps); #endif } break; case AUDIOIOC_SHUTDOWN: { DEBUGASSERT(lower->ops->shutdown != NULL); audvdbg("AUDIOIOC_SHUTDOWN\n"); /* Call the lower-half driver initialize handler */ ret = lower->ops->shutdown(lower); } break; /* AUDIOIOC_START - Start the audio stream. The AUDIOIOC_SETCHARACTERISTICS * command must have previously been sent. * * ioctl argument: Audio session */ case AUDIOIOC_START: { audvdbg("AUDIOIOC_START\n"); DEBUGASSERT(lower->ops->start != NULL); /* Start the audio stream */ #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; ret = audio_start(upper, session); #else ret = audio_start(upper); #endif } break; /* AUDIOIOC_STOP - Stop the audio stream. * * ioctl argument: Audio session */ #ifndef CONFIG_AUDIO_EXCLUDE_STOP case AUDIOIOC_STOP: { audvdbg("AUDIOIOC_STOP\n"); DEBUGASSERT(lower->ops->stop != NULL); if (upper->started) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; ret = lower->ops->stop(lower, session); #else ret = lower->ops->stop(lower); #endif upper->started = false; } } break; #endif /* CONFIG_AUDIO_EXCLUDE_STOP */ /* AUDIOIOC_PAUSE - Pause the audio stream. * * ioctl argument: Audio session */ #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME case AUDIOIOC_PAUSE: { audvdbg("AUDIOIOC_PAUSE\n"); DEBUGASSERT(lower->ops->pause != NULL); if (upper->started) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; ret = lower->ops->pause(lower, session); #else ret = lower->ops->pause(lower); #endif } } break; /* AUDIOIOC_RESUME - Resume the audio stream. * * ioctl argument: Audio session */ case AUDIOIOC_RESUME: { audvdbg("AUDIOIOC_RESUME\n"); DEBUGASSERT(lower->ops->resume != NULL); if (upper->started) { #ifdef CONFIG_AUDIO_MULTI_SESSION session = (FAR void *) arg; ret = lower->ops->resume(lower, session); #else ret = lower->ops->resume(lower); #endif } } break; #endif /* CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME */ /* AUDIOIOC_ALLOCBUFFER - Allocate an audio buffer * * ioctl argument: pointer to an audio_buf_desc_s structure */ case AUDIOIOC_ALLOCBUFFER: { audvdbg("AUDIOIOC_ALLOCBUFFER\n"); bufdesc = (FAR struct audio_buf_desc_s *) arg; if (lower->ops->allocbuffer) { ret = lower->ops->allocbuffer(lower, bufdesc); } else { /* Perform a simple kumalloc operation assuming 1 session */ ret = apb_alloc(bufdesc); } } break; /* AUDIOIOC_FREEBUFFER - Free an audio buffer * * ioctl argument: pointer to an audio_buf_desc_s structure */ case AUDIOIOC_FREEBUFFER: { audvdbg("AUDIOIOC_FREEBUFFER\n"); bufdesc = (FAR struct audio_buf_desc_s *) arg; if (lower->ops->freebuffer) { ret = lower->ops->freebuffer(lower, bufdesc); } else { /* Perform a simple kufree operation */ DEBUGASSERT(bufdesc->u.pBuffer != NULL); apb_free(bufdesc->u.pBuffer); ret = sizeof(struct audio_buf_desc_s); } } break; /* AUDIOIOC_ENQUEUEBUFFER - Enqueue an audio buffer * * ioctl argument: pointer to an audio_buf_desc_s structure */ case AUDIOIOC_ENQUEUEBUFFER: { audvdbg("AUDIOIOC_ENQUEUEBUFFER\n"); DEBUGASSERT(lower->ops->enqueuebuffer != NULL); bufdesc = (FAR struct audio_buf_desc_s *) arg; ret = lower->ops->enqueuebuffer(lower, bufdesc->u.pBuffer); } break; /* AUDIOIOC_REGISTERMQ - Register a client Message Queue * * TODO: This needs to have multi session support. */ case AUDIOIOC_REGISTERMQ: { audvdbg("AUDIOIOC_REGISTERMQ\n"); upper->usermq = (mqd_t) arg; ret = OK; } break; /* AUDIOIOC_UNREGISTERMQ - Register a client Message Queue * * TODO: This needs to have multi session support. */ case AUDIOIOC_UNREGISTERMQ: { audvdbg("AUDIOIOC_UNREGISTERMQ\n"); upper->usermq = NULL; ret = OK; } break; /* AUDIOIOC_RESERVE - Reserve a session with the driver * * ioctl argument - pointer to receive the session context */ case AUDIOIOC_RESERVE: { audvdbg("AUDIOIOC_RESERVE\n"); DEBUGASSERT(lower->ops->reserve != NULL); /* Call lower-half to perform the reservation */ #ifdef CONFIG_AUDIO_MULTI_SESSION ret = lower->ops->reserve(lower, (FAR void **) arg); #else ret = lower->ops->reserve(lower); #endif } break; /* AUDIOIOC_RESERVE - Reserve a session with the driver * * ioctl argument - pointer to receive the session context */ case AUDIOIOC_RELEASE: { audvdbg("AUDIOIOC_RELEASE\n"); DEBUGASSERT(lower->ops->release != NULL); /* Call lower-half to perform the release */ #ifdef CONFIG_AUDIO_MULTI_SESSION ret = lower->ops->release(lower, (FAR void *) arg); #else ret = lower->ops->release(lower); #endif } break; /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */ default: { audvdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg); DEBUGASSERT(lower->ops->ioctl != NULL); ret = lower->ops->ioctl(lower, cmd, arg); } break; } sem_post(&upper->exclsem); return ret; }