diff options
Diffstat (limited to 'sound')
456 files changed, 28893 insertions, 7171 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index d9077e91382b..6ddf646cda65 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev) struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver); int ret; - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 1c8e8131a716..a9e502a6cdeb 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -918,10 +918,8 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, } cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); - if (!cii) { - printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); + if (!cii) return -ENOMEM; - } /* use the private data to point to the codec info */ cii->sdev = soundbus_dev_get(dev); diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 6322e6392594..a67e6685b00c 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -47,9 +47,7 @@ static unsigned short pxa2xx_ac97_legacy_read(struct snd_ac97 *ac97, static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { - int __always_unused ret; - - ret = pxa2xx_ac97_write(ac97->num, reg, val); + pxa2xx_ac97_write(ac97->num, reg, val); } static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = { diff --git a/sound/core/control.c b/sound/core/control.c index 498e3701514a..a25c0d64d104 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -995,7 +995,10 @@ static int __snd_ctl_elem_info(struct snd_card *card, #ifdef CONFIG_SND_DEBUG info->access = 0; #endif - result = kctl->info(kctl, info); + result = snd_power_ref_and_wait(card); + if (!result) + result = kctl->info(kctl, info); + snd_power_unref(card); if (result >= 0) { snd_BUG_ON(info->access); index_offset = snd_ctl_get_ioff(kctl, &info->id); @@ -1042,9 +1045,6 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl, if (copy_from_user(&info, _info, sizeof(info))) return -EFAULT; - result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (result < 0) - return result; result = snd_ctl_elem_info(ctl, &info); if (result < 0) return result; @@ -1088,7 +1088,10 @@ static int snd_ctl_elem_read(struct snd_card *card, if (!snd_ctl_skip_validation(&info)) fill_remaining_elem_value(control, &info, pattern); - ret = kctl->get(kctl, control); + ret = snd_power_ref_and_wait(card); + if (!ret) + ret = kctl->get(kctl, control); + snd_power_unref(card); if (ret < 0) return ret; if (!snd_ctl_skip_validation(&info) && @@ -1113,10 +1116,6 @@ static int snd_ctl_elem_read_user(struct snd_card *card, if (IS_ERR(control)) return PTR_ERR(control); - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto error; - down_read(&card->controls_rwsem); result = snd_ctl_elem_read(card, control); up_read(&card->controls_rwsem); @@ -1154,7 +1153,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, } snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->put(kctl, control); + result = snd_power_ref_and_wait(card); + if (!result) + result = kctl->put(kctl, control); + snd_power_unref(card); if (result < 0) { up_write(&card->controls_rwsem); return result; @@ -1183,10 +1185,6 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, return PTR_ERR(control); card = file->card; - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto error; - result = snd_ctl_elem_write(card, file, control); if (result < 0) goto error; @@ -1669,7 +1667,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND}, }; struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)]; - int i; + int i, ret; /* Check support of the request for this element. */ for (i = 0; i < ARRAY_SIZE(pairs); ++i) { @@ -1687,7 +1685,11 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, vd->owner != NULL && vd->owner != file) return -EPERM; - return kctl->tlv.c(kctl, op_flag, size, buf); + ret = snd_power_ref_and_wait(file->card); + if (!ret) + ret = kctl->tlv.c(kctl, op_flag, size, buf); + snd_power_unref(file->card); + return ret; } static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id, @@ -1815,11 +1817,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg case SNDRV_CTL_IOCTL_POWER: return -ENOPROTOOPT; case SNDRV_CTL_IOCTL_POWER_STATE: -#ifdef CONFIG_PM - return put_user(card->power_state, ip) ? -EFAULT : 0; -#else return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0; -#endif } down_read(&snd_ioctl_rwsem); list_for_each_entry(p, &snd_control_ioctls, list) { diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 1d708aab9c98..470dabc60aa0 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -96,9 +96,6 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) goto error; - err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_info(ctl, data); if (err < 0) goto error; @@ -187,7 +184,10 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, return -ENOMEM; } info->id = *id; - err = kctl->info(kctl, info); + err = snd_power_ref_and_wait(card); + if (!err) + err = kctl->info(kctl, info); + snd_power_unref(card); up_read(&card->controls_rwsem); if (err >= 0) { err = info->type; @@ -298,9 +298,6 @@ static int ctl_elem_read_user(struct snd_card *card, if (err < 0) goto error; - err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_read(card, data); if (err < 0) goto error; @@ -326,9 +323,6 @@ static int ctl_elem_write_user(struct snd_ctl_file *file, if (err < 0) goto error; - err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_write(card, file, data); if (err < 0) goto error; diff --git a/sound/core/control_led.c b/sound/core/control_led.c index a90e31dbde61..764058cc345d 100644 --- a/sound/core/control_led.c +++ b/sound/core/control_led.c @@ -393,11 +393,11 @@ static void snd_ctl_led_dev_release(struct device *dev) * sysfs */ -static ssize_t show_mode(struct device *dev, +static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); - const char *str; + const char *str = NULL; switch (led->mode) { case MODE_FOLLOW_MUTE: str = "follow-mute"; break; @@ -408,7 +408,8 @@ static ssize_t show_mode(struct device *dev, return sprintf(buf, "%s\n", str); } -static ssize_t store_mode(struct device *dev, struct device_attribute *attr, +static ssize_t mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); @@ -437,7 +438,7 @@ static ssize_t store_mode(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_brightness(struct device *dev, +static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); @@ -445,8 +446,8 @@ static ssize_t show_brightness(struct device *dev, return sprintf(buf, "%u\n", ledtrig_audio_get(led->trigger_type)); } -static DEVICE_ATTR(mode, 0644, show_mode, store_mode); -static DEVICE_ATTR(brightness, 0444, show_brightness, NULL); +static DEVICE_ATTR_RW(mode); +static DEVICE_ATTR_RO(brightness); static struct attribute *snd_ctl_led_dev_attrs[] = { &dev_attr_mode.attr, @@ -580,22 +581,25 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si return count; } -static ssize_t parse_attach(struct device *dev, struct device_attribute *attr, +static ssize_t attach_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); return set_led_id(led_card, buf, count, true); } -static ssize_t parse_detach(struct device *dev, struct device_attribute *attr, +static ssize_t detach_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); return set_led_id(led_card, buf, count, false); } -static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); int err; @@ -608,8 +612,8 @@ static ssize_t ctl_reset(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t ctl_list(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t list_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct snd_ctl_led_card *led_card = container_of(dev, struct snd_ctl_led_card, dev); struct snd_card *card; @@ -642,10 +646,10 @@ static ssize_t ctl_list(struct device *dev, return buf2 - buf; } -static DEVICE_ATTR(attach, 0200, NULL, parse_attach); -static DEVICE_ATTR(detach, 0200, NULL, parse_detach); -static DEVICE_ATTR(reset, 0200, NULL, ctl_reset); -static DEVICE_ATTR(list, 0444, ctl_list, NULL); +static DEVICE_ATTR_WO(attach); +static DEVICE_ATTR_WO(detach); +static DEVICE_ATTR_WO(reset); +static DEVICE_ATTR_RO(list); static struct attribute *snd_ctl_led_card_attrs[] = { &dev_attr_attach.attr, diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 264b8ea64bc2..e95fa275c289 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -195,7 +195,8 @@ static int snd_hwdep_dsp_status(struct snd_hwdep *hw, return -ENXIO; memset(&info, 0, sizeof(info)); info.dsp_loaded = hw->dsp_loaded; - if ((err = hw->ops.dsp_status(hw, &info)) < 0) + err = hw->ops.dsp_status(hw, &info); + if (err < 0) return err; if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -500,7 +501,8 @@ static void __init snd_hwdep_proc_init(void) { struct snd_info_entry *entry; - if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { + entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL); + if (entry) { entry->c.text.read = snd_hwdep_proc_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index 83900485dd8c..1ba887c7954e 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -31,7 +31,8 @@ int snd_oss_info_register(int dev, int num, char *string) return -ENXIO; mutex_lock(&strings); if (string == NULL) { - if ((x = snd_sndstat_strings[num][dev]) != NULL) { + x = snd_sndstat_strings[num][dev]; + if (x) { kfree(x); x = NULL; } diff --git a/sound/core/init.c b/sound/core/init.c index ef41f5b3a240..1490568efdb0 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, mutex_init(&card->memory_mutex); #ifdef CONFIG_PM init_waitqueue_head(&card->power_sleep); + init_waitqueue_head(&card->power_ref_sleep); + atomic_set(&card->power_ref, 0); #endif init_waitqueue_head(&card->remove_sleep); card->sync_irq = -1; @@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card) #ifdef CONFIG_PM wake_up(&card->power_sleep); + snd_power_sync_ref(card); #endif return 0; } @@ -662,17 +665,15 @@ void snd_card_set_id(struct snd_card *card, const char *nid) } EXPORT_SYMBOL(snd_card_set_id); -static ssize_t -card_id_show_attr(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct snd_card *card = container_of(dev, struct snd_card, card_dev); return scnprintf(buf, PAGE_SIZE, "%s\n", card->id); } -static ssize_t -card_id_store_attr(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t id_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct snd_card *card = container_of(dev, struct snd_card, card_dev); char buf1[sizeof(card->id)]; @@ -700,17 +701,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr); +static DEVICE_ATTR_RW(id); -static ssize_t -card_number_show_attr(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t number_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct snd_card *card = container_of(dev, struct snd_card, card_dev); return scnprintf(buf, PAGE_SIZE, "%i\n", card->number); } -static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL); +static DEVICE_ATTR_RO(number); static struct attribute *card_dev_attrs[] = { &dev_attr_id.attr, @@ -770,7 +770,8 @@ int snd_card_register(struct snd_card *card) card->registered = true; } - if ((err = snd_device_register_all(card)) < 0) + err = snd_device_register_all(card); + if (err < 0) return err; mutex_lock(&snd_card_mutex); if (snd_cards[card->number]) { @@ -813,7 +814,8 @@ static void snd_card_info_read(struct snd_info_entry *entry, for (idx = count = 0; idx < SNDRV_CARDS; idx++) { mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) { + card = snd_cards[idx]; + if (card) { count++; snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", idx, @@ -837,7 +839,8 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer) for (idx = count = 0; idx < SNDRV_CARDS; idx++) { mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) { + card = snd_cards[idx]; + if (card) { count++; snd_iprintf(buffer, "%s\n", card->longname); } @@ -859,7 +862,8 @@ static void snd_card_module_info_read(struct snd_info_entry *entry, for (idx = 0; idx < SNDRV_CARDS; idx++) { mutex_lock(&snd_card_mutex); - if ((card = snd_cards[idx]) != NULL) + card = snd_cards[idx]; + if (card) snd_iprintf(buffer, "%2i %s\n", idx, card->module->name); mutex_unlock(&snd_card_mutex); @@ -1002,21 +1006,28 @@ EXPORT_SYMBOL(snd_card_file_remove); #ifdef CONFIG_PM /** - * snd_power_wait - wait until the power-state is changed. - * @card: soundcard structure - * @power_state: expected power state + * snd_power_ref_and_wait - wait until the card gets powered up + * @card: soundcard structure + * + * Take the power_ref reference count of the given card, and + * wait until the card gets powered up to SNDRV_CTL_POWER_D0 state. + * The refcount is down again while sleeping until power-up, hence this + * function can be used for syncing the floating control ops accesses, + * typically around calling control ops. * - * Waits until the power-state is changed. + * The caller needs to pull down the refcount via snd_power_unref() later + * no matter whether the error is returned from this function or not. * - * Return: Zero if successful, or a negative error code. + * Return: Zero if successful, or a negative error code. */ -int snd_power_wait(struct snd_card *card, unsigned int power_state) +int snd_power_ref_and_wait(struct snd_card *card) { wait_queue_entry_t wait; int result = 0; + snd_power_ref(card); /* fastpath */ - if (snd_power_get_state(card) == power_state) + if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) return 0; init_waitqueue_entry(&wait, current); add_wait_queue(&card->power_sleep, &wait); @@ -1025,13 +1036,33 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) result = -ENODEV; break; } - if (snd_power_get_state(card) == power_state) + if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) break; + snd_power_unref(card); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(30 * HZ); + snd_power_ref(card); } remove_wait_queue(&card->power_sleep, &wait); return result; } +EXPORT_SYMBOL_GPL(snd_power_ref_and_wait); + +/** + * snd_power_wait - wait until the card gets powered up (old form) + * @card: soundcard structure + * + * Wait until the card gets powered up to SNDRV_CTL_POWER_D0 state. + * + * Return: Zero if successful, or a negative error code. + */ +int snd_power_wait(struct snd_card *card) +{ + int ret; + + ret = snd_power_ref_and_wait(card); + snd_power_unref(card); + return ret; +} EXPORT_SYMBOL(snd_power_wait); #endif /* CONFIG_PM */ diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 966bef5acc75..83b79edfa52d 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -15,99 +15,27 @@ #include <asm/set_memory.h> #endif #include <sound/memalloc.h> +#include "memalloc_local.h" -/* - * - * Bus-specific memory allocators - * - */ - -#ifdef CONFIG_HAS_DMA -/* allocate the coherent DMA pages */ -static void snd_malloc_dev_pages(struct snd_dma_buffer *dmab, size_t size) -{ - gfp_t gfp_flags; +static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab); - gfp_flags = GFP_KERNEL - | __GFP_COMP /* compound page lets parts be mapped */ - | __GFP_NORETRY /* don't trigger OOM-killer */ - | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ - dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, - gfp_flags); -#ifdef CONFIG_X86 - if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) - set_memory_wc((unsigned long)dmab->area, - PAGE_ALIGN(size) >> PAGE_SHIFT); -#endif -} - -/* free the coherent DMA pages */ -static void snd_free_dev_pages(struct snd_dma_buffer *dmab) -{ -#ifdef CONFIG_X86 - if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) - set_memory_wb((unsigned long)dmab->area, - PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT); -#endif - dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); -} - -#ifdef CONFIG_GENERIC_ALLOCATOR -/** - * snd_malloc_dev_iram - allocate memory from on-chip internal ram - * @dmab: buffer allocation record to store the allocated data - * @size: number of bytes to allocate from the iram - * - * This function requires iram phandle provided via of_node - */ -static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size) +/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */ +static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab, + gfp_t default_gfp) { - struct device *dev = dmab->dev.dev; - struct gen_pool *pool = NULL; - - dmab->area = NULL; - dmab->addr = 0; - - if (dev->of_node) - pool = of_gen_pool_get(dev->of_node, "iram", 0); - - if (!pool) - return; - - /* Assign the pool into private_data field */ - dmab->private_data = pool; - - dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr, - PAGE_SIZE); + if (!dmab->dev.dev) + return default_gfp; + else + return (__force gfp_t)(unsigned long)dmab->dev.dev; } -/** - * snd_free_dev_iram - free allocated specific memory from on-chip internal ram - * @dmab: buffer allocation record to store the allocated data - */ -static void snd_free_dev_iram(struct snd_dma_buffer *dmab) +static int __snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size) { - struct gen_pool *pool = dmab->private_data; - - if (pool && dmab->area) - gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes); -} -#endif /* CONFIG_GENERIC_ALLOCATOR */ -#endif /* CONFIG_HAS_DMA */ - -/* - * - * ALSA generic memory management - * - */ + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); -static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev, - gfp_t default_gfp) -{ - if (!dev) - return default_gfp; - else - return (__force gfp_t)(unsigned long)dev; + if (WARN_ON_ONCE(!ops || !ops->alloc)) + return -EINVAL; + return ops->alloc(dmab, size); } /** @@ -126,7 +54,7 @@ static inline gfp_t snd_mem_get_gfp_flags(const struct device *dev, int snd_dma_alloc_pages(int type, struct device *device, size_t size, struct snd_dma_buffer *dmab) { - gfp_t gfp; + int err; if (WARN_ON(!size)) return -ENXIO; @@ -140,43 +68,10 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, dmab->area = NULL; dmab->addr = 0; dmab->private_data = NULL; - switch (type) { - case SNDRV_DMA_TYPE_CONTINUOUS: - gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL); - dmab->area = alloc_pages_exact(size, gfp); - break; - case SNDRV_DMA_TYPE_VMALLOC: - gfp = snd_mem_get_gfp_flags(device, GFP_KERNEL | __GFP_HIGHMEM); - dmab->area = __vmalloc(size, gfp); - break; -#ifdef CONFIG_HAS_DMA -#ifdef CONFIG_GENERIC_ALLOCATOR - case SNDRV_DMA_TYPE_DEV_IRAM: - snd_malloc_dev_iram(dmab, size); - if (dmab->area) - break; - /* Internal memory might have limited size and no enough space, - * so if we fail to malloc, try to fetch memory traditionally. - */ - dmab->dev.type = SNDRV_DMA_TYPE_DEV; - fallthrough; -#endif /* CONFIG_GENERIC_ALLOCATOR */ - case SNDRV_DMA_TYPE_DEV: - case SNDRV_DMA_TYPE_DEV_UC: - snd_malloc_dev_pages(dmab, size); - break; -#endif -#ifdef CONFIG_SND_DMA_SGBUF - case SNDRV_DMA_TYPE_DEV_SG: - case SNDRV_DMA_TYPE_DEV_UC_SG: - snd_malloc_sgbuf_pages(device, size, dmab, NULL); - break; -#endif - default: - pr_err("snd-malloc: invalid device type %d\n", type); - return -ENXIO; - } - if (! dmab->area) + err = __snd_dma_alloc_pages(dmab, size); + if (err < 0) + return err; + if (!dmab->area) return -ENOMEM; dmab->bytes = size; return 0; @@ -217,7 +112,6 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, } EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); - /** * snd_dma_free_pages - release the allocated buffer * @dmab: the buffer allocation record to release @@ -226,32 +120,288 @@ EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); */ void snd_dma_free_pages(struct snd_dma_buffer *dmab) { - switch (dmab->dev.type) { - case SNDRV_DMA_TYPE_CONTINUOUS: - free_pages_exact(dmab->area, dmab->bytes); - break; - case SNDRV_DMA_TYPE_VMALLOC: - vfree(dmab->area); - break; + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); + + if (ops && ops->free) + ops->free(dmab); +} +EXPORT_SYMBOL(snd_dma_free_pages); + +/** + * snd_dma_buffer_mmap - perform mmap of the given DMA buffer + * @dmab: buffer allocation information + * @area: VM area information + */ +int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) +{ + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); + + if (ops && ops->mmap) + return ops->mmap(dmab, area); + else + return -ENOENT; +} +EXPORT_SYMBOL(snd_dma_buffer_mmap); + +/** + * snd_sgbuf_get_addr - return the physical address at the corresponding offset + * @dmab: buffer allocation information + * @offset: offset in the ring buffer + */ +dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset) +{ + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); + + if (ops && ops->get_addr) + return ops->get_addr(dmab, offset); + else + return dmab->addr + offset; +} +EXPORT_SYMBOL(snd_sgbuf_get_addr); + +/** + * snd_sgbuf_get_page - return the physical page at the corresponding offset + * @dmab: buffer allocation information + * @offset: offset in the ring buffer + */ +struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset) +{ + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); + + if (ops && ops->get_page) + return ops->get_page(dmab, offset); + else + return virt_to_page(dmab->area + offset); +} +EXPORT_SYMBOL(snd_sgbuf_get_page); + +/** + * snd_sgbuf_get_chunk_size - compute the max chunk size with continuous pages + * on sg-buffer + * @dmab: buffer allocation information + * @ofs: offset in the ring buffer + * @size: the requested size + */ +unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, + unsigned int ofs, unsigned int size) +{ + const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); + + if (ops && ops->get_chunk_size) + return ops->get_chunk_size(dmab, ofs, size); + else + return size; +} +EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); + +/* + * Continuous pages allocator + */ +static int snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size) +{ + gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL); + + dmab->area = alloc_pages_exact(size, gfp); + return 0; +} + +static void snd_dma_continuous_free(struct snd_dma_buffer *dmab) +{ + free_pages_exact(dmab->area, dmab->bytes); +} + +static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) +{ + return remap_pfn_range(area, area->vm_start, + dmab->addr >> PAGE_SHIFT, + area->vm_end - area->vm_start, + area->vm_page_prot); +} + +static const struct snd_malloc_ops snd_dma_continuous_ops = { + .alloc = snd_dma_continuous_alloc, + .free = snd_dma_continuous_free, + .mmap = snd_dma_continuous_mmap, +}; + +/* + * VMALLOC allocator + */ +static int snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size) +{ + gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM); + + dmab->area = __vmalloc(size, gfp); + return 0; +} + +static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab) +{ + vfree(dmab->area); +} + +static int snd_dma_vmalloc_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) +{ + return remap_vmalloc_range(area, dmab->area, 0); +} + +static dma_addr_t snd_dma_vmalloc_get_addr(struct snd_dma_buffer *dmab, + size_t offset) +{ + return page_to_phys(vmalloc_to_page(dmab->area + offset)) + + offset % PAGE_SIZE; +} + +static struct page *snd_dma_vmalloc_get_page(struct snd_dma_buffer *dmab, + size_t offset) +{ + return vmalloc_to_page(dmab->area + offset); +} + +static unsigned int +snd_dma_vmalloc_get_chunk_size(struct snd_dma_buffer *dmab, + unsigned int ofs, unsigned int size) +{ + ofs %= PAGE_SIZE; + size += ofs; + if (size > PAGE_SIZE) + size = PAGE_SIZE; + return size - ofs; +} + +static const struct snd_malloc_ops snd_dma_vmalloc_ops = { + .alloc = snd_dma_vmalloc_alloc, + .free = snd_dma_vmalloc_free, + .mmap = snd_dma_vmalloc_mmap, + .get_addr = snd_dma_vmalloc_get_addr, + .get_page = snd_dma_vmalloc_get_page, + .get_chunk_size = snd_dma_vmalloc_get_chunk_size, +}; + #ifdef CONFIG_HAS_DMA +/* + * IRAM allocator + */ #ifdef CONFIG_GENERIC_ALLOCATOR - case SNDRV_DMA_TYPE_DEV_IRAM: - snd_free_dev_iram(dmab); - break; +static int snd_dma_iram_alloc(struct snd_dma_buffer *dmab, size_t size) +{ + struct device *dev = dmab->dev.dev; + struct gen_pool *pool; + + if (dev->of_node) { + pool = of_gen_pool_get(dev->of_node, "iram", 0); + /* Assign the pool into private_data field */ + dmab->private_data = pool; + + dmab->area = gen_pool_dma_alloc_align(pool, size, &dmab->addr, + PAGE_SIZE); + if (dmab->area) + return 0; + } + + /* Internal memory might have limited size and no enough space, + * so if we fail to malloc, try to fetch memory traditionally. + */ + dmab->dev.type = SNDRV_DMA_TYPE_DEV; + return __snd_dma_alloc_pages(dmab, size); +} + +static void snd_dma_iram_free(struct snd_dma_buffer *dmab) +{ + struct gen_pool *pool = dmab->private_data; + + if (pool && dmab->area) + gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes); +} + +static int snd_dma_iram_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) +{ + area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); + return remap_pfn_range(area, area->vm_start, + dmab->addr >> PAGE_SHIFT, + area->vm_end - area->vm_start, + area->vm_page_prot); +} + +static const struct snd_malloc_ops snd_dma_iram_ops = { + .alloc = snd_dma_iram_alloc, + .free = snd_dma_iram_free, + .mmap = snd_dma_iram_mmap, +}; #endif /* CONFIG_GENERIC_ALLOCATOR */ - case SNDRV_DMA_TYPE_DEV: - case SNDRV_DMA_TYPE_DEV_UC: - snd_free_dev_pages(dmab); - break; + +/* + * Coherent device pages allocator + */ +static int snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size) +{ + gfp_t gfp_flags; + + gfp_flags = GFP_KERNEL + | __GFP_COMP /* compound page lets parts be mapped */ + | __GFP_NORETRY /* don't trigger OOM-killer */ + | __GFP_NOWARN; /* no stack trace print - this call is non-critical */ + dmab->area = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, + gfp_flags); +#ifdef CONFIG_X86 + if (dmab->area && dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) + set_memory_wc((unsigned long)dmab->area, + PAGE_ALIGN(size) >> PAGE_SHIFT); #endif + return 0; +} + +static void snd_dma_dev_free(struct snd_dma_buffer *dmab) +{ +#ifdef CONFIG_X86 + if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC) + set_memory_wb((unsigned long)dmab->area, + PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT); +#endif + dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); +} + +static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area) +{ + return dma_mmap_coherent(dmab->dev.dev, area, + dmab->area, dmab->addr, dmab->bytes); +} + +static const struct snd_malloc_ops snd_dma_dev_ops = { + .alloc = snd_dma_dev_alloc, + .free = snd_dma_dev_free, + .mmap = snd_dma_dev_mmap, +}; +#endif /* CONFIG_HAS_DMA */ + +/* + * Entry points + */ +static const struct snd_malloc_ops *dma_ops[] = { + [SNDRV_DMA_TYPE_CONTINUOUS] = &snd_dma_continuous_ops, + [SNDRV_DMA_TYPE_VMALLOC] = &snd_dma_vmalloc_ops, +#ifdef CONFIG_HAS_DMA + [SNDRV_DMA_TYPE_DEV] = &snd_dma_dev_ops, + [SNDRV_DMA_TYPE_DEV_UC] = &snd_dma_dev_ops, +#ifdef CONFIG_GENERIC_ALLOCATOR + [SNDRV_DMA_TYPE_DEV_IRAM] = &snd_dma_iram_ops, +#endif /* CONFIG_GENERIC_ALLOCATOR */ +#endif /* CONFIG_HAS_DMA */ #ifdef CONFIG_SND_DMA_SGBUF - case SNDRV_DMA_TYPE_DEV_SG: - case SNDRV_DMA_TYPE_DEV_UC_SG: - snd_free_sgbuf_pages(dmab); - break; + [SNDRV_DMA_TYPE_DEV_SG] = &snd_dma_sg_ops, + [SNDRV_DMA_TYPE_DEV_UC_SG] = &snd_dma_sg_ops, #endif - default: - pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); - } +}; + +static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab) +{ + if (WARN_ON_ONCE(dmab->dev.type <= SNDRV_DMA_TYPE_UNKNOWN || + dmab->dev.type >= ARRAY_SIZE(dma_ops))) + return NULL; + return dma_ops[dmab->dev.type]; } -EXPORT_SYMBOL(snd_dma_free_pages); diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h new file mode 100644 index 000000000000..dbea7f2aed07 --- /dev/null +++ b/sound/core/memalloc_local.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only +#ifndef __MEMALLOC_LOCAL_H +#define __MEMALLOC_LOCAL_H + +struct snd_malloc_ops { + int (*alloc)(struct snd_dma_buffer *dmab, size_t size); + void (*free)(struct snd_dma_buffer *dmab); + dma_addr_t (*get_addr)(struct snd_dma_buffer *dmab, size_t offset); + struct page *(*get_page)(struct snd_dma_buffer *dmab, size_t offset); + unsigned int (*get_chunk_size)(struct snd_dma_buffer *dmab, + unsigned int ofs, unsigned int size); + int (*mmap)(struct snd_dma_buffer *dmab, struct vm_area_struct *area); +}; + +#ifdef CONFIG_SND_DMA_SGBUF +extern const struct snd_malloc_ops snd_dma_sg_ops; +#endif + +#endif /* __MEMALLOC_LOCAL_H */ diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index bec928327478..6a5abdd4271b 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -185,7 +185,8 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ int err; unsigned int index; - if ((err = mixer->get_recsrc(fmixer, &index)) < 0) + err = mixer->get_recsrc(fmixer, &index); + if (err < 0) return err; result = 1 << index; } else { @@ -517,7 +518,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -555,7 +557,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -620,7 +623,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -636,7 +640,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer, uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); if (uinfo->count > 1) uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); - if ((res = kctl->put(kctl, uctl)) < 0) + res = kctl->put(kctl, uctl); + if (res < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); @@ -661,7 +666,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); - if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { + kctl = snd_ctl_find_numid(card, numid); + if (!kctl) { up_read(&card->controls_rwsem); return; } @@ -681,7 +687,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer, } else { uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } - if ((res = kctl->put(kctl, uctl)) < 0) + res = kctl->put(kctl, uctl); + if (res < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); @@ -809,9 +816,11 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = -ENOENT; goto __unlock; } - if ((err = kctl->info(kctl, uinfo)) < 0) + err = kctl->info(kctl, uinfo); + if (err < 0) goto __unlock; - if ((err = kctl->get(kctl, uctl)) < 0) + err = kctl->get(kctl, uctl); + if (err < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) @@ -860,7 +869,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned err = -ENOENT; goto __unlock; } - if ((err = kctl->info(kctl, uinfo)) < 0) + err = kctl->info(kctl, uinfo); + if (err < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) @@ -915,7 +925,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl up_read(&card->controls_rwsem); return -ENOMEM; } - if ((err = kcontrol->info(kcontrol, info)) < 0) { + err = kcontrol->info(kcontrol, info); + if (err < 0) { up_read(&card->controls_rwsem); kfree(info); return err; @@ -1036,7 +1047,10 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, if (snd_mixer_oss_build_test_all(mixer, ptr, &slot)) return 0; down_read(&mixer->card->controls_rwsem); - if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { + kctl = NULL; + if (!ptr->index) + kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); + if (kctl) { struct snd_ctl_elem_info *uinfo; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); @@ -1343,9 +1357,10 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) if (mixer == NULL) return -ENOMEM; mutex_init(&mixer->reg_mutex); - if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, - card, 0, - &snd_mixer_oss_f_ops, card)) < 0) { + err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, + card, 0, + &snd_mixer_oss_f_ops, card); + if (err < 0) { dev_err(card->dev, "unable to register OSS mixer device %i:%i\n", card->number, 0); diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 86c39ee01aaa..82a818734a5f 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -955,9 +955,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) if (!direct) { /* add necessary plugins */ snd_pcm_oss_plugin_clear(substream); - if ((err = snd_pcm_plug_format_plugins(substream, - params, - sparams)) < 0) { + err = snd_pcm_plug_format_plugins(substream, params, sparams); + if (err < 0) { pcm_dbg(substream->pcm, "snd_pcm_plug_format_plugins failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); @@ -965,7 +964,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) } if (runtime->oss.plugin_first) { struct snd_pcm_plugin *plugin; - if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { + err = snd_pcm_plugin_build_io(substream, sparams, &plugin); + if (err < 0) { pcm_dbg(substream->pcm, "snd_pcm_plugin_build_io failed: %i\n", err); snd_pcm_oss_plugin_clear(substream); @@ -1011,7 +1011,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) sw_params->silence_size = frames; } - if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params); + if (err < 0) { pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); goto failure; } @@ -1573,7 +1574,8 @@ static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); } @@ -1645,7 +1647,8 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) runtime = substream->runtime; if (atomic_read(&substream->mmap_count)) goto __direct; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; atomic_inc(&runtime->oss.rw_ref); if (mutex_lock_interruptible(&runtime->oss.params_lock)) { @@ -1711,7 +1714,8 @@ unlock: substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (substream != NULL) { - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); @@ -1758,7 +1762,8 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.rate; } @@ -1795,7 +1800,8 @@ static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.channels; } @@ -1805,7 +1811,8 @@ static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.period_bytes; } @@ -1820,7 +1827,8 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) const struct snd_mask *format_mask; int fmt; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; if (atomic_read(&substream->mmap_count)) direct = 1; @@ -1890,7 +1898,8 @@ static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) + err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream); + if (err < 0) return err; return substream->runtime->oss.format; } @@ -2050,11 +2059,13 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (psubstream) { - if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) + err = snd_pcm_oss_make_ready(psubstream); + if (err < 0) return err; } if (csubstream) { - if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) + err = snd_pcm_oss_make_ready(csubstream); + if (err < 0) return err; } if (psubstream) { @@ -2141,7 +2152,8 @@ static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) @@ -2168,7 +2180,8 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream substream = pcm_oss_file->streams[stream]; if (substream == NULL) return -EINVAL; - if ((err = snd_pcm_oss_make_ready(substream)) < 0) + err = snd_pcm_oss_make_ready(substream); + if (err < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) { @@ -2239,9 +2252,11 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre return -EINVAL; runtime = substream->runtime; - if (runtime->oss.params && - (err = snd_pcm_oss_change_params(substream, false)) < 0) - return err; + if (runtime->oss.params) { + err = snd_pcm_oss_change_params(substream, false); + if (err < 0) + return err; + } info.fragsize = runtime->oss.period_bytes; info.fragstotal = runtime->periods; @@ -2601,7 +2616,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long case SNDCTL_DSP_SPEED: if (get_user(res, p)) return -EFAULT; - if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) + res = snd_pcm_oss_set_rate(pcm_oss_file, res); + if (res < 0) return res; return put_user(res, p); case SOUND_PCM_READ_RATE: @@ -2613,7 +2629,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long if (get_user(res, p)) return -EFAULT; res = res > 0 ? 2 : 1; - if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) + res = snd_pcm_oss_set_channels(pcm_oss_file, res); + if (res < 0) return res; return put_user(--res, p); case SNDCTL_DSP_GETBLKSIZE: @@ -2829,7 +2846,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) snd_pcm_state_t ostate; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(csubstream); - if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || + ostate = runtime->status->state; + if (ostate != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_capture_ready(csubstream)) mask |= EPOLLIN | EPOLLRDNORM; snd_pcm_stream_unlock_irq(csubstream); @@ -3043,7 +3061,8 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) struct snd_pcm_str *pstr = &pcm->streams[stream]; if (pstr->substream_count == 0) continue; - if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { + entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root); + if (entry) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->mode = S_IFREG | 0644; entry->c.text.read = snd_pcm_oss_proc_read; @@ -3191,7 +3210,8 @@ static int __init alsa_pcm_oss_init(void) adsp_map[i] = 1; } } - if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) + err = snd_pcm_notify(&snd_pcm_oss_notify, 0); + if (err < 0) return err; return 0; } diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index d5ca161d588c..061ba06bc926 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -59,7 +59,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t } else { format = &plugin->dst_format; } - if ((width = snd_pcm_format_physical_width(format->format)) < 0) + width = snd_pcm_format_physical_width(format->format); + if (width < 0) return width; size = frames * format->channels * width; if (snd_BUG_ON(size % 8)) @@ -572,7 +573,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plu } v = plugin->buf_channels; *channels = v; - if ((width = snd_pcm_format_physical_width(format->format)) < 0) + width = snd_pcm_format_physical_width(format->format); + if (width < 0) return width; nchannels = format->channels; if (snd_BUG_ON(plugin->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && @@ -600,16 +602,17 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st while (plugin) { if (frames <= 0) return frames; - if ((next = plugin->next) != NULL) { + next = plugin->next; + if (next) { snd_pcm_sframes_t frames1 = frames; if (plugin->dst_frames) { frames1 = plugin->dst_frames(plugin, frames); if (frames1 <= 0) return frames1; } - if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { + err = next->client_channels(next, frames1, &dst_channels); + if (err < 0) return err; - } if (err != frames1) { frames = err; if (plugin->src_frames) { @@ -621,7 +624,8 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, st } else dst_channels = NULL; pdprintf("write plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) + frames = plugin->transfer(plugin, src_channels, dst_channels, frames); + if (frames < 0) return frames; src_channels = dst_channels; plugin = next; @@ -643,16 +647,18 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str src_channels = NULL; plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { - if ((next = plugin->next) != NULL) { - if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { + next = plugin->next; + if (next) { + err = plugin->client_channels(plugin, frames, &dst_channels); + if (err < 0) return err; - } frames = err; } else { dst_channels = dst_channels_final; } pdprintf("read plugin: %s, %li\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) + frames = plugin->transfer(plugin, src_channels, dst_channels, frames); + if (frames < 0) return frames; plugin = next; src_channels = dst_channels; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index b163164a83ec..6fd3677685d7 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1004,7 +1004,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) substream->pstr->substream_opened--; } -static ssize_t show_pcm_class(struct device *dev, +static ssize_t pcm_class_show(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_pcm_str *pstr = container_of(dev, struct snd_pcm_str, dev); @@ -1024,7 +1024,7 @@ static ssize_t show_pcm_class(struct device *dev, return sprintf(buf, "%s\n", str); } -static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL); +static DEVICE_ATTR_RO(pcm_class); static struct attribute *pcm_dev_attrs[] = { &dev_attr_pcm_class.attr, NULL diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 590a46a9e78d..a59de24695ec 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -239,7 +239,8 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime; int err; - if (! (runtime = substream->runtime)) + runtime = substream->runtime; + if (!runtime) return -ENOTTY; data = kmalloc(sizeof(*data), GFP_KERNEL); @@ -343,7 +344,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - if ((ch = substream->runtime->channels) > 128) + ch = substream->runtime->channels; + if (ch > 128) return -EINVAL; if (get_user(buf, &data32->bufs) || get_user(frames, &data32->frames)) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b7e3d8f44511..7d5883432085 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1778,27 +1778,38 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, EXPORT_SYMBOL(snd_pcm_lib_ioctl); /** - * snd_pcm_period_elapsed - update the pcm status for the next period - * @substream: the pcm substream instance + * snd_pcm_period_elapsed_under_stream_lock() - update the status of runtime for the next period + * under acquired lock of PCM substream. + * @substream: the instance of pcm substream. + * + * This function is called when the batch of audio data frames as the same size as the period of + * buffer is already processed in audio data transmission. + * + * The call of function updates the status of runtime with the latest position of audio data + * transmission, checks overrun and underrun over buffer, awaken user processes from waiting for + * available audio data frames, sampling audio timestamp, and performs stop or drain the PCM + * substream according to configured threshold. + * + * The function is intended to use for the case that PCM driver operates audio data frames under + * acquired lock of PCM substream; e.g. in callback of any operation of &snd_pcm_ops in process + * context. In any interrupt context, it's preferrable to use ``snd_pcm_period_elapsed()`` instead + * since lock of PCM substream should be acquired in advance. * - * This function is called from the interrupt handler when the - * PCM has processed the period size. It will update the current - * pointer, wake up sleepers, etc. + * Developer should pay enough attention that some callbacks in &snd_pcm_ops are done by the call of + * function: * - * Even if more than one periods have elapsed since the last call, you - * have to call this only once. + * - .pointer - to retrieve current position of audio data transmission by frame count or XRUN state. + * - .trigger - with SNDRV_PCM_TRIGGER_STOP at XRUN or DRAINING state. + * - .get_time_info - to retrieve audio time stamp if needed. + * + * Even if more than one periods have elapsed since the last call, you have to call this only once. */ -void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) +void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; - unsigned long flags; - if (snd_BUG_ON(!substream)) - return; - - snd_pcm_stream_lock_irqsave(substream, flags); if (PCM_RUNTIME_CHECK(substream)) - goto _unlock; + return; runtime = substream->runtime; if (!snd_pcm_running(substream) || @@ -1811,7 +1822,30 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) #endif _end: kill_fasync(&runtime->fasync, SIGIO, POLL_IN); - _unlock: +} +EXPORT_SYMBOL(snd_pcm_period_elapsed_under_stream_lock); + +/** + * snd_pcm_period_elapsed() - update the status of runtime for the next period by acquiring lock of + * PCM substream. + * @substream: the instance of PCM substream. + * + * This function is mostly similar to ``snd_pcm_period_elapsed_under_stream_lock()`` except for + * acquiring lock of PCM substream voluntarily. + * + * It's typically called by any type of IRQ handler when hardware IRQ occurs to notify event that + * the batch of audio data frames as the same size as the period of buffer is already processed in + * audio data transmission. + */ +void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) +{ + unsigned long flags; + + if (snd_BUG_ON(!substream)) + return; + + snd_pcm_stream_lock_irqsave(substream, flags); + snd_pcm_period_elapsed_under_stream_lock(substream); snd_pcm_stream_unlock_irqrestore(substream, flags); } EXPORT_SYMBOL(snd_pcm_period_elapsed); diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h index e3b3558aeab6..fe9689b8a6a6 100644 --- a/sound/core/pcm_local.h +++ b/sound/core/pcm_local.h @@ -65,11 +65,6 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream); void snd_pcm_group_init(struct snd_pcm_group *group); void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq); -#ifdef CONFIG_SND_DMA_SGBUF -struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, - unsigned long offset); -#endif - #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime) /* loop over all PCM substreams */ diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 542a75babdee..d7621ed105bd 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -337,27 +337,6 @@ void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type, } EXPORT_SYMBOL(snd_pcm_set_managed_buffer_all); -#ifdef CONFIG_SND_DMA_SGBUF -/* - * snd_pcm_sgbuf_ops_page - get the page struct at the given offset - * @substream: the pcm substream instance - * @offset: the buffer offset - * - * Used as the page callback of PCM ops. - * - * Return: The page struct at the given buffer offset. %NULL on failure. - */ -struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset) -{ - struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream); - - unsigned int idx = offset >> PAGE_SHIFT; - if (idx >= (unsigned int)sgbuf->pages) - return NULL; - return sgbuf->page_table[idx]; -} -#endif /* CONFIG_SND_DMA_SGBUF */ - /** * snd_pcm_lib_malloc_pages - allocate the DMA buffer * @substream: the substream to allocate the DMA buffer to diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 257d412eac5d..4866aed97aac 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -266,7 +266,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format) int val; if (!valid_format(format)) return -EINVAL; - if ((val = pcm_formats[(INT)format].signd) < 0) + val = pcm_formats[(INT)format].signd; + if (val < 0) return -EINVAL; return val; } @@ -314,7 +315,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) int val; if (!valid_format(format)) return -EINVAL; - if ((val = pcm_formats[(INT)format].le) < 0) + val = pcm_formats[(INT)format].le; + if (val < 0) return -EINVAL; return val; } @@ -350,7 +352,8 @@ int snd_pcm_format_width(snd_pcm_format_t format) int val; if (!valid_format(format)) return -EINVAL; - if ((val = pcm_formats[(INT)format].width) == 0) + val = pcm_formats[(INT)format].width; + if (!val) return -EINVAL; return val; } @@ -368,7 +371,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) int val; if (!valid_format(format)) return -EINVAL; - if ((val = pcm_formats[(INT)format].phys) == 0) + val = pcm_formats[(INT)format].phys; + if (!val) return -EINVAL; return val; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8dbe86cf2e4f..14e32825c339 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -768,7 +768,8 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, if (cpu_latency_qos_request_active(&substream->latency_pm_qos_req)) cpu_latency_qos_remove_request(&substream->latency_pm_qos_req); - if ((usecs = period_to_usecs(runtime)) >= 0) + usecs = period_to_usecs(runtime); + if (usecs >= 0) cpu_latency_qos_add_request(&substream->latency_pm_qos_req, usecs); return 0; @@ -2658,7 +2659,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, goto error; } - if ((err = substream->ops->open(substream)) < 0) + err = substream->ops->open(substream); + if (err < 0) goto error; substream->hw_opened = 1; @@ -2799,6 +2801,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file) if (snd_BUG_ON(!substream)) return -ENXIO; pcm = substream->pcm; + + /* block until the device gets woken up as it may touch the hardware */ + snd_power_wait(pcm->card); + mutex_lock(&pcm->open_mutex); snd_pcm_release_substream(substream); kfree(pcm_file); @@ -3193,7 +3199,7 @@ static int snd_pcm_common_ioctl(struct file *file, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0); + res = snd_power_wait(substream->pcm->card); if (res < 0) return res; @@ -3638,24 +3644,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file } #endif /* coherent mmap */ -static inline struct page * -snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs) -{ - void *vaddr = substream->runtime->dma_area + ofs; - - switch (substream->dma_buffer.dev.type) { -#ifdef CONFIG_SND_DMA_SGBUF - case SNDRV_DMA_TYPE_DEV_SG: - case SNDRV_DMA_TYPE_DEV_UC_SG: - return snd_pcm_sgbuf_ops_page(substream, ofs); -#endif /* CONFIG_SND_DMA_SGBUF */ - case SNDRV_DMA_TYPE_VMALLOC: - return vmalloc_to_page(vaddr); - default: - return virt_to_page(vaddr); - } -} - /* * fault callback for mmapping a RAM page */ @@ -3677,7 +3665,7 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf) if (substream->ops->page) page = substream->ops->page(substream, offset); else - page = snd_pcm_default_page_ops(substream, offset); + page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset); if (!page) return VM_FAULT_SIGBUS; get_page(page); @@ -3712,22 +3700,9 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) { area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; -#ifdef CONFIG_GENERIC_ALLOCATOR - if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) { - area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); - return remap_pfn_range(area, area->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - area->vm_end - area->vm_start, area->vm_page_prot); - } -#endif /* CONFIG_GENERIC_ALLOCATOR */ - if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page && - (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV || - substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_UC)) - return dma_mmap_coherent(substream->dma_buffer.dev.dev, - area, - substream->runtime->dma_area, - substream->runtime->dma_addr, - substream->runtime->dma_bytes); + if (!substream->ops->page && + !snd_dma_buffer_mmap(snd_pcm_get_dma_buf(substream), area)) + return 0; /* mmap with fault handler */ area->vm_ops = &snd_pcm_vm_ops_data_fault; return 0; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index aca00af93afe..6c0a4a67ad2e 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -680,9 +680,12 @@ static int resize_runtime_buffer(struct snd_rawmidi_runtime *runtime, bool is_input) { char *newbuf, *oldbuf; + unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK; if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) return -EINVAL; + if (framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP && (params->buffer_size & 0x1f) != 0) + return -EINVAL; if (params->avail_min < 1 || params->avail_min > params->buffer_size) return -EINVAL; if (params->buffer_size != runtime->buffer_size) { @@ -720,8 +723,24 @@ EXPORT_SYMBOL(snd_rawmidi_output_params); int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, struct snd_rawmidi_params *params) { + unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK; + unsigned int clock_type = params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK; + int err; + + if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE) + return -EINVAL; + else if (clock_type > SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW) + return -EINVAL; + if (framing > SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) + return -EINVAL; snd_rawmidi_drain_input(substream); - return resize_runtime_buffer(substream->runtime, params, true); + err = resize_runtime_buffer(substream->runtime, params, true); + if (err < 0) + return err; + + substream->framing = framing; + substream->clock_type = clock_type; + return 0; } EXPORT_SYMBOL(snd_rawmidi_input_params); @@ -963,6 +982,62 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card, return -ENOIOCTLCMD; } +static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream, + const unsigned char *buffer, int src_count, const struct timespec64 *tstamp) +{ + struct snd_rawmidi_runtime *runtime = substream->runtime; + struct snd_rawmidi_framing_tstamp *dest_ptr; + struct snd_rawmidi_framing_tstamp frame = { .tv_sec = tstamp->tv_sec, .tv_nsec = tstamp->tv_nsec }; + int dest_frames = 0; + int orig_count = src_count; + int frame_size = sizeof(struct snd_rawmidi_framing_tstamp); + + BUILD_BUG_ON(frame_size != 0x20); + if (snd_BUG_ON((runtime->hw_ptr & 0x1f) != 0)) + return -EINVAL; + + while (src_count > 0) { + if ((int)(runtime->buffer_size - runtime->avail) < frame_size) { + runtime->xruns += src_count; + break; + } + if (src_count >= SNDRV_RAWMIDI_FRAMING_DATA_LENGTH) + frame.length = SNDRV_RAWMIDI_FRAMING_DATA_LENGTH; + else { + frame.length = src_count; + memset(frame.data, 0, SNDRV_RAWMIDI_FRAMING_DATA_LENGTH); + } + memcpy(frame.data, buffer, frame.length); + buffer += frame.length; + src_count -= frame.length; + dest_ptr = (struct snd_rawmidi_framing_tstamp *) (runtime->buffer + runtime->hw_ptr); + *dest_ptr = frame; + runtime->avail += frame_size; + runtime->hw_ptr += frame_size; + runtime->hw_ptr %= runtime->buffer_size; + dest_frames++; + } + return orig_count - src_count; +} + +static struct timespec64 get_framing_tstamp(struct snd_rawmidi_substream *substream) +{ + struct timespec64 ts64 = {0, 0}; + + switch (substream->clock_type) { + case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW: + ktime_get_raw_ts64(&ts64); + break; + case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC: + ktime_get_ts64(&ts64); + break; + case SNDRV_RAWMIDI_MODE_CLOCK_REALTIME: + ktime_get_real_ts64(&ts64); + break; + } + return ts64; +} + /** * snd_rawmidi_receive - receive the input data from the device * @substream: the rawmidi substream @@ -977,6 +1052,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, const unsigned char *buffer, int count) { unsigned long flags; + struct timespec64 ts64 = get_framing_tstamp(substream); int result = 0, count1; struct snd_rawmidi_runtime *runtime = substream->runtime; @@ -987,8 +1063,11 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, "snd_rawmidi_receive: input is not active!!!\n"); return -EINVAL; } + spin_lock_irqsave(&runtime->lock, flags); - if (count == 1) { /* special case, faster code */ + if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) { + result = receive_with_tstamp_framing(substream, buffer, count, &ts64); + } else if (count == 1) { /* special case, faster code */ substream->bytes++; if (runtime->avail < runtime->buffer_size) { runtime->buffer[runtime->hw_ptr++] = buffer[0]; @@ -1541,6 +1620,8 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, struct snd_rawmidi_substream *substream; struct snd_rawmidi_runtime *runtime; unsigned long buffer_size, avail, xruns; + unsigned int clock_type; + static const char *clock_names[4] = { "none", "realtime", "monotonic", "monotonic raw" }; rmidi = entry->private_data; snd_iprintf(buffer, "%s\n\n", rmidi->name); @@ -1596,6 +1677,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, " Avail : %lu\n" " Overruns : %lu\n", buffer_size, avail, xruns); + if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) { + clock_type = substream->clock_type >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT; + if (!snd_BUG_ON(clock_type >= ARRAY_SIZE(clock_names))) + snd_iprintf(buffer, + " Framing : tstamp\n" + " Clock type : %s\n", + clock_names[clock_type]); + } } } } diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index 7397130976d0..68a93443583c 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c @@ -13,7 +13,8 @@ struct snd_rawmidi_params32 { u32 buffer_size; u32 avail_min; unsigned int no_active_sensing; /* avoid bit-field */ - unsigned char reserved[16]; + unsigned int mode; + unsigned char reserved[12]; } __attribute__((packed)); static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, @@ -25,6 +26,7 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, if (get_user(params.stream, &src->stream) || get_user(params.buffer_size, &src->buffer_size) || get_user(params.avail_min, &src->avail_min) || + get_user(params.mode, &src->mode) || get_user(val, &src->no_active_sensing)) return -EFAULT; params.no_active_sensing = val; diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 250a92b18726..77c1214acd90 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -67,13 +67,16 @@ static int __init alsa_seq_oss_init(void) { int rc; - if ((rc = register_device()) < 0) + rc = register_device(); + if (rc < 0) goto error; - if ((rc = register_proc()) < 0) { + rc = register_proc(); + if (rc < 0) { unregister_device(); goto error; } - if ((rc = snd_seq_oss_create_client()) < 0) { + rc = snd_seq_oss_create_client(); + if (rc < 0) { unregister_proc(); unregister_device(); goto error; @@ -133,7 +136,8 @@ odev_release(struct inode *inode, struct file *file) { struct seq_oss_devinfo *dp; - if ((dp = file->private_data) == NULL) + dp = file->private_data; + if (!dp) return 0; mutex_lock(®ister_mutex); @@ -226,16 +230,18 @@ register_device(void) int rc; mutex_lock(®ister_mutex); - if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, - NULL, 0, - &seq_oss_f_ops, NULL)) < 0) { + rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, + NULL, 0, + &seq_oss_f_ops, NULL); + if (rc < 0) { pr_err("ALSA: seq_oss: can't register device seq\n"); mutex_unlock(®ister_mutex); return rc; } - if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, - NULL, 0, - &seq_oss_f_ops, NULL)) < 0) { + rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, + NULL, 0, + &seq_oss_f_ops, NULL); + if (rc < 0) { pr_err("ALSA: seq_oss: can't register device music\n"); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); mutex_unlock(®ister_mutex); diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index 4534a154b8c8..0ee4a5081fd6 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -94,10 +94,10 @@ snd_seq_oss_create_client(void) port_callback.event_input = receive_announce; port->kernel = &port_callback; - call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); - if ((system_port = port->addr.port) >= 0) { + if (call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port) >= 0) { struct snd_seq_port_subscribe subs; + system_port = port->addr.port; memset(&subs, 0, sizeof(subs)); subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; @@ -354,7 +354,8 @@ alloc_seq_queue(struct seq_oss_devinfo *dp) qinfo.owner = system_client; qinfo.locked = 1; strcpy(qinfo.name, "OSS Sequencer Emulation"); - if ((rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo)) < 0) + rc = call_ctl(SNDRV_SEQ_IOCTL_CREATE_QUEUE, &qinfo); + if (rc < 0) return rc; dp->queue = qinfo.queue; return 0; @@ -485,7 +486,8 @@ snd_seq_oss_system_info_read(struct snd_info_buffer *buf) snd_iprintf(buf, "\nNumber of applications: %d\n", num_clients); for (i = 0; i < num_clients; i++) { snd_iprintf(buf, "\nApplication %d: ", i); - if ((dp = client_table[i]) == NULL) { + dp = client_table[i]; + if (!dp) { snd_iprintf(buf, "*empty*\n"); continue; } diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 3f82c196de46..1e3bf086f867 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -152,7 +152,8 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) /* * look for the identical slot */ - if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) { + mdev = find_slot(pinfo->addr.client, pinfo->addr.port); + if (mdev) { /* already exists */ snd_use_lock_free(&mdev->use_lock); return 0; @@ -218,7 +219,8 @@ snd_seq_oss_midi_check_exit_port(int client, int port) unsigned long flags; int index; - if ((mdev = find_slot(client, port)) != NULL) { + mdev = find_slot(client, port); + if (mdev) { spin_lock_irqsave(®ister_lock, flags); midi_devs[mdev->seq_device] = NULL; spin_unlock_irqrestore(®ister_lock, flags); @@ -250,7 +252,8 @@ snd_seq_oss_midi_clear_all(void) spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) { - if ((mdev = midi_devs[i]) != NULL) { + mdev = midi_devs[i]; + if (mdev) { snd_midi_event_free(mdev->coder); kfree(mdev); midi_devs[i] = NULL; @@ -318,7 +321,8 @@ snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode) struct seq_oss_midi *mdev; struct snd_seq_port_subscribe subs; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return -ENODEV; /* already used? */ @@ -384,7 +388,8 @@ snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev) struct seq_oss_midi *mdev; struct snd_seq_port_subscribe subs; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return -ENODEV; if (! mdev->opened || mdev->devinfo != dp) { snd_use_lock_free(&mdev->use_lock); @@ -421,7 +426,8 @@ snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev) struct seq_oss_midi *mdev; int mode; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return 0; mode = 0; @@ -443,7 +449,8 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) { struct seq_oss_midi *mdev; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return; if (! mdev->opened) { snd_use_lock_free(&mdev->use_lock); @@ -491,7 +498,8 @@ snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_ad { struct seq_oss_midi *mdev; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return; addr->client = mdev->client; addr->port = mdev->port; @@ -511,7 +519,8 @@ snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data) if (dp->readq == NULL) return 0; - if ((mdev = find_slot(ev->source.client, ev->source.port)) == NULL) + mdev = find_slot(ev->source.client, ev->source.port); + if (!mdev) return 0; if (! (mdev->opened & PERM_READ)) { snd_use_lock_free(&mdev->use_lock); @@ -623,7 +632,8 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru { struct seq_oss_midi *mdev; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return -ENODEV; if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); @@ -642,7 +652,8 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info { struct seq_oss_midi *mdev; - if ((mdev = get_mididev(dp, dev)) == NULL) + mdev = get_mididev(dp, dev); + if (!mdev) return -ENXIO; inf->device = dev; inf->dev_type = 0; /* FIXME: ?? */ diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c index 537d5f423e20..8a142fd54a19 100644 --- a/sound/core/seq/oss/seq_oss_rw.c +++ b/sound/core/seq/oss/seq_oss_rw.c @@ -132,7 +132,8 @@ snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, } /* insert queue */ - if ((err = insert_queue(dp, &rec, opt)) < 0) + err = insert_queue(dp, &rec, opt); + if (err < 0) break; result += ev_size; diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 722f5059b300..e3394919daa0 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -451,7 +451,8 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, if (info->is_midi) return 0; - if ((rec = get_synthdev(dp, dev)) == NULL) + rec = get_synthdev(dp, dev); + if (!rec) return -ENXIO; if (rec->oper.load_patch == NULL) @@ -569,7 +570,8 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u info = get_synthinfo_nospec(dp, dev); if (!info || info->is_midi) return -ENXIO; - if ((rec = get_synthdev(dp, dev)) == NULL) + rec = get_synthdev(dp, dev); + if (!rec) return -ENXIO; if (rec->oper.ioctl == NULL) rc = -ENXIO; @@ -619,7 +621,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in inf->device = dev; strscpy(inf->name, minf.name, sizeof(inf->name)); } else { - if ((rec = get_synthdev(dp, dev)) == NULL) + rec = get_synthdev(dp, dev); + if (!rec) return -ENXIO; inf->synth_type = rec->synth_type; inf->synth_subtype = rec->synth_subtype; diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c index 0a02a59103b4..3e3209ce53b1 100644 --- a/sound/core/seq/oss/seq_oss_writeq.c +++ b/sound/core/seq/oss/seq_oss_writeq.c @@ -27,7 +27,8 @@ snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen) struct seq_oss_writeq *q; struct snd_seq_client_pool pool; - if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) + q = kzalloc(sizeof(*q), GFP_KERNEL); + if (!q) return NULL; q->dp = dp; q->maxlen = maxlen; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index b6a24fb5e76b..2e9d695d336c 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -416,7 +416,10 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, if (snd_BUG_ON(!client)) return -ENXIO; - if (!client->accept_input || (fifo = client->data.user.fifo) == NULL) + if (!client->accept_input) + return -ENXIO; + fifo = client->data.user.fifo; + if (!fifo) return -ENXIO; if (atomic_read(&fifo->overflow) > 0) { @@ -435,9 +438,9 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, int nonblock; nonblock = (file->f_flags & O_NONBLOCK) || result > 0; - if ((err = snd_seq_fifo_cell_out(fifo, &cell, nonblock)) < 0) { + err = snd_seq_fifo_cell_out(fifo, &cell, nonblock); + if (err < 0) break; - } if (snd_seq_ev_is_variable(&cell->event)) { struct snd_seq_event tmpev; tmpev = cell->event; @@ -970,7 +973,8 @@ static int snd_seq_client_enqueue_event(struct snd_seq_client *client, return err; /* we got a cell. enqueue it. */ - if ((err = snd_seq_enqueue_event(cell, atomic, hop)) < 0) { + err = snd_seq_enqueue_event(cell, atomic, hop); + if (err < 0) { snd_seq_cell_free(cell); return err; } @@ -1312,7 +1316,8 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) return -EINVAL; } if (client->type == KERNEL_CLIENT) { - if ((callback = info->kernel) != NULL) { + callback = info->kernel; + if (callback) { if (callback->owner) port->owner = callback->owner; port->private_data = callback->private_data; @@ -1466,13 +1471,17 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) + receiver = snd_seq_client_use_ptr(subs->dest.client); + if (!receiver) goto __end; - if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (!sender) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (!sport) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) + dport = snd_seq_port_use_ptr(receiver, subs->dest.port); + if (!dport) goto __end; result = check_subscription_permission(client, sport, dport, subs); @@ -1508,13 +1517,17 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) + receiver = snd_seq_client_use_ptr(subs->dest.client); + if (!receiver) goto __end; - if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (!sender) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (!sport) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) + dport = snd_seq_port_use_ptr(receiver, subs->dest.port); + if (!dport) goto __end; result = check_subscription_permission(client, sport, dport, subs); @@ -1926,9 +1939,11 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, struct snd_seq_client_port *sport = NULL; result = -EINVAL; - if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) + sender = snd_seq_client_use_ptr(subs->sender.client); + if (!sender) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) + sport = snd_seq_port_use_ptr(sender, subs->sender.port); + if (!sport) goto __end; result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest, subs); @@ -1955,9 +1970,11 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) struct list_head *p; int i; - if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL) + cptr = snd_seq_client_use_ptr(subs->root.client); + if (!cptr) goto __end; - if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL) + port = snd_seq_port_use_ptr(cptr, subs->root.port); + if (!port) goto __end; switch (subs->type) { diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index cd5a4cad8881..ac760b1e3d12 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -109,7 +109,8 @@ create_port(int idx, int type) struct snd_seq_port_callback pcb; struct snd_seq_dummy_port *rec; - if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) + rec = kzalloc(sizeof(*rec), GFP_KERNEL); + if (!rec) return NULL; rec->client = my_client; diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index eaaa8b5830bb..f8e02e98709a 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -143,7 +143,8 @@ static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f) { struct snd_seq_event_cell *cell; - if ((cell = f->head) != NULL) { + cell = f->head; + if (cell) { f->head = cell->next; /* reset tail if this was the last element */ diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index e245bb6ba533..b7aee23fc387 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -69,7 +69,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, int len, err; struct snd_seq_event_cell *cell; - if ((len = get_var_len(event)) <= 0) + len = get_var_len(event); + if (len <= 0) return len; if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { @@ -133,7 +134,8 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char int len, newlen; int err; - if ((len = get_var_len(event)) < 0) + len = get_var_len(event); + if (len < 0) return len; newlen = len; if (size_aligned > 0) diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 6825940ea2cf..4589aac09154 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -101,7 +101,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i if (snd_BUG_ON(!substream || !buf)) return -EINVAL; runtime = substream->runtime; - if ((tmp = runtime->avail) < count) { + tmp = runtime->avail; + if (tmp < count) { if (printk_ratelimit()) pr_err("ALSA: seq_midi: MIDI output buffer overrun\n"); return -ENOMEM; @@ -167,10 +168,11 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe struct snd_rawmidi_params params; /* open midi port */ - if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, - msynth->subdevice, - SNDRV_RAWMIDI_LFLG_INPUT, - &msynth->input_rfile)) < 0) { + err = snd_rawmidi_kernel_open(msynth->card, msynth->device, + msynth->subdevice, + SNDRV_RAWMIDI_LFLG_INPUT, + &msynth->input_rfile); + if (err < 0) { pr_debug("ALSA: seq_midi: midi input open failed!!!\n"); return err; } @@ -178,7 +180,8 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe memset(¶ms, 0, sizeof(params)); params.avail_min = 1; params.buffer_size = input_buffer_size; - if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms)) < 0) { + err = snd_rawmidi_input_params(msynth->input_rfile.input, ¶ms); + if (err < 0) { snd_rawmidi_kernel_release(&msynth->input_rfile); return err; } @@ -209,10 +212,11 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info struct snd_rawmidi_params params; /* open midi port */ - if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device, - msynth->subdevice, - SNDRV_RAWMIDI_LFLG_OUTPUT, - &msynth->output_rfile)) < 0) { + err = snd_rawmidi_kernel_open(msynth->card, msynth->device, + msynth->subdevice, + SNDRV_RAWMIDI_LFLG_OUTPUT, + &msynth->output_rfile); + if (err < 0) { pr_debug("ALSA: seq_midi: midi output open failed!!!\n"); return err; } @@ -220,7 +224,8 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info params.avail_min = 1; params.buffer_size = output_buffer_size; params.no_active_sensing = 1; - if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms)) < 0) { + err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms); + if (err < 0) { snd_rawmidi_kernel_release(&msynth->output_rfile); return err; } diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 13cfc2d47fa7..d6c02dea976c 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c @@ -222,7 +222,8 @@ struct snd_seq_queue *snd_seq_queue_find_name(char *name) struct snd_seq_queue *q; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) != NULL) { + q = queueptr(i); + if (q) { if (strncmp(q->name, name, sizeof(q->name)) == 0) return q; queuefree(q); @@ -432,7 +433,8 @@ int snd_seq_queue_timer_open(int queueid) if (queue == NULL) return -EINVAL; tmr = queue->timer; - if ((result = snd_seq_timer_open(queue)) < 0) { + result = snd_seq_timer_open(queue); + if (result < 0) { snd_seq_timer_defaults(tmr); result = snd_seq_timer_open(queue); } @@ -548,7 +550,8 @@ void snd_seq_queue_client_leave(int client) /* delete own queues from queue list */ for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queue_list_remove(i, client)) != NULL) + q = queue_list_remove(i, client); + if (q) queue_delete(q); } @@ -556,7 +559,8 @@ void snd_seq_queue_client_leave(int client) * they are not owned by this client */ for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) + q = queueptr(i); + if (!q) continue; if (test_bit(client, q->clients_bitmap)) { snd_seq_prioq_leave(q->tickq, client, 0); @@ -578,7 +582,8 @@ void snd_seq_queue_client_leave_cells(int client) struct snd_seq_queue *q; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) + q = queueptr(i); + if (!q) continue; snd_seq_prioq_leave(q->tickq, client, 0); snd_seq_prioq_leave(q->timeq, client, 0); @@ -593,7 +598,8 @@ void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info) struct snd_seq_queue *q; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) + q = queueptr(i); + if (!q) continue; if (test_bit(client, q->clients_bitmap) && (! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) || @@ -724,7 +730,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry, int owner; for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) { - if ((q = queueptr(i)) == NULL) + q = queueptr(i); + if (!q) continue; tmr = q->timer; diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 77d7037d1476..4abc38c70cae 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -482,10 +482,11 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi int err; *rrmidi = NULL; - if ((err = snd_rawmidi_new(card, "VirMidi", device, - 16, /* may be configurable */ - 16, /* may be configurable */ - &rmidi)) < 0) + err = snd_rawmidi_new(card, "VirMidi", device, + 16, /* may be configurable */ + 16, /* may be configurable */ + &rmidi); + if (err < 0) return err; strcpy(rmidi->name, rmidi->id); rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 29ddb76187e5..232cf3f1bcb3 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -10,20 +10,34 @@ #include <linux/vmalloc.h> #include <linux/export.h> #include <sound/memalloc.h> - +#include "memalloc_local.h" + +struct snd_sg_page { + void *buf; + dma_addr_t addr; +}; + +struct snd_sg_buf { + int size; /* allocated byte size */ + int pages; /* allocated pages */ + int tblsize; /* allocated table size */ + struct snd_sg_page *table; /* address table */ + struct page **page_table; /* page table (for vmap/vunmap) */ + struct device *dev; +}; /* table entries are align to 32 */ #define SGBUF_TBL_ALIGN 32 #define sgbuf_align_table(tbl) ALIGN((tbl), SGBUF_TBL_ALIGN) -int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) +static void snd_dma_sg_free(struct snd_dma_buffer *dmab) { struct snd_sg_buf *sgbuf = dmab->private_data; struct snd_dma_buffer tmpb; int i; - if (! sgbuf) - return -EINVAL; + if (!sgbuf) + return; vunmap(dmab->area); dmab->area = NULL; @@ -45,15 +59,11 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab) kfree(sgbuf->page_table); kfree(sgbuf); dmab->private_data = NULL; - - return 0; } #define MAX_ALLOC_PAGES 32 -void *snd_malloc_sgbuf_pages(struct device *device, - size_t size, struct snd_dma_buffer *dmab, - size_t *res_size) +static int snd_dma_sg_alloc(struct snd_dma_buffer *dmab, size_t size) { struct snd_sg_buf *sgbuf; unsigned int i, pages, chunk, maxpages; @@ -63,18 +73,16 @@ void *snd_malloc_sgbuf_pages(struct device *device, int type = SNDRV_DMA_TYPE_DEV; pgprot_t prot = PAGE_KERNEL; - dmab->area = NULL; - dmab->addr = 0; dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); - if (! sgbuf) - return NULL; + if (!sgbuf) + return -ENOMEM; if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_UC_SG) { type = SNDRV_DMA_TYPE_DEV_UC; #ifdef pgprot_noncached prot = pgprot_noncached(PAGE_KERNEL); #endif } - sgbuf->dev = device; + sgbuf->dev = dmab->dev.dev; pages = snd_sgbuf_aligned_pages(size); sgbuf->tblsize = sgbuf_align_table(pages); table = kcalloc(sgbuf->tblsize, sizeof(*table), GFP_KERNEL); @@ -94,12 +102,10 @@ void *snd_malloc_sgbuf_pages(struct device *device, if (chunk > maxpages) chunk = maxpages; chunk <<= PAGE_SHIFT; - if (snd_dma_alloc_pages_fallback(type, device, + if (snd_dma_alloc_pages_fallback(type, dmab->dev.dev, chunk, &tmpb) < 0) { if (!sgbuf->pages) goto _failed; - if (!res_size) - goto _failed; size = sgbuf->pages * PAGE_SIZE; break; } @@ -124,27 +130,42 @@ void *snd_malloc_sgbuf_pages(struct device *device, dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, prot); if (! dmab->area) goto _failed; - if (res_size) - *res_size = sgbuf->size; - return dmab->area; + return 0; _failed: - snd_free_sgbuf_pages(dmab); /* free the table */ - return NULL; + snd_dma_sg_free(dmab); /* free the table */ + return -ENOMEM; } -/* - * compute the max chunk size with continuous pages on sg-buffer - */ -unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, - unsigned int ofs, unsigned int size) +static dma_addr_t snd_dma_sg_get_addr(struct snd_dma_buffer *dmab, + size_t offset) +{ + struct snd_sg_buf *sgbuf = dmab->private_data; + dma_addr_t addr; + + addr = sgbuf->table[offset >> PAGE_SHIFT].addr; + addr &= ~((dma_addr_t)PAGE_SIZE - 1); + return addr + offset % PAGE_SIZE; +} + +static struct page *snd_dma_sg_get_page(struct snd_dma_buffer *dmab, + size_t offset) +{ + struct snd_sg_buf *sgbuf = dmab->private_data; + unsigned int idx = offset >> PAGE_SHIFT; + + if (idx >= (unsigned int)sgbuf->pages) + return NULL; + return sgbuf->page_table[idx]; +} + +static unsigned int snd_dma_sg_get_chunk_size(struct snd_dma_buffer *dmab, + unsigned int ofs, + unsigned int size) { struct snd_sg_buf *sg = dmab->private_data; unsigned int start, end, pg; - if (!sg) - return size; - start = ofs >> PAGE_SHIFT; end = (ofs + size - 1) >> PAGE_SHIFT; /* check page continuity */ @@ -160,4 +181,11 @@ unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, /* ok, all on continuous pages */ return size; } -EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); + +const struct snd_malloc_ops snd_dma_sg_ops = { + .alloc = snd_dma_sg_alloc, + .free = snd_dma_sg_free, + .get_addr = snd_dma_sg_get_addr, + .get_page = snd_dma_sg_get_page, + .get_chunk_size = snd_dma_sg_get_chunk_size, +}; diff --git a/sound/core/sound.c b/sound/core/sound.c index af89e51dd44a..df5571d98629 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -357,7 +357,8 @@ static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_bu mutex_lock(&sound_mutex); for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) { - if (!(mptr = snd_minors[minor])) + mptr = snd_minors[minor]; + if (!mptr) continue; if (mptr->card >= 0) { if (mptr->device >= 0) diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 610f317bea9d..7ed0a2a91035 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -217,7 +217,8 @@ static void snd_minor_info_oss_read(struct snd_info_entry *entry, mutex_lock(&sound_oss_mutex); for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) { - if (!(mptr = snd_oss_minors[minor])) + mptr = snd_oss_minors[minor]; + if (!mptr) continue; if (mptr->card >= 0) snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor, diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 8c552e25805a..d0b55dbb411a 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -104,7 +104,8 @@ static int snd_mpu401_probe(struct platform_device *devptr) err = snd_mpu401_create(&devptr->dev, dev, &card); if (err < 0) return err; - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } @@ -182,7 +183,8 @@ static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, err = snd_mpu401_create(&pnp_dev->dev, dev, &card); if (err < 0) return err; - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } @@ -227,7 +229,8 @@ static int __init alsa_card_mpu401_init(void) { int i, err; - if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) + err = platform_driver_register(&snd_mpu401_driver); + if (err < 0) return err; for (i = 0; i < SNDRV_CARDS; i++) { diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 65982d6babfc..f435b9b4ae24 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -271,8 +271,11 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream) int err; mpu = substream->rmidi->private_data; - if (mpu->open_input && (err = mpu->open_input(mpu)) < 0) - return err; + if (mpu->open_input) { + err = mpu->open_input(mpu); + if (err < 0) + return err; + } if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) { if (snd_mpu401_do_reset(mpu) < 0) goto error_out; @@ -293,8 +296,11 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream) int err; mpu = substream->rmidi->private_data; - if (mpu->open_output && (err = mpu->open_output(mpu)) < 0) - return err; + if (mpu->open_output) { + err = mpu->open_output(mpu); + if (err < 0) + return err; + } if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { if (snd_mpu401_do_reset(mpu) < 0) goto error_out; @@ -524,8 +530,9 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; - if ((err = snd_rawmidi_new(card, "MPU-401U", device, - out_enable, in_enable, &rmidi)) < 0) + err = snd_rawmidi_new(card, "MPU-401U", device, + out_enable, in_enable, &rmidi); + if (err < 0) return err; mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); if (!mpu) { diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index df4b7f9cd50f..0e95b08d34d6 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -566,7 +566,8 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id) */ static int snd_mtpav_get_ISA(struct mtpav *mcard) { - if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) { + mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI"); + if (!mcard->res_port) { snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port); return -EBUSY; } @@ -628,10 +629,11 @@ static int snd_mtpav_get_RAWMIDI(struct mtpav *mcard) hwports = 8; mcard->num_ports = hwports; - if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, - &mcard->rmidi)) < 0) + rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0, + mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, + mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1, + &mcard->rmidi); + if (rval < 0) return rval; rawmidi = mcard->rmidi; rawmidi->private_data = mcard; @@ -744,7 +746,8 @@ static int __init alsa_card_mtpav_init(void) { int err; - if ((err = platform_driver_register(&snd_mtpav_driver)) < 0) + err = platform_driver_register(&snd_mtpav_driver); + if (err < 0) return err; device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 322d530ab07b..d3bc9e8c407d 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -950,7 +950,8 @@ static int snd_mts64_probe(struct platform_device *pdev) goto free_pardev; } - if ((err = snd_mts64_create(card, pardev, &mts)) < 0) { + err = snd_mts64_create(card, pardev, &mts); + if (err < 0) { snd_printd("Cannot create main component\n"); goto release_pardev; } @@ -963,19 +964,22 @@ static int snd_mts64_probe(struct platform_device *pdev) goto __err; } - if ((err = snd_mts64_rawmidi_create(card)) < 0) { + err = snd_mts64_rawmidi_create(card); + if (err < 0) { snd_printd("Creating Rawmidi component failed\n"); goto __err; } /* init device */ - if ((err = mts64_device_init(p)) < 0) + err = mts64_device_init(p); + if (err < 0) goto __err; platform_set_drvdata(pdev, card); /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_printd("Cannot register card\n"); goto __err; } @@ -1031,7 +1035,8 @@ static int __init snd_mts64_module_init(void) { int err; - if ((err = platform_driver_register(&snd_mts64_driver)) < 0) + err = platform_driver_register(&snd_mts64_driver); + if (err < 0) return err; if (parport_register_driver(&mts64_parport_driver) != 0) { diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 9259522483c8..6c1f1cc092d8 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -243,7 +243,8 @@ static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no) tid.card = opl3->card->number; tid.device = timer_no; tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) { + err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer); + if (err >= 0) { strcpy(timer->name, "AdLib timer #1"); timer->private_data = opl3; timer->hw = snd_opl3_timer1; @@ -263,7 +264,8 @@ static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no) tid.card = opl3->card->number; tid.device = timer_no; tid.subdevice = 0; - if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) { + err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer); + if (err >= 0) { strcpy(timer->name, "AdLib timer #2"); timer->private_data = opl3; timer->hw = snd_opl3_timer2; @@ -348,7 +350,8 @@ int snd_opl3_new(struct snd_card *card, spin_lock_init(&opl3->reg_lock); spin_lock_init(&opl3->timer_lock); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops); + if (err < 0) { snd_opl3_free(opl3); return err; } @@ -396,19 +399,23 @@ int snd_opl3_create(struct snd_card *card, int err; *ropl3 = NULL; - if ((err = snd_opl3_new(card, hardware, &opl3)) < 0) + err = snd_opl3_new(card, hardware, &opl3); + if (err < 0) return err; if (! integrated) { - if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) { + opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)"); + if (!opl3->res_l_port) { snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port); snd_device_free(card, opl3); return -EBUSY; } - if (r_port != 0 && - (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) { - snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); - snd_device_free(card, opl3); - return -EBUSY; + if (r_port != 0) { + opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)"); + if (!opl3->res_r_port) { + snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port); + snd_device_free(card, opl3); + return -EBUSY; + } } } opl3->l_port = l_port; @@ -423,7 +430,8 @@ int snd_opl3_create(struct snd_card *card, break; default: opl3->command = &snd_opl2_command; - if ((err = snd_opl3_detect(opl3)) < 0) { + err = snd_opl3_detect(opl3); + if (err < 0) { snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n", opl3->l_port, opl3->r_port); snd_device_free(card, opl3); @@ -449,11 +457,14 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) { int err; - if (timer1_dev >= 0) - if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0) + if (timer1_dev >= 0) { + err = snd_opl3_timer1_init(opl3, timer1_dev); + if (err < 0) return err; + } if (timer2_dev >= 0) { - if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) { + err = snd_opl3_timer2_init(opl3, timer2_dev); + if (err < 0) { snd_device_free(opl3->card, opl3->timer1); opl3->timer1 = NULL; return err; @@ -477,7 +488,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, /* create hardware dependent device (direct FM) */ - if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) { + err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw); + if (err < 0) { snd_device_free(card, opl3); return err; } diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index eb23c55323ae..e1b69c65c3c8 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -180,8 +180,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, if (vp2->state == SNDRV_OPL3_ST_ON_2OP) { /* kill two voices, EXPENSIVE */ bp++; - voice_time = (voice_time > vp->time) ? - voice_time : vp->time; + voice_time = max(voice_time, vp2->time); } } else { /* allocate 2op voice */ diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index c82c7c1c0714..7645365eec89 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -136,7 +136,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) if (snd_BUG_ON(!arg)) return -ENXIO; - if ((err = snd_opl3_synth_setup(opl3)) < 0) + err = snd_opl3_synth_setup(opl3); + if (err < 0) return err; /* fill the argument data */ @@ -144,7 +145,8 @@ static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure) arg->addr.client = opl3->oss_chset->client; arg->addr.port = opl3->oss_chset->port; - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) + err = snd_opl3_synth_use_inc(opl3); + if (err < 0) return err; opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH; diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index cd2a01b5e2e1..75de1299c3dc 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -92,7 +92,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe struct snd_opl3 *opl3 = private_data; int err; - if ((err = snd_opl3_synth_setup(opl3)) < 0) + err = snd_opl3_synth_setup(opl3); + if (err < 0) return err; if (use_internal_drums) { @@ -107,7 +108,8 @@ static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe } if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) { - if ((err = snd_opl3_synth_use_inc(opl3)) < 0) + err = snd_opl3_synth_use_inc(opl3); + if (err < 0) return err; } opl3->synth_mode = SNDRV_OPL3_MODE_SEQ; @@ -227,7 +229,8 @@ static int snd_opl3_seq_probe(struct device *_dev) if (client < 0) return client; - if ((err = snd_opl3_synth_create_port(opl3)) < 0) { + err = snd_opl3_synth_create_port(opl3); + if (err < 0) { snd_seq_delete_kernel_client(client); opl3->seq_client = -1; return err; diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 2f4514ed47c5..52a656735365 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -749,7 +749,8 @@ static int snd_portman_probe(struct platform_device *pdev) goto free_pardev; } - if ((err = portman_create(card, pardev, &pm)) < 0) { + err = portman_create(card, pardev, &pm); + if (err < 0) { snd_printd("Cannot create main component\n"); goto release_pardev; } @@ -762,19 +763,22 @@ static int snd_portman_probe(struct platform_device *pdev) goto __err; } - if ((err = snd_portman_rawmidi_create(card)) < 0) { + err = snd_portman_rawmidi_create(card); + if (err < 0) { snd_printd("Creating Rawmidi component failed\n"); goto __err; } /* init device */ - if ((err = portman_device_init(pm)) < 0) + err = portman_device_init(pm); + if (err < 0) goto __err; platform_set_drvdata(pdev, card); /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_printd("Cannot register card\n"); goto __err; } @@ -831,7 +835,8 @@ static int __init snd_portman_module_init(void) { int err; - if ((err = platform_driver_register(&snd_portman_driver)) < 0) + err = platform_driver_register(&snd_portman_driver); + if (err < 0) return err; if (parport_register_driver(&portman_parport_driver) != 0) { diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 6d5d1ca59ecf..da9983cba01c 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -783,7 +783,8 @@ static int snd_uart16550_create(struct snd_card *card, int err; - if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL) + uart = kzalloc(sizeof(*uart), GFP_KERNEL); + if (!uart) return -ENOMEM; uart->adaptor = adaptor; uart->card = card; @@ -792,7 +793,8 @@ static int snd_uart16550_create(struct snd_card *card, uart->base = iobase; uart->drop_on_full = droponfull; - if ((err = snd_uart16550_detect(uart)) <= 0) { + err = snd_uart16550_detect(uart); + if (err <= 0) { printk(KERN_ERR "no UART detected at 0x%lx\n", iobase); snd_uart16550_free(uart); return -ENODEV; @@ -818,7 +820,8 @@ static int snd_uart16550_create(struct snd_card *card, uart->timer_running = 0; /* Register device */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops); + if (err < 0) { snd_uart16550_free(uart); return err; } @@ -932,14 +935,10 @@ static int snd_serial_probe(struct platform_device *devptr) strcpy(card->driver, "Serial"); strcpy(card->shortname, "Serial MIDI (UART16550A)"); - if ((err = snd_uart16550_create(card, - port[dev], - irq[dev], - speed[dev], - base[dev], - adaptor[dev], - droponfull[dev], - &uart)) < 0) + err = snd_uart16550_create(card, port[dev], irq[dev], speed[dev], + base[dev], adaptor[dev], droponfull[dev], + &uart); + if (err < 0) goto _err; err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi); @@ -952,7 +951,8 @@ static int snd_serial_probe(struct platform_device *devptr) uart->base, uart->irq); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto _err; platform_set_drvdata(devptr, card); @@ -992,7 +992,8 @@ static int __init alsa_card_serial_init(void) { int i, cards, err; - if ((err = platform_driver_register(&snd_serial_driver)) < 0) + err = platform_driver_register(&snd_serial_driver); + if (err < 0) return err; cards = 0; diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index a22e5b1a5458..a10449af5a76 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c @@ -110,20 +110,25 @@ static int vx_transfer_end(struct vx_core *chip, int cmd) { int err; - if ((err = vx_reset_chk(chip)) < 0) + err = vx_reset_chk(chip); + if (err < 0) return err; /* irq MESS_READ/WRITE_END */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) + err = vx_send_irq_dsp(chip, cmd); + if (err < 0) return err; /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) + err = vx_wait_isr_bit(chip, ISR_CHK); + if (err < 0) return err; /* If error, Read RX */ - if ((err = vx_inb(chip, ISR)) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { + err = vx_inb(chip, ISR); + if (err & ISR_ERR) { + err = vx_wait_for_rx_full(chip); + if (err < 0) { snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n"); return err; } @@ -232,7 +237,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) if (chip->chip_status & VX_STAT_IS_STALE) return -EBUSY; - if ((err = vx_reset_chk(chip)) < 0) { + err = vx_reset_chk(chip); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n"); return err; } @@ -254,7 +260,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) rmh->Cmd[0] &= MASK_1_WORD_COMMAND; /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { + err = vx_wait_isr_bit(chip, ISR_TX_EMPTY); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n"); return err; } @@ -265,18 +272,21 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) vx_outb(chip, TXL, rmh->Cmd[0] & 0xff); /* Trigger irq MESSAGE */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) { + err = vx_send_irq_dsp(chip, IRQ_MESSAGE); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n"); return err; } /* Wait for CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) + err = vx_wait_isr_bit(chip, ISR_CHK); + if (err < 0) return err; /* If error, get error value from RX */ if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) { + err = vx_wait_for_rx_full(chip); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n"); return err; } @@ -292,7 +302,8 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) if (rmh->LgCmd > 1) { for (i = 1; i < rmh->LgCmd; i++) { /* Wait for TX ready */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { + err = vx_wait_isr_bit(chip, ISR_TX_READY); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n"); return err; } @@ -303,13 +314,15 @@ int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh) vx_outb(chip, TXL, rmh->Cmd[i] & 0xff); /* Trigger irq MESS_READ_NEXT */ - if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) { + err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n"); return err; } } /* Wait for TX empty */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) { + err = vx_wait_isr_bit(chip, ISR_TX_READY); + if (err < 0) { snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n"); return err; } @@ -362,17 +375,21 @@ int vx_send_rih_nolock(struct vx_core *chip, int cmd) #if 0 printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd); #endif - if ((err = vx_reset_chk(chip)) < 0) + err = vx_reset_chk(chip); + if (err < 0) return err; /* send the IRQ */ - if ((err = vx_send_irq_dsp(chip, cmd)) < 0) + err = vx_send_irq_dsp(chip, cmd); + if (err < 0) return err; /* Wait CHK = 1 */ - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) + err = vx_wait_isr_bit(chip, ISR_CHK); + if (err < 0) return err; /* If error, read RX */ if (vx_inb(chip, ISR) & ISR_ERR) { - if ((err = vx_wait_for_rx_full(chip)) < 0) + err = vx_wait_for_rx_full(chip); + if (err < 0) return err; err = vx_inb(chip, RXH) << 16; err |= vx_inb(chip, RXM) << 8; @@ -648,7 +665,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) vx_reset_board(chip, cold_reset); vx_validate_irq(chip, 0); - if ((err = snd_vx_load_boot_image(chip, boot)) < 0) + err = snd_vx_load_boot_image(chip, boot); + if (err < 0) return err; msleep(10); @@ -678,7 +696,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) for (i = 0; i < dsp->size; i += 3) { image = dsp->data + i; /* Wait DSP ready for a new read */ - if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) { + err = vx_wait_isr_bit(chip, ISR_TX_EMPTY); + if (err < 0) { printk(KERN_ERR "dsp loading error at position %d\n", i); return err; @@ -698,7 +717,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) msleep(200); - if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0) + err = vx_wait_isr_bit(chip, ISR_CHK); + if (err < 0) return err; vx_toggle_dac_mute(chip, 0); diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index 01baa6d872e9..efbb644edba1 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -78,15 +78,19 @@ int snd_vx_setup_firmware(struct vx_core *chip) /* ok, we reached to the last one */ /* create the devices if not built yet */ - if ((err = snd_vx_pcm_new(chip)) < 0) + err = snd_vx_pcm_new(chip); + if (err < 0) return err; - if ((err = snd_vx_mixer_new(chip)) < 0) + err = snd_vx_mixer_new(chip); + if (err < 0) return err; - if (chip->ops->add_controls) - if ((err = chip->ops->add_controls(chip)) < 0) + if (chip->ops->add_controls) { + err = chip->ops->add_controls(chip); + if (err < 0) return err; + } chip->chip_status |= VX_STAT_DEVICE_INIT; chip->chip_status |= VX_STAT_CHIP_INIT; diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index 13099f8c84d6..53d78eb13c53 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -910,7 +910,8 @@ int snd_vx_mixer_new(struct vx_core *chip) temp = vx_control_output_level; temp.index = i; temp.tlv.p = chip->hw->output_level_db_scale; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } @@ -921,22 +922,26 @@ int snd_vx_mixer_new(struct vx_core *chip) temp.index = i; temp.name = "PCM Playback Volume"; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; temp = vx_control_output_switch; temp.index = i; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; temp = vx_control_monitor_gain; temp.index = i; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; temp = vx_control_monitor_switch; temp.index = i; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } for (i = 0; i < chip->hw->num_outs; i++) { @@ -944,20 +949,25 @@ int snd_vx_mixer_new(struct vx_core *chip) temp.index = i; temp.name = "PCM Capture Volume"; temp.private_value = (i * 2) | (1 << 8); - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } /* Audio source */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip)); + if (err < 0) return err; /* clock mode */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip)); + if (err < 0) return err; /* IEC958 controls */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip)); + if (err < 0) return err; /* VU, peak, saturation meters */ for (c = 0; c < 2; c++) { @@ -968,7 +978,8 @@ int snd_vx_mixer_new(struct vx_core *chip) temp = vx_control_saturation; temp.index = i; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } sprintf(name, "%s VU Meter", dir[c]); @@ -976,14 +987,16 @@ int snd_vx_mixer_new(struct vx_core *chip) temp.index = i; temp.name = name; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; sprintf(name, "%s Peak Meter", dir[c]); temp = vx_control_peak_meter; temp.index = i; temp.name = name; temp.private_value = val; - if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } } diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index daffda99b4f7..3924f5283745 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -341,10 +341,12 @@ static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state) } } - if ((err = vx_conf_pipe(chip, pipe)) < 0) + err = vx_conf_pipe(chip, pipe); + if (err < 0) return err; - if ((err = vx_send_irqa(chip)) < 0) + err = vx_send_irqa(chip); + if (err < 0) return err; /* If it completes successfully, wait for the pipes @@ -680,8 +682,9 @@ static void vx_pcm_playback_transfer(struct vx_core *chip, if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE)) return; for (i = 0; i < nchunks; i++) { - if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe, - chip->ibl.size)) < 0) + err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe, + chip->ibl.size); + if (err < 0) return; } } @@ -698,7 +701,8 @@ static void vx_pcm_playback_update(struct vx_core *chip, struct snd_pcm_runtime *runtime = subs->runtime; if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) { - if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0) + err = vx_update_pipe_position(chip, runtime, pipe); + if (err < 0) return; if (pipe->transferred >= (int)runtime->period_size) { pipe->transferred %= runtime->period_size; @@ -747,11 +751,13 @@ static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd) pipe->running = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0) + err = vx_toggle_pipe(chip, pipe, 0); + if (err < 0) return err; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) + err = vx_toggle_pipe(chip, pipe, 1); + if (err < 0) return err; break; default: @@ -792,13 +798,15 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode); vx_init_rmh(&rmh, CMD_FREE_PIPE); vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0); - if ((err = vx_send_msg(chip, &rmh)) < 0) + err = vx_send_msg(chip, &rmh); + if (err < 0) return err; vx_init_rmh(&rmh, CMD_RES_PIPE); vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels); if (data_mode) rmh.Cmd[0] |= BIT_DATA_MODE; - if ((err = vx_send_msg(chip, &rmh)) < 0) + err = vx_send_msg(chip, &rmh); + if (err < 0) return err; pipe->data_mode = data_mode; } @@ -810,7 +818,8 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) } vx_set_clock(chip, runtime->rate); - if ((err = vx_set_format(chip, pipe, runtime)) < 0) + err = vx_set_format(chip, pipe, runtime); + if (err < 0) return err; if (vx_is_pcmcia(chip)) { @@ -1187,7 +1196,8 @@ int snd_vx_pcm_new(struct vx_core *chip) unsigned int i; int err; - if ((err = vx_init_audio_io(chip)) < 0) + err = vx_init_audio_io(chip); + if (err < 0) return err; for (i = 0; i < chip->hw->num_codecs; i++) { diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 9897bd26a438..fd109bea4c53 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -18,8 +18,25 @@ config SND_DICE select SND_HWDEP select SND_FIREWIRE_LIB help - Say Y here to include support for many DACs based on the DICE - chip family (DICE-II/Jr/Mini) which TC Applied Technologies produces. + Say Y here to include support for devices based on the DICE chip family + (DICE-II/TCD2210(Mini)/TCD2220(Jr.)) which TC Applied Technologies (TCAT) produced. + * Allen and Heath Zed R16 + * Alesis iO 14/26 FireWire, MasterControl, MultiMix 8/12/16 FireWire + * Avid Mbox 3 Pro + * FlexRadio Systems FLEX-3000, FLEX-5000 + * Focusrite Liquid Saffire 56 + * Focusrite Saffire Pro 14, Pro 24, Pro 24 DSP, Pro 26, Pro 40(TCD2220) + * Harman Music Group Lexicon I-ONIX FW810S + * Loud Technologies Mackie Onyx Blackbird, Onyx 820i/1220i/1620i/1640i (latter models) + * M-Audio ProFire 610/2626 + * Mytek Stereo192-DSD DAC + * Midas Klark Teknik VeniceF series + * PreSonus FireStudio, FireStudio Mobile, FireStudio Project, FireStudio Tube + * PreSonus StudioLive 16.4.2, 16.0.2, 24.4.2, 32.4.2 + * Solid State Logic Duende Classic, Duende Mini + * TC Electronic Studio Konnekt 48, Konnekt 24D, Konnekt Live, Impact Twin + * TC Electronic Digital Konnekt x32, Desktop Konnekt 6 + * Weiss Engineering ADC2, Vesta, Minerva, AFI1, DAC1, INT202, DAC202 To compile this driver as a module, choose M here: the module will be called snd-dice. @@ -38,7 +55,7 @@ config SND_OXFW * Mackie(Loud) Onyx 1640i (former model) * Mackie(Loud) Onyx Satellite * Mackie(Loud) Tapco Link.Firewire - * Mackie(Loud) d.4 pro + * Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC) * Mackie(Loud) U.420/U.420d * TASCAM FireOne * Stanton Controllers & Systems 1 Deck/Mixer @@ -84,7 +101,7 @@ config SND_BEBOB * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 * BridgeCo RDAudio1/Audio5 * Mackie Onyx 1220/1620/1640 (FireWire I/O Card) - * Mackie d.2 (FireWire Option) and d.2 Pro + * Mackie d.2 (optional FireWire card with DM1000 ASIC) * Stanton FinalScratch 2 (ScratchAmp) * Tascam IF-FW/DM * Behringer XENIX UFX 1204/1604 @@ -110,6 +127,7 @@ config SND_BEBOB * M-Audio Ozonic/NRV10/ProfireLightBridge * M-Audio FireWire 1814/ProjectMix IO * Digidesign Mbox 2 Pro + * ToneWeal FW66 To compile this driver as a module, choose M here: the module will be called snd-bebob. @@ -148,12 +166,16 @@ config SND_FIREWIRE_MOTU select SND_HWDEP help Say Y here to enable support for FireWire devices which MOTU produced: + * 828 + * 896 * 828mk2 * Traveler * Ultralite * 8pre * 828mk3 (FireWire only) * 828mk3 (Hybrid) + * Ultralite mk3 (FireWire only) + * Ultralite mk3 (Hybrid) * Audio Express * 4pre diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index fea92e148790..d9c700f652bb 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -410,10 +410,10 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, * @s: the AMDTP stream to initialize * @unit: the target of the stream * @dir: the direction of stream - * @flags: the packet transmission method to use + * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants. */ int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, - enum amdtp_stream_direction dir, enum cip_flags flags) + enum amdtp_stream_direction dir, unsigned int flags) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; diff --git a/sound/firewire/amdtp-am824.h b/sound/firewire/amdtp-am824.h index 06d280783581..2b092b1061ba 100644 --- a/sound/firewire/amdtp-am824.h +++ b/sound/firewire/amdtp-am824.h @@ -45,5 +45,5 @@ void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port, struct snd_rawmidi_substream *midi); int amdtp_am824_init(struct amdtp_stream *s, struct fw_unit *unit, - enum amdtp_stream_direction dir, enum cip_flags flags); + enum amdtp_stream_direction dir, unsigned int flags); #endif diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h index aa53c13b89d3..5fd2aeccdfc2 100644 --- a/sound/firewire/amdtp-stream-trace.h +++ b/sound/firewire/amdtp-stream-trace.h @@ -49,7 +49,7 @@ TRACE_EVENT(amdtp_packet, __entry->data_blocks = data_blocks; __entry->data_block_counter = data_block_counter, __entry->packet_index = packet_index; - __entry->irq = !!in_interrupt(); + __entry->irq = !!in_softirq(); __entry->index = index; ), TP_printk( diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 5805c5de39fb..9be2260e4ca2 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -20,7 +20,7 @@ #define CYCLES_PER_SECOND 8000 #define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) -#define OHCI_MAX_SECOND 8 +#define OHCI_SECOND_MODULUS 8 /* Always support Linux tracing subsystem. */ #define CREATE_TRACE_POINTS @@ -33,7 +33,8 @@ #define TAG_NO_CIP_HEADER 0 #define TAG_CIP 1 -/* common isochronous packet header parameters */ +// Common Isochronous Packet (CIP) header parameters. Use two quadlets CIP header when supported. +#define CIP_HEADER_QUADLETS 2 #define CIP_EOH_SHIFT 31 #define CIP_EOH (1u << CIP_EOH_SHIFT) #define CIP_EOH_MASK 0x80000000 @@ -48,36 +49,46 @@ #define CIP_FMT_MASK 0x3f000000 #define CIP_FDF_MASK 0x00ff0000 #define CIP_FDF_SHIFT 16 +#define CIP_FDF_NO_DATA 0xff #define CIP_SYT_MASK 0x0000ffff #define CIP_SYT_NO_INFO 0xffff +#define CIP_SYT_CYCLE_MODULUS 16 +#define CIP_NO_DATA ((CIP_FDF_NO_DATA << CIP_FDF_SHIFT) | CIP_SYT_NO_INFO) + +#define CIP_HEADER_SIZE (sizeof(__be32) * CIP_HEADER_QUADLETS) /* Audio and Music transfer protocol specific parameters */ #define CIP_FMT_AM 0x10 #define AMDTP_FDF_NO_DATA 0xff -// For iso header, tstamp and 2 CIP header. -#define IR_CTX_HEADER_SIZE_CIP 16 // For iso header and tstamp. -#define IR_CTX_HEADER_SIZE_NO_CIP 8 +#define IR_CTX_HEADER_DEFAULT_QUADLETS 2 +// Add nothing. +#define IR_CTX_HEADER_SIZE_NO_CIP (sizeof(__be32) * IR_CTX_HEADER_DEFAULT_QUADLETS) +// Add two quadlets CIP header. +#define IR_CTX_HEADER_SIZE_CIP (IR_CTX_HEADER_SIZE_NO_CIP + CIP_HEADER_SIZE) #define HEADER_TSTAMP_MASK 0x0000ffff -#define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header. +#define IT_PKT_HEADER_SIZE_CIP CIP_HEADER_SIZE #define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing. -static void pcm_period_work(struct work_struct *work); +// The initial firmware of OXFW970 can postpone transmission of packet during finishing +// asynchronous transaction. This module accepts 5 cycles to skip as maximum to avoid buffer +// overrun. Actual device can skip more, then this module stops the packet streaming. +#define IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES 5 /** * amdtp_stream_init - initialize an AMDTP stream structure * @s: the AMDTP stream to initialize * @unit: the target of the stream * @dir: the direction of stream - * @flags: the packet transmission method to use + * @flags: the details of the streaming protocol consist of cip_flags enumeration-constants. * @fmt: the value of fmt field in CIP header * @process_ctx_payloads: callback handler to process payloads of isoc context * @protocol_size: the size to allocate newly for protocol */ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, - enum amdtp_stream_direction dir, enum cip_flags flags, + enum amdtp_stream_direction dir, unsigned int flags, unsigned int fmt, amdtp_stream_process_ctx_payloads_t process_ctx_payloads, unsigned int protocol_size) @@ -94,18 +105,13 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, s->flags = flags; s->context = ERR_PTR(-1); mutex_init(&s->mutex); - INIT_WORK(&s->period_work, pcm_period_work); s->packet_index = 0; - init_waitqueue_head(&s->callback_wait); - s->callbacked = false; + init_waitqueue_head(&s->ready_wait); s->fmt = fmt; s->process_ctx_payloads = process_ctx_payloads; - if (dir == AMDTP_OUT_STREAM) - s->ctx_data.rx.syt_override = -1; - return 0; } EXPORT_SYMBOL(amdtp_stream_init); @@ -183,14 +189,13 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, unsigned int maximum_usec_per_period; int err; - hw->info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | + hw->info = SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP; - /* SNDRV_PCM_INFO_BATCH */ hw->periods_min = 2; hw->periods_max = UINT_MAX; @@ -287,22 +292,29 @@ int amdtp_stream_set_parameters(struct amdtp_stream *s, unsigned int rate, s->syt_interval = amdtp_syt_intervals[sfc]; // default buffering in the device. - if (s->direction == AMDTP_OUT_STREAM) { - s->ctx_data.rx.transfer_delay = - TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; - - if (s->flags & CIP_BLOCKING) { - // additional buffering needed to adjust for no-data - // packets. - s->ctx_data.rx.transfer_delay += - TICKS_PER_SECOND * s->syt_interval / rate; - } - } + s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; + + // additional buffering needed to adjust for no-data packets. + if (s->flags & CIP_BLOCKING) + s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate; return 0; } EXPORT_SYMBOL(amdtp_stream_set_parameters); +// The CIP header is processed in context header apart from context payload. +static int amdtp_stream_get_max_ctx_payload_size(struct amdtp_stream *s) +{ + unsigned int multiplier; + + if (s->flags & CIP_JUMBO_PAYLOAD) + multiplier = IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES; + else + multiplier = 1; + + return s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier; +} + /** * amdtp_stream_get_max_payload - get the stream's packet size * @s: the AMDTP stream @@ -312,16 +324,14 @@ EXPORT_SYMBOL(amdtp_stream_set_parameters); */ unsigned int amdtp_stream_get_max_payload(struct amdtp_stream *s) { - unsigned int multiplier = 1; - unsigned int cip_header_size = 0; + unsigned int cip_header_size; - if (s->flags & CIP_JUMBO_PAYLOAD) - multiplier = 5; if (!(s->flags & CIP_NO_HEADER)) - cip_header_size = sizeof(__be32) * 2; + cip_header_size = CIP_HEADER_SIZE; + else + cip_header_size = 0; - return cip_header_size + - s->syt_interval * s->data_block_quadlets * sizeof(__be32) * multiplier; + return cip_header_size + amdtp_stream_get_max_ctx_payload_size(s); } EXPORT_SYMBOL(amdtp_stream_get_max_payload); @@ -333,32 +343,46 @@ EXPORT_SYMBOL(amdtp_stream_get_max_payload); */ void amdtp_stream_pcm_prepare(struct amdtp_stream *s) { - cancel_work_sync(&s->period_work); s->pcm_buffer_pointer = 0; s->pcm_period_pointer = 0; } EXPORT_SYMBOL(amdtp_stream_pcm_prepare); -static unsigned int calculate_data_blocks(unsigned int *data_block_state, - bool is_blocking, bool is_no_info, - unsigned int syt_interval, enum cip_sfc sfc) +static void pool_blocking_data_blocks(struct amdtp_stream *s, struct seq_desc *descs, + const unsigned int seq_size, unsigned int seq_tail, + unsigned int count) { - unsigned int data_blocks; + const unsigned int syt_interval = s->syt_interval; + int i; + + for (i = 0; i < count; ++i) { + struct seq_desc *desc = descs + seq_tail; - /* Blocking mode. */ - if (is_blocking) { - /* This module generate empty packet for 'no data'. */ - if (is_no_info) - data_blocks = 0; + if (desc->syt_offset != CIP_SYT_NO_INFO) + desc->data_blocks = syt_interval; else - data_blocks = syt_interval; - /* Non-blocking mode. */ - } else { + desc->data_blocks = 0; + + seq_tail = (seq_tail + 1) % seq_size; + } +} + +static void pool_ideal_nonblocking_data_blocks(struct amdtp_stream *s, struct seq_desc *descs, + const unsigned int seq_size, unsigned int seq_tail, + unsigned int count) +{ + const enum cip_sfc sfc = s->sfc; + unsigned int state = s->ctx_data.rx.data_block_state; + int i; + + for (i = 0; i < count; ++i) { + struct seq_desc *desc = descs + seq_tail; + if (!cip_sfc_is_base_44100(sfc)) { // Sample_rate / 8000 is an integer, and precomputed. - data_blocks = *data_block_state; + desc->data_blocks = state; } else { - unsigned int phase = *data_block_state; + unsigned int phase = state; /* * This calculates the number of data blocks per packet so that @@ -370,18 +394,19 @@ static unsigned int calculate_data_blocks(unsigned int *data_block_state, */ if (sfc == CIP_SFC_44100) /* 6 6 5 6 5 6 5 ... */ - data_blocks = 5 + ((phase & 1) ^ - (phase == 0 || phase >= 40)); + desc->data_blocks = 5 + ((phase & 1) ^ (phase == 0 || phase >= 40)); else /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ - data_blocks = 11 * (sfc >> 1) + (phase == 0); + desc->data_blocks = 11 * (sfc >> 1) + (phase == 0); if (++phase >= (80 >> (sfc >> 1))) phase = 0; - *data_block_state = phase; + state = phase; } + + seq_tail = (seq_tail + 1) % seq_size; } - return data_blocks; + s->ctx_data.rx.data_block_state = state; } static unsigned int calculate_syt_offset(unsigned int *last_syt_offset, @@ -423,6 +448,149 @@ static unsigned int calculate_syt_offset(unsigned int *last_syt_offset, return syt_offset; } +static void pool_ideal_syt_offsets(struct amdtp_stream *s, struct seq_desc *descs, + const unsigned int seq_size, unsigned int seq_tail, + unsigned int count) +{ + const enum cip_sfc sfc = s->sfc; + unsigned int last = s->ctx_data.rx.last_syt_offset; + unsigned int state = s->ctx_data.rx.syt_offset_state; + int i; + + for (i = 0; i < count; ++i) { + struct seq_desc *desc = descs + seq_tail; + + desc->syt_offset = calculate_syt_offset(&last, &state, sfc); + + seq_tail = (seq_tail + 1) % seq_size; + } + + s->ctx_data.rx.last_syt_offset = last; + s->ctx_data.rx.syt_offset_state = state; +} + +static unsigned int compute_syt_offset(unsigned int syt, unsigned int cycle, + unsigned int transfer_delay) +{ + unsigned int cycle_lo = (cycle % CYCLES_PER_SECOND) & 0x0f; + unsigned int syt_cycle_lo = (syt & 0xf000) >> 12; + unsigned int syt_offset; + + // Round up. + if (syt_cycle_lo < cycle_lo) + syt_cycle_lo += CIP_SYT_CYCLE_MODULUS; + syt_cycle_lo -= cycle_lo; + + // Subtract transfer delay so that the synchronization offset is not so large + // at transmission. + syt_offset = syt_cycle_lo * TICKS_PER_CYCLE + (syt & 0x0fff); + if (syt_offset < transfer_delay) + syt_offset += CIP_SYT_CYCLE_MODULUS * TICKS_PER_CYCLE; + + return syt_offset - transfer_delay; +} + +// Both of the producer and consumer of the queue runs in the same clock of IEEE 1394 bus. +// Additionally, the sequence of tx packets is severely checked against any discontinuity +// before filling entries in the queue. The calculation is safe even if it looks fragile by +// overrun. +static unsigned int calculate_cached_cycle_count(struct amdtp_stream *s, unsigned int head) +{ + const unsigned int cache_size = s->ctx_data.tx.cache.size; + unsigned int cycles = s->ctx_data.tx.cache.tail; + + if (cycles < head) + cycles += cache_size; + cycles -= head; + + return cycles; +} + +static void cache_seq(struct amdtp_stream *s, const struct pkt_desc *descs, unsigned int desc_count) +{ + const unsigned int transfer_delay = s->transfer_delay; + const unsigned int cache_size = s->ctx_data.tx.cache.size; + struct seq_desc *cache = s->ctx_data.tx.cache.descs; + unsigned int cache_tail = s->ctx_data.tx.cache.tail; + bool aware_syt = !(s->flags & CIP_UNAWARE_SYT); + int i; + + for (i = 0; i < desc_count; ++i) { + struct seq_desc *dst = cache + cache_tail; + const struct pkt_desc *src = descs + i; + + if (aware_syt && src->syt != CIP_SYT_NO_INFO) + dst->syt_offset = compute_syt_offset(src->syt, src->cycle, transfer_delay); + else + dst->syt_offset = CIP_SYT_NO_INFO; + dst->data_blocks = src->data_blocks; + + cache_tail = (cache_tail + 1) % cache_size; + } + + s->ctx_data.tx.cache.tail = cache_tail; +} + +static void pool_ideal_seq_descs(struct amdtp_stream *s, unsigned int count) +{ + struct seq_desc *descs = s->ctx_data.rx.seq.descs; + unsigned int seq_tail = s->ctx_data.rx.seq.tail; + const unsigned int seq_size = s->ctx_data.rx.seq.size; + + pool_ideal_syt_offsets(s, descs, seq_size, seq_tail, count); + + if (s->flags & CIP_BLOCKING) + pool_blocking_data_blocks(s, descs, seq_size, seq_tail, count); + else + pool_ideal_nonblocking_data_blocks(s, descs, seq_size, seq_tail, count); + + s->ctx_data.rx.seq.tail = (seq_tail + count) % seq_size; +} + +static void pool_replayed_seq(struct amdtp_stream *s, unsigned int count) +{ + struct amdtp_stream *target = s->ctx_data.rx.replay_target; + const struct seq_desc *cache = target->ctx_data.tx.cache.descs; + const unsigned int cache_size = target->ctx_data.tx.cache.size; + unsigned int cache_head = s->ctx_data.rx.cache_head; + struct seq_desc *descs = s->ctx_data.rx.seq.descs; + const unsigned int seq_size = s->ctx_data.rx.seq.size; + unsigned int seq_tail = s->ctx_data.rx.seq.tail; + int i; + + for (i = 0; i < count; ++i) { + descs[seq_tail] = cache[cache_head]; + seq_tail = (seq_tail + 1) % seq_size; + cache_head = (cache_head + 1) % cache_size; + } + + s->ctx_data.rx.seq.tail = seq_tail; + s->ctx_data.rx.cache_head = cache_head; +} + +static void pool_seq_descs(struct amdtp_stream *s, unsigned int count) +{ + struct amdtp_domain *d = s->domain; + + if (!d->replay.enable || !s->ctx_data.rx.replay_target) { + pool_ideal_seq_descs(s, count); + } else { + if (!d->replay.on_the_fly) { + pool_replayed_seq(s, count); + } else { + struct amdtp_stream *tx = s->ctx_data.rx.replay_target; + const unsigned int cache_size = tx->ctx_data.tx.cache.size; + const unsigned int cache_head = s->ctx_data.rx.cache_head; + unsigned int cached_cycles = calculate_cached_cycle_count(tx, cache_head); + + if (cached_cycles > count && cached_cycles > cache_size / 2) + pool_replayed_seq(s, count); + else + pool_ideal_seq_descs(s, count); + } + } +} + static void update_pcm_pointers(struct amdtp_stream *s, struct snd_pcm_substream *pcm, unsigned int frames) @@ -437,18 +605,21 @@ static void update_pcm_pointers(struct amdtp_stream *s, s->pcm_period_pointer += frames; if (s->pcm_period_pointer >= pcm->runtime->period_size) { s->pcm_period_pointer -= pcm->runtime->period_size; - queue_work(system_highpri_wq, &s->period_work); - } -} -static void pcm_period_work(struct work_struct *work) -{ - struct amdtp_stream *s = container_of(work, struct amdtp_stream, - period_work); - struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); - - if (pcm) - snd_pcm_period_elapsed(pcm); + // The program in user process should periodically check the status of intermediate + // buffer associated to PCM substream to process PCM frames in the buffer, instead + // of receiving notification of period elapsed by poll wait. + if (!pcm->runtime->no_period_wakeup) { + if (in_softirq()) { + // In software IRQ context for 1394 OHCI. + snd_pcm_period_elapsed(pcm); + } else { + // In process context of ALSA PCM application under acquired lock of + // PCM substream. + snd_pcm_period_elapsed_under_stream_lock(pcm); + } + } + } } static int queue_packet(struct amdtp_stream *s, struct fw_iso_packet *params, @@ -505,7 +676,7 @@ static void generate_cip_header(struct amdtp_stream *s, __be32 cip_header[2], } static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, - struct fw_iso_packet *params, + struct fw_iso_packet *params, unsigned int header_length, unsigned int data_blocks, unsigned int data_block_counter, unsigned int syt, unsigned int index) @@ -516,16 +687,15 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle, payload_length = data_blocks * sizeof(__be32) * s->data_block_quadlets; params->payload_length = payload_length; - if (!(s->flags & CIP_NO_HEADER)) { + if (header_length > 0) { cip_header = (__be32 *)params->header; generate_cip_header(s, cip_header, data_block_counter, syt); - params->header_length = 2 * sizeof(__be32); - payload_length += params->header_length; + params->header_length = header_length; } else { cip_header = NULL; } - trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks, + trace_amdtp_packet(s, cycle, cip_header, payload_length + header_length, data_blocks, data_block_counter, s->packet_index, index); } @@ -569,8 +739,7 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, /* Calculate data blocks */ fdf = (cip_header[1] & CIP_FDF_MASK) >> CIP_FDF_SHIFT; - if (payload_length < sizeof(__be32) * 2 || - (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { + if (payload_length == 0 || (fmt == CIP_FMT_AM && fdf == AMDTP_FDF_NO_DATA)) { *data_blocks = 0; } else { unsigned int data_block_quadlets = @@ -585,8 +754,7 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, if (s->flags & CIP_WRONG_DBS) data_block_quadlets = s->data_block_quadlets; - *data_blocks = (payload_length / sizeof(__be32) - 2) / - data_block_quadlets; + *data_blocks = payload_length / sizeof(__be32) / data_block_quadlets; } /* Check data block counter continuity */ @@ -620,109 +788,163 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf, *data_block_counter = dbc; - *syt = cip_header[1] & CIP_SYT_MASK; + if (!(s->flags & CIP_UNAWARE_SYT)) + *syt = cip_header[1] & CIP_SYT_MASK; return 0; } static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle, const __be32 *ctx_header, - unsigned int *payload_length, unsigned int *data_blocks, unsigned int *data_block_counter, unsigned int *syt, unsigned int packet_index, unsigned int index) { + unsigned int payload_length; const __be32 *cip_header; unsigned int cip_header_size; - int err; - *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; + payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT; if (!(s->flags & CIP_NO_HEADER)) - cip_header_size = 8; + cip_header_size = CIP_HEADER_SIZE; else cip_header_size = 0; - if (*payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) { + if (payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) { dev_err(&s->unit->device, "Detect jumbo payload: %04x %04x\n", - *payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length); + payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length); return -EIO; } if (cip_header_size > 0) { - cip_header = ctx_header + 2; - err = check_cip_header(s, cip_header, *payload_length, - data_blocks, data_block_counter, syt); - if (err < 0) - return err; + if (payload_length >= cip_header_size) { + int err; + + cip_header = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS; + err = check_cip_header(s, cip_header, payload_length - cip_header_size, + data_blocks, data_block_counter, syt); + if (err < 0) + return err; + } else { + // Handle the cycle so that empty packet arrives. + cip_header = NULL; + *data_blocks = 0; + *syt = 0; + } } else { cip_header = NULL; - err = 0; - *data_blocks = *payload_length / sizeof(__be32) / - s->data_block_quadlets; + *data_blocks = payload_length / sizeof(__be32) / s->data_block_quadlets; *syt = 0; if (*data_block_counter == UINT_MAX) *data_block_counter = 0; } - trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks, + trace_amdtp_packet(s, cycle, cip_header, payload_length, *data_blocks, *data_block_counter, packet_index, index); - return err; + return 0; } // In CYCLE_TIMER register of IEEE 1394, 7 bits are used to represent second. On // the other hand, in DMA descriptors of 1394 OHCI, 3 bits are used to represent // it. Thus, via Linux firewire subsystem, we can get the 3 bits for second. -static inline u32 compute_cycle_count(__be32 ctx_header_tstamp) +static inline u32 compute_ohci_cycle_count(__be32 ctx_header_tstamp) { u32 tstamp = be32_to_cpu(ctx_header_tstamp) & HEADER_TSTAMP_MASK; return (((tstamp >> 13) & 0x07) * 8000) + (tstamp & 0x1fff); } -static inline u32 increment_cycle_count(u32 cycle, unsigned int addend) +static inline u32 increment_ohci_cycle_count(u32 cycle, unsigned int addend) { cycle += addend; - if (cycle >= OHCI_MAX_SECOND * CYCLES_PER_SECOND) - cycle -= OHCI_MAX_SECOND * CYCLES_PER_SECOND; + if (cycle >= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND) + cycle -= OHCI_SECOND_MODULUS * CYCLES_PER_SECOND; return cycle; } +static int compare_ohci_cycle_count(u32 lval, u32 rval) +{ + if (lval == rval) + return 0; + else if (lval < rval && rval - lval < OHCI_SECOND_MODULUS * CYCLES_PER_SECOND / 2) + return -1; + else + return 1; +} + // Align to actual cycle count for the packet which is going to be scheduled. // This module queued the same number of isochronous cycle as the size of queue // to kip isochronous cycle, therefore it's OK to just increment the cycle by // the size of queue for scheduled cycle. -static inline u32 compute_it_cycle(const __be32 ctx_header_tstamp, - unsigned int queue_size) +static inline u32 compute_ohci_it_cycle(const __be32 ctx_header_tstamp, + unsigned int queue_size) { - u32 cycle = compute_cycle_count(ctx_header_tstamp); - return increment_cycle_count(cycle, queue_size); + u32 cycle = compute_ohci_cycle_count(ctx_header_tstamp); + return increment_ohci_cycle_count(cycle, queue_size); } static int generate_device_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, const __be32 *ctx_header, - unsigned int packets) + unsigned int packets, + unsigned int *desc_count) { + unsigned int next_cycle = s->next_cycle; unsigned int dbc = s->data_block_counter; unsigned int packet_index = s->packet_index; unsigned int queue_size = s->queue_size; int i; int err; + *desc_count = 0; for (i = 0; i < packets; ++i) { - struct pkt_desc *desc = descs + i; + struct pkt_desc *desc = descs + *desc_count; unsigned int cycle; - unsigned int payload_length; + bool lost; unsigned int data_blocks; unsigned int syt; - cycle = compute_cycle_count(ctx_header[1]); + cycle = compute_ohci_cycle_count(ctx_header[1]); + lost = (next_cycle != cycle); + if (lost) { + if (s->flags & CIP_NO_HEADER) { + // Fireface skips transmission just for an isoc cycle corresponding + // to empty packet. + unsigned int prev_cycle = next_cycle; + + next_cycle = increment_ohci_cycle_count(next_cycle, 1); + lost = (next_cycle != cycle); + if (!lost) { + // Prepare a description for the skipped cycle for + // sequence replay. + desc->cycle = prev_cycle; + desc->syt = 0; + desc->data_blocks = 0; + desc->data_block_counter = dbc; + desc->ctx_payload = NULL; + ++desc; + ++(*desc_count); + } + } else if (s->flags & CIP_JUMBO_PAYLOAD) { + // OXFW970 skips transmission for several isoc cycles during + // asynchronous transaction. The sequence replay is impossible due + // to the reason. + unsigned int safe_cycle = increment_ohci_cycle_count(next_cycle, + IR_JUMBO_PAYLOAD_MAX_SKIP_CYCLES); + lost = (compare_ohci_cycle_count(safe_cycle, cycle) > 0); + } + if (lost) { + dev_err(&s->unit->device, "Detect discontinuity of cycle: %d %d\n", + next_cycle, cycle); + return -EIO; + } + } - err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length, - &data_blocks, &dbc, &syt, packet_index, i); + err = parse_ir_ctx_header(s, cycle, ctx_header, &data_blocks, &dbc, &syt, + packet_index, i); if (err < 0) return err; @@ -735,12 +957,13 @@ static int generate_device_pkt_descs(struct amdtp_stream *s, if (!(s->flags & CIP_DBC_IS_END_EVENT)) dbc = (dbc + desc->data_blocks) & 0xff; - ctx_header += - s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); - + next_cycle = increment_ohci_cycle_count(next_cycle, 1); + ++(*desc_count); + ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); packet_index = (packet_index + 1) % queue_size; } + s->next_cycle = next_cycle; s->data_block_counter = dbc; return 0; @@ -757,29 +980,28 @@ static unsigned int compute_syt(unsigned int syt_offset, unsigned int cycle, return syt & CIP_SYT_MASK; } -static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, - const __be32 *ctx_header, unsigned int packets, - const struct seq_desc *seq_descs, - unsigned int seq_size) +static void generate_pkt_descs(struct amdtp_stream *s, const __be32 *ctx_header, unsigned int packets) { + struct pkt_desc *descs = s->pkt_descs; + const struct seq_desc *seq_descs = s->ctx_data.rx.seq.descs; + const unsigned int seq_size = s->ctx_data.rx.seq.size; unsigned int dbc = s->data_block_counter; - unsigned int seq_index = s->ctx_data.rx.seq_index; + unsigned int seq_head = s->ctx_data.rx.seq.head; + bool aware_syt = !(s->flags & CIP_UNAWARE_SYT); int i; for (i = 0; i < packets; ++i) { struct pkt_desc *desc = descs + i; unsigned int index = (s->packet_index + i) % s->queue_size; - const struct seq_desc *seq = seq_descs + seq_index; - unsigned int syt; + const struct seq_desc *seq = seq_descs + seq_head; - desc->cycle = compute_it_cycle(*ctx_header, s->queue_size); + desc->cycle = compute_ohci_it_cycle(*ctx_header, s->queue_size); + + if (aware_syt && seq->syt_offset != CIP_SYT_NO_INFO) + desc->syt = compute_syt(seq->syt_offset, desc->cycle, s->transfer_delay); + else + desc->syt = CIP_SYT_NO_INFO; - syt = seq->syt_offset; - if (syt != CIP_SYT_NO_INFO) { - syt = compute_syt(syt, desc->cycle, - s->ctx_data.rx.transfer_delay); - } - desc->syt = syt; desc->data_blocks = seq->data_blocks; if (s->flags & CIP_DBC_IS_END_EVENT) @@ -792,19 +1014,19 @@ static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs, desc->ctx_payload = s->buffer.packets[index].buffer; - seq_index = (seq_index + 1) % seq_size; + seq_head = (seq_head + 1) % seq_size; ++ctx_header; } s->data_block_counter = dbc; - s->ctx_data.rx.seq_index = seq_index; + s->ctx_data.rx.seq.head = seq_head; } static inline void cancel_stream(struct amdtp_stream *s) { s->packet_index = -1; - if (in_interrupt()) + if (in_softirq()) amdtp_stream_pcm_abort(s); WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN); } @@ -822,16 +1044,17 @@ static void process_ctx_payloads(struct amdtp_stream *s, update_pcm_pointers(s, pcm, pcm_frames); } -static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, - size_t header_length, void *header, - void *private_data) +static void process_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data) { struct amdtp_stream *s = private_data; const struct amdtp_domain *d = s->domain; const __be32 *ctx_header = header; - unsigned int events_per_period = s->ctx_data.rx.events_per_period; + const unsigned int events_per_period = d->events_per_period; unsigned int event_count = s->ctx_data.rx.event_count; + unsigned int pkt_header_length; unsigned int packets; + bool need_hw_irq; int i; if (s->packet_index < 0) @@ -840,34 +1063,44 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, // Calculate the number of packets in buffer and check XRUN. packets = header_length / sizeof(*ctx_header); - generate_pkt_descs(s, s->pkt_descs, ctx_header, packets, d->seq_descs, - d->seq_size); + pool_seq_descs(s, packets); + + generate_pkt_descs(s, ctx_header, packets); process_ctx_payloads(s, s->pkt_descs, packets); + if (!(s->flags & CIP_NO_HEADER)) + pkt_header_length = IT_PKT_HEADER_SIZE_CIP; + else + pkt_header_length = 0; + + if (s == d->irq_target) { + // At NO_PERIOD_WAKEUP mode, the packets for all IT/IR contexts are processed by + // the tasks of user process operating ALSA PCM character device by calling ioctl(2) + // with some requests, instead of scheduled hardware IRQ of an IT context. + struct snd_pcm_substream *pcm = READ_ONCE(s->pcm); + need_hw_irq = !pcm || !pcm->runtime->no_period_wakeup; + } else { + need_hw_irq = false; + } + for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = s->pkt_descs + i; - unsigned int syt; struct { struct fw_iso_packet params; - __be32 header[IT_PKT_HEADER_SIZE_CIP / sizeof(__be32)]; + __be32 header[CIP_HEADER_QUADLETS]; } template = { {0}, {0} }; bool sched_irq = false; - if (s->ctx_data.rx.syt_override < 0) - syt = desc->syt; - else - syt = s->ctx_data.rx.syt_override; - - build_it_pkt_header(s, desc->cycle, &template.params, + build_it_pkt_header(s, desc->cycle, &template.params, pkt_header_length, desc->data_blocks, desc->data_block_counter, - syt, i); + desc->syt, i); if (s == s->domain->irq_target) { event_count += desc->data_blocks; if (event_count >= events_per_period) { event_count -= events_per_period; - sched_irq = true; + sched_irq = need_hw_irq; } } @@ -880,13 +1113,99 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp, s->ctx_data.rx.event_count = event_count; } -static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, - size_t header_length, void *header, - void *private_data) +static void skip_rx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + const __be32 *ctx_header = header; + unsigned int packets; + unsigned int cycle; + int i; + + if (s->packet_index < 0) + return; + + packets = header_length / sizeof(*ctx_header); + + cycle = compute_ohci_it_cycle(ctx_header[packets - 1], s->queue_size); + s->next_cycle = increment_ohci_cycle_count(cycle, 1); + + for (i = 0; i < packets; ++i) { + struct fw_iso_packet params = { + .header_length = 0, + .payload_length = 0, + }; + bool sched_irq = (s == d->irq_target && i == packets - 1); + + if (queue_out_packet(s, ¶ms, sched_irq) < 0) { + cancel_stream(s); + return; + } + } +} + +static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data); + +static void process_rx_packets_intermediately(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + __be32 *ctx_header = header; + const unsigned int queue_size = s->queue_size; + unsigned int packets; + unsigned int offset; + + if (s->packet_index < 0) + return; + + packets = header_length / sizeof(*ctx_header); + + offset = 0; + while (offset < packets) { + unsigned int cycle = compute_ohci_it_cycle(ctx_header[offset], queue_size); + + if (compare_ohci_cycle_count(cycle, d->processing_cycle.rx_start) >= 0) + break; + + ++offset; + } + + if (offset > 0) { + unsigned int length = sizeof(*ctx_header) * offset; + + skip_rx_packets(context, tstamp, length, ctx_header, private_data); + if (amdtp_streaming_error(s)) + return; + + ctx_header += offset; + header_length -= length; + } + + if (offset < packets) { + s->ready_processing = true; + wake_up(&s->ready_wait); + + process_rx_packets(context, tstamp, header_length, ctx_header, private_data); + if (amdtp_streaming_error(s)) + return; + + if (s == d->irq_target) + s->context->callback.sc = irq_target_callback; + else + s->context->callback.sc = process_rx_packets; + } +} + +static void process_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data) { struct amdtp_stream *s = private_data; __be32 *ctx_header = header; unsigned int packets; + unsigned int desc_count; int i; int err; @@ -896,14 +1215,20 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, // Calculate the number of packets in buffer and check XRUN. packets = header_length / s->ctx_data.tx.ctx_header_size; - err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets); + desc_count = 0; + err = generate_device_pkt_descs(s, s->pkt_descs, ctx_header, packets, &desc_count); if (err < 0) { if (err != -EAGAIN) { cancel_stream(s); return; } } else { - process_ctx_payloads(s, s->pkt_descs, packets); + struct amdtp_domain *d = s->domain; + + process_ctx_payloads(s, s->pkt_descs, desc_count); + + if (d->replay.enable) + cache_seq(s, s->pkt_descs, desc_count); } for (i = 0; i < packets; ++i) { @@ -916,79 +1241,194 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp, } } -static void pool_ideal_seq_descs(struct amdtp_domain *d, unsigned int packets) +static void drop_tx_packets(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data) { - struct amdtp_stream *irq_target = d->irq_target; - unsigned int seq_tail = d->seq_tail; - unsigned int seq_size = d->seq_size; - unsigned int min_avail; - struct amdtp_stream *s; + struct amdtp_stream *s = private_data; + const __be32 *ctx_header = header; + unsigned int packets; + unsigned int cycle; + int i; - min_avail = d->seq_size; - list_for_each_entry(s, &d->streams, list) { - unsigned int seq_index; - unsigned int avail; + if (s->packet_index < 0) + return; + + packets = header_length / s->ctx_data.tx.ctx_header_size; - if (s->direction == AMDTP_IN_STREAM) - continue; + ctx_header += (packets - 1) * s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header); + cycle = compute_ohci_cycle_count(ctx_header[1]); + s->next_cycle = increment_ohci_cycle_count(cycle, 1); - seq_index = s->ctx_data.rx.seq_index; - avail = d->seq_tail; - if (seq_index > avail) - avail += d->seq_size; - avail -= seq_index; + for (i = 0; i < packets; ++i) { + struct fw_iso_packet params = {0}; - if (avail < min_avail) - min_avail = avail; + if (queue_in_packet(s, ¶ms) < 0) { + cancel_stream(s); + return; + } } +} - while (min_avail < packets) { - struct seq_desc *desc = d->seq_descs + seq_tail; +static void process_tx_packets_intermediately(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + __be32 *ctx_header; + unsigned int packets; + unsigned int offset; - desc->syt_offset = calculate_syt_offset(&d->last_syt_offset, - &d->syt_offset_state, irq_target->sfc); - desc->data_blocks = calculate_data_blocks(&d->data_block_state, - !!(irq_target->flags & CIP_BLOCKING), - desc->syt_offset == CIP_SYT_NO_INFO, - irq_target->syt_interval, irq_target->sfc); + if (s->packet_index < 0) + return; - ++seq_tail; - seq_tail %= seq_size; + packets = header_length / s->ctx_data.tx.ctx_header_size; - ++min_avail; + offset = 0; + ctx_header = header; + while (offset < packets) { + unsigned int cycle = compute_ohci_cycle_count(ctx_header[1]); + + if (compare_ohci_cycle_count(cycle, d->processing_cycle.tx_start) >= 0) + break; + + ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); + ++offset; } - d->seq_tail = seq_tail; + ctx_header = header; + + if (offset > 0) { + size_t length = s->ctx_data.tx.ctx_header_size * offset; + + drop_tx_packets(context, tstamp, length, ctx_header, s); + if (amdtp_streaming_error(s)) + return; + + ctx_header += length / sizeof(*ctx_header); + header_length -= length; + } + + if (offset < packets) { + s->ready_processing = true; + wake_up(&s->ready_wait); + + process_tx_packets(context, tstamp, header_length, ctx_header, s); + if (amdtp_streaming_error(s)) + return; + + context->callback.sc = process_tx_packets; + } } -static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, - size_t header_length, void *header, - void *private_data) +static void drop_tx_packets_initially(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, void *private_data) { - struct amdtp_stream *irq_target = private_data; - struct amdtp_domain *d = irq_target->domain; - unsigned int packets = header_length / sizeof(__be32); - struct amdtp_stream *s; + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + __be32 *ctx_header; + unsigned int count; + unsigned int events; + int i; + + if (s->packet_index < 0) + return; + + count = header_length / s->ctx_data.tx.ctx_header_size; + + // Attempt to detect any event in the batch of packets. + events = 0; + ctx_header = header; + for (i = 0; i < count; ++i) { + unsigned int payload_quads = + (be32_to_cpu(*ctx_header) >> ISO_DATA_LENGTH_SHIFT) / sizeof(__be32); + unsigned int data_blocks; + + if (s->flags & CIP_NO_HEADER) { + data_blocks = payload_quads / s->data_block_quadlets; + } else { + __be32 *cip_headers = ctx_header + IR_CTX_HEADER_DEFAULT_QUADLETS; + + if (payload_quads < CIP_HEADER_QUADLETS) { + data_blocks = 0; + } else { + payload_quads -= CIP_HEADER_QUADLETS; + + if (s->flags & CIP_UNAWARE_SYT) { + data_blocks = payload_quads / s->data_block_quadlets; + } else { + u32 cip1 = be32_to_cpu(cip_headers[1]); + + // NODATA packet can includes any data blocks but they are + // not available as event. + if ((cip1 & CIP_NO_DATA) == CIP_NO_DATA) + data_blocks = 0; + else + data_blocks = payload_quads / s->data_block_quadlets; + } + } + } - // Record enough entries with extra 3 cycles at least. - pool_ideal_seq_descs(d, packets + 3); + events += data_blocks; - out_stream_callback(context, tstamp, header_length, header, irq_target); - if (amdtp_streaming_error(irq_target)) - goto error; + ctx_header += s->ctx_data.tx.ctx_header_size / sizeof(__be32); + } + + drop_tx_packets(context, tstamp, header_length, header, s); + + if (events > 0) + s->ctx_data.tx.event_starts = true; + + // Decide the cycle count to begin processing content of packet in IR contexts. + { + unsigned int stream_count = 0; + unsigned int event_starts_count = 0; + unsigned int cycle = UINT_MAX; + + list_for_each_entry(s, &d->streams, list) { + if (s->direction == AMDTP_IN_STREAM) { + ++stream_count; + if (s->ctx_data.tx.event_starts) + ++event_starts_count; + } + } + + if (stream_count == event_starts_count) { + unsigned int next_cycle; + + list_for_each_entry(s, &d->streams, list) { + if (s->direction != AMDTP_IN_STREAM) + continue; + + next_cycle = increment_ohci_cycle_count(s->next_cycle, + d->processing_cycle.tx_init_skip); + if (cycle == UINT_MAX || + compare_ohci_cycle_count(next_cycle, cycle) > 0) + cycle = next_cycle; + + s->context->callback.sc = process_tx_packets_intermediately; + } + + d->processing_cycle.tx_start = cycle; + } + } +} + +static void process_ctxs_in_domain(struct amdtp_domain *d) +{ + struct amdtp_stream *s; list_for_each_entry(s, &d->streams, list) { - if (s != irq_target && amdtp_stream_running(s)) { + if (s != d->irq_target && amdtp_stream_running(s)) fw_iso_context_flush_completions(s->context); - if (amdtp_streaming_error(s)) - goto error; - } + + if (amdtp_streaming_error(s)) + goto error; } return; error: - if (amdtp_stream_running(irq_target)) - cancel_stream(irq_target); + if (amdtp_stream_running(d->irq_target)) + cancel_stream(d->irq_target); list_for_each_entry(s, &d->streams, list) { if (amdtp_stream_running(s)) @@ -996,37 +1436,99 @@ error: } } -// this is executed one time. +static void irq_target_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, + void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + + process_rx_packets(context, tstamp, header_length, header, private_data); + process_ctxs_in_domain(d); +} + +static void irq_target_callback_intermediately(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + + process_rx_packets_intermediately(context, tstamp, header_length, header, private_data); + process_ctxs_in_domain(d); +} + +static void irq_target_callback_skip(struct fw_iso_context *context, u32 tstamp, + size_t header_length, void *header, void *private_data) +{ + struct amdtp_stream *s = private_data; + struct amdtp_domain *d = s->domain; + bool ready_to_start; + + skip_rx_packets(context, tstamp, header_length, header, private_data); + process_ctxs_in_domain(d); + + if (d->replay.enable && !d->replay.on_the_fly) { + unsigned int rx_count = 0; + unsigned int rx_ready_count = 0; + struct amdtp_stream *rx; + + list_for_each_entry(rx, &d->streams, list) { + struct amdtp_stream *tx; + unsigned int cached_cycles; + + if (rx->direction != AMDTP_OUT_STREAM) + continue; + ++rx_count; + + tx = rx->ctx_data.rx.replay_target; + cached_cycles = calculate_cached_cycle_count(tx, 0); + if (cached_cycles > tx->ctx_data.tx.cache.size / 2) + ++rx_ready_count; + } + + ready_to_start = (rx_count == rx_ready_count); + } else { + ready_to_start = true; + } + + // Decide the cycle count to begin processing content of packet in IT contexts. All of IT + // contexts are expected to start and get callback when reaching here. + if (ready_to_start) { + unsigned int cycle = s->next_cycle; + list_for_each_entry(s, &d->streams, list) { + if (s->direction != AMDTP_OUT_STREAM) + continue; + + if (compare_ohci_cycle_count(s->next_cycle, cycle) > 0) + cycle = s->next_cycle; + + if (s == d->irq_target) + s->context->callback.sc = irq_target_callback_intermediately; + else + s->context->callback.sc = process_rx_packets_intermediately; + } + + d->processing_cycle.rx_start = cycle; + } +} + +// This is executed one time. For in-stream, first packet has come. For out-stream, prepared to +// transmit first packet. static void amdtp_stream_first_callback(struct fw_iso_context *context, u32 tstamp, size_t header_length, void *header, void *private_data) { struct amdtp_stream *s = private_data; - const __be32 *ctx_header = header; - u32 cycle; - - /* - * For in-stream, first packet has come. - * For out-stream, prepared to transmit first packet - */ - s->callbacked = true; - wake_up(&s->callback_wait); + struct amdtp_domain *d = s->domain; if (s->direction == AMDTP_IN_STREAM) { - cycle = compute_cycle_count(ctx_header[1]); - - context->callback.sc = in_stream_callback; + context->callback.sc = drop_tx_packets_initially; } else { - cycle = compute_it_cycle(*ctx_header, s->queue_size); - - if (s == s->domain->irq_target) - context->callback.sc = irq_target_callback; + if (s == d->irq_target) + context->callback.sc = irq_target_callback_skip; else - context->callback.sc = out_stream_callback; + context->callback.sc = skip_rx_packets; } - s->start_cycle = cycle; - context->callback.sc(context, tstamp, header_length, header, s); } @@ -1035,8 +1537,6 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, * @s: the AMDTP stream to start * @channel: the isochronous channel on the bus * @speed: firewire speed code - * @start_cycle: the isochronous cycle to start the context. Start immediately - * if negative value is given. * @queue_size: The number of packets in the queue. * @idle_irq_interval: the interval to queue packet during initial state. * @@ -1045,8 +1545,7 @@ static void amdtp_stream_first_callback(struct fw_iso_context *context, * device can be started. */ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, - int start_cycle, unsigned int queue_size, - unsigned int idle_irq_interval) + unsigned int queue_size, unsigned int idle_irq_interval) { bool is_irq_target = (s == s->domain->irq_target); unsigned int ctx_header_size; @@ -1075,27 +1574,21 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, } // initialize packet buffer. - max_ctx_payload_size = amdtp_stream_get_max_payload(s); if (s->direction == AMDTP_IN_STREAM) { dir = DMA_FROM_DEVICE; type = FW_ISO_CONTEXT_RECEIVE; - if (!(s->flags & CIP_NO_HEADER)) { - max_ctx_payload_size -= 8; + if (!(s->flags & CIP_NO_HEADER)) ctx_header_size = IR_CTX_HEADER_SIZE_CIP; - } else { + else ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP; - } } else { dir = DMA_TO_DEVICE; type = FW_ISO_CONTEXT_TRANSMIT; ctx_header_size = 0; // No effect for IT context. - - if (!(s->flags & CIP_NO_HEADER)) - max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP; } + max_ctx_payload_size = amdtp_stream_get_max_ctx_payload_size(s); - err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, - max_ctx_payload_size, dir); + err = iso_packets_buffer_init(&s->buffer, s->unit, queue_size, max_ctx_payload_size, dir); if (err < 0) goto err_unlock; s->queue_size = queue_size; @@ -1116,6 +1609,50 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, if (s->direction == AMDTP_IN_STREAM) { s->ctx_data.tx.max_ctx_payload_length = max_ctx_payload_size; s->ctx_data.tx.ctx_header_size = ctx_header_size; + s->ctx_data.tx.event_starts = false; + + if (s->domain->replay.enable) { + // struct fw_iso_context.drop_overflow_headers is false therefore it's + // possible to cache much unexpectedly. + s->ctx_data.tx.cache.size = max_t(unsigned int, s->syt_interval * 2, + queue_size * 3 / 2); + s->ctx_data.tx.cache.tail = 0; + s->ctx_data.tx.cache.descs = kcalloc(s->ctx_data.tx.cache.size, + sizeof(*s->ctx_data.tx.cache.descs), GFP_KERNEL); + if (!s->ctx_data.tx.cache.descs) { + err = -ENOMEM; + goto err_context; + } + } + } else { + static const struct { + unsigned int data_block; + unsigned int syt_offset; + } *entry, initial_state[] = { + [CIP_SFC_32000] = { 4, 3072 }, + [CIP_SFC_48000] = { 6, 1024 }, + [CIP_SFC_96000] = { 12, 1024 }, + [CIP_SFC_192000] = { 24, 1024 }, + [CIP_SFC_44100] = { 0, 67 }, + [CIP_SFC_88200] = { 0, 67 }, + [CIP_SFC_176400] = { 0, 67 }, + }; + + s->ctx_data.rx.seq.descs = kcalloc(queue_size, sizeof(*s->ctx_data.rx.seq.descs), GFP_KERNEL); + if (!s->ctx_data.rx.seq.descs) { + err = -ENOMEM; + goto err_context; + } + s->ctx_data.rx.seq.size = queue_size; + s->ctx_data.rx.seq.tail = 0; + s->ctx_data.rx.seq.head = 0; + + entry = &initial_state[s->sfc]; + s->ctx_data.rx.data_block_state = entry->data_block; + s->ctx_data.rx.syt_offset_state = entry->syt_offset; + s->ctx_data.rx.last_syt_offset = TICKS_PER_CYCLE; + + s->ctx_data.rx.event_count = 0; } if (s->flags & CIP_NO_HEADER) @@ -1158,8 +1695,8 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, if ((s->flags & CIP_EMPTY_WITH_TAG0) || (s->flags & CIP_NO_HEADER)) tag |= FW_ISO_CONTEXT_MATCH_TAG0; - s->callbacked = false; - err = fw_iso_context_start(s->context, start_cycle, 0, tag); + s->ready_processing = false; + err = fw_iso_context_start(s->context, -1, 0, tag); if (err < 0) goto err_pkt_descs; @@ -1169,6 +1706,12 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed, err_pkt_descs: kfree(s->pkt_descs); err_context: + if (s->direction == AMDTP_OUT_STREAM) { + kfree(s->ctx_data.rx.seq.descs); + } else { + if (s->domain->replay.enable) + kfree(s->ctx_data.tx.cache.descs); + } fw_iso_context_destroy(s->context); s->context = ERR_PTR(-1); err_buffer: @@ -1191,28 +1734,12 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, { struct amdtp_stream *irq_target = d->irq_target; + // Process isochronous packets queued till recent isochronous cycle to handle PCM frames. if (irq_target && amdtp_stream_running(irq_target)) { - // This function is called in software IRQ context of - // period_work or process context. - // - // When the software IRQ context was scheduled by software IRQ - // context of IT contexts, queued packets were already handled. - // Therefore, no need to flush the queue in buffer furthermore. - // - // When the process context reach here, some packets will be - // already queued in the buffer. These packets should be handled - // immediately to keep better granularity of PCM pointer. - // - // Later, the process context will sometimes schedules software - // IRQ context of the period_work. Then, no need to flush the - // queue by the same reason as described in the above - if (current_work() != &s->period_work) { - // Queued packet should be processed without any kernel - // preemption to keep latency against bus cycle. - preempt_disable(); + // In software IRQ context, the call causes dead-lock to disable the tasklet + // synchronously. + if (!in_softirq()) fw_iso_context_flush_completions(irq_target->context); - preempt_enable(); - } } return READ_ONCE(s->pcm_buffer_pointer); @@ -1232,13 +1759,8 @@ int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s) // Process isochronous packets for recent isochronous cycle to handle // queued PCM frames. - if (irq_target && amdtp_stream_running(irq_target)) { - // Queued packet should be processed without any kernel - // preemption to keep latency against bus cycle. - preempt_disable(); + if (irq_target && amdtp_stream_running(irq_target)) fw_iso_context_flush_completions(irq_target->context); - preempt_enable(); - } return 0; } @@ -1272,14 +1794,18 @@ static void amdtp_stream_stop(struct amdtp_stream *s) return; } - cancel_work_sync(&s->period_work); fw_iso_context_stop(s->context); fw_iso_context_destroy(s->context); s->context = ERR_PTR(-1); iso_packets_buffer_destroy(&s->buffer, s->unit); kfree(s->pkt_descs); - s->callbacked = false; + if (s->direction == AMDTP_OUT_STREAM) { + kfree(s->ctx_data.rx.seq.descs); + } else { + if (s->domain->replay.enable) + kfree(s->ctx_data.tx.cache.descs); + } mutex_unlock(&s->mutex); } @@ -1311,8 +1837,6 @@ int amdtp_domain_init(struct amdtp_domain *d) d->events_per_period = 0; - d->seq_descs = NULL; - return 0; } EXPORT_SYMBOL_GPL(amdtp_domain_init); @@ -1355,26 +1879,49 @@ int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, } EXPORT_SYMBOL_GPL(amdtp_domain_add_stream); -static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle) +// Make the reference from rx stream to tx stream for sequence replay. When the number of tx streams +// is less than the number of rx streams, the first tx stream is selected. +static int make_association(struct amdtp_domain *d) { - int generation; - int rcode; - __be32 reg; - u32 data; - - // This is a request to local 1394 OHCI controller and expected to - // complete without any event waiting. - generation = fw_card->generation; - smp_rmb(); // node_id vs. generation. - rcode = fw_run_transaction(fw_card, TCODE_READ_QUADLET_REQUEST, - fw_card->node_id, generation, SCODE_100, - CSR_REGISTER_BASE + CSR_CYCLE_TIME, - ®, sizeof(reg)); - if (rcode != RCODE_COMPLETE) - return -EIO; + unsigned int dst_index = 0; + struct amdtp_stream *rx; + + // Make association to replay target. + list_for_each_entry(rx, &d->streams, list) { + if (rx->direction == AMDTP_OUT_STREAM) { + unsigned int src_index = 0; + struct amdtp_stream *tx = NULL; + struct amdtp_stream *s; + + list_for_each_entry(s, &d->streams, list) { + if (s->direction == AMDTP_IN_STREAM) { + if (dst_index == src_index) { + tx = s; + break; + } + + ++src_index; + } + } + if (!tx) { + // Select the first entry. + list_for_each_entry(s, &d->streams, list) { + if (s->direction == AMDTP_IN_STREAM) { + tx = s; + break; + } + } + // No target is available to replay sequence. + if (!tx) + return -EINVAL; + } - data = be32_to_cpu(reg); - *cur_cycle = data >> 12; + rx->ctx_data.rx.replay_target = tx; + rx->ctx_data.rx.cache_head = 0; + + ++dst_index; + } + } return 0; } @@ -1382,39 +1929,44 @@ static int get_current_cycle_time(struct fw_card *fw_card, int *cur_cycle) /** * amdtp_domain_start - start sending packets for isoc context in the domain. * @d: the AMDTP domain. - * @ir_delay_cycle: the cycle delay to start all IR contexts. + * @tx_init_skip_cycles: the number of cycles to skip processing packets at initial stage of IR + * contexts. + * @replay_seq: whether to replay the sequence of packet in IR context for the sequence of packet in + * IT context. + * @replay_on_the_fly: transfer rx packets according to nominal frequency, then begin to replay + * according to arrival of events in tx packets. */ -int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) +int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq, + bool replay_on_the_fly) { - static const struct { - unsigned int data_block; - unsigned int syt_offset; - } *entry, initial_state[] = { - [CIP_SFC_32000] = { 4, 3072 }, - [CIP_SFC_48000] = { 6, 1024 }, - [CIP_SFC_96000] = { 12, 1024 }, - [CIP_SFC_192000] = { 24, 1024 }, - [CIP_SFC_44100] = { 0, 67 }, - [CIP_SFC_88200] = { 0, 67 }, - [CIP_SFC_176400] = { 0, 67 }, - }; unsigned int events_per_buffer = d->events_per_buffer; unsigned int events_per_period = d->events_per_period; - unsigned int idle_irq_interval; unsigned int queue_size; struct amdtp_stream *s; - int cycle; + bool found = false; int err; + if (replay_seq) { + err = make_association(d); + if (err < 0) + return err; + } + d->replay.enable = replay_seq; + d->replay.on_the_fly = replay_on_the_fly; + // Select an IT context as IRQ target. list_for_each_entry(s, &d->streams, list) { - if (s->direction == AMDTP_OUT_STREAM) + if (s->direction == AMDTP_OUT_STREAM) { + found = true; break; + } } - if (!s) + if (!found) return -ENXIO; d->irq_target = s; + d->processing_cycle.tx_init_skip = tx_init_skip_cycles; + // This is a case that AMDTP streams in domain run just for MIDI // substream. Use the number of events equivalent to 10 msec as // interval of hardware IRQ. @@ -1426,82 +1978,24 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) queue_size = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_buffer, amdtp_rate_table[d->irq_target->sfc]); - d->seq_descs = kcalloc(queue_size, sizeof(*d->seq_descs), GFP_KERNEL); - if (!d->seq_descs) - return -ENOMEM; - d->seq_size = queue_size; - d->seq_tail = 0; - - entry = &initial_state[s->sfc]; - d->data_block_state = entry->data_block; - d->syt_offset_state = entry->syt_offset; - d->last_syt_offset = TICKS_PER_CYCLE; - - if (ir_delay_cycle > 0) { - struct fw_card *fw_card = fw_parent_device(s->unit)->card; - - err = get_current_cycle_time(fw_card, &cycle); - if (err < 0) - goto error; - - // No need to care overflow in cycle field because of enough - // width. - cycle += ir_delay_cycle; - - // Round up to sec field. - if ((cycle & 0x00001fff) >= CYCLES_PER_SECOND) { - unsigned int sec; - - // The sec field can overflow. - sec = (cycle & 0xffffe000) >> 13; - cycle = (++sec << 13) | - ((cycle & 0x00001fff) / CYCLES_PER_SECOND); - } - - // In OHCI 1394 specification, lower 2 bits are available for - // sec field. - cycle &= 0x00007fff; - } else { - cycle = -1; - } - list_for_each_entry(s, &d->streams, list) { - int cycle_match; + unsigned int idle_irq_interval = 0; - if (s->direction == AMDTP_IN_STREAM) { - cycle_match = cycle; - } else { - // IT context starts immediately. - cycle_match = -1; - s->ctx_data.rx.seq_index = 0; + if (s->direction == AMDTP_OUT_STREAM && s == d->irq_target) { + idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, + amdtp_rate_table[d->irq_target->sfc]); } - if (s != d->irq_target) { - err = amdtp_stream_start(s, s->channel, s->speed, - cycle_match, queue_size, 0); - if (err < 0) - goto error; - } + // Starts immediately but actually DMA context starts several hundred cycles later. + err = amdtp_stream_start(s, s->channel, s->speed, queue_size, idle_irq_interval); + if (err < 0) + goto error; } - s = d->irq_target; - s->ctx_data.rx.events_per_period = events_per_period; - s->ctx_data.rx.event_count = 0; - s->ctx_data.rx.seq_index = 0; - - idle_irq_interval = DIV_ROUND_UP(CYCLES_PER_SECOND * events_per_period, - amdtp_rate_table[d->irq_target->sfc]); - err = amdtp_stream_start(s, s->channel, s->speed, -1, queue_size, - idle_irq_interval); - if (err < 0) - goto error; - return 0; error: list_for_each_entry(s, &d->streams, list) amdtp_stream_stop(s); - kfree(d->seq_descs); - d->seq_descs = NULL; return err; } EXPORT_SYMBOL_GPL(amdtp_domain_start); @@ -1526,8 +2020,5 @@ void amdtp_domain_stop(struct amdtp_domain *d) d->events_per_period = 0; d->irq_target = NULL; - - kfree(d->seq_descs); - d->seq_descs = NULL; } EXPORT_SYMBOL_GPL(amdtp_domain_stop); diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index a3daa1f2c1c4..1f957c946c95 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -35,6 +35,8 @@ * @CIP_NO_HEADERS: a lack of headers in packets * @CIP_UNALIGHED_DBC: Only for in-stream. The value of dbc is not alighed to * the value of current SYT_INTERVAL; e.g. initial value is not zero. + * @CIP_UNAWARE_SYT: For outgoing packet, the value in SYT field of CIP is 0xffff. + * For incoming packet, the value in SYT field of CIP is not handled. */ enum cip_flags { CIP_NONBLOCKING = 0x00, @@ -48,6 +50,7 @@ enum cip_flags { CIP_HEADER_WITHOUT_EOH = 0x80, CIP_NO_HEADER = 0x100, CIP_UNALIGHED_DBC = 0x200, + CIP_UNAWARE_SYT = 0x400, }; /** @@ -112,7 +115,8 @@ typedef unsigned int (*amdtp_stream_process_ctx_payloads_t)( struct amdtp_domain; struct amdtp_stream { struct fw_unit *unit; - enum cip_flags flags; + // The combination of cip_flags enumeration-constants. + unsigned int flags; enum amdtp_stream_direction direction; struct mutex mutex; @@ -134,19 +138,37 @@ struct amdtp_stream { // Fixed interval of dbc between previos/current // packets. unsigned int dbc_interval; + + // The device starts multiplexing events to the packet. + bool event_starts; + + struct { + struct seq_desc *descs; + unsigned int size; + unsigned int tail; + } cache; } tx; struct { - // To calculate CIP data blocks and tstamp. - unsigned int transfer_delay; - unsigned int seq_index; - // To generate CIP header. unsigned int fdf; - int syt_override; // To generate constant hardware IRQ. unsigned int event_count; - unsigned int events_per_period; + + // To calculate CIP data blocks and tstamp. + struct { + struct seq_desc *descs; + unsigned int size; + unsigned int tail; + unsigned int head; + } seq; + + unsigned int data_block_state; + unsigned int syt_offset_state; + unsigned int last_syt_offset; + + struct amdtp_stream *replay_target; + unsigned int cache_head; } rx; } ctx_data; @@ -157,20 +179,21 @@ struct amdtp_stream { unsigned int sph; unsigned int fmt; - /* Internal flags. */ + // Internal flags. + unsigned int transfer_delay; enum cip_sfc sfc; unsigned int syt_interval; /* For a PCM substream processing. */ struct snd_pcm_substream *pcm; - struct work_struct period_work; snd_pcm_uframes_t pcm_buffer_pointer; unsigned int pcm_period_pointer; - /* To wait for first packet. */ - bool callbacked; - wait_queue_head_t callback_wait; - u32 start_cycle; + // To start processing content of packets at the same cycle in several contexts for + // each direction. + bool ready_processing; + wait_queue_head_t ready_wait; + unsigned int next_cycle; /* For backends to process data blocks. */ void *protocol; @@ -184,7 +207,7 @@ struct amdtp_stream { }; int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit, - enum amdtp_stream_direction dir, enum cip_flags flags, + enum amdtp_stream_direction dir, unsigned int flags, unsigned int fmt, amdtp_stream_process_ctx_payloads_t process_ctx_payloads, unsigned int protocol_size); @@ -259,21 +282,6 @@ static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) return sfc & 1; } -/** - * amdtp_stream_wait_callback - sleep till callbacked or timeout - * @s: the AMDTP stream - * @timeout: msec till timeout - * - * If this function return false, the AMDTP stream should be stopped. - */ -static inline bool amdtp_stream_wait_callback(struct amdtp_stream *s, - unsigned int timeout) -{ - return wait_event_timeout(s->callback_wait, - s->callbacked, - msecs_to_jiffies(timeout)) > 0; -} - struct seq_desc { unsigned int syt_offset; unsigned int data_blocks; @@ -287,13 +295,16 @@ struct amdtp_domain { struct amdtp_stream *irq_target; - struct seq_desc *seq_descs; - unsigned int seq_size; - unsigned int seq_tail; + struct { + unsigned int tx_init_skip; + unsigned int tx_start; + unsigned int rx_start; + } processing_cycle; - unsigned int data_block_state; - unsigned int syt_offset_state; - unsigned int last_syt_offset; + struct { + bool enable:1; + bool on_the_fly:1; + } replay; }; int amdtp_domain_init(struct amdtp_domain *d); @@ -302,7 +313,8 @@ void amdtp_domain_destroy(struct amdtp_domain *d); int amdtp_domain_add_stream(struct amdtp_domain *d, struct amdtp_stream *s, int channel, int speed); -int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle); +int amdtp_domain_start(struct amdtp_domain *d, unsigned int tx_init_skip_cycles, bool replay_seq, + bool replay_on_the_fly); void amdtp_domain_stop(struct amdtp_domain *d); static inline int amdtp_domain_set_events_per_period(struct amdtp_domain *d, @@ -319,4 +331,25 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d, struct amdtp_stream *s); int amdtp_domain_stream_pcm_ack(struct amdtp_domain *d, struct amdtp_stream *s); +/** + * amdtp_domain_wait_ready - sleep till being ready to process packets or timeout + * @d: the AMDTP domain + * @timeout_ms: msec till timeout + * + * If this function return false, the AMDTP domain should be stopped. + */ +static inline bool amdtp_domain_wait_ready(struct amdtp_domain *d, unsigned int timeout_ms) +{ + struct amdtp_stream *s; + + list_for_each_entry(s, &d->streams, list) { + unsigned int j = msecs_to_jiffies(timeout_ms); + + if (wait_event_interruptible_timeout(s->ready_wait, s->ready_processing, j) <= 0) + return false; + } + + return true; +} + #endif diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index daeecfa8b9aa..06a7ced218e2 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -40,14 +40,12 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_EDIROL 0x000040ab #define VEN_PRESONUS 0x00000a92 #define VEN_BRIDGECO 0x000007f5 -#define VEN_MACKIE1 0x0000000f -#define VEN_MACKIE2 0x00000ff2 +#define VEN_MACKIE 0x00000ff2 #define VEN_STANTON 0x00001260 #define VEN_TASCAM 0x0000022e #define VEN_BEHRINGER 0x00001564 #define VEN_APOGEE 0x000003db #define VEN_ESI 0x00000f1b -#define VEN_ACOUSTIC 0x00000002 #define VEN_CME 0x0000000a #define VEN_PHONIC 0x00001496 #define VEN_LYNX 0x000019e5 @@ -56,14 +54,15 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_TERRATEC 0x00000aac #define VEN_YAMAHA 0x0000a0de #define VEN_FOCUSRITE 0x0000130e -#define VEN_MAUDIO1 0x00000d6c -#define VEN_MAUDIO2 0x000007f5 +#define VEN_MAUDIO 0x00000d6c #define VEN_DIGIDESIGN 0x00a07e +#define OUI_SHOUYO 0x002327 #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 #define MODEL_MAUDIO_FW1814 0x00010071 #define MODEL_MAUDIO_PROJECTMIX 0x00010091 +#define MODEL_MAUDIO_PROFIRELIGHTBRIDGE 0x000100a1 static int name_device(struct snd_bebob *bebob) @@ -74,7 +73,6 @@ name_device(struct snd_bebob *bebob) u32 hw_id; u32 data[2] = {0}; u32 revision; - u32 version; int err; /* get vendor name from root directory */ @@ -107,12 +105,6 @@ name_device(struct snd_bebob *bebob) if (err < 0) goto end; - err = snd_bebob_read_quad(bebob->unit, INFO_OFFSET_BEBOB_VERSION, - &version); - if (err < 0) - goto end; - bebob->version = version; - strcpy(bebob->card->driver, "BeBoB"); strcpy(bebob->card->shortname, model); strcpy(bebob->card->mixername, model); @@ -135,6 +127,9 @@ bebob_card_free(struct snd_card *card) mutex_unlock(&devices_mutex); snd_bebob_stream_destroy_duplex(bebob); + + mutex_destroy(&bebob->mutex); + fw_unit_put(bebob->unit); } static const struct snd_bebob_spec * @@ -162,16 +157,55 @@ check_audiophile_booted(struct fw_unit *unit) return strncmp(name, "FW Audiophile Bootloader", 24) != 0; } -static void -do_registration(struct work_struct *work) +static int detect_quirks(struct snd_bebob *bebob, const struct ieee1394_device_id *entry) +{ + if (entry->vendor_id == VEN_MAUDIO) { + switch (entry->model_id) { + case MODEL_MAUDIO_PROFIRELIGHTBRIDGE: + // M-Audio ProFire Lightbridge has a quirk to transfer packets with + // discontinuous cycle or data block counter in early stage of packet + // streaming. The cycle span from the first packet with event is variable. + bebob->quirks |= SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC; + break; + case MODEL_MAUDIO_FW1814: + case MODEL_MAUDIO_PROJECTMIX: + // At high sampling rate, M-Audio special firmware transmits empty packet + // with the value of dbc incremented by 8. + bebob->quirks |= SND_BEBOB_QUIRK_WRONG_DBC; + break; + default: + break; + } + } + + return 0; +} + +static int bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_bebob *bebob = - container_of(work, struct snd_bebob, dwork.work); unsigned int card_index; + struct snd_card *card; + struct snd_bebob *bebob; + const struct snd_bebob_spec *spec; int err; - if (bebob->registered) - return; + if (entry->vendor_id == VEN_FOCUSRITE && + entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH) + spec = get_saffire_spec(unit); + else if (entry->vendor_id == VEN_MAUDIO && + entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH && + !check_audiophile_booted(unit)) + spec = NULL; + else + spec = (const struct snd_bebob_spec *)entry->driver_data; + + if (spec == NULL) { + // To boot up M-Audio models. + if (entry->vendor_id == VEN_MAUDIO || entry->vendor_id == VEN_BRIDGECO) + return snd_bebob_maudio_load_firmware(unit); + else + return -ENODEV; + } mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; card_index++) { @@ -180,27 +214,40 @@ do_registration(struct work_struct *work) } if (card_index >= SNDRV_CARDS) { mutex_unlock(&devices_mutex); - return; + return -ENOENT; } - err = snd_card_new(&bebob->unit->device, index[card_index], - id[card_index], THIS_MODULE, 0, &bebob->card); + err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, + sizeof(*bebob), &card); if (err < 0) { mutex_unlock(&devices_mutex); - return; + return err; } + card->private_free = bebob_card_free; set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); - bebob->card->private_free = bebob_card_free; - bebob->card->private_data = bebob; + bebob = card->private_data; + bebob->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, bebob); + bebob->card = card; + bebob->card_index = card_index; + + bebob->spec = spec; + mutex_init(&bebob->mutex); + spin_lock_init(&bebob->lock); + init_waitqueue_head(&bebob->hwdep_wait); err = name_device(bebob); if (err < 0) goto error; + err = detect_quirks(bebob, entry); + if (err < 0) + goto error; + if (bebob->spec == &maudio_special_spec) { - if (bebob->entry->model_id == MODEL_MAUDIO_FW1814) + if (entry->model_id == MODEL_MAUDIO_FW1814) err = snd_bebob_maudio_special_discover(bebob, true); else err = snd_bebob_maudio_special_discover(bebob, false); @@ -230,80 +277,26 @@ do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(bebob->card); + err = snd_card_register(card); if (err < 0) goto error; - bebob->registered = true; - - return; -error: - snd_card_free(bebob->card); - dev_info(&bebob->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int -bebob_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) -{ - struct snd_bebob *bebob; - const struct snd_bebob_spec *spec; - - if (entry->vendor_id == VEN_FOCUSRITE && - entry->model_id == MODEL_FOCUSRITE_SAFFIRE_BOTH) - spec = get_saffire_spec(unit); - else if (entry->vendor_id == VEN_MAUDIO1 && - entry->model_id == MODEL_MAUDIO_AUDIOPHILE_BOTH && - !check_audiophile_booted(unit)) - spec = NULL; - else - spec = (const struct snd_bebob_spec *)entry->driver_data; - - if (spec == NULL) { - if (entry->vendor_id == VEN_MAUDIO1 || - entry->vendor_id == VEN_MAUDIO2) - return snd_bebob_maudio_load_firmware(unit); - else - return -ENODEV; - } - - /* Allocate this independent of sound card instance. */ - bebob = devm_kzalloc(&unit->device, sizeof(struct snd_bebob), - GFP_KERNEL); - if (!bebob) - return -ENOMEM; - bebob->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, bebob); - - bebob->entry = entry; - bebob->spec = spec; - mutex_init(&bebob->mutex); - spin_lock_init(&bebob->lock); - init_waitqueue_head(&bebob->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&bebob->dwork, do_registration); - - if (entry->vendor_id != VEN_MAUDIO1 || - (entry->model_id != MODEL_MAUDIO_FW1814 && - entry->model_id != MODEL_MAUDIO_PROJECTMIX)) { - snd_fw_schedule_registration(unit, &bebob->dwork); - } else { - /* - * This is a workaround. This bus reset seems to have an effect - * to make devices correctly handling transactions. Without - * this, the devices have gap_count mismatch. This causes much - * failure of transaction. - * - * Just after registration, user-land application receive - * signals from dbus and starts I/Os. To avoid I/Os till the - * future bus reset, registration is done in next update(). - */ - fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, - false, true); + if (entry->vendor_id == VEN_MAUDIO && + (entry->model_id == MODEL_MAUDIO_FW1814 || entry->model_id == MODEL_MAUDIO_PROJECTMIX)) { + // This is a workaround. This bus reset seems to have an effect to make devices + // correctly handling transactions. Without this, the devices have gap_count + // mismatch. This causes much failure of transaction. + // + // Just after registration, user-land application receive signals from dbus and + // starts I/Os. To avoid I/Os till the future bus reset, registration is done in + // next update(). + fw_schedule_bus_reset(fw_parent_device(bebob->unit)->card, false, true); } return 0; +error: + snd_card_free(card); + return err; } /* @@ -330,11 +323,7 @@ bebob_update(struct fw_unit *unit) if (bebob == NULL) return; - /* Postpone a workqueue for deferred registration. */ - if (!bebob->registered) - snd_fw_schedule_registration(unit, &bebob->dwork); - else - fcp_bus_reset(bebob->unit); + fcp_bus_reset(bebob->unit); } static void bebob_remove(struct fw_unit *unit) @@ -344,20 +333,8 @@ static void bebob_remove(struct fw_unit *unit) if (bebob == NULL) return; - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&bebob->dwork); - - if (bebob->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(bebob->card); - } - - mutex_destroy(&bebob->mutex); - fw_unit_put(bebob->unit); + // Block till all of ALSA character devices are released. + snd_card_free(bebob->card); } static const struct snd_bebob_rate_spec normal_rate_spec = { @@ -370,6 +347,22 @@ static const struct snd_bebob_spec spec_normal = { .meter = NULL }; +#define SPECIFIER_1394TA 0x00a02d + +// The immediate entry for version in unit directory differs depending on models: +// * 0x010001 +// * 0x014001 +#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ +{ \ + .match_flags = IEEE1394_MATCH_VENDOR_ID | \ + IEEE1394_MATCH_MODEL_ID | \ + IEEE1394_MATCH_SPECIFIER_ID, \ + .vendor_id = vendor, \ + .model_id = model, \ + .specifier_id = SPECIFIER_1394TA, \ + .driver_data = (kernel_ulong_t)data \ +} + static const struct ieee1394_device_id bebob_id_table[] = { /* Edirol, FA-66 */ SND_BEBOB_DEV_ENTRY(VEN_EDIROL, 0x00010049, &spec_normal), @@ -386,9 +379,9 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* BridgeCo, Audio5 */ SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ - SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal), - // Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in). - SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal), + SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010065, &spec_normal), + // Mackie, d.2 (optional Firewire card with DM1000). + SND_BEBOB_DEV_ENTRY(VEN_MACKIE, 0x00010067, &spec_normal), /* Stanton, ScratchAmp */ SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), /* Tascam, IF-FW DM */ @@ -410,17 +403,18 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_APOGEE, 0x01eeee, &spec_normal), /* ESI, Quatafire610 */ SND_BEBOB_DEV_ENTRY(VEN_ESI, 0x00010064, &spec_normal), - /* AcousticReality, eARMasterOne */ - SND_BEBOB_DEV_ENTRY(VEN_ACOUSTIC, 0x00000002, &spec_normal), /* CME, MatrixKFW */ SND_BEBOB_DEV_ENTRY(VEN_CME, 0x00030000, &spec_normal), - /* Phonic, Helix Board 12 MkII */ + // Phonic Helix Board 12 FireWire MkII. SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00050000, &spec_normal), - /* Phonic, Helix Board 18 MkII */ + // Phonic Helix Board 18 FireWire MkII. SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00060000, &spec_normal), - /* Phonic, Helix Board 24 MkII */ + // Phonic Helix Board 24 FireWire MkII. SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00070000, &spec_normal), - /* Phonic, Helix Board 12 Universal/18 Universal/24 Universal */ + // Phonic FireFly 808 FireWire. + SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00080000, &spec_normal), + // Phonic FireFly 202, 302, 808 Universal. + // Phinic Helix Board 12/18/24 FireWire, 12/18/24 Universal SND_BEBOB_DEV_ENTRY(VEN_PHONIC, 0x00000000, &spec_normal), /* Lynx, Aurora 8/16 (LT-FW) */ SND_BEBOB_DEV_ENTRY(VEN_LYNX, 0x00000001, &spec_normal), @@ -438,7 +432,8 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &yamaha_terratec_spec), /* TerraTec Electronic GmbH, EWS MIC2/MIC8 */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000005, &spec_normal), - /* Terratec Electronic GmbH, Aureon 7.1 Firewire */ + // Terratec Electronic GmbH, Aureon 7.1 Firewire. + // AcousticReality, eAR Master One, Eroica, Figaro, and Ciaccona. Perhaps Terratec OEM. SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal), /* Yamaha, GO44 */ SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_terratec_spec), @@ -447,45 +442,35 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* Focusrite, SaffirePro 26 I/O */ SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec), /* Focusrite, SaffirePro 10 I/O */ - { - // The combination of vendor_id and model_id is the same as the - // same as the one of Liquid Saffire 56. - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID | - IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .vendor_id = VEN_FOCUSRITE, - .model_id = 0x000006, - .specifier_id = 0x00a02d, - .version = 0x010001, - .driver_data = (kernel_ulong_t)&saffirepro_10_spec, - }, + SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x000006, &saffirepro_10_spec), /* Focusrite, Saffire(no label and LE) */ SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, MODEL_FOCUSRITE_SAFFIRE_BOTH, &saffire_spec), - /* M-Audio, Firewire 410 */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010058, NULL), /* bootloader */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO2, 0x00010046, &maudio_fw410_spec), + // M-Audio, Firewire 410. The vendor field is left as BridgeCo. AG. + SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010058, NULL), + SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010046, &maudio_fw410_spec), /* M-Audio, Firewire Audiophile */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_AUDIOPHILE_BOTH, + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_AUDIOPHILE_BOTH, &maudio_audiophile_spec), /* M-Audio, Firewire Solo */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010062, &maudio_solo_spec), + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010062, &maudio_solo_spec), /* M-Audio, Ozonic */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x0000000a, &maudio_ozonic_spec), + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x0000000a, &maudio_ozonic_spec), /* M-Audio NRV10 */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010081, &maudio_nrv10_spec), + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010081, &maudio_nrv10_spec), /* M-Audio, ProFireLightbridge */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x000100a1, &spec_normal), + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROFIRELIGHTBRIDGE, &spec_normal), /* Firewire 1814 */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, 0x00010070, NULL), /* bootloader */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_FW1814, + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, 0x00010070, NULL), /* bootloader */ + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_FW1814, &maudio_special_spec), /* M-Audio ProjectMix */ - SND_BEBOB_DEV_ENTRY(VEN_MAUDIO1, MODEL_MAUDIO_PROJECTMIX, + SND_BEBOB_DEV_ENTRY(VEN_MAUDIO, MODEL_MAUDIO_PROJECTMIX, &maudio_special_spec), /* Digidesign Mbox 2 Pro */ SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), + // Toneweal FW66. + SND_BEBOB_DEV_ENTRY(OUI_SHOUYO, 0x020002, &spec_normal), /* IDs are unknown but able to be supported */ /* Apogee, Mini-ME Firewire */ /* Apogee, Mini-DAC Firewire */ @@ -496,11 +481,6 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* Infrasonic, Windy6 */ /* Mackie, Digital X Bus x.200 */ /* Mackie, Digital X Bus x.400 */ - /* Phonic, HB 12 */ - /* Phonic, HB 24 */ - /* Phonic, HB 18 */ - /* Phonic, FireFly 202 */ - /* Phonic, FireFly 302 */ /* Rolf Spuler, Firewire Guitar */ {} }; diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index 4e0ed84adbee..4d73ecb30d79 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -75,6 +75,11 @@ struct snd_bebob_spec { const struct snd_bebob_meter_spec *meter; }; +enum snd_bebob_quirk { + SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC = (1 << 0), + SND_BEBOB_QUIRK_WRONG_DBC = (1 << 1), +}; + struct snd_bebob { struct snd_card *card; struct fw_unit *unit; @@ -83,11 +88,8 @@ struct snd_bebob { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - - const struct ieee1394_device_id *entry; const struct snd_bebob_spec *spec; + unsigned int quirks; // Combination of snd_bebob_quirk enumerations. unsigned int midi_input_ports; unsigned int midi_output_ports; @@ -113,9 +115,6 @@ struct snd_bebob { /* for M-Audio special devices */ void *maudio_special_quirk; - /* For BeBoB version quirk. */ - unsigned int version; - struct amdtp_domain domain; }; @@ -254,13 +253,4 @@ extern const struct snd_bebob_spec maudio_special_spec; int snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814); int snd_bebob_maudio_load_firmware(struct fw_unit *unit); -#define SND_BEBOB_DEV_ENTRY(vendor, model, data) \ -{ \ - .match_flags = IEEE1394_MATCH_VENDOR_ID | \ - IEEE1394_MATCH_MODEL_ID, \ - .vendor_id = vendor, \ - .model_id = model, \ - .driver_data = (kernel_ulong_t)data \ -} - #endif diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index b612ee3e33b6..8629b14ded76 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c @@ -7,8 +7,7 @@ #include "./bebob.h" -#define CALLBACK_TIMEOUT 2500 -#define FW_ISO_RESOURCE_DELAY 1000 +#define READY_TIMEOUT_MS 4000 /* * NOTE; @@ -402,12 +401,6 @@ static void break_both_connections(struct snd_bebob *bebob) { cmp_connection_break(&bebob->in_conn); cmp_connection_break(&bebob->out_conn); - - // These models seem to be in transition state for a longer time. When - // accessing in the state, any transactions is corrupted. In the worst - // case, the device is going to reboot. - if (bebob->version < 2) - msleep(600); } static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) @@ -437,6 +430,7 @@ static int start_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) { + unsigned int flags = CIP_BLOCKING; enum amdtp_stream_direction dir_stream; struct cmp_connection *conn; enum cmp_direction dir_conn; @@ -452,32 +446,21 @@ static int init_stream(struct snd_bebob *bebob, struct amdtp_stream *stream) dir_conn = CMP_INPUT; } + if (stream == &bebob->tx_stream) { + if (bebob->quirks & SND_BEBOB_QUIRK_WRONG_DBC) + flags |= CIP_EMPTY_HAS_WRONG_DBC; + } + err = cmp_connection_init(conn, bebob->unit, dir_conn, 0); if (err < 0) return err; - err = amdtp_am824_init(stream, bebob->unit, dir_stream, CIP_BLOCKING); + err = amdtp_am824_init(stream, bebob->unit, dir_stream, flags); if (err < 0) { cmp_connection_destroy(conn); return err; } - if (stream == &bebob->tx_stream) { - // BeBoB v3 transfers packets with these qurks: - // - In the beginning of streaming, the value of dbc is - // incremented even if no data blocks are transferred. - // - The value of dbc is reset suddenly. - if (bebob->version > 2) - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC | - CIP_SKIP_DBC_ZERO_CHECK; - - // At high sampling rate, M-Audio special firmware transmits - // empty packet with the value of dbc incremented by 8 but the - // others are valid to IEC 61883-1. - if (bebob->maudio_special_quirk) - bebob->tx_stream.flags |= CIP_EMPTY_HAS_WRONG_DBC; - } - return 0; } @@ -624,9 +607,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) if (!amdtp_stream_running(&bebob->rx_stream)) { enum snd_bebob_clock_type src; - struct amdtp_stream *master, *slave; unsigned int curr_rate; - unsigned int ir_delay_cycle; + unsigned int tx_init_skip_cycles; if (bebob->maudio_special_quirk) { err = bebob->spec->rate->get(bebob, &curr_rate); @@ -638,36 +620,28 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) if (err < 0) return err; - if (src != SND_BEBOB_CLOCK_TYPE_SYT) { - master = &bebob->tx_stream; - slave = &bebob->rx_stream; - } else { - master = &bebob->rx_stream; - slave = &bebob->tx_stream; - } - - err = start_stream(bebob, master); + err = start_stream(bebob, &bebob->rx_stream); if (err < 0) goto error; - err = start_stream(bebob, slave); + err = start_stream(bebob, &bebob->tx_stream); if (err < 0) goto error; - // The device postpones start of transmission mostly for 1 sec - // after receives packets firstly. For safe, IR context starts - // 0.4 sec (=3200 cycles) later to version 1 or 2 firmware, - // 2.0 sec (=16000 cycles) for version 3 firmware. This is - // within 2.5 sec (=CALLBACK_TIMEOUT). - // Furthermore, some devices transfer isoc packets with - // discontinuous counter in the beginning of packet streaming. - // The delay has an effect to avoid detection of this - // discontinuity. - if (bebob->version < 2) - ir_delay_cycle = 3200; + if (!(bebob->quirks & SND_BEBOB_QUIRK_INITIAL_DISCONTINUOUS_DBC)) + tx_init_skip_cycles = 0; else - ir_delay_cycle = 16000; - err = amdtp_domain_start(&bebob->domain, ir_delay_cycle); + tx_init_skip_cycles = 16000; + + // MEMO: Some devices start packet transmission long enough after establishment of + // CMP connection. In the early stage of packet streaming, any device transfers + // NODATA packets. After several hundred cycles, it begins to multiplex event into + // the packet with adequate value of syt field in CIP header. Some devices are + // strictly to generate any discontinuity in the sequence of tx packet when they + // receives inadequate sequence of value in syt field of CIP header. In the case, + // the request to break CMP connection is often corrupted, then any transaction + // results in unrecoverable error, sometimes generate bus-reset. + err = amdtp_domain_start(&bebob->domain, tx_init_skip_cycles, true, false); if (err < 0) goto error; @@ -684,10 +658,9 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob) } } - if (!amdtp_stream_wait_callback(&bebob->rx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&bebob->tx_stream, - CALLBACK_TIMEOUT)) { + // Some devices postpone start of transmission mostly for 1 sec after receives + // packets firstly. + if (!amdtp_domain_wait_ready(&bebob->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } @@ -883,6 +856,11 @@ static int detect_midi_ports(struct snd_bebob *bebob, err = avc_bridgeco_get_plug_ch_count(bebob->unit, addr, &ch_count); if (err < 0) break; + // Yamaha GO44, GO46, Terratec Phase 24, Phase x24 reports 0 for the number of + // channels in external output plug 3 (MIDI type) even if it has a pair of physical + // MIDI jacks. As a workaround, assume it as one. + if (ch_count == 0) + ch_count = 1; *midi_ports += ch_count; } @@ -961,12 +939,12 @@ int snd_bebob_stream_discover(struct snd_bebob *bebob) if (err < 0) goto end; - err = detect_midi_ports(bebob, bebob->rx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_IN, + err = detect_midi_ports(bebob, bebob->tx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_IN, plugs[2], &bebob->midi_input_ports); if (err < 0) goto end; - err = detect_midi_ports(bebob, bebob->tx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_OUT, + err = detect_midi_ports(bebob, bebob->rx_stream_formations, addr, AVC_BRIDGECO_PLUG_DIR_OUT, plugs[3], &bebob->midi_output_ports); if (err < 0) goto end; diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index c4dfe76500c2..f99e00083141 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -8,8 +8,8 @@ #include "dice.h" -#define CALLBACK_TIMEOUT 200 -#define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC) +#define READY_TIMEOUT_MS 200 +#define NOTIFICATION_TIMEOUT_MS 100 struct reg_params { unsigned int count; @@ -57,13 +57,9 @@ int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate, return -EINVAL; } -/* - * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE - * to GLOBAL_STATUS. Especially, just after powering on, these are different. - */ -static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate) +static int select_clock(struct snd_dice *dice, unsigned int rate) { - __be32 reg, nominal; + __be32 reg; u32 data; int i; int err; @@ -94,19 +90,8 @@ static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate) return err; if (wait_for_completion_timeout(&dice->clock_accepted, - msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) { - /* - * Old versions of Dice firmware transfer no notification when - * the same clock status as current one is set. In this case, - * just check current clock status. - */ - err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS, - &nominal, sizeof(nominal)); - if (err < 0) - return err; - if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED)) - return -ETIMEDOUT; - } + msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) + return -ETIMEDOUT; return 0; } @@ -304,7 +289,7 @@ int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate, // Just after owning the unit (GLOBAL_OWNER), the unit can // return invalid stream formats. Selecting clock parameters // have an effect for the unit to refine it. - err = ensure_phase_lock(dice, rate); + err = select_clock(dice, rate); if (err < 0) return err; @@ -459,20 +444,17 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice) goto error; } - err = amdtp_domain_start(&dice->domain, 0); + // MEMO: The device immediately starts packet transmission when enabled. Some + // devices are strictly to generate any discontinuity in the sequence of tx packet + // when they receives invalid sequence of presentation time in CIP header. The + // sequence replay for media clock recovery can suppress the behaviour. + err = amdtp_domain_start(&dice->domain, 0, true, false); if (err < 0) goto error; - for (i = 0; i < MAX_STREAMS; i++) { - if ((i < tx_params.count && - !amdtp_stream_wait_callback(&dice->tx_stream[i], - CALLBACK_TIMEOUT)) || - (i < rx_params.count && - !amdtp_stream_wait_callback(&dice->rx_stream[i], - CALLBACK_TIMEOUT))) { - err = -ETIMEDOUT; - goto error; - } + if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) { + err = -ETIMEDOUT; + goto error; } } @@ -653,7 +635,7 @@ int snd_dice_stream_detect_current_formats(struct snd_dice *dice) * invalid stream formats. Selecting clock parameters have an effect * for the unit to refine it. */ - err = ensure_phase_lock(dice, rate); + err = select_clock(dice, rate); if (err < 0) return err; diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index 2c0dde29a024..92941ef83cd5 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -155,7 +155,7 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, fw_send_response(card, request, RCODE_COMPLETE); - if (bits & NOTIFY_LOCK_CHG) + if (bits & NOTIFY_CLOCK_ACCEPTED) complete(&dice->clock_accepted); wake_up(&dice->hwdep_wait); } diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 239d164b0eea..f75902bc8e74 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -135,22 +135,51 @@ static void dice_card_free(struct snd_card *card) snd_dice_stream_destroy_duplex(dice); snd_dice_transaction_destroy(dice); + + mutex_destroy(&dice->mutex); + fw_unit_put(dice->unit); } -static void do_registration(struct work_struct *work) +static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work); + struct snd_card *card; + struct snd_dice *dice; + snd_dice_detect_formats_t detect_formats; int err; - if (dice->registered) - return; + if (!entry->driver_data && entry->vendor_id != OUI_SSL) { + err = check_dice_category(unit); + if (err < 0) + return -ENODEV; + } - err = snd_card_new(&dice->unit->device, -1, NULL, THIS_MODULE, 0, - &dice->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dice), &card); if (err < 0) - return; - dice->card->private_free = dice_card_free; - dice->card->private_data = dice; + return err; + card->private_free = dice_card_free; + + dice = card->private_data; + dice->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, dice); + dice->card = card; + + if (!entry->driver_data) + detect_formats = snd_dice_stream_detect_current_formats; + else + detect_formats = (snd_dice_detect_formats_t)entry->driver_data; + + // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer + // frequency. + // * Avid M-Box 3 Pro + // * M-Audio Profire 610 + // * M-Audio Profire 2626 + if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID) + dice->disable_double_pcm_frames = true; + + spin_lock_init(&dice->lock); + mutex_init(&dice->mutex); + init_completion(&dice->clock_accepted); + init_waitqueue_head(&dice->hwdep_wait); err = snd_dice_transaction_init(dice); if (err < 0) @@ -162,7 +191,7 @@ static void do_registration(struct work_struct *work) dice_card_strings(dice); - err = dice->detect_formats(dice); + err = detect_formats(dice); if (err < 0) goto error; @@ -184,105 +213,34 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(dice->card); + err = snd_card_register(card); if (err < 0) goto error; - dice->registered = true; - - return; -error: - snd_card_free(dice->card); - dev_info(&dice->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int dice_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_dice *dice; - int err; - - if (!entry->driver_data && entry->vendor_id != OUI_SSL) { - err = check_dice_category(unit); - if (err < 0) - return -ENODEV; - } - - /* Allocate this independent of sound card instance. */ - dice = devm_kzalloc(&unit->device, sizeof(struct snd_dice), GFP_KERNEL); - if (!dice) - return -ENOMEM; - dice->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, dice); - - if (!entry->driver_data) { - dice->detect_formats = snd_dice_stream_detect_current_formats; - } else { - dice->detect_formats = - (snd_dice_detect_formats_t)entry->driver_data; - } - - // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer - // frequency. - // * Avid M-Box 3 Pro - // * M-Audio Profire 610 - // * M-Audio Profire 2626 - if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID) - dice->disable_double_pcm_frames = true; - - spin_lock_init(&dice->lock); - mutex_init(&dice->mutex); - init_completion(&dice->clock_accepted); - init_waitqueue_head(&dice->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&dice->dwork, do_registration); - snd_fw_schedule_registration(unit, &dice->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void dice_remove(struct fw_unit *unit) { struct snd_dice *dice = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&dice->dwork); - - if (dice->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(dice->card); - } - - mutex_destroy(&dice->mutex); - fw_unit_put(dice->unit); + // Block till all of ALSA character devices are released. + snd_card_free(dice->card); } static void dice_bus_reset(struct fw_unit *unit) { struct snd_dice *dice = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!dice->registered) - snd_fw_schedule_registration(unit, &dice->dwork); - /* The handler address register becomes initialized. */ snd_dice_transaction_reinit(dice); - /* - * After registration, userspace can start packet streaming, then this - * code block works fine. - */ - if (dice->registered) { - mutex_lock(&dice->mutex); - snd_dice_stream_update_duplex(dice); - mutex_unlock(&dice->mutex); - } + mutex_lock(&dice->mutex); + snd_dice_stream_update_duplex(dice); + mutex_unlock(&dice->mutex); } #define DICE_INTERFACE 0x000001 diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 3c967d1b3605..fd440cc625f9 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -78,9 +78,6 @@ struct snd_dice { spinlock_t lock; struct mutex mutex; - bool registered; - struct delayed_work dwork; - /* Offsets for sub-addresses */ unsigned int global_offset; unsigned int rx_offset; @@ -93,7 +90,6 @@ struct snd_dice { unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT]; unsigned int tx_midi_ports[MAX_STREAMS]; unsigned int rx_midi_ports[MAX_STREAMS]; - snd_dice_detect_formats_t detect_formats; struct fw_address_handler notification_handler; int owner_generation; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index d613642a2ce3..59b86c8d89e1 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -396,16 +396,13 @@ int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; - enum cip_flags flags; + unsigned int flags = CIP_NONBLOCKING | CIP_UNAWARE_SYT; // Use different mode between incoming/outgoing. - if (dir == AMDTP_IN_STREAM) { - flags = CIP_NONBLOCKING; + if (dir == AMDTP_IN_STREAM) process_ctx_payloads = process_ir_ctx_payloads; - } else { - flags = CIP_BLOCKING; + else process_ctx_payloads = process_it_ctx_payloads; - } return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, process_ctx_payloads, sizeof(struct amdtp_dot)); diff --git a/sound/firewire/digi00x/digi00x-stream.c b/sound/firewire/digi00x/digi00x-stream.c index 405d6903bfbc..a15f55b0dce3 100644 --- a/sound/firewire/digi00x/digi00x-stream.c +++ b/sound/firewire/digi00x/digi00x-stream.c @@ -7,7 +7,7 @@ #include "digi00x.h" -#define CALLBACK_TIMEOUT 500 +#define READY_TIMEOUT_MS 200 const unsigned int snd_dg00x_stream_rates[SND_DG00X_RATE_COUNT] = { [SND_DG00X_RATE_44100] = 44100, @@ -375,14 +375,15 @@ int snd_dg00x_stream_start_duplex(struct snd_dg00x *dg00x) if (err < 0) goto error; - err = amdtp_domain_start(&dg00x->domain, 0); + // NOTE: The device doesn't start packet transmission till receiving any packet. + // It ignores presentation time expressed by the value of syt field of CIP header + // in received packets. The sequence of the number of data blocks per packet is + // important for media clock recovery. + err = amdtp_domain_start(&dg00x->domain, 0, true, true); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&dg00x->rx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&dg00x->tx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&dg00x->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } diff --git a/sound/firewire/digi00x/digi00x.c b/sound/firewire/digi00x/digi00x.c index ab8408966ec3..995302808c27 100644 --- a/sound/firewire/digi00x/digi00x.c +++ b/sound/firewire/digi00x/digi00x.c @@ -47,23 +47,32 @@ static void dg00x_card_free(struct snd_card *card) snd_dg00x_stream_destroy_duplex(dg00x); snd_dg00x_transaction_unregister(dg00x); + + mutex_destroy(&dg00x->mutex); + fw_unit_put(dg00x->unit); } -static void do_registration(struct work_struct *work) +static int snd_dg00x_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_dg00x *dg00x = - container_of(work, struct snd_dg00x, dwork.work); + struct snd_card *card; + struct snd_dg00x *dg00x; int err; - if (dg00x->registered) - return; - - err = snd_card_new(&dg00x->unit->device, -1, NULL, THIS_MODULE, 0, - &dg00x->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dg00x), &card); if (err < 0) - return; - dg00x->card->private_free = dg00x_card_free; - dg00x->card->private_data = dg00x; + return err; + card->private_free = dg00x_card_free; + + dg00x = card->private_data; + dg00x->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, dg00x); + dg00x->card = card; + + mutex_init(&dg00x->mutex); + spin_lock_init(&dg00x->lock); + init_waitqueue_head(&dg00x->hwdep_wait); + + dg00x->is_console = entry->model_id == MODEL_CONSOLE; err = name_card(dg00x); if (err < 0) @@ -91,85 +100,33 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(dg00x->card); + err = snd_card_register(card); if (err < 0) goto error; - dg00x->registered = true; - - return; -error: - snd_card_free(dg00x->card); - dev_info(&dg00x->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int snd_dg00x_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_dg00x *dg00x; - - /* Allocate this independent of sound card instance. */ - dg00x = devm_kzalloc(&unit->device, sizeof(struct snd_dg00x), - GFP_KERNEL); - if (!dg00x) - return -ENOMEM; - - dg00x->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, dg00x); - - mutex_init(&dg00x->mutex); - spin_lock_init(&dg00x->lock); - init_waitqueue_head(&dg00x->hwdep_wait); - - dg00x->is_console = entry->model_id == MODEL_CONSOLE; - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&dg00x->dwork, do_registration); - snd_fw_schedule_registration(unit, &dg00x->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void snd_dg00x_update(struct fw_unit *unit) { struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!dg00x->registered) - snd_fw_schedule_registration(unit, &dg00x->dwork); - snd_dg00x_transaction_reregister(dg00x); - /* - * After registration, userspace can start packet streaming, then this - * code block works fine. - */ - if (dg00x->registered) { - mutex_lock(&dg00x->mutex); - snd_dg00x_stream_update_duplex(dg00x); - mutex_unlock(&dg00x->mutex); - } + mutex_lock(&dg00x->mutex); + snd_dg00x_stream_update_duplex(dg00x); + mutex_unlock(&dg00x->mutex); } static void snd_dg00x_remove(struct fw_unit *unit) { struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&dg00x->dwork); - - if (dg00x->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(dg00x->card); - } - - mutex_destroy(&dg00x->mutex); - fw_unit_put(dg00x->unit); + // Block till all of ALSA character devices are released. + snd_card_free(dg00x->card); } static const struct ieee1394_device_id snd_dg00x_id_table[] = { diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 129de8edd5ea..82b647d383c5 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -37,9 +37,6 @@ struct snd_dg00x { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - struct amdtp_stream tx_stream; struct fw_iso_resources tx_resources; diff --git a/sound/firewire/fireface/amdtp-ff.c b/sound/firewire/fireface/amdtp-ff.c index 119c0076b17a..98177b0666d3 100644 --- a/sound/firewire/fireface/amdtp-ff.c +++ b/sound/firewire/fireface/amdtp-ff.c @@ -168,6 +168,6 @@ int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit, else process_ctx_payloads = process_it_ctx_payloads; - return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0, + return amdtp_stream_init(s, unit, dir, CIP_BLOCKING | CIP_UNAWARE_SYT | CIP_NO_HEADER, 0, process_ctx_payloads, sizeof(struct amdtp_ff)); } diff --git a/sound/firewire/fireface/ff-stream.c b/sound/firewire/fireface/ff-stream.c index 5452115c0ef9..95bf405adb3d 100644 --- a/sound/firewire/fireface/ff-stream.c +++ b/sound/firewire/fireface/ff-stream.c @@ -7,7 +7,7 @@ #include "ff.h" -#define CALLBACK_TIMEOUT_MS 200 +#define READY_TIMEOUT_MS 200 int snd_ff_stream_get_multiplier_mode(enum cip_sfc sfc, enum snd_ff_stream_mode *mode) @@ -199,14 +199,15 @@ int snd_ff_stream_start_duplex(struct snd_ff *ff, unsigned int rate) if (err < 0) goto error; - err = amdtp_domain_start(&ff->domain, 0); + // NOTE: The device doesn't transfer packets unless receiving any packet. The + // sequence of tx packets includes cycle skip corresponding to empty packet or + // NODATA packet in IEC 61883-1/6. The sequence of the number of data blocks per + // packet is important for media clock recovery. + err = amdtp_domain_start(&ff->domain, 0, true, true); if (err < 0) goto error; - if (!amdtp_stream_wait_callback(&ff->rx_stream, - CALLBACK_TIMEOUT_MS) || - !amdtp_stream_wait_callback(&ff->tx_stream, - CALLBACK_TIMEOUT_MS)) { + if (!amdtp_domain_wait_ready(&ff->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index bc39269415d2..7bf51d062021 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -42,22 +42,33 @@ static void ff_card_free(struct snd_card *card) snd_ff_stream_destroy_duplex(ff); snd_ff_transaction_unregister(ff); + + mutex_destroy(&ff->mutex); + fw_unit_put(ff->unit); } -static void do_registration(struct work_struct *work) +static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_ff *ff = container_of(work, struct snd_ff, dwork.work); + struct snd_card *card; + struct snd_ff *ff; int err; - if (ff->registered) - return; - - err = snd_card_new(&ff->unit->device, -1, NULL, THIS_MODULE, 0, - &ff->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*ff), &card); if (err < 0) - return; - ff->card->private_free = ff_card_free; - ff->card->private_data = ff; + return err; + card->private_free = ff_card_free; + + ff = card->private_data; + ff->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, ff); + ff->card = card; + + mutex_init(&ff->mutex); + spin_lock_init(&ff->lock); + init_waitqueue_head(&ff->hwdep_wait); + + ff->unit_version = entry->version; + ff->spec = (const struct snd_ff_spec *)entry->driver_data; err = snd_ff_transaction_register(ff); if (err < 0) @@ -83,76 +94,31 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(ff->card); + err = snd_card_register(card); if (err < 0) goto error; - ff->registered = true; - - return; -error: - snd_card_free(ff->card); - dev_info(&ff->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int snd_ff_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_ff *ff; - - ff = devm_kzalloc(&unit->device, sizeof(struct snd_ff), GFP_KERNEL); - if (!ff) - return -ENOMEM; - ff->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, ff); - - mutex_init(&ff->mutex); - spin_lock_init(&ff->lock); - init_waitqueue_head(&ff->hwdep_wait); - - ff->unit_version = entry->version; - ff->spec = (const struct snd_ff_spec *)entry->driver_data; - - /* Register this sound card later. */ - INIT_DEFERRABLE_WORK(&ff->dwork, do_registration); - snd_fw_schedule_registration(unit, &ff->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void snd_ff_update(struct fw_unit *unit) { struct snd_ff *ff = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!ff->registered) - snd_fw_schedule_registration(unit, &ff->dwork); - snd_ff_transaction_reregister(ff); - if (ff->registered) - snd_ff_stream_update_duplex(ff); + snd_ff_stream_update_duplex(ff); } static void snd_ff_remove(struct fw_unit *unit) { struct snd_ff *ff = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_work_sync(&ff->dwork.work); - - if (ff->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(ff->card); - } - - mutex_destroy(&ff->mutex); - fw_unit_put(ff->unit); + // Block till all of ALSA character devices are released. + snd_card_free(ff->card); } static const struct snd_ff_spec spec_ff800 = { diff --git a/sound/firewire/fireface/ff.h b/sound/firewire/fireface/ff.h index 705e7df4f929..0535f0b58b67 100644 --- a/sound/firewire/fireface/ff.h +++ b/sound/firewire/fireface/ff.h @@ -69,9 +69,6 @@ struct snd_ff { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - enum snd_ff_unit_version unit_version; const struct snd_ff_spec *spec; diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c index b1cc013a3540..ffb6dd796243 100644 --- a/sound/firewire/fireworks/fireworks.c +++ b/sound/firewire/fireworks/fireworks.c @@ -194,19 +194,19 @@ efw_card_free(struct snd_card *card) snd_efw_stream_destroy_duplex(efw); snd_efw_transaction_remove_instance(efw); + + mutex_destroy(&efw->mutex); + fw_unit_put(efw->unit); } -static void -do_registration(struct work_struct *work) +static int efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_efw *efw = container_of(work, struct snd_efw, dwork.work); unsigned int card_index; + struct snd_card *card; + struct snd_efw *efw; int err; - if (efw->registered) - return; - - /* check registered cards */ + // check registered cards. mutex_lock(&devices_mutex); for (card_index = 0; card_index < SNDRV_CARDS; ++card_index) { if (!test_bit(card_index, devices_used) && enable[card_index]) @@ -214,26 +214,32 @@ do_registration(struct work_struct *work) } if (card_index >= SNDRV_CARDS) { mutex_unlock(&devices_mutex); - return; + return -ENOENT; } - err = snd_card_new(&efw->unit->device, index[card_index], - id[card_index], THIS_MODULE, 0, &efw->card); + err = snd_card_new(&unit->device, index[card_index], id[card_index], THIS_MODULE, + sizeof(*efw), &card); if (err < 0) { mutex_unlock(&devices_mutex); - return; + return err; } + card->private_free = efw_card_free; set_bit(card_index, devices_used); mutex_unlock(&devices_mutex); - efw->card->private_free = efw_card_free; - efw->card->private_data = efw; + efw = card->private_data; + efw->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, efw); + efw->card = card; + efw->card_index = card_index; + + mutex_init(&efw->mutex); + spin_lock_init(&efw->lock); + init_waitqueue_head(&efw->hwdep_wait); - /* prepare response buffer */ - snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, - SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); - efw->resp_buf = devm_kzalloc(&efw->card->card_dev, - snd_efw_resp_buf_size, GFP_KERNEL); + // prepare response buffer. + snd_efw_resp_buf_size = clamp(snd_efw_resp_buf_size, SND_EFW_RESPONSE_MAXIMUM_BYTES, 4096U); + efw->resp_buf = devm_kzalloc(&card->card_dev, snd_efw_resp_buf_size, GFP_KERNEL); if (!efw->resp_buf) { err = -ENOMEM; goto error; @@ -265,80 +271,48 @@ do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(efw->card); + err = snd_card_register(card); if (err < 0) goto error; - efw->registered = true; - - return; -error: - snd_card_free(efw->card); - dev_info(&efw->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int -efw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) -{ - struct snd_efw *efw; - - efw = devm_kzalloc(&unit->device, sizeof(struct snd_efw), GFP_KERNEL); - if (efw == NULL) - return -ENOMEM; - efw->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, efw); - - mutex_init(&efw->mutex); - spin_lock_init(&efw->lock); - init_waitqueue_head(&efw->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&efw->dwork, do_registration); - snd_fw_schedule_registration(unit, &efw->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void efw_update(struct fw_unit *unit) { struct snd_efw *efw = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!efw->registered) - snd_fw_schedule_registration(unit, &efw->dwork); - snd_efw_transaction_bus_reset(efw->unit); - /* - * After registration, userspace can start packet streaming, then this - * code block works fine. - */ - if (efw->registered) { - mutex_lock(&efw->mutex); - snd_efw_stream_update_duplex(efw); - mutex_unlock(&efw->mutex); - } + mutex_lock(&efw->mutex); + snd_efw_stream_update_duplex(efw); + mutex_unlock(&efw->mutex); } static void efw_remove(struct fw_unit *unit) { struct snd_efw *efw = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&efw->dwork); - - if (efw->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(efw->card); - } + // Block till all of ALSA character devices are released. + snd_card_free(efw->card); +} - mutex_destroy(&efw->mutex); - fw_unit_put(efw->unit); +#define SPECIFIER_1394TA 0x00a02d +#define VERSION_EFW 0x010000 + +#define SND_EFW_DEV_ENTRY(vendor, model) \ +{ \ + .match_flags = IEEE1394_MATCH_VENDOR_ID | \ + IEEE1394_MATCH_MODEL_ID | \ + IEEE1394_MATCH_SPECIFIER_ID | \ + IEEE1394_MATCH_VERSION, \ + .vendor_id = vendor,\ + .model_id = model, \ + .specifier_id = SPECIFIER_1394TA, \ + .version = VERSION_EFW, \ } static const struct ieee1394_device_id efw_id_table[] = { diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h index 654e28a6669f..c8d5879efe28 100644 --- a/sound/firewire/fireworks/fireworks.h +++ b/sound/firewire/fireworks/fireworks.h @@ -65,9 +65,6 @@ struct snd_efw { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - /* for transaction */ u32 seqnum; bool resp_addr_changable; @@ -181,7 +178,7 @@ struct snd_efw_phys_meters { } __packed; enum snd_efw_clock_source { SND_EFW_CLOCK_SOURCE_INTERNAL = 0, - SND_EFW_CLOCK_SOURCE_SYTMATCH = 1, + // Unused. SND_EFW_CLOCK_SOURCE_WORDCLOCK = 2, SND_EFW_CLOCK_SOURCE_SPDIF = 3, SND_EFW_CLOCK_SOURCE_ADAT_1 = 4, @@ -227,12 +224,4 @@ int snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode); int snd_efw_create_hwdep_device(struct snd_efw *efw); -#define SND_EFW_DEV_ENTRY(vendor, model) \ -{ \ - .match_flags = IEEE1394_MATCH_VENDOR_ID | \ - IEEE1394_MATCH_MODEL_ID, \ - .vendor_id = vendor,\ - .model_id = model \ -} - #endif diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 2206af0fef42..ac66f08acd6b 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c @@ -6,7 +6,7 @@ */ #include "./fireworks.h" -#define CALLBACK_TIMEOUT 100 +#define READY_TIMEOUT_MS 1000 static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) { @@ -29,7 +29,7 @@ static int init_stream(struct snd_efw *efw, struct amdtp_stream *stream) if (err < 0) return err; - err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING); + err = amdtp_am824_init(stream, efw->unit, s_dir, CIP_BLOCKING | CIP_UNAWARE_SYT); if (err < 0) { amdtp_stream_destroy(stream); cmp_connection_destroy(conn); @@ -264,6 +264,15 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw) return err; if (!amdtp_stream_running(&efw->rx_stream)) { + unsigned int tx_init_skip_cycles; + + // Audiofire 2/4 skip an isochronous cycle several thousands after starting + // packet transmission. + if (efw->is_fireworks3 && !efw->is_af9) + tx_init_skip_cycles = 6000; + else + tx_init_skip_cycles = 0; + err = start_stream(efw, &efw->rx_stream, rate); if (err < 0) goto error; @@ -272,15 +281,14 @@ int snd_efw_stream_start_duplex(struct snd_efw *efw) if (err < 0) goto error; - err = amdtp_domain_start(&efw->domain, 0); + // NOTE: The device ignores presentation time expressed by the value of syt field + // of CIP header in received packets. The sequence of the number of data blocks per + // packet is important for media clock recovery. + err = amdtp_domain_start(&efw->domain, tx_init_skip_cycles, true, false); if (err < 0) goto error; - // Wait first callback. - if (!amdtp_stream_wait_callback(&efw->rx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&efw->tx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&efw->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c index 85c4f4477c7f..e0a2337e8f27 100644 --- a/sound/firewire/lib.c +++ b/sound/firewire/lib.c @@ -67,38 +67,6 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, } EXPORT_SYMBOL(snd_fw_transaction); -#define PROBE_DELAY_MS (2 * MSEC_PER_SEC) - -/** - * snd_fw_schedule_registration - schedule work for sound card registration - * @unit: an instance for unit on IEEE 1394 bus - * @dwork: delayed work with callback function - * - * This function is not designed for general purposes. When new unit is - * connected to IEEE 1394 bus, the bus is under bus-reset state because of - * topological change. In this state, units tend to fail both of asynchronous - * and isochronous communication. To avoid this problem, this function is used - * to postpone sound card registration after the state. The callers must - * set up instance of delayed work in advance. - */ -void snd_fw_schedule_registration(struct fw_unit *unit, - struct delayed_work *dwork) -{ - u64 now, delay; - - now = get_jiffies_64(); - delay = fw_parent_device(unit)->card->reset_jiffies - + msecs_to_jiffies(PROBE_DELAY_MS); - - if (time_after64(delay, now)) - delay -= now; - else - delay = 0; - - mod_delayed_work(system_wq, dwork, delay); -} -EXPORT_SYMBOL(snd_fw_schedule_registration); - MODULE_DESCRIPTION("FireWire audio helper functions"); MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); MODULE_LICENSE("GPL v2"); diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h index dc815dc3933e..664dfdb9e58d 100644 --- a/sound/firewire/lib.h +++ b/sound/firewire/lib.h @@ -23,7 +23,4 @@ static inline bool rcode_is_permanent_error(int rcode) return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; } -void snd_fw_schedule_registration(struct fw_unit *unit, - struct delayed_work *dwork); - #endif diff --git a/sound/firewire/motu/Makefile b/sound/firewire/motu/Makefile index 7c502d35103c..acdf66564fb0 100644 --- a/sound/firewire/motu/Makefile +++ b/sound/firewire/motu/Makefile @@ -3,5 +3,6 @@ CFLAGS_amdtp-motu.o := -I$(src) snd-firewire-motu-objs := motu.o amdtp-motu.o motu-transaction.o motu-stream.o \ motu-proc.o motu-pcm.o motu-midi.o motu-hwdep.o \ - motu-protocol-v2.o motu-protocol-v3.o + motu-protocol-v2.o motu-protocol-v3.o \ + motu-protocol-v1.o obj-$(CONFIG_SND_FIREWIRE_MOTU) += snd-firewire-motu.o diff --git a/sound/firewire/motu/amdtp-motu.c b/sound/firewire/motu/amdtp-motu.c index edb31ac26868..5388b85fb60e 100644 --- a/sound/firewire/motu/amdtp-motu.c +++ b/sound/firewire/motu/amdtp-motu.c @@ -16,6 +16,14 @@ #define CIP_FMT_MOTU_TX_V3 0x22 #define MOTU_FDF_AM824 0x22 +#define TICKS_PER_CYCLE 3072 +#define CYCLES_PER_SECOND 8000 +#define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) + +#define CIP_SPH_CYCLE_SHIFT 12 +#define CIP_SPH_CYCLE_MASK 0x01fff000 +#define CIP_SPH_OFFSET_MASK 0x00000fff + /* * Nominally 3125 bytes/second, but the MIDI port's clock might be * 1% too slow, and the bus clock 100 ppm too fast. @@ -23,14 +31,6 @@ #define MIDI_BYTES_PER_SECOND 3093 struct amdtp_motu { - /* For timestamp processing. */ - unsigned int quotient_ticks_per_event; - unsigned int remainder_ticks_per_event; - unsigned int next_ticks; - unsigned int next_accumulated; - unsigned int next_cycles; - unsigned int next_seconds; - unsigned int pcm_chunks; unsigned int pcm_byte_offset; @@ -41,26 +41,16 @@ struct amdtp_motu { int midi_db_count; unsigned int midi_db_interval; + + struct amdtp_motu_cache *cache; }; int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, unsigned int midi_ports, struct snd_motu_packet_format *formats) { - static const struct { - unsigned int quotient_ticks_per_event; - unsigned int remainder_ticks_per_event; - } params[] = { - [CIP_SFC_44100] = { 557, 123 }, - [CIP_SFC_48000] = { 512, 0 }, - [CIP_SFC_88200] = { 278, 282 }, - [CIP_SFC_96000] = { 256, 0 }, - [CIP_SFC_176400] = { 139, 141 }, - [CIP_SFC_192000] = { 128, 0 }, - }; struct amdtp_motu *p = s->protocol; unsigned int pcm_chunks, data_chunks, data_block_quadlets; - unsigned int delay; unsigned int mode; int i, err; @@ -97,19 +87,6 @@ int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, p->midi_db_count = 0; p->midi_db_interval = rate / MIDI_BYTES_PER_SECOND; - /* IEEE 1394 bus requires. */ - delay = 0x2e00; - - /* For no-data or empty packets to adjust PCM sampling frequency. */ - delay += 8000 * 3072 * s->syt_interval / rate; - - p->next_seconds = 0; - p->next_cycles = delay / 3072; - p->quotient_ticks_per_event = params[s->sfc].quotient_ticks_per_event; - p->remainder_ticks_per_event = params[s->sfc].remainder_ticks_per_event; - p->next_ticks = delay % 3072; - p->next_accumulated = 0; - return 0; } @@ -322,6 +299,34 @@ static void probe_tracepoints_events(struct amdtp_stream *s, } } +static void cache_event_offsets(struct amdtp_motu_cache *cache, const __be32 *buf, + unsigned int data_blocks, unsigned int data_block_quadlets) +{ + unsigned int *event_offsets = cache->event_offsets; + const unsigned int cache_size = cache->size; + unsigned int cache_tail = cache->tail; + unsigned int base_tick = cache->tx_cycle_count * TICKS_PER_CYCLE; + int i; + + for (i = 0; i < data_blocks; ++i) { + u32 sph = be32_to_cpu(*buf); + unsigned int tick; + + tick = ((sph & CIP_SPH_CYCLE_MASK) >> CIP_SPH_CYCLE_SHIFT) * TICKS_PER_CYCLE + + (sph & CIP_SPH_OFFSET_MASK); + + if (tick < base_tick) + tick += TICKS_PER_SECOND; + event_offsets[cache_tail] = tick - base_tick; + + cache_tail = (cache_tail + 1) % cache_size; + buf += data_block_quadlets; + } + + cache->tail = cache_tail; + cache->tx_cycle_count = (cache->tx_cycle_count + 1) % CYCLES_PER_SECOND; +} + static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *descs, unsigned int packets, @@ -331,12 +336,17 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, unsigned int pcm_frames = 0; int i; + if (p->cache->tx_cycle_count == UINT_MAX) + p->cache->tx_cycle_count = (s->domain->processing_cycle.tx_start % CYCLES_PER_SECOND); + // For data block processing. for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = descs + i; __be32 *buf = desc->ctx_payload; unsigned int data_blocks = desc->data_blocks; + cache_event_offsets(p->cache, buf, data_blocks, s->data_block_quadlets); + if (pcm) { read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames); pcm_frames += data_blocks; @@ -354,46 +364,26 @@ static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s, return pcm_frames; } -static inline void compute_next_elapse_from_start(struct amdtp_motu *p) -{ - p->next_accumulated += p->remainder_ticks_per_event; - if (p->next_accumulated >= 441) { - p->next_accumulated -= 441; - p->next_ticks++; - } - - p->next_ticks += p->quotient_ticks_per_event; - if (p->next_ticks >= 3072) { - p->next_ticks -= 3072; - p->next_cycles++; - } - - if (p->next_cycles >= 8000) { - p->next_cycles -= 8000; - p->next_seconds++; - } - - if (p->next_seconds >= 128) - p->next_seconds -= 128; -} - -static void write_sph(struct amdtp_stream *s, __be32 *buffer, - unsigned int data_blocks) +static void write_sph(struct amdtp_motu_cache *cache, __be32 *buffer, unsigned int data_blocks, + unsigned int data_block_quadlets) { - struct amdtp_motu *p = s->protocol; - unsigned int next_cycles; - unsigned int i; - u32 sph; + unsigned int *event_offsets = cache->event_offsets; + const unsigned int cache_size = cache->size; + unsigned int cache_head = cache->head; + unsigned int base_tick = cache->rx_cycle_count * TICKS_PER_CYCLE; + int i; for (i = 0; i < data_blocks; i++) { - next_cycles = (s->start_cycle + p->next_cycles) % 8000; - sph = ((next_cycles << 12) | p->next_ticks) & 0x01ffffff; + unsigned int tick = (base_tick + event_offsets[cache_head]) % TICKS_PER_SECOND; + u32 sph = ((tick / TICKS_PER_CYCLE) << CIP_SPH_CYCLE_SHIFT) | (tick % TICKS_PER_CYCLE); *buffer = cpu_to_be32(sph); - compute_next_elapse_from_start(p); - - buffer += s->data_block_quadlets; + cache_head = (cache_head + 1) % cache_size; + buffer += data_block_quadlets; } + + cache->head = cache_head; + cache->rx_cycle_count = (cache->rx_cycle_count + 1) % CYCLES_PER_SECOND; } static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, @@ -405,6 +395,9 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, unsigned int pcm_frames = 0; int i; + if (p->cache->rx_cycle_count == UINT_MAX) + p->cache->rx_cycle_count = (s->domain->processing_cycle.rx_start % CYCLES_PER_SECOND); + // For data block processing. for (i = 0; i < packets; ++i) { const struct pkt_desc *desc = descs + i; @@ -423,7 +416,7 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, // TODO: how to interact control messages between userspace? - write_sph(s, buf, data_blocks); + write_sph(p->cache, buf, data_blocks, s->data_block_quadlets); } // For tracepoints. @@ -436,11 +429,12 @@ static unsigned int process_it_ctx_payloads(struct amdtp_stream *s, int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, - const struct snd_motu_spec *spec) + const struct snd_motu_spec *spec, struct amdtp_motu_cache *cache) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; int fmt = CIP_FMT_MOTU; - int flags = CIP_BLOCKING; + unsigned int flags = CIP_BLOCKING | CIP_UNAWARE_SYT; + struct amdtp_motu *p; int err; if (dir == AMDTP_IN_STREAM) { @@ -478,9 +472,10 @@ int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, if (dir == AMDTP_OUT_STREAM) { // Use fixed value for FDF field. s->ctx_data.rx.fdf = MOTU_FDF_AM824; - // Not used. - s->ctx_data.rx.syt_override = 0xffff; } + p = s->protocol; + p->cache = cache; + return 0; } diff --git a/sound/firewire/motu/motu-protocol-v1.c b/sound/firewire/motu/motu-protocol-v1.c new file mode 100644 index 000000000000..f1d6a326dc07 --- /dev/null +++ b/sound/firewire/motu/motu-protocol-v1.c @@ -0,0 +1,470 @@ +// SPDX-License-Identifier: GPL-2.0-only + +// motu-protocol-v1.c - a part of driver for MOTU FireWire series +// +// Copyright (c) 2021 Takashi Sakamoto <o-takashi@sakamocchi.jp> +// +// Licensed under the terms of the GNU General Public License, version 2. + +#include "motu.h" + +#include <linux/delay.h> + +// Status register for MOTU 828 (0x'ffff'f000'0b00). +// +// 0xffff0000: ISOC_COMM_CONTROL_MASK in motu-stream.c. +// 0x00008000: mode of optical input interface. +// 0x00008000: for S/PDIF signal. +// 0x00000000: disabled or for ADAT signal. +// 0x00004000: mode of optical output interface. +// 0x00004000: for S/PDIF signal. +// 0x00000000: disabled or for ADAT signal. +// 0x00003f00: monitor input mode. +// 0x00000800: analog-1/2 +// 0x00001a00: analog-3/4 +// 0x00002c00: analog-5/6 +// 0x00003e00: analog-7/8 +// 0x00000000: analog-1 +// 0x00000900: analog-2 +// 0x00001200: analog-3 +// 0x00001b00: analog-4 +// 0x00002400: analog-5 +// 0x00002d00: analog-6 +// 0x00003600: analog-7 +// 0x00003f00: analog-8 +// 0x00000080: enable stream input. +// 0x00000040: disable monitor input. +// 0x00000008: enable main out. +// 0x00000004: rate of sampling clock. +// 0x00000004: 48.0 kHz +// 0x00000000: 44.1 kHz +// 0x00000023: source of sampling clock. +// 0x00000003: source packet header (SPH) +// 0x00000002: S/PDIF on optical/coaxial interface. +// 0x00000021: ADAT on optical interface +// 0x00000001: ADAT on Dsub 9pin +// 0x00000000: internal + +#define CLK_828_STATUS_OFFSET 0x0b00 +#define CLK_828_STATUS_MASK 0x0000ffff +#define CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF 0x00008000 +#define CLK_828_STATUS_FLAG_OPT_OUT_IFACE_IS_SPDIF 0x00004000 +#define CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES 0x00000080 +#define CLK_828_STATUS_FLAG_ENABLE_OUTPUT 0x00000008 +#define CLK_828_STATUS_FLAG_RATE_48000 0x00000004 +#define CLK_828_STATUS_MASK_SRC 0x00000023 +#define CLK_828_STATUS_FLAG_SRC_ADAT_ON_OPT 0x00000021 +#define CLK_828_STATUS_FLAG_SRC_SPH 0x00000003 +#define CLK_828_STATUS_FLAG_SRC_SPDIF 0x00000002 +#define CLK_828_STATUS_FLAG_SRC_ADAT_ON_DSUB 0x00000001 +#define CLK_828_STATUS_FLAG_SRC_INTERNAL 0x00000000 + +// Status register for MOTU 896 (0x'ffff'f000'0b14). +// +// 0xf0000000: enable physical and stream input to DAC. +// 0x80000000: disable +// 0x40000000: disable +// 0x20000000: enable (prior to the other bits) +// 0x10000000: disable +// 0x00000000: disable +// 0x08000000: speed of word clock signal output on BNC interface. +// 0x00000000: force to low rate (44.1/48.0 kHz). +// 0x08000000: follow to system clock. +// 0x04000000: something relevant to clock. +// 0x03000000: enable output. +// 0x02000000: enabled irreversibly once standing unless the device voluntarily disables it. +// 0x01000000: enabled irreversibly once standing unless the device voluntarily disables it. +// 0x00ffff00: monitor input mode. +// 0x00000000: disabled +// 0x00004800: analog-1/2 +// 0x00005a00: analog-3/4 +// 0x00006c00: analog-5/6 +// 0x00007e00: analog-7/8 +// 0x00104800: AES/EBU-1/2 +// 0x00004000: analog-1 +// 0x00004900: analog-2 +// 0x00005200: analog-3 +// 0x00005b00: analog-4 +// 0x00006400: analog-5 +// 0x00006d00: analog-6 +// 0x00007600: analog-7 +// 0x00007f00: analog-8 +// 0x00104000: AES/EBU-1 +// 0x00104900: AES/EBU-2 +// 0x00000060: sample rate conversion for AES/EBU input/output. +// 0x00000000: None +// 0x00000020: input signal is converted to system rate +// 0x00000040: output is slave to input, ignoring system rate +// 0x00000060: output is double rate than system rate +// 0x00000018: nominal rate of sampling clock. +// 0x00000000: 44.1 kHz +// 0x00000008: 48.0 kHz +// 0x00000010: 88.2 kHz +// 0x00000018: 96.0 kHz +// 0x00000007: source of sampling clock. +// 0x00000000: internal +// 0x00000001: ADAT on optical interface +// 0x00000002: AES/EBU on XLR +// 0x00000003: source packet header (SPH) +// 0x00000004: word clock on BNC +// 0x00000005: ADAT on Dsub 9pin + +#define CLK_896_STATUS_OFFSET 0x0b14 +#define CLK_896_STATUS_FLAG_FETCH_ENABLE 0x20000000 +#define CLK_896_STATUS_FLAG_OUTPUT_ON 0x03000000 +#define CLK_896_STATUS_MASK_SRC 0x00000007 +#define CLK_896_STATUS_FLAG_SRC_INTERNAL 0x00000000 +#define CLK_896_STATUS_FLAG_SRC_ADAT_ON_OPT 0x00000001 +#define CLK_896_STATUS_FLAG_SRC_AESEBU 0x00000002 +#define CLK_896_STATUS_FLAG_SRC_SPH 0x00000003 +#define CLK_896_STATUS_FLAG_SRC_WORD 0x00000004 +#define CLK_896_STATUS_FLAG_SRC_ADAT_ON_DSUB 0x00000005 +#define CLK_896_STATUS_MASK_RATE 0x00000018 +#define CLK_896_STATUS_FLAG_RATE_44100 0x00000000 +#define CLK_896_STATUS_FLAG_RATE_48000 0x00000008 +#define CLK_896_STATUS_FLAG_RATE_88200 0x00000010 +#define CLK_896_STATUS_FLAG_RATE_96000 0x00000018 + +static void parse_clock_rate_828(u32 data, unsigned int *rate) +{ + if (data & CLK_828_STATUS_FLAG_RATE_48000) + *rate = 48000; + else + *rate = 44100; +} + +static int get_clock_rate_828(struct snd_motu *motu, unsigned int *rate) +{ + __be32 reg; + int err; + + err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + parse_clock_rate_828(be32_to_cpu(reg), rate); + + return 0; +} + +static int parse_clock_rate_896(u32 data, unsigned int *rate) +{ + switch (data & CLK_896_STATUS_MASK_RATE) { + case CLK_896_STATUS_FLAG_RATE_44100: + *rate = 44100; + break; + case CLK_896_STATUS_FLAG_RATE_48000: + *rate = 48000; + break; + case CLK_896_STATUS_FLAG_RATE_88200: + *rate = 88200; + break; + case CLK_896_STATUS_FLAG_RATE_96000: + *rate = 96000; + break; + default: + return -ENXIO; + } + + return 0; +} + +static int get_clock_rate_896(struct snd_motu *motu, unsigned int *rate) +{ + __be32 reg; + int err; + + err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + return parse_clock_rate_896(be32_to_cpu(reg), rate); +} + +int snd_motu_protocol_v1_get_clock_rate(struct snd_motu *motu, unsigned int *rate) +{ + if (motu->spec == &snd_motu_spec_828) + return get_clock_rate_828(motu, rate); + else if (motu->spec == &snd_motu_spec_896) + return get_clock_rate_896(motu, rate); + else + return -ENXIO; +} + +static int set_clock_rate_828(struct snd_motu *motu, unsigned int rate) +{ + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg) & CLK_828_STATUS_MASK; + + data &= ~CLK_828_STATUS_FLAG_RATE_48000; + if (rate == 48000) + data |= CLK_828_STATUS_FLAG_RATE_48000; + + reg = cpu_to_be32(data); + return snd_motu_transaction_write(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); +} + +static int set_clock_rate_896(struct snd_motu *motu, unsigned int rate) +{ + unsigned int flag; + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg); + + switch (rate) { + case 44100: + flag = CLK_896_STATUS_FLAG_RATE_44100; + break; + case 48000: + flag = CLK_896_STATUS_FLAG_RATE_48000; + break; + case 88200: + flag = CLK_896_STATUS_FLAG_RATE_88200; + break; + case 96000: + flag = CLK_896_STATUS_FLAG_RATE_96000; + break; + default: + return -EINVAL; + } + + data &= ~CLK_896_STATUS_MASK_RATE; + data |= flag; + + reg = cpu_to_be32(data); + return snd_motu_transaction_write(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); +} + +int snd_motu_protocol_v1_set_clock_rate(struct snd_motu *motu, unsigned int rate) +{ + if (motu->spec == &snd_motu_spec_828) + return set_clock_rate_828(motu, rate); + else if (motu->spec == &snd_motu_spec_896) + return set_clock_rate_896(motu, rate); + else + return -ENXIO; +} + +static int get_clock_source_828(struct snd_motu *motu, enum snd_motu_clock_source *src) +{ + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg) & CLK_828_STATUS_MASK; + + switch (data & CLK_828_STATUS_MASK_SRC) { + case CLK_828_STATUS_FLAG_SRC_ADAT_ON_OPT: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + break; + case CLK_828_STATUS_FLAG_SRC_SPH: + *src = SND_MOTU_CLOCK_SOURCE_SPH; + break; + case CLK_828_STATUS_FLAG_SRC_SPDIF: + { + if (data & CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF) + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + else + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT; + break; + } + case CLK_828_STATUS_FLAG_SRC_ADAT_ON_DSUB: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB; + break; + case CLK_828_STATUS_FLAG_SRC_INTERNAL: + *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; + break; + default: + return -ENXIO; + } + + return 0; +} + +static int get_clock_source_896(struct snd_motu *motu, enum snd_motu_clock_source *src) +{ + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg); + + switch (data & CLK_896_STATUS_MASK_SRC) { + case CLK_896_STATUS_FLAG_SRC_INTERNAL: + *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; + break; + case CLK_896_STATUS_FLAG_SRC_ADAT_ON_OPT: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + break; + case CLK_896_STATUS_FLAG_SRC_AESEBU: + *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR; + break; + case CLK_896_STATUS_FLAG_SRC_SPH: + *src = SND_MOTU_CLOCK_SOURCE_SPH; + break; + case CLK_896_STATUS_FLAG_SRC_WORD: + *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; + break; + case CLK_896_STATUS_FLAG_SRC_ADAT_ON_DSUB: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB; + break; + default: + return -ENXIO; + } + + return 0; +} + +int snd_motu_protocol_v1_get_clock_source(struct snd_motu *motu, enum snd_motu_clock_source *src) +{ + if (motu->spec == &snd_motu_spec_828) + return get_clock_source_828(motu, src); + else if (motu->spec == &snd_motu_spec_896) + return get_clock_source_896(motu, src); + else + return -ENXIO; +} + +static int switch_fetching_mode_828(struct snd_motu *motu, bool enable) +{ + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg) & CLK_828_STATUS_MASK; + + data &= ~(CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES | CLK_828_STATUS_FLAG_ENABLE_OUTPUT); + if (enable) { + // This transaction should be initiated after the device receives batch of packets + // since the device voluntarily mutes outputs. As a workaround, yield processor over + // 100 msec. + msleep(100); + data |= CLK_828_STATUS_FLAG_FETCH_PCM_FRAMES | CLK_828_STATUS_FLAG_ENABLE_OUTPUT; + } + + reg = cpu_to_be32(data); + return snd_motu_transaction_write(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); +} + +static int switch_fetching_mode_896(struct snd_motu *motu, bool enable) +{ + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg); + + data &= ~CLK_896_STATUS_FLAG_FETCH_ENABLE; + if (enable) + data |= CLK_896_STATUS_FLAG_FETCH_ENABLE | CLK_896_STATUS_FLAG_OUTPUT_ON; + + reg = cpu_to_be32(data); + return snd_motu_transaction_write(motu, CLK_896_STATUS_OFFSET, ®, sizeof(reg)); +} + +int snd_motu_protocol_v1_switch_fetching_mode(struct snd_motu *motu, bool enable) +{ + if (motu->spec == &snd_motu_spec_828) + return switch_fetching_mode_828(motu, enable); + else if (motu->spec == &snd_motu_spec_896) + return switch_fetching_mode_896(motu, enable); + else + return -ENXIO; +} + +static int detect_packet_formats_828(struct snd_motu *motu) +{ + __be32 reg; + u32 data; + int err; + + motu->tx_packet_formats.pcm_byte_offset = 4; + motu->tx_packet_formats.msg_chunks = 2; + + motu->rx_packet_formats.pcm_byte_offset = 4; + motu->rx_packet_formats.msg_chunks = 0; + + err = snd_motu_transaction_read(motu, CLK_828_STATUS_OFFSET, ®, sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg) & CLK_828_STATUS_MASK; + + // The number of chunks is just reduced when SPDIF is activated. + if (!(data & CLK_828_STATUS_FLAG_OPT_IN_IFACE_IS_SPDIF)) + motu->tx_packet_formats.pcm_chunks[0] += 8; + + if (!(data & CLK_828_STATUS_FLAG_OPT_OUT_IFACE_IS_SPDIF)) + motu->rx_packet_formats.pcm_chunks[0] += 8; + + return 0; +} + +static int detect_packet_formats_896(struct snd_motu *motu) +{ + // 24bit PCM frames follow to source packet header without message chunk. + motu->tx_packet_formats.pcm_byte_offset = 4; + motu->rx_packet_formats.pcm_byte_offset = 4; + + // No message chunk in data block. + motu->tx_packet_formats.msg_chunks = 0; + motu->rx_packet_formats.msg_chunks = 0; + + // Always enable optical interface for ADAT signal since the device have no registers + // to refer to current configuration. + motu->tx_packet_formats.pcm_chunks[0] += 8; + motu->tx_packet_formats.pcm_chunks[1] += 8; + + motu->rx_packet_formats.pcm_chunks[0] += 8; + motu->rx_packet_formats.pcm_chunks[1] += 8; + + return 0; +} + +int snd_motu_protocol_v1_cache_packet_formats(struct snd_motu *motu) +{ + memcpy(motu->tx_packet_formats.pcm_chunks, motu->spec->tx_fixed_pcm_chunks, + sizeof(motu->tx_packet_formats.pcm_chunks)); + memcpy(motu->rx_packet_formats.pcm_chunks, motu->spec->rx_fixed_pcm_chunks, + sizeof(motu->rx_packet_formats.pcm_chunks)); + + if (motu->spec == &snd_motu_spec_828) + return detect_packet_formats_828(motu); + else if (motu->spec == &snd_motu_spec_896) + return detect_packet_formats_896(motu); + else + return 0; +} + +const struct snd_motu_spec snd_motu_spec_828 = { + .name = "828", + .protocol_version = SND_MOTU_PROTOCOL_V1, + .tx_fixed_pcm_chunks = {10, 0, 0}, + .rx_fixed_pcm_chunks = {10, 0, 0}, +}; + +const struct snd_motu_spec snd_motu_spec_896 = { + .name = "896", + .tx_fixed_pcm_chunks = {10, 10, 0}, + .rx_fixed_pcm_chunks = {10, 10, 0}, +}; diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index e59e69ab1538..93d5df1ae550 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -12,6 +12,13 @@ #define V2_CLOCK_RATE_SHIFT 3 #define V2_CLOCK_SRC_MASK 0x00000007 #define V2_CLOCK_SRC_SHIFT 0 +#define V2_CLOCK_SRC_AESEBU_ON_XLR 0x07 +#define V2_CLOCK_SRC_ADAT_ON_DSUB 0x05 +#define V2_CLOCK_SRC_WORD_ON_BNC 0x04 +#define V2_CLOCK_SRC_SPH 0x03 +#define V2_CLOCK_SRC_SPDIF 0x02 // on either coaxial or optical +#define V2_CLOCK_SRC_ADAT_ON_OPT 0x01 +#define V2_CLOCK_SRC_INTERNAL 0x00 #define V2_CLOCK_FETCH_ENABLE 0x02000000 #define V2_CLOCK_MODEL_SPECIFIC 0x04000000 @@ -78,64 +85,51 @@ int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu, sizeof(reg)); } -static int detect_clock_source_optical_model(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) +static int get_clock_source(struct snd_motu *motu, u32 data, + enum snd_motu_clock_source *src) { - switch (data) { - case 0: + switch (data & V2_CLOCK_SRC_MASK) { + case V2_CLOCK_SRC_INTERNAL: *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; break; - case 1: + case V2_CLOCK_SRC_ADAT_ON_OPT: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + break; + case V2_CLOCK_SRC_SPDIF: { - __be32 reg; - - // To check the configuration of optical interface. - int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, - ®, sizeof(reg)); - if (err < 0) - return err; - - if (be32_to_cpu(reg) & 0x00000200) - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT; - else - *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + bool support_iec60958_on_opt = (motu->spec == &snd_motu_spec_828mk2 || + motu->spec == &snd_motu_spec_traveler); + + if (!support_iec60958_on_opt) { + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + } else { + __be32 reg; + + // To check the configuration of optical interface. + int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, ®, + sizeof(reg)); + if (err < 0) + return err; + + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == + V2_OPT_IFACE_MODE_SPDIF) + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT; + else + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; + } break; } - case 2: - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; - break; - case 3: + case V2_CLOCK_SRC_SPH: *src = SND_MOTU_CLOCK_SOURCE_SPH; break; - case 4: + case V2_CLOCK_SRC_WORD_ON_BNC: *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; break; - case 5: + case V2_CLOCK_SRC_ADAT_ON_DSUB: *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_DSUB; break; - default: - *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; - break; - } - - return 0; -} - -static int v2_detect_clock_source(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) -{ - switch (data) { - case 0: - *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; - break; - case 2: - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; - break; - case 3: - *src = SND_MOTU_CLOCK_SOURCE_SPH; - break; - case 4: - *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; + case V2_CLOCK_SRC_AESEBU_ON_XLR: + *src = SND_MOTU_CLOCK_SOURCE_AESEBU_ON_XLR; break; default: *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; @@ -145,17 +139,6 @@ static int v2_detect_clock_source(struct snd_motu *motu, u32 data, return 0; } -static int get_clock_source(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) -{ - data &= V2_CLOCK_SRC_MASK; - if (motu->spec == &snd_motu_spec_828mk2 || - motu->spec == &snd_motu_spec_traveler) - return detect_clock_source_optical_model(motu, data, src); - else - return v2_detect_clock_source(motu, data, src); -} - int snd_motu_protocol_v2_get_clock_source(struct snd_motu *motu, enum snd_motu_clock_source *src) { @@ -235,59 +218,9 @@ int snd_motu_protocol_v2_switch_fetching_mode(struct snd_motu *motu, } } -static int detect_packet_formats_828mk2(struct snd_motu *motu, u32 data) -{ - if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->tx_packet_formats.pcm_chunks[0] += 8; - motu->tx_packet_formats.pcm_chunks[1] += 4; - } - - if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->rx_packet_formats.pcm_chunks[0] += 8; - motu->rx_packet_formats.pcm_chunks[1] += 4; - } - - return 0; -} - -static int detect_packet_formats_traveler(struct snd_motu *motu, u32 data) -{ - if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->tx_packet_formats.pcm_chunks[0] += 8; - motu->tx_packet_formats.pcm_chunks[1] += 4; - } - - if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->rx_packet_formats.pcm_chunks[0] += 8; - motu->rx_packet_formats.pcm_chunks[1] += 4; - } - - return 0; -} - -static int detect_packet_formats_8pre(struct snd_motu *motu, u32 data) -{ - if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->tx_packet_formats.pcm_chunks[0] += 8; - motu->tx_packet_formats.pcm_chunks[1] += 8; - } - - if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == - V2_OPT_IFACE_MODE_ADAT) { - motu->rx_packet_formats.pcm_chunks[0] += 8; - motu->rx_packet_formats.pcm_chunks[1] += 8; - } - - return 0; -} - int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) { + bool has_two_opt_ifaces = (motu->spec == &snd_motu_spec_8pre); __be32 reg; u32 data; int err; @@ -311,14 +244,25 @@ int snd_motu_protocol_v2_cache_packet_formats(struct snd_motu *motu) motu->spec->rx_fixed_pcm_chunks, sizeof(motu->rx_packet_formats.pcm_chunks)); - if (motu->spec == &snd_motu_spec_828mk2) - return detect_packet_formats_828mk2(motu, data); - else if (motu->spec == &snd_motu_spec_traveler) - return detect_packet_formats_traveler(motu, data); - else if (motu->spec == &snd_motu_spec_8pre) - return detect_packet_formats_8pre(motu, data); - else - return 0; + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == V2_OPT_IFACE_MODE_ADAT) { + motu->tx_packet_formats.pcm_chunks[0] += 8; + + if (!has_two_opt_ifaces) + motu->tx_packet_formats.pcm_chunks[1] += 4; + else + motu->tx_packet_formats.pcm_chunks[1] += 8; + } + + if (((data & V2_OPT_OUT_IFACE_MASK) >> V2_OPT_OUT_IFACE_SHIFT) == V2_OPT_IFACE_MODE_ADAT) { + motu->rx_packet_formats.pcm_chunks[0] += 8; + + if (!has_two_opt_ifaces) + motu->rx_packet_formats.pcm_chunks[1] += 4; + else + motu->rx_packet_formats.pcm_chunks[1] += 8; + } + + return 0; } const struct snd_motu_spec snd_motu_spec_828mk2 = { @@ -353,6 +297,7 @@ const struct snd_motu_spec snd_motu_spec_8pre = { .protocol_version = SND_MOTU_PROTOCOL_V2, .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, - .tx_fixed_pcm_chunks = {10, 6, 0}, - .rx_fixed_pcm_chunks = {10, 6, 0}, + // Two dummy chunks always in the end of data block. + .tx_fixed_pcm_chunks = {10, 10, 0}, + .rx_fixed_pcm_chunks = {6, 6, 0}, }; diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c index 4e6b0e449ee4..56e4504e7ec9 100644 --- a/sound/firewire/motu/motu-protocol-v3.c +++ b/sound/firewire/motu/motu-protocol-v3.c @@ -13,6 +13,12 @@ #define V3_CLOCK_RATE_MASK 0x0000ff00 #define V3_CLOCK_RATE_SHIFT 8 #define V3_CLOCK_SOURCE_MASK 0x000000ff +#define V3_CLOCK_SRC_INTERNAL 0x00 +#define V3_CLOCK_SRC_WORD_ON_BNC 0x01 +#define V3_CLOCK_SRC_SPH 0x02 +#define V3_CLOCK_SRC_SPDIF_ON_COAX 0x10 +#define V3_CLOCK_SRC_OPT_IFACE_A 0x18 +#define V3_CLOCK_SRC_OPT_IFACE_B 0x19 #define V3_OPT_IFACE_MODE_OFFSET 0x0c94 #define V3_ENABLE_OPT_IN_IFACE_A 0x00000001 @@ -97,28 +103,37 @@ int snd_motu_protocol_v3_set_clock_rate(struct snd_motu *motu, return 0; } -static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) +int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src) { + __be32 reg; + u32 data; + int err; + + err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, + sizeof(reg)); + if (err < 0) + return err; + data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK; + switch (data) { - case 0x00: + case V3_CLOCK_SRC_INTERNAL: *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; break; - case 0x01: + case V3_CLOCK_SRC_WORD_ON_BNC: *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; break; - case 0x02: + case V3_CLOCK_SRC_SPH: *src = SND_MOTU_CLOCK_SOURCE_SPH; break; - case 0x10: + case V3_CLOCK_SRC_SPDIF_ON_COAX: *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; break; - case 0x18: - case 0x19: + case V3_CLOCK_SRC_OPT_IFACE_A: + case V3_CLOCK_SRC_OPT_IFACE_B: { __be32 reg; u32 options; - int err; err = snd_motu_transaction_read(motu, V3_OPT_IFACE_MODE_OFFSET, ®, sizeof(reg)); @@ -126,7 +141,7 @@ static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data, return err; options = be32_to_cpu(reg); - if (data == 0x18) { + if (data == V3_CLOCK_SRC_OPT_IFACE_A) { if (options & V3_NO_ADAT_OPT_IN_IFACE_A) *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT_A; else @@ -137,7 +152,6 @@ static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data, else *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT_B; } - break; } default: @@ -148,49 +162,6 @@ static int detect_clock_source_828mk3(struct snd_motu *motu, u32 data, return 0; } -static int v3_detect_clock_source(struct snd_motu *motu, u32 data, - enum snd_motu_clock_source *src) -{ - switch (data) { - case 0x00: - *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; - break; - case 0x01: - *src = SND_MOTU_CLOCK_SOURCE_WORD_ON_BNC; - break; - case 0x02: - *src = SND_MOTU_CLOCK_SOURCE_SPH; - break; - case 0x10: - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; - break; - default: - *src = SND_MOTU_CLOCK_SOURCE_UNKNOWN; - break; - } - - return 0; -} - -int snd_motu_protocol_v3_get_clock_source(struct snd_motu *motu, - enum snd_motu_clock_source *src) -{ - __be32 reg; - u32 data; - int err; - - err = snd_motu_transaction_read(motu, V3_CLOCK_STATUS_OFFSET, ®, - sizeof(reg)); - if (err < 0) - return err; - data = be32_to_cpu(reg) & V3_CLOCK_SOURCE_MASK; - - if (motu->spec == &snd_motu_spec_828mk3) - return detect_clock_source_828mk3(motu, data, src); - else - return v3_detect_clock_source(motu, data, src); -} - int snd_motu_protocol_v3_switch_fetching_mode(struct snd_motu *motu, bool enable) { @@ -284,14 +255,14 @@ int snd_motu_protocol_v3_cache_packet_formats(struct snd_motu *motu) motu->spec->rx_fixed_pcm_chunks, sizeof(motu->rx_packet_formats.pcm_chunks)); - if (motu->spec == &snd_motu_spec_828mk3) + if (motu->spec == &snd_motu_spec_828mk3_fw || motu->spec == &snd_motu_spec_828mk3_hybrid) return detect_packet_formats_828mk3(motu, data); else return 0; } -const struct snd_motu_spec snd_motu_spec_828mk3 = { +const struct snd_motu_spec snd_motu_spec_828mk3_fw = { .name = "828mk3", .protocol_version = SND_MOTU_PROTOCOL_V3, .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | @@ -300,6 +271,15 @@ const struct snd_motu_spec snd_motu_spec_828mk3 = { .rx_fixed_pcm_chunks = {14, 14, 10}, }; +const struct snd_motu_spec snd_motu_spec_828mk3_hybrid = { + .name = "828mk3", + .protocol_version = SND_MOTU_PROTOCOL_V3, + .flags = SND_MOTU_SPEC_RX_MIDI_3RD_Q | + SND_MOTU_SPEC_TX_MIDI_3RD_Q, + .tx_fixed_pcm_chunks = {18, 18, 14}, + .rx_fixed_pcm_chunks = {14, 14, 14}, // Additional 4 dummy chunks at higher rate. +}; + const struct snd_motu_spec snd_motu_spec_ultralite_mk3 = { .name = "UltraLiteMk3", .protocol_version = SND_MOTU_PROTOCOL_V3, diff --git a/sound/firewire/motu/motu-stream.c b/sound/firewire/motu/motu-stream.c index 2028c5419f6f..9e6ca39ebd7f 100644 --- a/sound/firewire/motu/motu-stream.c +++ b/sound/firewire/motu/motu-stream.c @@ -7,7 +7,7 @@ #include "motu.h" -#define CALLBACK_TIMEOUT 200 +#define READY_TIMEOUT_MS 200 #define ISOC_COMM_CONTROL_OFFSET 0x0b00 #define ISOC_COMM_CONTROL_MASK 0xffff0000 @@ -153,6 +153,9 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate, fw_iso_resources_free(&motu->tx_resources); fw_iso_resources_free(&motu->rx_resources); + kfree(motu->cache.event_offsets); + motu->cache.event_offsets = NULL; + err = snd_motu_protocol_set_clock_rate(motu, rate); if (err < 0) { dev_err(&motu->unit->device, @@ -181,6 +184,15 @@ int snd_motu_stream_reserve_duplex(struct snd_motu *motu, unsigned int rate, fw_iso_resources_free(&motu->rx_resources); return err; } + + motu->cache.size = motu->tx_stream.syt_interval * frames_per_buffer; + motu->cache.event_offsets = kcalloc(motu->cache.size, sizeof(*motu->cache.event_offsets), + GFP_KERNEL); + if (!motu->cache.event_offsets) { + fw_iso_resources_free(&motu->tx_resources); + fw_iso_resources_free(&motu->rx_resources); + return -ENOMEM; + } } return 0; @@ -260,14 +272,19 @@ int snd_motu_stream_start_duplex(struct snd_motu *motu) if (err < 0) goto stop_streams; - err = amdtp_domain_start(&motu->domain, 0); + motu->cache.tail = 0; + motu->cache.tx_cycle_count = UINT_MAX; + motu->cache.head = 0; + motu->cache.rx_cycle_count = UINT_MAX; + + // NOTE: The device requires both of replay; the sequence of the number of data + // blocks per packet, and the sequence of source packet header per data block as + // presentation time. + err = amdtp_domain_start(&motu->domain, 0, true, false); if (err < 0) goto stop_streams; - if (!amdtp_stream_wait_callback(&motu->tx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&motu->rx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&motu->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto stop_streams; } @@ -296,6 +313,9 @@ void snd_motu_stream_stop_duplex(struct snd_motu *motu) fw_iso_resources_free(&motu->tx_resources); fw_iso_resources_free(&motu->rx_resources); + + kfree(motu->cache.event_offsets); + motu->cache.event_offsets = NULL; } } @@ -317,7 +337,7 @@ static int init_stream(struct snd_motu *motu, struct amdtp_stream *s) if (err < 0) return err; - err = amdtp_motu_init(s, motu->unit, dir, motu->spec); + err = amdtp_motu_init(s, motu->unit, dir, motu->spec, &motu->cache); if (err < 0) fw_iso_resources_destroy(resources); diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c index a4929c1302dc..543136578c70 100644 --- a/sound/firewire/motu/motu.c +++ b/sound/firewire/motu/motu.c @@ -57,22 +57,31 @@ static void motu_card_free(struct snd_card *card) snd_motu_transaction_unregister(motu); snd_motu_stream_destroy_duplex(motu); + + mutex_destroy(&motu->mutex); + fw_unit_put(motu->unit); } -static void do_registration(struct work_struct *work) +static int motu_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_motu *motu = container_of(work, struct snd_motu, dwork.work); + struct snd_card *card; + struct snd_motu *motu; int err; - if (motu->registered) - return; - - err = snd_card_new(&motu->unit->device, -1, NULL, THIS_MODULE, 0, - &motu->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*motu), &card); if (err < 0) - return; - motu->card->private_free = motu_card_free; - motu->card->private_data = motu; + return err; + card->private_free = motu_card_free; + + motu = card->private_data; + motu->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, motu); + motu->card = card; + + motu->spec = (const struct snd_motu_spec *)entry->driver_data; + mutex_init(&motu->mutex); + spin_lock_init(&motu->lock); + init_waitqueue_head(&motu->hwdep_wait); name_card(motu); @@ -103,71 +112,28 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(motu->card); + err = snd_card_register(card); if (err < 0) goto error; - motu->registered = true; - - return; -error: - snd_card_free(motu->card); - dev_info(&motu->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int motu_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_motu *motu; - - /* Allocate this independently of sound card instance. */ - motu = devm_kzalloc(&unit->device, sizeof(struct snd_motu), GFP_KERNEL); - if (!motu) - return -ENOMEM; - motu->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, motu); - - motu->spec = (const struct snd_motu_spec *)entry->driver_data; - mutex_init(&motu->mutex); - spin_lock_init(&motu->lock); - init_waitqueue_head(&motu->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&motu->dwork, do_registration); - snd_fw_schedule_registration(unit, &motu->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void motu_remove(struct fw_unit *unit) { struct snd_motu *motu = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&motu->dwork); - - if (motu->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(motu->card); - } - - mutex_destroy(&motu->mutex); - fw_unit_put(motu->unit); + // Block till all of ALSA character devices are released. + snd_card_free(motu->card); } static void motu_bus_update(struct fw_unit *unit) { struct snd_motu *motu = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!motu->registered) - snd_fw_schedule_registration(unit, &motu->dwork); - /* The handler address register becomes initialized. */ snd_motu_transaction_reregister(motu); } @@ -184,13 +150,16 @@ static void motu_bus_update(struct fw_unit *unit) } static const struct ieee1394_device_id motu_id_table[] = { + SND_MOTU_DEV_ENTRY(0x000001, &snd_motu_spec_828), + SND_MOTU_DEV_ENTRY(0x000002, &snd_motu_spec_896), SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2), SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), - SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only. + SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3_fw), // FireWire only. SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only. - SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid. + SND_MOTU_DEV_ENTRY(0x000030, &snd_motu_spec_ultralite_mk3), // Hybrid. + SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3_hybrid), // Hybrid. SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), { } diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h index 3d0236ee6716..73f36d1be515 100644 --- a/sound/firewire/motu/motu.h +++ b/sound/firewire/motu/motu.h @@ -39,15 +39,21 @@ struct snd_motu_packet_format { unsigned char pcm_chunks[3]; }; +struct amdtp_motu_cache { + unsigned int *event_offsets; + unsigned int size; + unsigned int tail; + unsigned int tx_cycle_count; + unsigned int head; + unsigned int rx_cycle_count; +}; + struct snd_motu { struct snd_card *card; struct fw_unit *unit; struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - /* Model dependent information. */ const struct snd_motu_spec *spec; @@ -70,6 +76,8 @@ struct snd_motu { wait_queue_head_t hwdep_wait; struct amdtp_domain domain; + + struct amdtp_motu_cache cache; }; enum snd_motu_spec_flags { @@ -99,6 +107,7 @@ enum snd_motu_clock_source { }; enum snd_motu_protocol_version { + SND_MOTU_PROTOCOL_V1, SND_MOTU_PROTOCOL_V2, SND_MOTU_PROTOCOL_V3, }; @@ -106,25 +115,31 @@ enum snd_motu_protocol_version { struct snd_motu_spec { const char *const name; enum snd_motu_protocol_version protocol_version; - enum snd_motu_spec_flags flags; + // The combination of snd_motu_spec_flags enumeration-constants. + unsigned int flags; unsigned char tx_fixed_pcm_chunks[3]; unsigned char rx_fixed_pcm_chunks[3]; }; +extern const struct snd_motu_spec snd_motu_spec_828; +extern const struct snd_motu_spec snd_motu_spec_896; + extern const struct snd_motu_spec snd_motu_spec_828mk2; extern const struct snd_motu_spec snd_motu_spec_traveler; extern const struct snd_motu_spec snd_motu_spec_ultralite; extern const struct snd_motu_spec snd_motu_spec_8pre; -extern const struct snd_motu_spec snd_motu_spec_828mk3; +extern const struct snd_motu_spec snd_motu_spec_828mk3_fw; +extern const struct snd_motu_spec snd_motu_spec_828mk3_hybrid; extern const struct snd_motu_spec snd_motu_spec_ultralite_mk3; extern const struct snd_motu_spec snd_motu_spec_audio_express; extern const struct snd_motu_spec snd_motu_spec_4pre; int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, - const struct snd_motu_spec *spec); + const struct snd_motu_spec *spec, + struct amdtp_motu_cache *cache); int amdtp_motu_set_parameters(struct amdtp_stream *s, unsigned int rate, unsigned int midi_ports, struct snd_motu_packet_format *formats); @@ -160,6 +175,16 @@ int snd_motu_create_midi_devices(struct snd_motu *motu); int snd_motu_create_hwdep_device(struct snd_motu *motu); +int snd_motu_protocol_v1_get_clock_rate(struct snd_motu *motu, + unsigned int *rate); +int snd_motu_protocol_v1_set_clock_rate(struct snd_motu *motu, + unsigned int rate); +int snd_motu_protocol_v1_get_clock_source(struct snd_motu *motu, + enum snd_motu_clock_source *src); +int snd_motu_protocol_v1_switch_fetching_mode(struct snd_motu *motu, + bool enable); +int snd_motu_protocol_v1_cache_packet_formats(struct snd_motu *motu); + int snd_motu_protocol_v2_get_clock_rate(struct snd_motu *motu, unsigned int *rate); int snd_motu_protocol_v2_set_clock_rate(struct snd_motu *motu, @@ -187,6 +212,8 @@ static inline int snd_motu_protocol_get_clock_rate(struct snd_motu *motu, return snd_motu_protocol_v2_get_clock_rate(motu, rate); else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) return snd_motu_protocol_v3_get_clock_rate(motu, rate); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1) + return snd_motu_protocol_v1_get_clock_rate(motu, rate); else return -ENXIO; } @@ -198,6 +225,8 @@ static inline int snd_motu_protocol_set_clock_rate(struct snd_motu *motu, return snd_motu_protocol_v2_set_clock_rate(motu, rate); else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) return snd_motu_protocol_v3_set_clock_rate(motu, rate); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1) + return snd_motu_protocol_v1_set_clock_rate(motu, rate); else return -ENXIO; } @@ -209,6 +238,8 @@ static inline int snd_motu_protocol_get_clock_source(struct snd_motu *motu, return snd_motu_protocol_v2_get_clock_source(motu, source); else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) return snd_motu_protocol_v3_get_clock_source(motu, source); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1) + return snd_motu_protocol_v1_get_clock_source(motu, source); else return -ENXIO; } @@ -220,6 +251,8 @@ static inline int snd_motu_protocol_switch_fetching_mode(struct snd_motu *motu, return snd_motu_protocol_v2_switch_fetching_mode(motu, enable); else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) return snd_motu_protocol_v3_switch_fetching_mode(motu, enable); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1) + return snd_motu_protocol_v1_switch_fetching_mode(motu, enable); else return -ENXIO; } @@ -230,6 +263,8 @@ static inline int snd_motu_protocol_cache_packet_formats(struct snd_motu *motu) return snd_motu_protocol_v2_cache_packet_formats(motu); else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V3) return snd_motu_protocol_v3_cache_packet_formats(motu); + else if (motu->spec->protocol_version == SND_MOTU_PROTOCOL_V1) + return snd_motu_protocol_v1_cache_packet_formats(motu); else return -ENXIO; } diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 80c9dc13f1b5..0ef242fdd3bc 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c @@ -9,7 +9,7 @@ #include <linux/delay.h> #define AVC_GENERIC_FRAME_MAXIMUM_BYTES 512 -#define CALLBACK_TIMEOUT 200 +#define READY_TIMEOUT_MS 200 /* * According to datasheet of Oxford Semiconductor: @@ -153,12 +153,23 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) struct cmp_connection *conn; enum cmp_direction c_dir; enum amdtp_stream_direction s_dir; + unsigned int flags = CIP_UNAWARE_SYT; int err; + if (!(oxfw->quirks & SND_OXFW_QUIRK_BLOCKING_TRANSMISSION)) + flags |= CIP_NONBLOCKING; + else + flags |= CIP_BLOCKING; + if (stream == &oxfw->tx_stream) { conn = &oxfw->out_conn; c_dir = CMP_OUTPUT; s_dir = AMDTP_IN_STREAM; + + if (oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD) + flags |= CIP_JUMBO_PAYLOAD; + if (oxfw->quirks & SND_OXFW_QUIRK_WRONG_DBS) + flags |= CIP_WRONG_DBS; } else { conn = &oxfw->in_conn; c_dir = CMP_INPUT; @@ -169,24 +180,12 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) if (err < 0) return err; - err = amdtp_am824_init(stream, oxfw->unit, s_dir, CIP_NONBLOCKING); + err = amdtp_am824_init(stream, oxfw->unit, s_dir, flags); if (err < 0) { cmp_connection_destroy(conn); return err; } - /* - * OXFW starts to transmit packets with non-zero dbc. - * OXFW postpone transferring packets till handling any asynchronous - * packets. As a result, next isochronous packet includes more data - * blocks than IEC 61883-6 defines. - */ - if (stream == &oxfw->tx_stream) { - oxfw->tx_stream.flags |= CIP_JUMBO_PAYLOAD; - if (oxfw->wrong_dbs) - oxfw->tx_stream.flags |= CIP_WRONG_DBS; - } - return 0; } @@ -338,6 +337,9 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) } if (!amdtp_stream_running(&oxfw->rx_stream)) { + unsigned int tx_init_skip_cycles = 0; + bool replay_seq = false; + err = start_stream(oxfw, &oxfw->rx_stream); if (err < 0) { dev_err(&oxfw->unit->device, @@ -353,26 +355,27 @@ int snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw) "fail to prepare tx stream: %d\n", err); goto error; } + + if (oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD) { + // Just after changing sampling transfer frequency, many cycles are + // skipped for packet transmission. + tx_init_skip_cycles = 400; + } else { + replay_seq = true; + } } - err = amdtp_domain_start(&oxfw->domain, 0); + // NOTE: The device ignores presentation time expressed by the value of syt field + // of CIP header in received packets. The sequence of the number of data blocks per + // packet is important for media clock recovery. + err = amdtp_domain_start(&oxfw->domain, tx_init_skip_cycles, replay_seq, false); if (err < 0) goto error; - // Wait first packet. - if (!amdtp_stream_wait_callback(&oxfw->rx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&oxfw->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } - - if (oxfw->has_output) { - if (!amdtp_stream_wait_callback(&oxfw->tx_stream, - CALLBACK_TIMEOUT)) { - err = -ETIMEDOUT; - goto error; - } - } } return 0; diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 9eea25c46dc7..84971d78d152 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -23,6 +23,8 @@ #define OUI_APOGEE 0x0003db #define MODEL_SATELLITE 0x00200f +#define MODEL_SCS1M 0x001000 +#define MODEL_DUET_FW 0x01dddd #define SPECIFIER_1394TA 0x00a02d #define VERSION_AVC 0x010001 @@ -46,8 +48,6 @@ static bool detect_loud_models(struct fw_unit *unit) "Onyx-i", "Onyx 1640i", "d.Pro", - "Mackie Onyx Satellite", - "Tapco LINK.firewire 4x6", "U.420"}; char model[32]; int err; @@ -60,7 +60,7 @@ static bool detect_loud_models(struct fw_unit *unit) return match_string(models, ARRAY_SIZE(models), model) >= 0; } -static int name_card(struct snd_oxfw *oxfw) +static int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry) { struct fw_device *fw_dev = fw_parent_device(oxfw->unit); const struct compat_info *info; @@ -88,10 +88,12 @@ static int name_card(struct snd_oxfw *oxfw) goto end; be32_to_cpus(&firmware); + if (firmware >> 20 == 0x970) + oxfw->quirks |= SND_OXFW_QUIRK_JUMBO_PAYLOAD; + /* to apply card definitions */ - if (oxfw->entry->vendor_id == VENDOR_GRIFFIN || - oxfw->entry->vendor_id == VENDOR_LACIE) { - info = (const struct compat_info *)oxfw->entry->driver_data; + if (entry->vendor_id == VENDOR_GRIFFIN || entry->vendor_id == VENDOR_LACIE) { + info = (const struct compat_info *)entry->driver_data; d = info->driver_name; v = info->vendor_name; m = info->model_name; @@ -120,9 +122,12 @@ static void oxfw_card_free(struct snd_card *card) if (oxfw->has_output || oxfw->has_input) snd_oxfw_stream_destroy_duplex(oxfw); + + mutex_destroy(&oxfw->mutex); + fw_unit_put(oxfw->unit); } -static int detect_quirks(struct snd_oxfw *oxfw) +static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id *entry) { struct fw_device *fw_dev = fw_parent_device(oxfw->unit); struct fw_csr_iterator it; @@ -133,28 +138,35 @@ static int detect_quirks(struct snd_oxfw *oxfw) * Add ALSA control elements for two models to keep compatibility to * old firewire-speaker module. */ - if (oxfw->entry->vendor_id == VENDOR_GRIFFIN) + if (entry->vendor_id == VENDOR_GRIFFIN) return snd_oxfw_add_spkr(oxfw, false); - if (oxfw->entry->vendor_id == VENDOR_LACIE) + if (entry->vendor_id == VENDOR_LACIE) return snd_oxfw_add_spkr(oxfw, true); /* * Stanton models supports asynchronous transactions for unique MIDI * messages. */ - if (oxfw->entry->vendor_id == OUI_STANTON) { - /* No physical MIDI ports. */ + if (entry->vendor_id == OUI_STANTON) { + oxfw->quirks |= SND_OXFW_QUIRK_SCS_TRANSACTION; + if (entry->model_id == MODEL_SCS1M) + oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; + + // No physical MIDI ports. oxfw->midi_input_ports = 0; oxfw->midi_output_ports = 0; return snd_oxfw_scs1x_add(oxfw); } + if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW) + oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; + /* * TASCAM FireOne has physical control and requires a pair of additional * MIDI ports. */ - if (oxfw->entry->vendor_id == VENDOR_TASCAM) { + if (entry->vendor_id == VENDOR_TASCAM) { oxfw->midi_input_ports++; oxfw->midi_output_ports++; return 0; @@ -175,27 +187,35 @@ static int detect_quirks(struct snd_oxfw *oxfw) * value in 'dbs' field of CIP header against its format information. */ if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE) - oxfw->wrong_dbs = true; + oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS; return 0; } -static void do_registration(struct work_struct *work) +static int oxfw_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_oxfw *oxfw = container_of(work, struct snd_oxfw, dwork.work); + struct snd_card *card; + struct snd_oxfw *oxfw; int err; - if (oxfw->registered) - return; + if (entry->vendor_id == VENDOR_LOUD && entry->model_id == 0 && !detect_loud_models(unit)) + return -ENODEV; - err = snd_card_new(&oxfw->unit->device, -1, NULL, THIS_MODULE, 0, - &oxfw->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*oxfw), &card); if (err < 0) - return; - oxfw->card->private_free = oxfw_card_free; - oxfw->card->private_data = oxfw; + return err; + card->private_free = oxfw_card_free; + + oxfw = card->private_data; + oxfw->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, oxfw); + oxfw->card = card; - err = name_card(oxfw); + mutex_init(&oxfw->mutex); + spin_lock_init(&oxfw->lock); + init_waitqueue_head(&oxfw->hwdep_wait); + + err = name_card(oxfw, entry); if (err < 0) goto error; @@ -203,7 +223,7 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = detect_quirks(oxfw); + err = detect_quirks(oxfw, entry); if (err < 0) goto error; @@ -227,85 +247,38 @@ static void do_registration(struct work_struct *work) goto error; } - err = snd_card_register(oxfw->card); + err = snd_card_register(card); if (err < 0) goto error; - oxfw->registered = true; - - return; -error: - snd_card_free(oxfw->card); - dev_info(&oxfw->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int oxfw_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_oxfw *oxfw; - - if (entry->vendor_id == VENDOR_LOUD && !detect_loud_models(unit)) - return -ENODEV; - - /* Allocate this independent of sound card instance. */ - oxfw = devm_kzalloc(&unit->device, sizeof(struct snd_oxfw), GFP_KERNEL); - if (!oxfw) - return -ENOMEM; - oxfw->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, oxfw); - - oxfw->entry = entry; - mutex_init(&oxfw->mutex); - spin_lock_init(&oxfw->lock); - init_waitqueue_head(&oxfw->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&oxfw->dwork, do_registration); - snd_fw_schedule_registration(unit, &oxfw->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void oxfw_bus_reset(struct fw_unit *unit) { struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); - if (!oxfw->registered) - snd_fw_schedule_registration(unit, &oxfw->dwork); - fcp_bus_reset(oxfw->unit); - if (oxfw->registered) { - if (oxfw->has_output || oxfw->has_input) { - mutex_lock(&oxfw->mutex); - snd_oxfw_stream_update_duplex(oxfw); - mutex_unlock(&oxfw->mutex); - } - - if (oxfw->entry->vendor_id == OUI_STANTON) - snd_oxfw_scs1x_update(oxfw); + if (oxfw->has_output || oxfw->has_input) { + mutex_lock(&oxfw->mutex); + snd_oxfw_stream_update_duplex(oxfw); + mutex_unlock(&oxfw->mutex); } + + if (oxfw->quirks & SND_OXFW_QUIRK_SCS_TRANSACTION) + snd_oxfw_scs1x_update(oxfw); } static void oxfw_remove(struct fw_unit *unit) { struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&oxfw->dwork); - - if (oxfw->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(oxfw->card); - } - - mutex_destroy(&oxfw->mutex); - fw_unit_put(oxfw->unit); + // Block till all of ALSA character devices are released. + snd_card_free(oxfw->card); } static const struct compat_info griffin_firewave = { @@ -320,81 +293,67 @@ static const struct compat_info lacie_speakers = { .model_name = "FireWire Speakers", }; +#define OXFW_DEV_ENTRY(vendor, model, data) \ +{ \ + .match_flags = IEEE1394_MATCH_VENDOR_ID | \ + IEEE1394_MATCH_MODEL_ID | \ + IEEE1394_MATCH_SPECIFIER_ID | \ + IEEE1394_MATCH_VERSION, \ + .vendor_id = vendor, \ + .model_id = model, \ + .specifier_id = SPECIFIER_1394TA, \ + .version = VERSION_AVC, \ + .driver_data = (kernel_ulong_t)data, \ +} + static const struct ieee1394_device_id oxfw_id_table[] = { - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID | - IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .vendor_id = VENDOR_GRIFFIN, - .model_id = 0x00f970, - .specifier_id = SPECIFIER_1394TA, - .version = VERSION_AVC, - .driver_data = (kernel_ulong_t)&griffin_firewave, - }, - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID | - IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION, - .vendor_id = VENDOR_LACIE, - .model_id = 0x00f970, - .specifier_id = SPECIFIER_1394TA, - .version = VERSION_AVC, - .driver_data = (kernel_ulong_t)&lacie_speakers, - }, - /* Behringer,F-Control Audio 202 */ - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = VENDOR_BEHRINGER, - .model_id = 0x00fc22, - }, - /* - * Any Mackie(Loud) models (name string/model id): - * Onyx-i series (former models): 0x081216 - * Mackie Onyx Satellite: 0x00200f - * Tapco LINK.firewire 4x6: 0x000460 - * d.4 pro: Unknown - * U.420: Unknown - * U.420d: Unknown - */ + // + // OXFW970 devices: + // Initial firmware has a quirk to postpone isoc packet transmission during finishing async + // transaction. As a result, several isochronous cycles are skipped to transfer the packets + // and the audio data frames which should have been transferred during the cycles are put + // into packet at the first isoc cycle after the postpone. Furthermore, the value of SYT + // field in CIP header is not reliable as synchronization timing, + // + OXFW_DEV_ENTRY(VENDOR_GRIFFIN, 0x00f970, &griffin_firewave), + OXFW_DEV_ENTRY(VENDOR_LACIE, 0x00f970, &lacie_speakers), + // Behringer,F-Control Audio 202. The value of SYT field is not reliable at all. + OXFW_DEV_ENTRY(VENDOR_BEHRINGER, 0x00fc22, NULL), + // Loud Technologies, Tapco Link.FireWire 4x6. The value of SYT field is always 0xffff. + OXFW_DEV_ENTRY(VENDOR_LOUD, 0x000460, NULL), + // Loud Technologies, Mackie Onyx Satellite. Although revised version of firmware is + // installed to avoid the postpone, the value of SYT field is always 0xffff. + OXFW_DEV_ENTRY(VENDOR_LOUD, MODEL_SATELLITE, NULL), + // Miglia HarmonyAudio. Not yet identified. + + // + // OXFW971 devices: + // The value of SYT field in CIP header is enough reliable. Both of blocking and non-blocking + // transmission methods are available. + // + // Any Mackie(Loud) models (name string/model id): + // Onyx-i series (former models): 0x081216 + // Onyx 1640i: 0x001640 + // d.2 pro/d.4 pro (built-in card): Unknown + // U.420: Unknown + // U.420d: Unknown { .match_flags = IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .vendor_id = VENDOR_LOUD, + .model_id = 0, .specifier_id = SPECIFIER_1394TA, .version = VERSION_AVC, }, - /* TASCAM, FireOne */ - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = VENDOR_TASCAM, - .model_id = 0x800007, - }, - /* Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m) */ - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = OUI_STANTON, - .model_id = 0x001000, - }, - /* Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d) */ - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = OUI_STANTON, - .model_id = 0x002000, - }, - // APOGEE, duet FireWire - { - .match_flags = IEEE1394_MATCH_VENDOR_ID | - IEEE1394_MATCH_MODEL_ID, - .vendor_id = OUI_APOGEE, - .model_id = 0x01dddd, - }, + // TASCAM, FireOne. + OXFW_DEV_ENTRY(VENDOR_TASCAM, 0x800007, NULL), + // Stanton, Stanton Controllers & Systems 1 Mixer (SCS.1m). + OXFW_DEV_ENTRY(OUI_STANTON, MODEL_SCS1M, NULL), + // Stanton, Stanton Controllers & Systems 1 Deck (SCS.1d). + OXFW_DEV_ENTRY(OUI_STANTON, 0x002000, NULL), + // APOGEE, duet FireWire. + OXFW_DEV_ENTRY(OUI_APOGEE, MODEL_DUET_FW, NULL), { } }; MODULE_DEVICE_TABLE(ieee1394, oxfw_id_table); diff --git a/sound/firewire/oxfw/oxfw.h b/sound/firewire/oxfw/oxfw.h index fa2d7f9e2dc3..ee47abcb0c90 100644 --- a/sound/firewire/oxfw/oxfw.h +++ b/sound/firewire/oxfw/oxfw.h @@ -32,6 +32,18 @@ #include "../amdtp-am824.h" #include "../cmp.h" +enum snd_oxfw_quirk { + // Postpone transferring packets during handling asynchronous transaction. As a result, + // next isochronous packet includes more events than one packet can include. + SND_OXFW_QUIRK_JUMBO_PAYLOAD = 0x01, + // The dbs field of CIP header in tx packet is wrong. + SND_OXFW_QUIRK_WRONG_DBS = 0x02, + // Blocking transmission mode is used. + SND_OXFW_QUIRK_BLOCKING_TRANSMISSION = 0x04, + // Stanton SCS1.d and SCS1.m support unique transaction. + SND_OXFW_QUIRK_SCS_TRANSACTION = 0x08, +}; + /* This is an arbitrary number for convinience. */ #define SND_OXFW_STREAM_FORMAT_ENTRIES 10 struct snd_oxfw { @@ -40,10 +52,8 @@ struct snd_oxfw { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; - - bool wrong_dbs; + // The combination of snd_oxfw_quirk enumeration-constants. + unsigned int quirks; bool has_output; bool has_input; u8 *tx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES]; @@ -62,7 +72,6 @@ struct snd_oxfw { bool dev_lock_changed; wait_queue_head_t hwdep_wait; - const struct ieee1394_device_id *entry; void *spec; struct amdtp_domain domain; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index f823a2ab3544..64d66a802545 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -228,6 +228,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, enum amdtp_stream_direction dir, unsigned int pcm_channels) { amdtp_stream_process_ctx_payloads_t process_ctx_payloads; + unsigned int flags = CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK | CIP_UNAWARE_SYT; struct amdtp_tscm *p; unsigned int fmt; int err; @@ -240,8 +241,7 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, process_ctx_payloads = process_it_ctx_payloads; } - err = amdtp_stream_init(s, unit, dir, - CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt, + err = amdtp_stream_init(s, unit, dir, flags, fmt, process_ctx_payloads, sizeof(struct amdtp_tscm)); if (err < 0) return 0; @@ -249,8 +249,6 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, if (dir == AMDTP_OUT_STREAM) { // Use fixed value for FDF field. s->ctx_data.rx.fdf = 0x00; - // Not used. - s->ctx_data.rx.syt_override = 0x0000; } /* This protocol uses fixed number of data channels for PCM samples. */ diff --git a/sound/firewire/tascam/tascam-stream.c b/sound/firewire/tascam/tascam-stream.c index eb07e1decf9b..53e094cc411f 100644 --- a/sound/firewire/tascam/tascam-stream.c +++ b/sound/firewire/tascam/tascam-stream.c @@ -11,7 +11,7 @@ #define CLOCK_STATUS_MASK 0xffff0000 #define CLOCK_CONFIG_MASK 0x0000ffff -#define CALLBACK_TIMEOUT 500 +#define READY_TIMEOUT_MS 4000 static int get_clock(struct snd_tscm *tscm, u32 *data) { @@ -423,6 +423,8 @@ int snd_tscm_stream_reserve_duplex(struct snd_tscm *tscm, unsigned int rate, fw_iso_resources_free(&tscm->rx_resources); return err; } + + tscm->need_long_tx_init_skip = (rate != curr_rate); } return 0; @@ -454,6 +456,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) if (!amdtp_stream_running(&tscm->rx_stream)) { int spd = fw_parent_device(tscm->unit)->max_speed; + unsigned int tx_init_skip_cycles; err = set_stream_formats(tscm, rate); if (err < 0) @@ -473,14 +476,23 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate) if (err < 0) goto error; - err = amdtp_domain_start(&tscm->domain, 0); + if (tscm->need_long_tx_init_skip) + tx_init_skip_cycles = 16000; + else + tx_init_skip_cycles = 0; + + // MEMO: Just after starting packet streaming, it transfers packets without any + // event. Enough after receiving the sequence of packets, it multiplexes events into + // the packet. However, just after changing sampling transfer frequency, it stops + // multiplexing during packet transmission. Enough after, it restarts multiplexing + // again. The device ignores presentation time expressed by the value of syt field + // of CIP header in received packets. The sequence of the number of data blocks per + // packet is important for media clock recovery. + err = amdtp_domain_start(&tscm->domain, tx_init_skip_cycles, true, true); if (err < 0) return err; - if (!amdtp_stream_wait_callback(&tscm->rx_stream, - CALLBACK_TIMEOUT) || - !amdtp_stream_wait_callback(&tscm->tx_stream, - CALLBACK_TIMEOUT)) { + if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) { err = -ETIMEDOUT; goto error; } @@ -502,6 +514,8 @@ void snd_tscm_stream_stop_duplex(struct snd_tscm *tscm) fw_iso_resources_free(&tscm->tx_resources); fw_iso_resources_free(&tscm->rx_resources); + + tscm->need_long_tx_init_skip = false; } } diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c index 75f2edd8e78f..eb58d3fcf087 100644 --- a/sound/firewire/tascam/tascam.c +++ b/sound/firewire/tascam/tascam.c @@ -90,19 +90,31 @@ static void tscm_card_free(struct snd_card *card) snd_tscm_transaction_unregister(tscm); snd_tscm_stream_destroy_duplex(tscm); + + mutex_destroy(&tscm->mutex); + fw_unit_put(tscm->unit); } -static void do_registration(struct work_struct *work) +static int snd_tscm_probe(struct fw_unit *unit, + const struct ieee1394_device_id *entry) { - struct snd_tscm *tscm = container_of(work, struct snd_tscm, dwork.work); + struct snd_card *card; + struct snd_tscm *tscm; int err; - err = snd_card_new(&tscm->unit->device, -1, NULL, THIS_MODULE, 0, - &tscm->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*tscm), &card); if (err < 0) - return; - tscm->card->private_free = tscm_card_free; - tscm->card->private_data = tscm; + return err; + card->private_free = tscm_card_free; + + tscm = card->private_data; + tscm->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, tscm); + tscm->card = card; + + mutex_init(&tscm->mutex); + spin_lock_init(&tscm->lock); + init_waitqueue_head(&tscm->hwdep_wait); err = identify_model(tscm); if (err < 0) @@ -130,81 +142,33 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(tscm->card); + err = snd_card_register(card); if (err < 0) goto error; - tscm->registered = true; - - return; -error: - snd_card_free(tscm->card); - dev_info(&tscm->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int snd_tscm_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_tscm *tscm; - - /* Allocate this independent of sound card instance. */ - tscm = devm_kzalloc(&unit->device, sizeof(struct snd_tscm), GFP_KERNEL); - if (!tscm) - return -ENOMEM; - tscm->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, tscm); - - mutex_init(&tscm->mutex); - spin_lock_init(&tscm->lock); - init_waitqueue_head(&tscm->hwdep_wait); - - /* Allocate and register this sound card later. */ - INIT_DEFERRABLE_WORK(&tscm->dwork, do_registration); - snd_fw_schedule_registration(unit, &tscm->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void snd_tscm_update(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!tscm->registered) - snd_fw_schedule_registration(unit, &tscm->dwork); - snd_tscm_transaction_reregister(tscm); - /* - * After registration, userspace can start packet streaming, then this - * code block works fine. - */ - if (tscm->registered) { - mutex_lock(&tscm->mutex); - snd_tscm_stream_update_duplex(tscm); - mutex_unlock(&tscm->mutex); - } + mutex_lock(&tscm->mutex); + snd_tscm_stream_update_duplex(tscm); + mutex_unlock(&tscm->mutex); } static void snd_tscm_remove(struct fw_unit *unit) { struct snd_tscm *tscm = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_delayed_work_sync(&tscm->dwork); - - if (tscm->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(tscm->card); - } - - mutex_destroy(&tscm->mutex); - fw_unit_put(tscm->unit); + // Block till all of ALSA character devices are released. + snd_card_free(tscm->card); } static const struct ieee1394_device_id snd_tscm_id_table[] = { diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 78b7a08986a1..d07ffcb27be6 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -70,8 +70,6 @@ struct snd_tscm { struct mutex mutex; spinlock_t lock; - bool registered; - struct delayed_work dwork; const struct snd_tscm_spec *spec; struct fw_iso_resources tx_resources; @@ -99,6 +97,7 @@ struct snd_tscm { unsigned int push_pos; struct amdtp_domain domain; + bool need_long_tx_init_skip; }; #define TSCM_ADDR_BASE 0xffff00000000ull diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c index 8634d4f466b3..65012af6a36e 100644 --- a/sound/i2c/cs8427.c +++ b/sound/i2c/cs8427.c @@ -50,7 +50,8 @@ int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg, buf[0] = reg & 0x7f; buf[1] = val; - if ((err = snd_i2c_sendbytes(device, buf, 2)) != 2) { + err = snd_i2c_sendbytes(device, buf, 2); + if (err != 2) { snd_printk(KERN_ERR "unable to send bytes 0x%02x:0x%02x " "to CS8427 (%i)\n", buf[0], buf[1], err); return err < 0 ? err : -EIO; @@ -65,12 +66,14 @@ static int snd_cs8427_reg_read(struct snd_i2c_device *device, unsigned char reg) int err; unsigned char buf; - if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { + err = snd_i2c_sendbytes(device, ®, 1); + if (err != 1) { snd_printk(KERN_ERR "unable to send register 0x%x byte " "to CS8427\n", reg); return err < 0 ? err : -EIO; } - if ((err = snd_i2c_readbytes(device, &buf, 1)) != 1) { + err = snd_i2c_readbytes(device, &buf, 1); + if (err != 1) { snd_printk(KERN_ERR "unable to read register 0x%x byte " "from CS8427\n", reg); return err < 0 ? err : -EIO; @@ -108,7 +111,8 @@ static int snd_cs8427_send_corudata(struct snd_i2c_device *device, if (!memcmp(hw_data, ndata, count)) return 0; - if ((err = snd_cs8427_select_corudata(device, udata)) < 0) + err = snd_cs8427_select_corudata(device, udata); + if (err < 0) return err; memcpy(hw_data, ndata, count); if (udata) { @@ -209,7 +213,8 @@ int snd_cs8427_init(struct snd_i2c_bus *bus, goto __fail; /* send initial values */ memcpy(chip->regmap + (initvals1[0] & 0x7f), initvals1 + 1, 6); - if ((err = snd_i2c_sendbytes(device, initvals1, 7)) != 7) { + err = snd_i2c_sendbytes(device, initvals1, 7); + if (err != 7) { err = err < 0 ? err : -EIO; goto __fail; } @@ -217,11 +222,13 @@ int snd_cs8427_init(struct snd_i2c_bus *bus, memset(buf, 0, 7); /* from address 9 to 15 */ buf[0] = 9; /* register */ - if ((err = snd_i2c_sendbytes(device, buf, 7)) != 7) + err = snd_i2c_sendbytes(device, buf, 7); + if (err != 7) goto __fail; /* send transfer initialization sequence */ memcpy(chip->regmap + (initvals2[0] & 0x7f), initvals2 + 1, 3); - if ((err = snd_i2c_sendbytes(device, initvals2, 4)) != 4) { + err = snd_i2c_sendbytes(device, initvals2, 4); + if (err != 4) { err = err < 0 ? err : -EIO; goto __fail; } @@ -383,7 +390,8 @@ static int snd_cs8427_qsubcode_get(struct snd_kcontrol *kcontrol, int err; snd_i2c_lock(device->bus); - if ((err = snd_i2c_sendbytes(device, ®, 1)) != 1) { + err = snd_i2c_sendbytes(device, ®, 1); + if (err != 1) { snd_printk(KERN_ERR "unable to send register 0x%x byte " "to CS8427\n", reg); snd_i2c_unlock(device->bus); diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 2ce0a97957ab..c0cffe28989b 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -97,7 +97,8 @@ int snd_ak4114_create(struct snd_card *card, chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); chip->rcs1 = reg_read(chip, AK4114_REG_RCS1); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops); + if (err < 0) goto __fail; if (r_ak4114) diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 905be2d0780b..1bc43e927d82 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -86,7 +86,8 @@ int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t chip->rcs1 = reg_read(chip, AK4117_REG_RCS1); chip->rcs2 = reg_read(chip, AK4117_REG_RCS2); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops); + if (err < 0) goto __fail; if (r_ak4117) diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index 08eb6a873768..037d6293f728 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c @@ -115,7 +115,8 @@ static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol, bytes[count++] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] = tea->mright; } if (count > 0) { - if ((err = snd_i2c_sendbytes(tea->device, bytes, count)) < 0) + err = snd_i2c_sendbytes(tea->device, bytes, count); + if (err < 0) change = err; } snd_i2c_unlock(tea->bus); @@ -160,7 +161,8 @@ static int snd_tea6330t_put_master_switch(struct snd_kcontrol *kcontrol, bytes[0] = TEA6330T_SADDR_VOLUME_LEFT; bytes[1] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT]; bytes[2] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT]; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 3)) < 0) + err = snd_i2c_sendbytes(tea->device, bytes, 3); + if (err < 0) change = err; snd_i2c_unlock(tea->bus); return change; @@ -207,7 +209,8 @@ static int snd_tea6330t_put_bass(struct snd_kcontrol *kcontrol, change = tea->regs[TEA6330T_SADDR_BASS] != val1; bytes[0] = TEA6330T_SADDR_BASS; bytes[1] = tea->regs[TEA6330T_SADDR_BASS] = val1; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0) + err = snd_i2c_sendbytes(tea->device, bytes, 2); + if (err < 0) change = err; snd_i2c_unlock(tea->bus); return change; @@ -254,7 +257,8 @@ static int snd_tea6330t_put_treble(struct snd_kcontrol *kcontrol, change = tea->regs[TEA6330T_SADDR_TREBLE] != val1; bytes[0] = TEA6330T_SADDR_TREBLE; bytes[1] = tea->regs[TEA6330T_SADDR_TREBLE] = val1; - if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0) + err = snd_i2c_sendbytes(tea->device, bytes, 2); + if (err < 0) change = err; snd_i2c_unlock(tea->bus); return change; @@ -280,14 +284,15 @@ int snd_tea6330t_update_mixer(struct snd_card *card, struct tea6330t *tea; const struct snd_kcontrol_new *knew; unsigned int idx; - int err = -ENOMEM; + int err; u8 default_treble, default_bass; unsigned char bytes[7]; tea = kzalloc(sizeof(*tea), GFP_KERNEL); if (tea == NULL) return -ENOMEM; - if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) { + err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device); + if (err < 0) { kfree(tea); return err; } @@ -327,18 +332,21 @@ int snd_tea6330t_update_mixer(struct snd_card *card, bytes[0] = TEA6330T_SADDR_VOLUME_LEFT; for (idx = 0; idx < 6; idx++) bytes[idx+1] = tea->regs[idx]; - if ((err = snd_i2c_sendbytes(device, bytes, 7)) < 0) + err = snd_i2c_sendbytes(device, bytes, 7); + if (err < 0) goto __error; strcat(card->mixername, ",TEA6330T"); - if ((err = snd_component_add(card, "TEA6330T")) < 0) + err = snd_component_add(card, "TEA6330T"); + if (err < 0) goto __error; for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) { knew = &snd_tea6330t_controls[idx]; if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble")) continue; - if ((err = snd_ctl_add(card, snd_ctl_new1(knew, tea))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(knew, tea)); + if (err < 0) goto __error; } diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index f11af983b3b6..fa5bed0d5a6f 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c @@ -131,16 +131,18 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, return error; chip = card->private_data; - if ((error = snd_card_ad1816a_pnp(dev, pcard, pid))) { + error = snd_card_ad1816a_pnp(dev, pcard, pid); + if (error) { snd_card_free(card); return error; } - if ((error = snd_ad1816a_create(card, port[dev], - irq[dev], - dma1[dev], - dma2[dev], - chip)) < 0) { + error = snd_ad1816a_create(card, port[dev], + irq[dev], + dma1[dev], + dma2[dev], + chip); + if (error) { snd_card_free(card); return error; } @@ -152,12 +154,14 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d", card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]); - if ((error = snd_ad1816a_pcm(chip, 0)) < 0) { + error = snd_ad1816a_pcm(chip, 0); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_ad1816a_mixer(chip)) < 0) { + error = snd_ad1816a_mixer(chip); + if (error < 0) { snd_card_free(card); return error; } @@ -189,7 +193,8 @@ static int snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard, } } - if ((error = snd_card_register(card)) < 0) { + error = snd_card_register(card); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 01381fe7c0c9..6d4999b30461 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c @@ -155,7 +155,8 @@ static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode) snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE, AD1816A_TIMER_IRQ_ENABLE, 0x0000); } - if (!((chip->mode &= ~mode) & AD1816A_MODE_OPEN)) + chip->mode &= ~mode; + if (!(chip->mode & AD1816A_MODE_OPEN)) chip->mode = 0; spin_unlock_irqrestore(&chip->lock, flags); @@ -426,7 +427,8 @@ static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int error; - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0) + error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK); + if (error < 0) return error; runtime->hw = snd_ad1816a_playback; snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max); @@ -441,7 +443,8 @@ static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int error; - if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0) + error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE); + if (error < 0) return error; runtime->hw = snd_ad1816a_capture; snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max); @@ -586,7 +589,8 @@ int snd_ad1816a_create(struct snd_card *card, chip->dma1 = -1; chip->dma2 = -1; - if ((chip->res_port = request_region(port, 16, "AD1816A")) == NULL) { + chip->res_port = request_region(port, 16, "AD1816A"); + if (!chip->res_port) { snd_printk(KERN_ERR "ad1816a: can't grab port 0x%lx\n", port); snd_ad1816a_free(chip); return -EBUSY; @@ -615,7 +619,8 @@ int snd_ad1816a_create(struct snd_card *card, chip->port = port; spin_lock_init(&chip->lock); - if ((error = snd_ad1816a_probe(chip))) { + error = snd_ad1816a_probe(chip); + if (error) { snd_ad1816a_free(chip); return error; } @@ -623,7 +628,8 @@ int snd_ad1816a_create(struct snd_card *card, snd_ad1816a_init(chip); /* Register device */ - if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (error < 0) { snd_ad1816a_free(chip); return error; } @@ -652,7 +658,8 @@ int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device) int error; struct snd_pcm *pcm; - if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm))) + error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm); + if (error) return error; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1816a_playback_ops); @@ -682,7 +689,8 @@ int snd_ad1816a_timer(struct snd_ad1816a *chip, int device) tid.card = chip->card->number; tid.device = device; tid.subdevice = 0; - if ((error = snd_timer_new(chip->card, "AD1816A", &tid, &timer)) < 0) + error = snd_timer_new(chip->card, "AD1816A", &tid, &timer); + if (error < 0) return error; strcpy(timer->name, snd_ad1816a_chip_id(chip)); timer->private_data = chip; @@ -944,7 +952,8 @@ int snd_ad1816a_mixer(struct snd_ad1816a *chip) strcpy(card->mixername, snd_ad1816a_chip_id(chip)); for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip)); + if (err < 0) return err; } return 0; diff --git a/sound/isa/als100.c b/sound/isa/als100.c index bacb7a1b930c..d4597fdfe091 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -177,7 +177,8 @@ static int snd_card_als100_probe(int dev, return error; acard = card->private_data; - if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) { + error = snd_card_als100_pnp(dev, acard, pcard, pid); + if (error) { snd_card_free(card); return error; } @@ -211,12 +212,14 @@ static int snd_card_als100_probe(int dev, dma16[dev]); } - if ((error = snd_sb16dsp_pcm(chip, 0)) < 0) { + error = snd_sb16dsp_pcm(chip, 0); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_sbmixer_new(chip)) < 0) { + error = snd_sbmixer_new(chip); + if (error < 0) { snd_card_free(card); return error; } @@ -245,18 +248,21 @@ static int snd_card_als100_probe(int dev, snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", fm_port[dev], fm_port[dev] + 2); } else { - if ((error = snd_opl3_timer_new(opl3, 0, 1)) < 0) { + error = snd_opl3_timer_new(opl3, 0, 1); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (error < 0) { snd_card_free(card); return error; } } } - if ((error = snd_card_register(card)) < 0) { + error = snd_card_register(card); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index 867e9ae8f65a..dd5c059b3744 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c @@ -148,9 +148,11 @@ static int snd_card_azt2320_enable_wss(unsigned long port) { int error; - if ((error = snd_card_azt2320_command(port, 0x09))) + error = snd_card_azt2320_command(port, 0x09); + if (error) return error; - if ((error = snd_card_azt2320_command(port, 0x00))) + error = snd_card_azt2320_command(port, 0x00); + if (error) return error; mdelay(5); @@ -174,12 +176,14 @@ static int snd_card_azt2320_probe(int dev, return error; acard = card->private_data; - if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { + error = snd_card_azt2320_pnp(dev, acard, pcard, pid); + if (error) { snd_card_free(card); return error; } - if ((error = snd_card_azt2320_enable_wss(port[dev]))) { + error = snd_card_azt2320_enable_wss(port[dev]); + if (error) { snd_card_free(card); return error; } @@ -228,18 +232,21 @@ static int snd_card_azt2320_probe(int dev, snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n", fm_port[dev], fm_port[dev] + 2); } else { - if ((error = snd_opl3_timer_new(opl3, 1, 2)) < 0) { + error = snd_opl3_timer_new(opl3, 1, 2); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + error = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (error < 0) { snd_card_free(card); return error; } } } - if ((error = snd_card_register(card)) < 0) { + error = snd_card_register(card); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index bc112df10fc5..ef6d0a20efd8 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -284,7 +284,8 @@ static int cmi8330_add_sb_mixers(struct snd_sb *chip) } for (idx = 0; idx < ARRAY_SIZE(cmi8330_sb_mixers); idx++) { - if ((err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx])) < 0) + err = snd_sbmixer_add_ctl_elem(chip, &cmi8330_sb_mixers[idx]); + if (err < 0) return err; } return 0; @@ -307,7 +308,8 @@ static int snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard) } #ifdef ENABLE_SB_MIXER - if ((err = cmi8330_add_sb_mixers(acard->sb)) < 0) + err = cmi8330_add_sb_mixers(acard->sb); + if (err < 0) return err; #endif return 0; @@ -432,7 +434,8 @@ static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip) snd_cmi8330_capture_open }; - if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm); + if (err < 0) return err; strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330"); pcm->private_data = chip; @@ -536,18 +539,19 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) return -ENODEV; } - if ((err = snd_sbdsp_create(card, sbport[dev], - sbirq[dev], - snd_sb16dsp_interrupt, - sbdma8[dev], - sbdma16[dev], - SB_HW_AUTO, &acard->sb)) < 0) { + err = snd_sbdsp_create(card, sbport[dev], + sbirq[dev], + snd_sb16dsp_interrupt, + sbdma8[dev], + sbdma16[dev], + SB_HW_AUTO, &acard->sb); + if (err < 0) { snd_printk(KERN_ERR PFX "SB16 device busy??\n"); return err; } if (acard->sb->hardware != SB_HW_16) { snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); - return err; + return -ENODEV; } snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ @@ -555,12 +559,14 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) snd_wss_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]); - if ((err = snd_cmi8330_mixer(card, acard)) < 0) { + err = snd_cmi8330_mixer(card, acard); + if (err < 0) { snd_printk(KERN_ERR PFX "failed to create mixers\n"); return err; } - if ((err = snd_cmi8330_pcm(card, acard)) < 0) { + err = snd_cmi8330_pcm(card, acard); + if (err < 0) { snd_printk(KERN_ERR PFX "failed to create pcms\n"); return err; } @@ -622,7 +628,8 @@ static int snd_cmi8330_isa_probe(struct device *pdev, err = snd_cmi8330_card_new(pdev, dev, &card); if (err < 0) return err; - if ((err = snd_cmi8330_probe(card, dev)) < 0) { + err = snd_cmi8330_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -683,12 +690,14 @@ static int snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, res = snd_cmi8330_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; - if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) { + res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid); + if (res < 0) { snd_printk(KERN_ERR PFX "PnP detection failed\n"); snd_card_free(card); return res; } - if ((res = snd_cmi8330_probe(card, dev)) < 0) { + res = snd_cmi8330_probe(card, dev); + if (res < 0) { snd_card_free(card); return res; } diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 186d7d4db45e..0b7fd17f8ecc 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -339,11 +339,13 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) int err; acard = card->private_data; - if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) - if ((acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB")) == NULL) { + if (sb_port[dev] > 0 && sb_port[dev] != SNDRV_AUTO_PORT) { + acard->res_sb_port = request_region(sb_port[dev], 16, IDENT " SB"); + if (!acard->res_sb_port) { printk(KERN_ERR IDENT ": unable to register SB port at 0x%lx\n", sb_port[dev]); return -EBUSY; } + } err = snd_cs4236_create(card, port[dev], cport[dev], irq[dev], @@ -393,7 +395,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev) OPL3_HW_OPL3_CS, 0, &opl3) < 0) { printk(KERN_WARNING IDENT ": OPL3 not detected\n"); } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) return err; } } @@ -444,7 +447,8 @@ static int snd_cs423x_isa_probe(struct device *pdev, err = snd_cs423x_card_new(pdev, dev, &card); if (err < 0) return err; - if ((err = snd_cs423x_probe(card, dev)) < 0) { + err = snd_cs423x_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -538,7 +542,8 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev, snd_card_free(card); return err; } - if ((err = snd_cs423x_probe(card, dev)) < 0) { + err = snd_cs423x_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -592,13 +597,15 @@ static int snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, res = snd_cs423x_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; - if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) { + res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid); + if (res < 0) { printk(KERN_ERR "isapnp detection failed and probing for " IDENT " is not supported\n"); snd_card_free(card); return res; } - if ((res = snd_cs423x_probe(card, dev)) < 0) { + res = snd_cs423x_probe(card, dev); + if (res < 0) { snd_card_free(card); return res; } diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 52f05adb1870..63957aea456b 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -1030,12 +1030,14 @@ int snd_cs4236_mixer(struct snd_wss *chip) if (chip->hardware == WSS_HW_CS4235 || chip->hardware == WSS_HW_CS4239) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip)); + if (err < 0) return err; } } else { for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip)); + if (err < 0) return err; } } @@ -1058,13 +1060,15 @@ int snd_cs4236_mixer(struct snd_wss *chip) kcontrol = NULL; } for (idx = 0; idx < count; idx++, kcontrol++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip)); + if (err < 0) return err; } if (chip->hardware == WSS_HW_CS4237B || chip->hardware == WSS_HW_CS4238B) { for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip)); + if (err < 0) return err; } } diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 1816e55c6edf..8554cb2263c1 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -971,7 +971,8 @@ int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip) strcpy(card->mixername, snd_es1688_chip_id(chip)); for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip)); + if (err < 0) return err; } for (idx = 0; idx < ES1688_INIT_TABLE_SIZE; idx++) { diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 375a4a6a4717..68b9c59e1127 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1573,7 +1573,8 @@ static int snd_es18xx_identify(struct snd_es18xx *chip) udelay(10); chip->ctrl_port += inb(chip->port + 0x05); - if ((chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL")) == NULL) { + chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL"); + if (!chip->res_ctrl_port) { snd_printk(KERN_ERR PFX "unable go grab port 0x%lx\n", chip->ctrl_port); return -EBUSY; } @@ -1832,41 +1833,48 @@ static int snd_es18xx_mixer(struct snd_card *card) break; } } - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } if (chip->caps & ES18XX_PCM2) { for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm2_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip)); + if (err < 0) return err; } } else { for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_pcm1_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip)); + if (err < 0) return err; } } if (chip->caps & ES18XX_RECMIX) { for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_recmix_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip)); + if (err < 0) return err; } } switch (chip->version) { default: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip)); + if (err < 0) return err; break; case 0x1869: case 0x1879: - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip)); + if (err < 0) return err; break; } if (chip->caps & ES18XX_SPATIALIZER) { for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_spatializer_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip)); + if (err < 0) return err; } } @@ -1879,7 +1887,8 @@ static int snd_es18xx_mixer(struct snd_card *card) else chip->hw_switch = kctl; kctl->private_free = snd_es18xx_hwv_free; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } @@ -2154,7 +2163,8 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr) err = snd_es18xx_card_new(devptr, dev, &card); if (err < 0) return err; - if ((err = snd_audiodrive_probe(card, dev)) < 0) { + err = snd_audiodrive_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -2169,19 +2179,22 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev) static const int possible_dmas[] = {1, 0, 3, 5, -1}; if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { + irq[dev] = snd_legacy_find_free_irq(possible_irqs); + if (irq[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + dma1[dev] = snd_legacy_find_free_dma(possible_dmas); + if (dma1[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + dma2[dev] = snd_legacy_find_free_dma(possible_dmas); + if (dma2[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); return -EBUSY; } @@ -2257,11 +2270,13 @@ static int snd_audiodrive_pnp_detect(struct pnp_dev *pdev, err = snd_es18xx_card_new(&pdev->dev, dev, &card); if (err < 0) return err; - if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { + err = snd_audiodrive_pnp(dev, card->private_data, pdev); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_audiodrive_probe(card, dev)) < 0) { + err = snd_audiodrive_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -2315,11 +2330,13 @@ static int snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, if (res < 0) return res; - if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { + res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid); + if (res < 0) { snd_card_free(card); return res; } - if ((res = snd_audiodrive_probe(card, dev)) < 0) { + res = snd_audiodrive_probe(card, dev); + if (res < 0) { snd_card_free(card); return res; } diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index b7518122a10d..3b46490271fe 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -156,12 +156,14 @@ int snd_gus_create(struct snd_card *card, gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL); gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA); /* allocate resources */ - if ((gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)")) == NULL) { + gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)"); + if (!gus->gf1.res_port1) { snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); snd_gus_free(gus); return -EBUSY; } - if ((gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)")) == NULL) { + gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)"); + if (!gus->gf1.res_port2) { snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); snd_gus_free(gus); return -EBUSY; @@ -206,7 +208,8 @@ int snd_gus_create(struct snd_card *card, gus->gf1.pcm_channels = pcm_channels; gus->gf1.volume_ramp = 25; gus->gf1.smooth_pan = 1; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops); + if (err < 0) { snd_gus_free(gus); return err; } @@ -384,7 +387,7 @@ static int snd_gus_check_version(struct snd_gus_card * gus) } } } - strcpy(card->shortname, card->longname); + strscpy(card->shortname, card->longname, sizeof(card->shortname)); gus->uart_enable = 1; /* standard GUSes doesn't have midi uart trouble */ snd_gus_init_control(gus); return 0; @@ -395,14 +398,17 @@ int snd_gus_initialize(struct snd_gus_card *gus) int err; if (!gus->interwave) { - if ((err = snd_gus_check_version(gus)) < 0) { + err = snd_gus_check_version(gus); + if (err < 0) { snd_printk(KERN_ERR "version check failed\n"); return err; } - if ((err = snd_gus_detect_memory(gus)) < 0) + err = snd_gus_detect_memory(gus); + if (err < 0) return err; } - if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) + err = snd_gus_init_dma_irq(gus, 1); + if (err < 0) return err; snd_gf1_start(gus); gus->initialized = 1; diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index cb02d18dde60..ff9480f249fe 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -210,7 +210,8 @@ int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) struct snd_gf1_mem_block *block; snd_gf1_mem_lock(alloc, 0); - if ((block = snd_gf1_mem_look(alloc, address)) != NULL) { + block = snd_gf1_mem_look(alloc, address); + if (block) { result = snd_gf1_mem_xfree(alloc, block); snd_gf1_mem_lock(alloc, 1); return result; diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c index 201d0c40d0d9..03f9cfcbf601 100644 --- a/sound/isa/gus/gus_mixer.c +++ b/sound/isa/gus/gus_mixer.c @@ -162,12 +162,14 @@ int snd_gf1_new_mixer(struct snd_gus_card * gus) if (!gus->ics_flag) { max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls); for (idx = 0; idx < max; idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus)); + if (err < 0) return err; } } else { for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus)); + if (err < 0) return err; } } diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index aca4ab90e5bc..230f65a0e4b0 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -430,17 +430,19 @@ static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory); pcmp->memory = 0; } - if ((block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, - SNDRV_GF1_MEM_OWNER_DRIVER, - "GF1 PCM", - runtime->dma_bytes, 1, 32, - NULL)) == NULL) + block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc, + SNDRV_GF1_MEM_OWNER_DRIVER, + "GF1 PCM", + runtime->dma_bytes, 1, 32, + NULL); + if (!block) return -ENOMEM; pcmp->memory = block->ptr; } pcmp->voices = params_channels(hw_params); if (pcmp->pvoices[0] == NULL) { - if ((pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) + pcmp->pvoices[0] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0); + if (!pcmp->pvoices[0]) return -ENOMEM; pcmp->pvoices[0]->handler_wave = snd_gf1_pcm_interrupt_wave; pcmp->pvoices[0]->handler_volume = snd_gf1_pcm_interrupt_volume; @@ -448,7 +450,8 @@ static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, pcmp->pvoices[0]->private_data = pcmp; } if (pcmp->voices > 1 && pcmp->pvoices[1] == NULL) { - if ((pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0)) == NULL) + pcmp->pvoices[1] = snd_gf1_alloc_voice(pcmp->gus, SNDRV_GF1_VOICE_TYPE_PCM, 0, 0); + if (!pcmp->pvoices[1]) return -ENOMEM; pcmp->pvoices[1]->handler_wave = snd_gf1_pcm_interrupt_wave; pcmp->pvoices[1]->handler_volume = snd_gf1_pcm_interrupt_volume; @@ -689,7 +692,8 @@ static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream) printk(KERN_DEBUG "playback.buffer = 0x%lx, gf1.pcm_buffer = 0x%lx\n", (long) pcm->playback.buffer, (long) gus->gf1.pcm_buffer); #endif - if ((err = snd_gf1_dma_init(gus)) < 0) + err = snd_gf1_dma_init(gus); + if (err < 0) return err; pcmp->flags = SNDRV_GF1_PCM_PFLG_NONE; pcmp->substream = substream; @@ -888,7 +892,8 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index) kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus); else kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus); - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; kctl->id.index = control_index; diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c index 4fb4ed79e262..3975848160e7 100644 --- a/sound/isa/gus/gus_uart.c +++ b/sound/isa/gus/gus_uart.c @@ -232,7 +232,8 @@ int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi); + if (err < 0) return err; strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1"); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_gf1_uart_output); diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c index 0fba5d8fe84f..bca1caa4968c 100644 --- a/sound/isa/gus/gusclassic.c +++ b/sound/isa/gus/gusclassic.c @@ -113,14 +113,16 @@ static int snd_gusclassic_detect(struct snd_gus_card *gus) unsigned char d; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 0) { snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 1) { snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c index da2b2ca6b721..a409a4a29afc 100644 --- a/sound/isa/gus/gusextreme.c +++ b/sound/isa/gus/gusextreme.c @@ -177,14 +177,16 @@ static int snd_gusextreme_detect(struct snd_gus_card *gus, udelay(100); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 0) { snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -EIO; } udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 1) { snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -EIO; } diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c index 24b945f1768d..ad118d462142 100644 --- a/sound/isa/gus/gusmax.c +++ b/sound/isa/gus/gusmax.c @@ -71,14 +71,16 @@ static int snd_gusmax_detect(struct snd_gus_card *gus) unsigned char d; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 0) { snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 1) { snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } @@ -136,20 +138,24 @@ static int snd_gusmax_mixer(struct snd_wss *chip) /* reassign AUXA to SYNTHESIZER */ strcpy(id1.name, "Aux Playback Switch"); strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; /* reassign AUXB to CD */ strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; #if 0 /* reassign Mono Input to MIC */ @@ -209,7 +215,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) xirq = irq[dev]; if (xirq == SNDRV_AUTO_IRQ) { - if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) { + xirq = snd_legacy_find_free_irq(possible_irqs); + if (xirq < 0) { snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); err = -EBUSY; goto _err; @@ -217,7 +224,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) } xdma1 = dma1[dev]; if (xdma1 == SNDRV_AUTO_DMA) { - if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) { + xdma1 = snd_legacy_find_free_dma(possible_dmas); + if (xdma1 < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); err = -EBUSY; goto _err; @@ -225,7 +233,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) } xdma2 = dma2[dev]; if (xdma2 == SNDRV_AUTO_DMA) { - if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) { + xdma2 = snd_legacy_find_free_dma(possible_dmas); + if (xdma2 < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); err = -EBUSY; goto _err; @@ -260,13 +269,15 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) if (err < 0) goto _err; - if ((err = snd_gusmax_detect(gus)) < 0) + err = snd_gusmax_detect(gus); + if (err < 0) goto _err; maxcard->gus_status_reg = gus->gf1.reg_irqstat; maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2; snd_gusmax_init(dev, card, gus); - if ((err = snd_gus_initialize(gus)) < 0) + err = snd_gus_initialize(gus); + if (err < 0) goto _err; if (!gus->max_flag) { @@ -307,7 +318,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev) goto _err; if (pcm_channels[dev] > 0) { - if ((err = snd_gf1_pcm_new(gus, 1, 1)) < 0) + err = snd_gf1_pcm_new(gus, 1, 1); + if (err < 0) goto _err; } err = snd_gusmax_mixer(wss); diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 99581fba4ca8..755de47d0bb6 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -204,7 +204,8 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard, port = 0x360; } while (port <= 0x380) { - if ((iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)")) != NULL) + iwcard->i2c_res = request_region(port, 1, "InterWave (I2C bus)"); + if (iwcard->i2c_res) break; port += 0x10; } @@ -217,11 +218,13 @@ static int snd_interwave_detect_stb(struct snd_interwave *iwcard, } sprintf(name, "InterWave-%i", card->number); - if ((err = snd_i2c_bus_create(card, name, NULL, &bus)) < 0) + err = snd_i2c_bus_create(card, name, NULL, &bus); + if (err < 0) return err; bus->private_value = port; bus->hw_ops.bit = &snd_interwave_i2c_bit_ops; - if ((err = snd_tea6330t_detect(bus, 0)) < 0) + err = snd_tea6330t_detect(bus, 0); + if (err < 0) return err; *rbus = bus; return 0; @@ -241,14 +244,16 @@ static int snd_interwave_detect(struct snd_interwave *iwcard, int d; snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0); /* reset GF1 */ - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 0) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 0) { snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } udelay(160); snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* release reset */ udelay(160); - if (((d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET)) & 0x07) != 1) { + d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET); + if ((d & 0x07) != 1) { snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d); return -ENODEV; } @@ -493,16 +498,20 @@ static int snd_interwave_mixer(struct snd_wss *chip) #if 0 /* remove mono microphone controls */ strcpy(id1.name, "Mic Playback Switch"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) + err = snd_ctl_remove_id(card, &id1); + if (err < 0) return err; strcpy(id1.name, "Mic Playback Volume"); - if ((err = snd_ctl_remove_id(card, &id1)) < 0) + err = snd_ctl_remove_id(card, &id1); + if (err < 0) return err; #endif /* add new master and mic controls */ - for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip)); + if (err < 0) return err; + } snd_wss_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f); snd_wss_out(chip, CS4231_LINE_RIGHT_OUTPUT, 0x9f); snd_wss_out(chip, CS4231_LEFT_MIC_INPUT, 0x9f); @@ -510,20 +519,24 @@ static int snd_interwave_mixer(struct snd_wss *chip) /* reassign AUXA to SYNTHESIZER */ strcpy(id1.name, "Aux Playback Switch"); strcpy(id2.name, "Synth Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "Synth Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; /* reassign AUXB to CD */ strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; return 0; } @@ -633,18 +646,20 @@ static int snd_interwave_probe(struct snd_card *card, int dev) xdma1 = dma1[dev]; xdma2 = dma2[dev]; - if ((err = snd_gus_create(card, - port[dev], - -xirq, xdma1, xdma2, - 0, 32, - pcm_channels[dev], effect[dev], &gus)) < 0) + err = snd_gus_create(card, + port[dev], + -xirq, xdma1, xdma2, + 0, 32, + pcm_channels[dev], effect[dev], &gus); + if (err < 0) return err; - if ((err = snd_interwave_detect(iwcard, gus, dev + err = snd_interwave_detect(iwcard, gus, dev #ifdef SNDRV_STB - , &i2c_bus + , &i2c_bus #endif - )) < 0) + ); + if (err < 0) return err; iwcard->gus_status_reg = gus->gf1.reg_irqstat; @@ -652,7 +667,8 @@ static int snd_interwave_probe(struct snd_card *card, int dev) snd_interwave_init(dev, gus); snd_interwave_detect_memory(gus); - if ((err = snd_gus_initialize(gus)) < 0) + err = snd_gus_initialize(gus); + if (err < 0) return err; if (request_irq(xirq, snd_interwave_interrupt, 0, @@ -708,19 +724,23 @@ static int snd_interwave_probe(struct snd_card *card, int dev) strcpy(id1.name, "Master Playback Switch"); strcpy(id2.name, id1.name); id2.index = 1; - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; strcpy(id1.name, "Master Playback Volume"); strcpy(id2.name, id1.name); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) return err; - if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0) + err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1); + if (err < 0) return err; } #endif gus->uart_enable = midi[dev]; - if ((err = snd_gf1_rawmidi_new(gus, 0)) < 0) + err = snd_gf1_rawmidi_new(gus, 0); + if (err < 0) return err; #ifndef SNDRV_STB @@ -758,7 +778,8 @@ static int snd_interwave_isa_probe1(int dev, struct device *devptr) if (err < 0) return err; - if ((err = snd_interwave_probe(card, dev)) < 0) { + err = snd_interwave_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -786,19 +807,22 @@ static int snd_interwave_isa_probe(struct device *pdev, static const int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1}; if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { + irq[dev] = snd_legacy_find_free_irq(possible_irqs); + if (irq[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); return -EBUSY; } } if (dma1[dev] == SNDRV_AUTO_DMA) { - if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + dma1[dev] = snd_legacy_find_free_dma(possible_dmas); + if (dma1[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA1\n"); return -EBUSY; } } if (dma2[dev] == SNDRV_AUTO_DMA) { - if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) { + dma2[dev] = snd_legacy_find_free_dma(possible_dmas); + if (dma2[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free DMA2\n"); return -EBUSY; } @@ -853,11 +877,13 @@ static int snd_interwave_pnp_detect(struct pnp_card_link *pcard, if (res < 0) return res; - if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) { + res = snd_interwave_pnp(dev, card->private_data, pcard, pid); + if (res < 0) { snd_card_free(card); return res; } - if ((res = snd_interwave_probe(card, dev)) < 0) { + res = snd_interwave_probe(card, dev); + if (res < 0) { snd_card_free(card); return res; } diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 9bde11d1cfe8..6f42f869928c 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -208,7 +208,8 @@ static int snd_opl3sa2_detect(struct snd_card *card) char str[2]; port = chip->port; - if ((chip->res_port = request_region(port, 2, "OPL3-SA control")) == NULL) { + chip->res_port = request_region(port, 2, "OPL3-SA control"); + if (!chip->res_port) { snd_printk(KERN_ERR PFX "can't grab port 0x%lx\n", port); return -EBUSY; } @@ -239,14 +240,16 @@ static int snd_opl3sa2_detect(struct snd_card *card) str[1] = 0; strcat(card->shortname, str); snd_opl3sa2_write(chip, OPL3SA2_MISC, tmp ^ 7); - if ((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC)) != tmp) { + tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MISC); + if (tmp1 != tmp) { snd_printd("OPL3-SA [0x%lx] detect (1) = 0x%x (0x%x)\n", port, tmp, tmp1); return -ENODEV; } /* try if the MIC register is accessible */ tmp = snd_opl3sa2_read(chip, OPL3SA2_MIC); snd_opl3sa2_write(chip, OPL3SA2_MIC, 0x8a); - if (((tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC)) & 0x9f) != 0x8a) { + tmp1 = snd_opl3sa2_read(chip, OPL3SA2_MIC); + if ((tmp1 & 0x9f) != 0x8a) { snd_printd("OPL3-SA [0x%lx] detect (2) = 0x%x (0x%x)\n", port, tmp, tmp1); return -ENODEV; } @@ -489,32 +492,38 @@ static int snd_opl3sa2_mixer(struct snd_card *card) /* reassign AUX0 to CD */ strcpy(id1.name, "Aux Playback Switch"); strcpy(id2.name, "CD Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); return err; } strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "CD Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); return err; } /* reassign AUX1 to FM */ strcpy(id1.name, "Aux Playback Switch"); id1.index = 1; strcpy(id2.name, "FM Playback Switch"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); return err; } strcpy(id1.name, "Aux Playback Volume"); strcpy(id2.name, "FM Playback Volume"); - if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) { + err = snd_ctl_rename_id(card, &id1, &id2); + if (err < 0) { snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n"); return err; } /* add OPL3SA2 controls */ for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0) + kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; switch (idx) { case 0: chip->master_switch = kctl; kctl->private_free = snd_opl3sa2_master_free; break; @@ -522,9 +531,11 @@ static int snd_opl3sa2_mixer(struct snd_card *card) } } if (chip->version > 2) { - for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip)); + if (err < 0) return err; + } } return 0; } @@ -677,20 +688,24 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev) if (err < 0) return err; if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) { - if ((err = snd_opl3_create(card, fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3, 0, &opl3)) < 0) + err = snd_opl3_create(card, fm_port[dev], + fm_port[dev] + 2, + OPL3_HW_OPL3, 0, &opl3); + if (err < 0) return err; - if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0) + err = snd_opl3_timer_new(opl3, 1, 2); + if (err < 0) return err; - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0) + err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth); + if (err < 0) return err; } if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, - midi_port[dev], - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) + err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2, + midi_port[dev], + MPU401_INFO_IRQ_HOOK, -1, + &chip->rmidi); + if (err < 0) return err; } sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", @@ -721,11 +736,13 @@ static int snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, err = snd_opl3sa2_card_new(&pdev->dev, dev, &card); if (err < 0) return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { + err = snd_opl3sa2_pnp(dev, card->private_data, pdev); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { + err = snd_opl3sa2_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -785,11 +802,13 @@ static int snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, err = snd_opl3sa2_card_new(&pdev->dev, dev, &card); if (err < 0) return err; - if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) { + err = snd_opl3sa2_pnp(dev, card->private_data, pdev); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { + err = snd_opl3sa2_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -865,7 +884,8 @@ static int snd_opl3sa2_isa_probe(struct device *pdev, err = snd_opl3sa2_card_new(pdev, dev, &card); if (err < 0) return err; - if ((err = snd_opl3sa2_probe(card, dev)) < 0) { + err = snd_opl3sa2_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index a510b201143c..e1fb7567fdcc 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -722,35 +722,43 @@ static int snd_miro_mixer(struct snd_card *card, } for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro)); + if (err < 0) return err; } if ((miro->aci->aci_product == 'A') || (miro->aci->aci_product == 'B')) { /* PCM1/PCM12 with power-amp and Line 2 */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro)); + if (err < 0) return err; } if ((miro->aci->aci_product == 'B') || (miro->aci->aci_product == 'C')) { /* PCM12/PCM20 with mic-preamp */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro)); + if (err < 0) return err; - if (miro->aci->aci_version >= 176) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0) + if (miro->aci->aci_version >= 176) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro)); + if (err < 0) return err; + } } if (miro->aci->aci_product == 'C') { /* PCM20 with radio and 7 band equalizer */ - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro)); + if (err < 0) return err; for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro)); + if (err < 0) return err; } } @@ -1178,7 +1186,8 @@ static int snd_card_miro_detect(struct snd_card *card, for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { - if ((err = snd_miro_init(chip, i)) < 0) + err = snd_miro_init(chip, i); + if (err < 0) return err; err = snd_miro_opti_check(chip); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 08e61d90057b..4bd1dc6707fc 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -970,32 +970,37 @@ static int snd_opti9xx_isa_probe(struct device *devptr, #endif /* CS4231 || OPTi93X */ if (mpu_port == SNDRV_AUTO_PORT) { - if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { + mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); + if (mpu_port < 0) { snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); return -EBUSY; } } if (irq == SNDRV_AUTO_IRQ) { - if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { + irq = snd_legacy_find_free_irq(possible_irqs); + if (irq < 0) { snd_printk(KERN_ERR "unable to find a free IRQ\n"); return -EBUSY; } } if (mpu_irq == SNDRV_AUTO_IRQ) { - if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) { + mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); + if (mpu_irq < 0) { snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); return -EBUSY; } } if (dma1 == SNDRV_AUTO_DMA) { - if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) { + dma1 = snd_legacy_find_free_dma(possible_dma1s); + if (dma1 < 0) { snd_printk(KERN_ERR "unable to find a free DMA1\n"); return -EBUSY; } } #if defined(CS4231) || defined(OPTi93X) if (dma2 == SNDRV_AUTO_DMA) { - if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) { + dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); + if (dma2 < 0) { snd_printk(KERN_ERR "unable to find a free DMA2\n"); return -EBUSY; } @@ -1006,11 +1011,13 @@ static int snd_opti9xx_isa_probe(struct device *devptr, if (error < 0) return error; - if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) { + error = snd_card_opti9xx_detect(card, card->private_data); + if (error < 0) { snd_card_free(card); return error; } - if ((error = snd_opti9xx_probe(card)) < 0) { + error = snd_opti9xx_probe(card); + if (error < 0) { snd_card_free(card); return error; } @@ -1111,7 +1118,8 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, return -ENODEV; } - if ((error = snd_opti9xx_init(chip, hw))) { + error = snd_opti9xx_init(chip, hw); + if (error) { snd_card_free(card); return error; } @@ -1121,7 +1129,8 @@ static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } - if ((error = snd_opti9xx_probe(card)) < 0) { + error = snd_opti9xx_probe(card); + if (error < 0) { snd_card_free(card); return error; } diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 1c90421a88dc..5e4187940265 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -1020,6 +1020,7 @@ static const struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = { static int snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) { + struct snd_kcontrol *kctl; int i, err = 0; if (snd_BUG_ON(!emu || !card)) @@ -1029,10 +1030,11 @@ snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) memset(emu->controls, 0, sizeof(emu->controls)); for (i = 0; i < EMU8000_NUM_CONTROLS; i++) { - if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0) { - emu->controls[i] = NULL; + kctl = snd_ctl_new1(mixer_defs[i], emu); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __error; - } + emu->controls[i] = kctl; } return 0; @@ -1095,9 +1097,10 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, hw->port1 = port; hw->port2 = port + 0x400; hw->port3 = port + 0x800; - if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) || - !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) || - !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) { + hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1"); + hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2"); + hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"); + if (!hw->res_port1 || !hw->res_port2 || !hw->res_port3) { snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3); snd_emu8000_free(hw); return -EBUSY; @@ -1118,12 +1121,14 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, } snd_emu8000_init_hw(hw); - if ((err = snd_emu8000_create_mixer(card, hw)) < 0) { + err = snd_emu8000_create_mixer(card, hw); + if (err < 0) { snd_emu8000_free(hw); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops); + if (err < 0) { snd_emu8000_free(hw); return err; } diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 0cb94cafb4c9..8c1e7f2bfc34 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -191,7 +191,8 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp, sp->v.truesize = truesize * 2; /* in bytes */ snd_emux_terminate_all(emu->emu); - if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0) + rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE); + if (rc) return rc; /* Set the address to start writing at */ diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 8e8257c574b0..f8d90a1e989b 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -626,7 +626,8 @@ static int emu8k_pcm_prepare(struct snd_pcm_substream *subs) int err, i, ch; snd_emux_terminate_all(rec->emu->emu); - if ((err = emu8k_open_dram_for_pcm(rec->emu, rec->voices)) != 0) + err = emu8k_open_dram_for_pcm(rec->emu, rec->voices); + if (err) return err; rec->dram_opened = 1; @@ -682,7 +683,8 @@ int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int inde struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0) + err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm); + if (err < 0) return err; pcm->private_data = emu; pcm->private_free = snd_emu8000_pcm_free; diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 63ef960abd25..d0f797c02841 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -332,14 +332,9 @@ static int snd_sb16_probe(struct snd_card *card, int dev) xdma8 = dma8[dev]; xdma16 = dma16[dev]; - if ((err = snd_sbdsp_create(card, - port[dev], - xirq, - snd_sb16dsp_interrupt, - xdma8, - xdma16, - SB_HW_AUTO, - &chip)) < 0) + err = snd_sbdsp_create(card, port[dev], xirq, snd_sb16dsp_interrupt, + xdma8, xdma16, SB_HW_AUTO, &chip); + if (err < 0) return err; acard->chip = chip; @@ -348,10 +343,14 @@ static int snd_sb16_probe(struct snd_card *card, int dev) return -ENODEV; } chip->mpu_port = mpu_port[dev]; - if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0) - return err; + if (!is_isapnp_selected(dev)) { + err = snd_sb16dsp_configure(chip); + if (err < 0) + return err; + } - if ((err = snd_sb16dsp_pcm(chip, 0)) < 0) + err = snd_sb16dsp_pcm(chip, 0); + if (err < 0) return err; strcpy(card->driver, @@ -371,10 +370,11 @@ static int snd_sb16_probe(struct snd_card *card, int dev) xdma8 >= 0 ? "&" : "", xdma16); if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, - chip->mpu_port, - MPU401_INFO_IRQ_HOOK, -1, - &chip->rmidi)) < 0) + err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB, + chip->mpu_port, + MPU401_INFO_IRQ_HOOK, -1, + &chip->rmidi); + if (err < 0) return err; chip->rmidi_callback = snd_mpu401_uart_interrupt; } @@ -397,12 +397,14 @@ static int snd_sb16_probe(struct snd_card *card, int dev) #else int seqdev = 1; #endif - if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0) + err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth); + if (err < 0) return err; } } - if ((err = snd_sbmixer_new(chip)) < 0) + err = snd_sbmixer_new(chip); + if (err < 0) return err; #ifdef CONFIG_SND_SB16_CSP @@ -419,8 +421,9 @@ static int snd_sb16_probe(struct snd_card *card, int dev) #endif #ifdef SNDRV_SBAWE_EMU8000 if (awe_port[dev] > 0) { - if ((err = snd_emu8000_new(card, 1, awe_port[dev], - seq_ports[dev], NULL)) < 0) { + err = snd_emu8000_new(card, 1, awe_port[dev], + seq_ports[dev], NULL); + if (err < 0) { snd_printk(KERN_ERR PFX "fatal error - EMU-8000 synthesizer not detected at 0x%lx\n", awe_port[dev]); return err; @@ -435,7 +438,8 @@ static int snd_sb16_probe(struct snd_card *card, int dev) (mic_agc[dev] ? 0x00 : 0x01)); spin_unlock_irqrestore(&chip->mixer_lock, flags); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) return err; return 0; @@ -484,7 +488,8 @@ static int snd_sb16_isa_probe1(int dev, struct device *pdev) awe_port[dev] = port[dev] + 0x400; #endif - if ((err = snd_sb16_probe(card, dev)) < 0) { + err = snd_sb16_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -506,19 +511,22 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev) static const int possible_dmas16[] = {5, 6, 7, -1}; if (irq[dev] == SNDRV_AUTO_IRQ) { - if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) { + irq[dev] = snd_legacy_find_free_irq(possible_irqs); + if (irq[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free IRQ\n"); return -EBUSY; } } if (dma8[dev] == SNDRV_AUTO_DMA) { - if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) { + dma8[dev] = snd_legacy_find_free_dma(possible_dmas8); + if (dma8[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n"); return -EBUSY; } } if (dma16[dev] == SNDRV_AUTO_DMA) { - if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) { + dma16[dev] = snd_legacy_find_free_dma(possible_dmas16); + if (dma16[dev] < 0) { snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n"); return -EBUSY; } @@ -591,8 +599,13 @@ static int snd_sb16_pnp_detect(struct pnp_card_link *pcard, res = snd_sb16_card_new(&pcard->card->dev, dev, &card); if (res < 0) return res; - if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 || - (res = snd_sb16_probe(card, dev)) < 0) { + res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid); + if (res < 0) { + snd_card_free(card); + return res; + } + res = snd_sb16_probe(card, dev); + if (res < 0) { snd_card_free(card); return res; } diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 4789345a8fdd..5bbe6695689d 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -112,10 +112,12 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep) if (csp_detect(chip, &version)) return -ENODEV; - if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0) + err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw); + if (err < 0) return err; - if ((p = kzalloc(sizeof(*p), GFP_KERNEL)) == NULL) { + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { snd_device_free(chip->card, hw); return -ENOMEM; } @@ -1034,6 +1036,7 @@ static const struct snd_kcontrol_new snd_sb_qsound_space = { static int snd_sb_qsound_build(struct snd_sb_csp * p) { struct snd_card *card; + struct snd_kcontrol *kctl; int err; if (snd_BUG_ON(!p)) @@ -1045,14 +1048,16 @@ static int snd_sb_qsound_build(struct snd_sb_csp * p) spin_lock_init(&p->q_lock); - if ((err = snd_ctl_add(card, p->qsound_switch = snd_ctl_new1(&snd_sb_qsound_switch, p))) < 0) { - p->qsound_switch = NULL; + kctl = snd_ctl_new1(&snd_sb_qsound_switch, p); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __error; - } - if ((err = snd_ctl_add(card, p->qsound_space = snd_ctl_new1(&snd_sb_qsound_space, p))) < 0) { - p->qsound_space = NULL; + p->qsound_switch = kctl; + kctl = snd_ctl_new1(&snd_sb_qsound_space, p); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __error; - } + p->qsound_space = kctl; return 0; @@ -1072,10 +1077,14 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) card = p->chip->card; down_write(&card->controls_rwsem); - if (p->qsound_switch) + if (p->qsound_switch) { snd_ctl_remove(card, p->qsound_switch); - if (p->qsound_space) + p->qsound_switch = NULL; + } + if (p->qsound_space) { snd_ctl_remove(card, p->qsound_space); + p->qsound_space = NULL; + } up_write(&card->controls_rwsem); /* cancel pending transfer of QSound parameters */ diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index aa4870531023..a9b87e159b2d 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -703,7 +703,8 @@ static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ct unsigned char nval, oval; int change; - if ((nval = ucontrol->value.enumerated.item[0]) > 2) + nval = ucontrol->value.enumerated.item[0]; + if (nval > 2) return -EINVAL; spin_lock_irqsave(&chip->reg_lock, flags); oval = snd_sb16_get_dma_mode(chip); @@ -836,7 +837,8 @@ int snd_sb16dsp_pcm(struct snd_sb *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm); + if (err < 0) return err; sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index ed3a87ebe3f4..b08e6e7690c9 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -101,12 +101,10 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) acard->fm_res = request_region(0x388, 4, "SoundBlaster FM"); if (port[dev] != SNDRV_AUTO_PORT) { - if ((err = snd_sbdsp_create(card, port[dev], irq[dev], - snd_sb8_interrupt, - dma8[dev], - -1, - SB_HW_AUTO, - &chip)) < 0) + err = snd_sbdsp_create(card, port[dev], irq[dev], + snd_sb8_interrupt, dma8[dev], + -1, SB_HW_AUTO, &chip); + if (err < 0) goto _err; } else { /* auto-probe legacy ports */ @@ -145,32 +143,35 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) goto _err; } - if ((err = snd_sb8dsp_pcm(chip, 0)) < 0) + err = snd_sb8dsp_pcm(chip, 0); + if (err < 0) goto _err; - if ((err = snd_sbmixer_new(chip)) < 0) + err = snd_sbmixer_new(chip); + if (err < 0) goto _err; if (chip->hardware == SB_HW_10 || chip->hardware == SB_HW_20) { - if ((err = snd_opl3_create(card, chip->port + 8, 0, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { + err = snd_opl3_create(card, chip->port + 8, 0, + OPL3_HW_AUTO, 1, &opl3); + if (err < 0) snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx\n", chip->port + 8); - } } else { - if ((err = snd_opl3_create(card, chip->port, chip->port + 2, - OPL3_HW_AUTO, 1, - &opl3)) < 0) { + err = snd_opl3_create(card, chip->port, chip->port + 2, + OPL3_HW_AUTO, 1, &opl3); + if (err < 0) { snd_printk(KERN_WARNING "sb8: no OPL device at 0x%lx-0x%lx\n", chip->port, chip->port + 2); } } if (err >= 0) { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) goto _err; } - if ((err = snd_sb8dsp_midi(chip, 0)) < 0) + err = snd_sb8dsp_midi(chip, 0); + if (err < 0) goto _err; strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8"); @@ -180,7 +181,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev) chip->port, irq[dev], dma8[dev]); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto _err; dev_set_drvdata(pdev, card); diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 8d01692c4f2a..2ed176a5a574 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -567,7 +567,8 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device) int err; size_t max_prealloc = 64 * 1024; - if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm); + if (err < 0) return err; sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff); pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index 8c01460539ed..618366d5d984 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c @@ -251,7 +251,8 @@ int snd_sb8dsp_midi(struct snd_sb *chip, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi); + if (err < 0) return err; strcpy(rmidi->name, "SB8 MIDI"); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output); diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index 61ea4078aa95..57121218ed24 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c @@ -238,7 +238,8 @@ int snd_sbdsp_create(struct snd_card *card, if (hardware == SB_HW_ALS4000) goto __skip_allocation; - if ((chip->res_port = request_region(port, 16, "SoundBlaster")) == NULL) { + chip->res_port = request_region(port, 16, "SoundBlaster"); + if (!chip->res_port) { snd_printk(KERN_ERR "sb: can't grab port 0x%lx\n", port); snd_sbdsp_free(chip); return -EBUSY; @@ -267,11 +268,13 @@ int snd_sbdsp_create(struct snd_card *card, __skip_allocation: chip->card = card; chip->hardware = hardware; - if ((err = snd_sbdsp_probe(chip)) < 0) { + err = snd_sbdsp_probe(chip); + if (err < 0) { snd_sbdsp_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_sbdsp_free(chip); return err; } diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 5de5506e7e60..fffd681e5bf7 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c @@ -485,7 +485,8 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty strscpy(ctl->id.name, name, sizeof(ctl->id.name)); ctl->id.index = index; ctl->private_value = value; - if ((err = snd_ctl_add(chip->card, ctl)) < 0) + err = snd_ctl_add(chip->card, ctl); + if (err < 0) return err; return 0; } @@ -736,33 +737,36 @@ int snd_sbmixer_new(struct snd_sb *chip) return 0; /* no mixer chip on SB1.x */ case SB_HW_20: case SB_HW_201: - if ((err = snd_sbmixer_init(chip, - snd_sb20_controls, - ARRAY_SIZE(snd_sb20_controls), - snd_sb20_init_values, - ARRAY_SIZE(snd_sb20_init_values), - "CTL1335")) < 0) + err = snd_sbmixer_init(chip, + snd_sb20_controls, + ARRAY_SIZE(snd_sb20_controls), + snd_sb20_init_values, + ARRAY_SIZE(snd_sb20_init_values), + "CTL1335"); + if (err < 0) return err; break; case SB_HW_PRO: case SB_HW_JAZZ16: - if ((err = snd_sbmixer_init(chip, - snd_sbpro_controls, - ARRAY_SIZE(snd_sbpro_controls), - snd_sbpro_init_values, - ARRAY_SIZE(snd_sbpro_init_values), - "CTL1345")) < 0) + err = snd_sbmixer_init(chip, + snd_sbpro_controls, + ARRAY_SIZE(snd_sbpro_controls), + snd_sbpro_init_values, + ARRAY_SIZE(snd_sbpro_init_values), + "CTL1345"); + if (err < 0) return err; break; case SB_HW_16: case SB_HW_ALS100: case SB_HW_CS5530: - if ((err = snd_sbmixer_init(chip, - snd_sb16_controls, - ARRAY_SIZE(snd_sb16_controls), - snd_sb16_init_values, - ARRAY_SIZE(snd_sb16_init_values), - "CTL1745")) < 0) + err = snd_sbmixer_init(chip, + snd_sb16_controls, + ARRAY_SIZE(snd_sb16_controls), + snd_sb16_init_values, + ARRAY_SIZE(snd_sb16_init_values), + "CTL1745"); + if (err < 0) return err; break; case SB_HW_ALS4000: @@ -775,12 +779,13 @@ int snd_sbmixer_new(struct snd_sb *chip) "ALS4000"); if (err < 0) return err; - if ((err = snd_sbmixer_init(chip, - snd_als4000_controls, - ARRAY_SIZE(snd_als4000_controls), - snd_als4000_init_values, - ARRAY_SIZE(snd_als4000_init_values), - "ALS4000")) < 0) + err = snd_sbmixer_init(chip, + snd_als4000_controls, + ARRAY_SIZE(snd_als4000_controls), + snd_als4000_init_values, + ARRAY_SIZE(snd_als4000_init_values), + "ALS4000"); + if (err < 0) return err; break; case SB_HW_DT019X: diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index a4437971df2f..dfdeaf7b6bf4 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -555,7 +555,8 @@ static int snd_wavefront_isa_probe(struct device *pdev, err = snd_wavefront_card_new(pdev, dev, &card); if (err < 0) return err; - if ((err = snd_wavefront_probe(card, dev)) < 0) { + err = snd_wavefront_probe(card, dev); + if (err < 0) { snd_card_free(card); return err; } @@ -610,7 +611,8 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard, } } - if ((res = snd_wavefront_probe(card, dev)) < 0) + res = snd_wavefront_probe(card, dev); + if (res < 0) return res; pnp_set_card_drvdata(pcard, card); diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index a337a86f7a65..72e775ac7ad7 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -239,7 +239,8 @@ static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) + midi = get_wavefront_midi(substream); + if (!midi) return -EIO; spin_lock_irqsave (&midi->open, flags); @@ -263,7 +264,8 @@ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substrea mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) + midi = get_wavefront_midi(substream); + if (!midi) return -EIO; spin_lock_irqsave (&midi->open, flags); @@ -287,7 +289,8 @@ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substrea mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) + midi = get_wavefront_midi(substream); + if (!midi) return -EIO; spin_lock_irqsave (&midi->open, flags); @@ -310,7 +313,8 @@ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substre mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) + midi = get_wavefront_midi(substream); + if (!midi) return -EIO; spin_lock_irqsave (&midi->open, flags); @@ -333,9 +337,9 @@ static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *subst mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) { + midi = get_wavefront_midi(substream); + if (!midi) return; - } spin_lock_irqsave (&midi->virtual, flags); if (up) { @@ -372,9 +376,9 @@ static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *subs mpu = *((snd_wavefront_mpu_id *) substream->rmidi->private_data); - if ((midi = get_wavefront_midi (substream)) == NULL) { + midi = get_wavefront_midi(substream); + if (!midi) return; - } spin_lock_irqsave (&midi->virtual, flags); if (up) { diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index d6420d224d09..69cbc79fbb71 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -339,7 +339,8 @@ snd_wavefront_cmd (snd_wavefront_t *dev, int c; struct wavefront_command *wfcmd; - if ((wfcmd = wavefront_get_command (cmd)) == NULL) { + wfcmd = wavefront_get_command(cmd); + if (!wfcmd) { snd_printk ("command 0x%x not supported.\n", cmd); return 1; @@ -391,7 +392,8 @@ snd_wavefront_cmd (snd_wavefront_t *dev, for (i = 0; i < wfcmd->read_cnt; i++) { - if ((c = wavefront_read (dev)) == -1) { + c = wavefront_read(dev); + if (c == -1) { DPRINT (WF_DEBUG_IO, "bad read for byte " "%d of 0x%x [%s].\n", i, cmd, wfcmd->action); @@ -401,7 +403,8 @@ snd_wavefront_cmd (snd_wavefront_t *dev, /* Now handle errors. Lots of special cases here */ if (c == 0xff) { - if ((c = wavefront_read (dev)) == -1) { + c = wavefront_read(dev); + if (c == -1) { DPRINT (WF_DEBUG_IO, "bad read for " "error byte at " "read byte %d " @@ -459,9 +462,9 @@ snd_wavefront_cmd (snd_wavefront_t *dev, of the standard value. */ - if ((ack = wavefront_read (dev)) == 0) { + ack = wavefront_read(dev); + if (ack == 0) ack = WF_ACK; - } if (ack != WF_ACK) { if (ack == -1) { @@ -475,7 +478,8 @@ snd_wavefront_cmd (snd_wavefront_t *dev, if (ack == 0xff) { /* explicit error */ - if ((err = wavefront_read (dev)) == -1) { + err = wavefront_read(dev); + if (err == -1) { DPRINT (WF_DEBUG_DATA, "cannot read err " "for 0x%x [%s].\n", @@ -603,9 +607,9 @@ wavefront_delete_sample (snd_wavefront_t *dev, int sample_num) wbuf[0] = sample_num & 0x7f; wbuf[1] = sample_num >> 7; - if ((x = snd_wavefront_cmd (dev, WFC_DELETE_SAMPLE, NULL, wbuf)) == 0) { + x = snd_wavefront_cmd(dev, WFC_DELETE_SAMPLE, NULL, wbuf); + if (!x) dev->sample_status[sample_num] = WF_ST_EMPTY; - } return x; } @@ -691,8 +695,9 @@ wavefront_get_patch_status (snd_wavefront_t *dev) patchnum[0] = i & 0x7f; patchnum[1] = i >> 7; - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PATCH, patchbuf, - patchnum)) == 0) { + x = snd_wavefront_cmd(dev, WFC_UPLOAD_PATCH, patchbuf, + patchnum); + if (x == 0) { dev->patch_status[i] |= WF_SLOT_FILLED; p = (wavefront_patch *) patchbuf; @@ -738,8 +743,9 @@ wavefront_get_program_status (snd_wavefront_t *dev) for (i = 0; i < WF_MAX_PROGRAM; i++) { prognum = i; - if ((x = snd_wavefront_cmd (dev, WFC_UPLOAD_PROGRAM, progbuf, - &prognum)) == 0) { + x = snd_wavefront_cmd(dev, WFC_UPLOAD_PROGRAM, progbuf, + &prognum); + if (x == 0) { dev->prog_status[i] |= WF_SLOT_USED; @@ -894,9 +900,9 @@ wavefront_send_sample (snd_wavefront_t *dev, if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) { int x; - if ((x = wavefront_find_free_sample (dev)) < 0) { + x = wavefront_find_free_sample(dev); + if (x < 0) return -ENOMEM; - } snd_printk ("unspecified sample => %d\n", x); header->number = x; } @@ -1137,7 +1143,8 @@ wavefront_send_sample (snd_wavefront_t *dev, nothing to do with DMA at all. */ - if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) { + dma_ack = wavefront_read(dev); + if (dma_ack != WF_DMA_ACK) { if (dma_ack == -1) { snd_printk ("upload sample " "DMA ack timeout\n"); @@ -1282,14 +1289,16 @@ wavefront_fetch_multisample (snd_wavefront_t *dev, char d[2]; int val; - if ((val = wavefront_read (dev)) == -1) { + val = wavefront_read(dev); + if (val == -1) { snd_printk ("upload multisample failed " "during sample loop.\n"); return -EIO; } d[0] = val; - if ((val = wavefront_read (dev)) == -1) { + val = wavefront_read(dev); + if (val == -1) { snd_printk ("upload multisample failed " "during sample loop.\n"); return -EIO; @@ -1910,7 +1919,8 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) goto gone_bad; } - if ((hwv[0] = wavefront_read (dev)) == -1) { + hwv[0] = wavefront_read(dev); + if (hwv[0] == -1) { snd_printk ("board not responding correctly.\n"); goto gone_bad; } @@ -1921,7 +1931,8 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) and tell us about it either way. */ - if ((hwv[0] = wavefront_read (dev)) == -1) { + hwv[0] = wavefront_read(dev); + if (hwv[0] == -1) { snd_printk ("on-board RAM test failed " "(bad error code).\n"); } else { @@ -1934,7 +1945,8 @@ wavefront_reset_to_cleanliness (snd_wavefront_t *dev) /* We're OK, just get the next byte of the HW version response */ - if ((hwv[1] = wavefront_read (dev)) == -1) { + hwv[1] = wavefront_read(dev); + if (hwv[1] == -1) { snd_printk ("incorrect h/w response.\n"); goto gone_bad; } @@ -2079,9 +2091,9 @@ wavefront_do_reset (snd_wavefront_t *dev) about it. */ - if ((dev->freemem = wavefront_freemem (dev)) < 0) { + dev->freemem = wavefront_freemem(dev); + if (dev->freemem < 0) goto gone_bad; - } snd_printk ("available DRAM %dk\n", dev->freemem / 1024); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index ea5d3cdfe4e4..743e0f05e335 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1493,7 +1493,8 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream) snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max); if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0) + err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1); + if (err < 0) return err; } @@ -1533,7 +1534,8 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream) snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max); if (chip->claim_dma) { - if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0) + err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2); + if (err < 0) return err; } @@ -1934,7 +1936,8 @@ int snd_wss_timer(struct snd_wss *chip, int device) tid.card = chip->card->number; tid.device = device; tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) + err = snd_timer_new(chip->card, "CS4231", &tid, &timer); + if (err < 0) return err; strcpy(timer->name, snd_wss_chip_id(chip)); timer->private_data = chip; diff --git a/sound/mips/snd-n64.c b/sound/mips/snd-n64.c index e35e93157755..463a6fe589eb 100644 --- a/sound/mips/snd-n64.c +++ b/sound/mips/snd-n64.c @@ -338,6 +338,10 @@ static int __init n64audio_probe(struct platform_device *pdev) strcpy(card->longname, "N64 Audio"); res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + err = -EINVAL; + goto fail_dma_alloc; + } if (devm_request_irq(&pdev->dev, res->start, n64audio_isr, IRQF_SHARED, "N64 Audio", priv)) { err = -EBUSY; diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 49679aa8631d..0c95828ac0b1 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -999,11 +999,9 @@ static int sq_ioctl(struct file *file, u_int cmd, u_long arg) case SNDCTL_DSP_RESET: sq_reset(); return 0; - break ; case SNDCTL_DSP_GETFMTS: fmt = dmasound.mach.hardware_afmts ; /* this is what OSS says.. */ return IOCTL_OUT(arg, fmt); - break ; case SNDCTL_DSP_GETBLKSIZE: /* this should tell the caller about bytes that the app can read/write - the app doesn't care about our internal buffers. @@ -1020,7 +1018,6 @@ static int sq_ioctl(struct file *file, u_int cmd, u_long arg) size = write_sq.user_frag_size ; } return IOCTL_OUT(arg, size); - break ; case SNDCTL_DSP_POST: /* all we are going to do is to tell the LL that any partial frags can be queued for output. @@ -1044,7 +1041,6 @@ static int sq_ioctl(struct file *file, u_int cmd, u_long arg) if (file->f_mode & shared_resource_owner) shared_resources_initialised = 0 ; return result ; - break ; case SOUND_PCM_READ_RATE: return IOCTL_OUT(arg, dmasound.soft.speed); case SNDCTL_DSP_SPEED: @@ -1123,7 +1119,6 @@ static int sq_ioctl(struct file *file, u_int cmd, u_long arg) the value is 'random' and that the user _must_ check the actual frags values using SNDCTL_DSP_GETBLKSIZE or similar */ return IOCTL_OUT(arg, data); - break ; case SNDCTL_DSP_GETOSPACE: /* */ @@ -1234,31 +1229,22 @@ static char *get_afmt_string(int afmt) switch(afmt) { case AFMT_MU_LAW: return "mu-law"; - break; case AFMT_A_LAW: return "A-law"; - break; case AFMT_U8: return "unsigned 8 bit"; - break; case AFMT_S8: return "signed 8 bit"; - break; case AFMT_S16_BE: return "signed 16 bit BE"; - break; case AFMT_U16_BE: return "unsigned 16 bit BE"; - break; case AFMT_S16_LE: return "signed 16 bit LE"; - break; case AFMT_U16_LE: return "unsigned 16 bit LE"; - break; case 0: return "format not set" ; - break ; default: break ; } diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index f2ca0a701987..1440db8b4177 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -915,10 +915,9 @@ snd_harmony_create(struct snd_card *card, spin_lock_init(&h->mixer_lock); spin_lock_init(&h->lock); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - h, &ops)) < 0) { - goto free_and_ret; - } + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, h, &ops); + if (err < 0) + goto free_and_ret; *rchip = h; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 012a7ee849e8..01f296d524ce 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1286,15 +1286,17 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, if (snd_ac97_try_bit(ac97, reg, 15)) { sprintf(name, "%s Switch", pfx); - if ((err = snd_ac97_cmute_new_stereo(card, name, reg, - check_stereo, check_amix, - ac97)) < 0) + err = snd_ac97_cmute_new_stereo(card, name, reg, + check_stereo, check_amix, + ac97); + if (err < 0) return err; } check_volume_resolution(ac97, reg, &lo_max, &hi_max); if (lo_max) { sprintf(name, "%s Volume", pfx); - if ((err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97)) < 0) + err = snd_ac97_cvol_new(card, name, reg, lo_max, hi_max, ac97); + if (err < 0) return err; } return 0; @@ -1333,9 +1335,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build center controls */ if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) && !(ac97->flags & AC97_AD_MULTI)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) + err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97)); + if (err < 0) return err; snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max); kctl->private_value &= ~(0xff << 16); @@ -1347,9 +1351,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build LFE controls */ if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) && !(ac97->flags & AC97_AD_MULTI)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) + err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97)); + if (err < 0) return err; snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max); kctl->private_value &= ~(0xff << 16); @@ -1362,23 +1368,26 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) && !(ac97->flags & AC97_AD_MULTI)) { /* Surround Master (0x38) is with stereo mutes */ - if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", - AC97_SURROUND_MASTER, 1, 0, - ac97)) < 0) + err = snd_ac97_cmix_new_stereo(card, "Surround Playback", + AC97_SURROUND_MASTER, 1, 0, + ac97); + if (err < 0) return err; } /* build headphone controls */ if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { - if ((err = snd_ac97_cmix_new(card, "Headphone Playback", - AC97_HEADPHONE, 0, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Headphone Playback", + AC97_HEADPHONE, 0, ac97); + if (err < 0) return err; } /* build master mono controls */ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { - if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", - AC97_MASTER_MONO, 0, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Master Mono Playback", + AC97_MASTER_MONO, 0, ac97); + if (err < 0) return err; } @@ -1386,7 +1395,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if (!(ac97->flags & AC97_HAS_NO_TONE)) { if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_TONE)) { for (idx = 0; idx < 2; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_controls_tone[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (ac97->id == AC97_ID_YMF743 || ac97->id == AC97_ID_YMF753) { @@ -1402,9 +1413,12 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && ((ac97->flags & AC97_HAS_PC_BEEP) || snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_4bit); snd_ac97_write_cache( ac97, @@ -1417,8 +1431,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Phone controls */ if (!(ac97->flags & AC97_HAS_NO_PHONE)) { if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { - if ((err = snd_ac97_cmix_new(card, "Phone Playback", - AC97_PHONE, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Phone Playback", + AC97_PHONE, 1, ac97); + if (err < 0) return err; } } @@ -1426,26 +1441,30 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build MIC controls */ if (!(ac97->flags & AC97_HAS_NO_MIC)) { if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { - if ((err = snd_ac97_cmix_new(card, "Mic Playback", - AC97_MIC, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Mic Playback", + AC97_MIC, 1, ac97); + if (err < 0) return err; - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97)); + if (err < 0) return err; } } /* build Line controls */ if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { - if ((err = snd_ac97_cmix_new(card, "Line Playback", - AC97_LINE, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Line Playback", + AC97_LINE, 1, ac97); + if (err < 0) return err; } /* build CD controls */ if (!(ac97->flags & AC97_HAS_NO_CD)) { if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { - if ((err = snd_ac97_cmix_new(card, "CD Playback", - AC97_CD, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "CD Playback", + AC97_CD, 1, ac97); + if (err < 0) return err; } } @@ -1453,8 +1472,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Video controls */ if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { - if ((err = snd_ac97_cmix_new(card, "Video Playback", - AC97_VIDEO, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Video Playback", + AC97_VIDEO, 1, ac97); + if (err < 0) return err; } } @@ -1462,8 +1482,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Aux controls */ if (!(ac97->flags & AC97_HAS_NO_AUX)) { if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { - if ((err = snd_ac97_cmix_new(card, "Aux Playback", - AC97_AUX, 1, ac97)) < 0) + err = snd_ac97_cmix_new(card, "Aux Playback", + AC97_AUX, 1, ac97); + if (err < 0) return err; } } @@ -1475,26 +1496,38 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) init_val = 0x9f9f; else init_val = 0x9f1f; - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[0] = init_val; if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[1] = init_val; } if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_5bit); - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[2] = init_val; } @@ -1515,7 +1548,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Capture controls */ if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97)); + if (err < 0) return err; if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { err = snd_ac97_cmute_new(card, "Capture Switch", @@ -1523,7 +1557,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if (err < 0) return err; } - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; set_tlv_db_scale(kctl, db_scale_rec_gain); snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); @@ -1531,52 +1567,62 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build MIC Capture controls */ if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { - for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) + for (idx = 0; idx < 2; idx++) { + kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } set_tlv_db_scale(kctl, db_scale_rec_gain); snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); } /* build PCM out path & mute control */ if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 15)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_PCM_OUT], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_PCM_OUT], ac97)); + if (err < 0) return err; } /* build Simulated Stereo Enhancement control */ if (ac97->caps & AC97_BC_SIM_STEREO) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97)); + if (err < 0) return err; } /* build 3D Stereo Enhancement control */ if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 13)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_3D], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_3D], ac97)); + if (err < 0) return err; } /* build Loudness control */ if (ac97->caps & AC97_BC_LOUDNESS) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97)); + if (err < 0) return err; } /* build Mono output select control */ if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 9)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MONO], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MONO], ac97)); + if (err < 0) return err; } /* build Mic select control */ if (snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 8)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MIC], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_MIC], ac97)); + if (err < 0) return err; } /* build ADC/DAC loopback control */ if (enable_loopback && snd_ac97_try_bit(ac97, AC97_GENERAL_PURPOSE, 7)) { - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOOPBACK], ac97))) < 0) + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOOPBACK], ac97)); + if (err < 0) return err; } @@ -1592,11 +1638,15 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) snd_ac97_write(ac97, AC97_3D_CONTROL, val); val = snd_ac97_read(ac97, AC97_3D_CONTROL); val = val == 0x0606; - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (val) kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16); - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[1], ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_controls_3d[1], ac97); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (val) kctl->private_value = AC97_3D_CONTROL | (1 << 8) | (7 << 16); @@ -1613,14 +1663,18 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { if (ac97->build_ops->build_spdif) { - if ((err = ac97->build_ops->build_spdif(ac97)) < 0) + err = ac97->build_ops->build_spdif(ac97); + if (err < 0) return err; } else { - for (idx = 0; idx < 5; idx++) - if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97))) < 0) + for (idx = 0; idx < 5; idx++) { + err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_spdif[idx], ac97)); + if (err < 0) return err; + } if (ac97->build_ops->build_post_spdif) { - if ((err = ac97->build_ops->build_post_spdif(ac97)) < 0) + err = ac97->build_ops->build_post_spdif(ac97); + if (err < 0) return err; } /* set default PCM S/PDIF params */ @@ -1632,9 +1686,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build chip specific controls */ - if (ac97->build_ops->build_specific) - if ((err = ac97->build_ops->build_specific(ac97)) < 0) + if (ac97->build_ops->build_specific) { + err = ac97->build_ops->build_specific(ac97); + if (err < 0) return err; + } if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) { kctl = snd_ac97_cnew(&snd_ac97_control_eapd, ac97); @@ -1642,7 +1698,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) return -ENOMEM; if (ac97->scaps & AC97_SCAP_INV_EAPD) set_inv_eapd(ac97, kctl); - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } @@ -1664,14 +1721,18 @@ static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97) snd_ac97_write(ac97, AC97_MISC_AFE, 0x0); /* build modem switches */ - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_ac97_controls_modem_switches[idx], ac97)); + if (err < 0) return err; + } /* build chip specific controls */ - if (ac97->build_ops->build_specific) - if ((err = ac97->build_ops->build_specific(ac97)) < 0) + if (ac97->build_ops->build_specific) { + err = ac97->build_ops->build_specific(ac97); + if (err < 0) return err; + } return 0; } @@ -1916,7 +1977,8 @@ int snd_ac97_bus(struct snd_card *card, int num, bus->clock = 48000; spin_lock_init(&bus->bus_lock); snd_ac97_bus_proc_init(bus); - if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); + if (err < 0) { snd_ac97_bus_free(bus); return err; } @@ -1944,7 +2006,8 @@ static int snd_ac97_dev_register(struct snd_device *device) dev_set_name(&ac97->dev, "%d-%d:%s", ac97->bus->card->number, ac97->num, snd_ac97_get_short_name(ac97)); - if ((err = device_register(&ac97->dev)) < 0) { + err = device_register(&ac97->dev); + if (err < 0) { ac97_err(ac97, "Can't register ac97 bus\n"); ac97->dev.bus = NULL; return err; @@ -2095,7 +2158,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) { /* test if we can write to the record gain volume register */ snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06); - if (((err = snd_ac97_read(ac97, AC97_REC_GAIN)) & 0x7fff) == 0x0a06) + err = snd_ac97_read(ac97, AC97_REC_GAIN); + if ((err & 0x7fff) == 0x0a06) ac97->scaps |= AC97_SCAP_AUDIO; } if (ac97->scaps & AC97_SCAP_AUDIO) { @@ -2248,7 +2312,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, } } sprintf(comp, "AC97a:%08x", ac97->id); - if ((err = snd_component_add(card, comp)) < 0) { + err = snd_component_add(card, comp); + if (err < 0) { snd_ac97_free(ac97); return err; } @@ -2268,7 +2333,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, } } sprintf(comp, "AC97m:%08x", ac97->id); - if ((err = snd_component_add(card, comp)) < 0) { + err = snd_component_add(card, comp); + if (err < 0) { snd_ac97_free(ac97); return err; } @@ -2280,7 +2346,8 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, if (ac97_is_audio(ac97)) update_power_regs(ac97); snd_ac97_proc_init(ac97); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops); + if (err < 0) { snd_ac97_free(ac97); return err; } diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1627a74baf3c..025c1666c1fc 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -29,9 +29,11 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro { int idx, err; - for (idx = 0; idx < count; idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97))) < 0) + for (idx = 0; idx < count; idx++) { + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&controls[idx], ac97)); + if (err < 0) return err; + } return 0; } @@ -416,7 +418,8 @@ static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif))) < 0) + err = patch_build_controls(ac97, snd_ac97_ymf753_controls_spdif, ARRAY_SIZE(snd_ac97_ymf753_controls_spdif)); + if (err < 0) return err; return 0; } @@ -461,7 +464,8 @@ static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97) int err, i; for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm97xx_snd_ac97_controls[i], ac97)); + if (err < 0) return err; } snd_ac97_write_cache(ac97, AC97_WM97XX_FMIXER_VOL, 0x0808); @@ -491,7 +495,8 @@ static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97) { int err, i; for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9704_snd_ac97_controls[i], ac97)); + if (err < 0) return err; } /* patch for DVD noise */ @@ -631,7 +636,8 @@ static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97) int err, i; for (i = 0; i < ARRAY_SIZE(wm9711_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm9711_snd_ac97_controls[i], ac97)); + if (err < 0) return err; } snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x0808); @@ -798,7 +804,8 @@ static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97) int err, i; for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97)); + if (err < 0) return err; } return 0; @@ -809,7 +816,8 @@ static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97) int err, i; for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) { - if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97)); + if (err < 0) return err; } snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); @@ -883,7 +891,8 @@ static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97) struct snd_kcontrol *kctl; int err; - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) + err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97)); + if (err < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); @@ -896,11 +905,15 @@ static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97) struct snd_kcontrol *kctl; int err; - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); + err = snd_ctl_add(ac97->bus->card, kctl); + if (err < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Depth"); kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0); - if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0) + kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97); + err = snd_ctl_add(ac97->bus->card, kctl); + if (err < 0) return err; strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth"); kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); @@ -927,18 +940,26 @@ static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97) int err; snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003); - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0) + if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) { + err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1); + if (err < 0) return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0) + } + if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) { + err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1); + if (err < 0) return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0) + } + if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) { + err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1); + if (err < 0) return err; - if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) - if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0) + } + if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) { + err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1); + if (err < 0) return err; + } return 0; } @@ -984,7 +1005,8 @@ static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97) snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL); snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); - if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1); + if (err < 0) return err; return patch_sigmatel_stac97xx_specific(ac97); } @@ -1262,14 +1284,17 @@ static int patch_cirrus_build_spdif(struct snd_ac97 * ac97) int err; /* con mask, pro mask, default */ - if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) + err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3); + if (err < 0) return err; /* switch, spsa */ - if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1); + if (err < 0) return err; switch (ac97->id & AC97_ID_CS_MASK) { case AC97_ID_CS4205: - if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[1], 1); + if (err < 0) return err; break; } @@ -1324,10 +1349,12 @@ static int patch_conexant_build_spdif(struct snd_ac97 * ac97) int err; /* con mask, pro mask, default */ - if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0) + err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3); + if (err < 0) return err; /* switch */ - if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1); + if (err < 0) return err; /* set default PCM S/PDIF params */ /* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */ @@ -1592,7 +1619,8 @@ static int patch_ad1885_specific(struct snd_ac97 * ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) + err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885)); + if (err < 0) return err; reset_tlv(ac97, "Headphone Playback Volume", db_scale_6bit_6db_max); @@ -1875,7 +1903,8 @@ static int patch_ad1981b_specific(struct snd_ac97 *ac97) { int err; - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1); + if (err < 0) return err; if (check_list(ac97, ad1981_jacks_denylist)) return 0; @@ -2060,7 +2089,8 @@ static int patch_ad1980_specific(struct snd_ac97 *ac97) { int err; - if ((err = patch_ad1888_specific(ac97)) < 0) + err = patch_ad1888_specific(ac97); + if (err < 0) return err; return patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1); } @@ -2168,7 +2198,8 @@ static int patch_ad1985_specific(struct snd_ac97 *ac97) "Master Surround Playback"); snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback"); - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1); + if (err < 0) return err; return patch_build_controls(ac97, snd_ac97_ad1985_controls, @@ -2460,7 +2491,8 @@ static int patch_ad1986_specific(struct snd_ac97 *ac97) { int err; - if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0) + err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1); + if (err < 0) return err; return patch_build_controls(ac97, snd_ac97_ad1986_controls, @@ -2582,10 +2614,12 @@ static int patch_alc650_specific(struct snd_ac97 * ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650))) < 0) + err = patch_build_controls(ac97, snd_ac97_controls_alc650, ARRAY_SIZE(snd_ac97_controls_alc650)); + if (err < 0) return err; if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0) + err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650)); + if (err < 0) return err; } if (ac97->id != AC97_ID_ALC650F) @@ -2735,10 +2769,12 @@ static int patch_alc655_specific(struct snd_ac97 * ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655))) < 0) + err = patch_build_controls(ac97, snd_ac97_controls_alc655, ARRAY_SIZE(snd_ac97_controls_alc655)); + if (err < 0) return err; if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0) + err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655)); + if (err < 0) return err; } return 0; @@ -2847,10 +2883,12 @@ static int patch_alc850_specific(struct snd_ac97 *ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0) + err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850)); + if (err < 0) return err; if (ac97->ext_id & AC97_EI_SPDIF) { - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0) + err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655)); + if (err < 0) return err; } return 0; @@ -3437,10 +3475,13 @@ static int patch_vt1616_specific(struct snd_ac97 * ac97) struct snd_kcontrol *kctl; int err; - if (snd_ac97_try_bit(ac97, 0x5a, 9)) - if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1)) < 0) + if (snd_ac97_try_bit(ac97, 0x5a, 9)) { + err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[0], 1); + if (err < 0) return err; - if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0) + } + err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1); + if (err < 0) return err; /* There is already a misnamed master switch. Rename it. */ @@ -3810,9 +3851,11 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = { static int patch_it2646_specific(struct snd_ac97 * ac97) { int err; - if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0) + err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646)); + if (err < 0) return err; - if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646))) < 0) + err = patch_build_controls(ac97, snd_ac97_spdif_controls_it2646, ARRAY_SIZE(snd_ac97_spdif_controls_it2646)); + if (err < 0) return err; return 0; } @@ -3845,9 +3888,11 @@ AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1) static int patch_si3036_specific(struct snd_ac97 * ac97) { int idx, err; - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++) { + err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_si3036[idx], ac97)); + if (err < 0) return err; + } return 0; } @@ -3912,9 +3957,11 @@ AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0), static int patch_ucb1400_specific(struct snd_ac97 * ac97) { int idx, err; - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) { + err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97)); + if (err < 0) return err; + } return 0; } diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 4520022801d9..5c78951dd596 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -852,7 +852,8 @@ snd_ad1889_create(struct snd_card *card, *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check PCI availability (32bit DMA) */ @@ -863,7 +864,8 @@ snd_ad1889_create(struct snd_card *card, } /* allocate chip specific data with zero-filled memory */ - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) { pci_disable_device(pci); return -ENOMEM; } @@ -874,7 +876,8 @@ snd_ad1889_create(struct snd_card *card, chip->irq = -1; /* (1) PCI resource allocation */ - if ((err = pci_request_regions(pci, card->driver)) < 0) + err = pci_request_regions(pci, card->driver); + if (err < 0) goto free_and_ret; chip->bar = pci_resource_start(pci, 0); @@ -900,12 +903,14 @@ snd_ad1889_create(struct snd_card *card, card->sync_irq = chip->irq; /* (2) initialization of the chip hardware */ - if ((err = snd_ad1889_init(chip)) < 0) { + err = snd_ad1889_init(chip); + if (err < 0) { snd_ad1889_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_ad1889_free(chip); return err; } diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c index e0a81f99f79a..6af88e7b86f8 100644 --- a/sound/pci/ak4531_codec.c +++ b/sound/pci/ak4531_codec.c @@ -384,7 +384,8 @@ int snd_ak4531_mixer(struct snd_card *card, return -ENOMEM; *ak4531 = *_ak4531; mutex_init(&ak4531->reg_mutex); - if ((err = snd_component_add(card, "AK4531")) < 0) { + err = snd_component_add(card, "AK4531"); + if (err < 0) { snd_ak4531_free(ak4531); return err; } @@ -398,13 +399,15 @@ int snd_ak4531_mixer(struct snd_card *card, ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]); /* recording source is mixer */ } for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531)); + if (err < 0) { snd_ak4531_free(ak4531); return err; } } snd_ak4531_proc_init(card, ak4531); - if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops); + if (err < 0) { snd_ak4531_free(ak4531); return err; } diff --git a/sound/pci/als300.c b/sound/pci/als300.c index bd4fd09e982b..668008fc21f7 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -298,7 +298,8 @@ static int snd_als300_ac97(struct snd_als300 *chip) .read = snd_als300_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); @@ -621,7 +622,8 @@ static int snd_als300_create(struct snd_card *card, }; *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { @@ -643,7 +645,8 @@ static int snd_als300_create(struct snd_card *card, chip->chip_type = chip_type; spin_lock_init(&chip->reg_lock); - if ((err = pci_request_regions(pci, "ALS300")) < 0) { + err = pci_request_regions(pci, "ALS300"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -673,14 +676,15 @@ static int snd_als300_create(struct snd_card *card, return err; } - if ((err = snd_als300_new_pcm(chip)) < 0) { + err = snd_als300_new_pcm(chip); + if (err < 0) { dev_err(card->dev, "Could not create PCM\n"); snd_als300_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_als300_free(chip); return err; } @@ -741,7 +745,8 @@ static int snd_als300_probe(struct pci_dev *pci, chip_type = pci_id->driver_data; - if ((err = snd_als300_create(card, pci, chip_type, &chip)) < 0) { + err = snd_als300_create(card, pci, chip_type, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -758,7 +763,8 @@ static int snd_als300_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->port, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 139ac2a3a0ef..509f317ee682 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -832,9 +832,10 @@ static int snd_card_als4000_probe(struct pci_dev *pci, } /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) { + err = pci_enable_device(pci); + if (err < 0) return err; - } + /* check, if we can restrict PCI DMA transfers to 24 bits */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n"); @@ -842,7 +843,8 @@ static int snd_card_als4000_probe(struct pci_dev *pci, return -ENXIO; } - if ((err = pci_request_regions(pci, "ALS4000")) < 0) { + err = pci_request_regions(pci, "ALS4000"); + if (err < 0) { pci_disable_device(pci); return err; } @@ -869,17 +871,17 @@ static int snd_card_als4000_probe(struct pci_dev *pci, /* disable all legacy ISA stuff */ snd_als4000_set_addr(acard->iobase, 0, 0, 0, 0); - if ((err = snd_sbdsp_create(card, - iobase + ALS4K_IOB_10_ADLIB_ADDR0, - pci->irq, + err = snd_sbdsp_create(card, + iobase + ALS4K_IOB_10_ADLIB_ADDR0, + pci->irq, /* internally registered as IRQF_SHARED in case of ALS4000 SB */ - snd_als4000_interrupt, - -1, - -1, - SB_HW_ALS4000, - &chip)) < 0) { + snd_als4000_interrupt, + -1, + -1, + SB_HW_ALS4000, + &chip); + if (err < 0) goto out_err; - } acard->chip = chip; chip->pci = pci; @@ -892,11 +894,12 @@ static int snd_card_als4000_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->alt_port, chip->irq); - if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, - iobase + ALS4K_IOB_30_MIDI_DATA, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_ALS4000, + iobase + ALS4K_IOB_30_MIDI_DATA, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); + if (err < 0) { dev_err(&pci->dev, "no MPU-401 device at 0x%lx?\n", iobase + ALS4K_IOB_30_MIDI_DATA); goto out_err; @@ -907,12 +910,13 @@ static int snd_card_als4000_probe(struct pci_dev *pci, * however there doesn't seem to be an ALSA API for this... * SPECS_PAGE: 21 */ - if ((err = snd_als4000_pcm(chip, 0)) < 0) { + err = snd_als4000_pcm(chip, 0); + if (err < 0) goto out_err; - } - if ((err = snd_sbmixer_new(chip)) < 0) { + + err = snd_sbmixer_new(chip); + if (err < 0) goto out_err; - } if (snd_opl3_create(card, iobase + ALS4K_IOB_10_ADLIB_ADDR0, @@ -922,16 +926,17 @@ static int snd_card_als4000_probe(struct pci_dev *pci, iobase + ALS4K_IOB_10_ADLIB_ADDR0, iobase + ALS4K_IOB_12_ADLIB_ADDR2); } else { - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) goto out_err; - } } snd_als4000_create_gameport(acard, dev); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) goto out_err; - } + pci_set_drvdata(pci, card); dev++; err = 0; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 579425ccbb6a..5f8aa35c4bea 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1039,7 +1039,8 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, /* direct SPDIF */ runtime->hw.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; runtime->private_data = dma; @@ -1415,7 +1416,8 @@ static int snd_atiixp_mixer_new(struct atiixp *chip, int clock, if (snd_atiixp_codec_detect(chip) < 0) return -ENXIO; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus); + if (err < 0) return err; pbus->clock = clock; chip->ac97_bus = pbus; @@ -1431,7 +1433,8 @@ static int snd_atiixp_mixer_new(struct atiixp *chip, int clock, ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; if (! chip->spdif_over_aclink) ac97.scaps |= AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i]); + if (err < 0) { chip->ac97[i] = NULL; /* to be sure */ dev_dbg(chip->card->dev, "codec %d not available for audio\n", i); @@ -1562,7 +1565,8 @@ static int snd_atiixp_create(struct snd_card *card, struct atiixp *chip; int err; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1576,7 +1580,8 @@ static int snd_atiixp_create(struct snd_card *card, chip->card = card; chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, "ATI IXP AC97")) < 0) { + err = pci_request_regions(pci, "ATI IXP AC97"); + if (err < 0) { pci_disable_device(pci); kfree(chip); return err; @@ -1599,7 +1604,8 @@ static int snd_atiixp_create(struct snd_card *card, card->sync_irq = chip->irq; pci_set_master(pci); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_atiixp_free(chip); return err; } @@ -1622,19 +1628,23 @@ static int snd_atiixp_probe(struct pci_dev *pci, strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA"); strcpy(card->shortname, "ATI IXP"); - if ((err = snd_atiixp_create(card, pci, &chip)) < 0) + err = snd_atiixp_create(card, pci, &chip); + if (err < 0) goto __error; card->private_data = chip; - if ((err = snd_atiixp_aclink_reset(chip)) < 0) + err = snd_atiixp_aclink_reset(chip); + if (err < 0) goto __error; chip->spdif_over_aclink = spdif_aclink; - if ((err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk)) < 0) + err = snd_atiixp_mixer_new(chip, ac97_clock, ac97_quirk); + if (err < 0) goto __error; - if ((err = snd_atiixp_pcm_new(chip)) < 0) + err = snd_atiixp_pcm_new(chip); + if (err < 0) goto __error; snd_atiixp_proc_init(chip); @@ -1647,7 +1657,8 @@ static int snd_atiixp_probe(struct pci_dev *pci, chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?", chip->addr, chip->irq); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto __error; pci_set_drvdata(pci, card); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 45e75afec7a0..9739c3a82777 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -856,12 +856,12 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, dma->substream = substream; runtime->hw = snd_atiixp_pcm_hw; dma->ac97_pcm_type = pcm_type; - if ((err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates)) < 0) + err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraints_rates); + if (err < 0) return err; - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; runtime->private_data = dma; @@ -1058,7 +1058,8 @@ static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) if (snd_atiixp_codec_detect(chip) < 0) return -ENXIO; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus); + if (err < 0) return err; pbus->clock = clock; chip->ac97_bus = pbus; @@ -1072,7 +1073,8 @@ static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) ac97.pci = chip->pci; ac97.num = i; ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i]); + if (err < 0) { chip->ac97[i] = NULL; /* to be sure */ dev_dbg(chip->card->dev, "codec %d not available for modem\n", i); @@ -1192,7 +1194,8 @@ static int snd_atiixp_create(struct snd_card *card, struct atiixp_modem *chip; int err; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1206,7 +1209,8 @@ static int snd_atiixp_create(struct snd_card *card, chip->card = card; chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, "ATI IXP MC97")) < 0) { + err = pci_request_regions(pci, "ATI IXP MC97"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1229,7 +1233,8 @@ static int snd_atiixp_create(struct snd_card *card, card->sync_irq = chip->irq; pci_set_master(pci); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_atiixp_free(chip); return err; } @@ -1252,17 +1257,21 @@ static int snd_atiixp_probe(struct pci_dev *pci, strcpy(card->driver, "ATIIXP-MODEM"); strcpy(card->shortname, "ATI IXP Modem"); - if ((err = snd_atiixp_create(card, pci, &chip)) < 0) + err = snd_atiixp_create(card, pci, &chip); + if (err < 0) goto __error; card->private_data = chip; - if ((err = snd_atiixp_aclink_reset(chip)) < 0) + err = snd_atiixp_aclink_reset(chip); + if (err < 0) goto __error; - if ((err = snd_atiixp_mixer_new(chip, ac97_clock)) < 0) + err = snd_atiixp_mixer_new(chip, ac97_clock); + if (err < 0) goto __error; - if ((err = snd_atiixp_pcm_new(chip)) < 0) + err = snd_atiixp_pcm_new(chip); + if (err < 0) goto __error; snd_atiixp_proc_init(chip); @@ -1272,7 +1281,8 @@ static int snd_atiixp_probe(struct pci_dev *pci, sprintf(card->longname, "%s rev %x at 0x%lx, irq %i", card->shortname, pci->revision, chip->addr, chip->irq); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto __error; pci_set_drvdata(pci, card); diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 1b37b7225b1d..1f7fee470266 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -46,8 +46,9 @@ MODULE_DEVICE_TABLE(pci, snd_vortex_ids); static void vortex_fix_latency(struct pci_dev *vortex) { int rc; - if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) { - dev_info(&vortex->dev, "vortex latency is 0xff\n"); + rc = pci_write_config_byte(vortex, 0x40, 0xff); + if (!rc) { + dev_info(&vortex->dev, "vortex latency is 0xff\n"); } else { dev_warn(&vortex->dev, "could not set vortex latency: pci error 0x%x\n", rc); @@ -65,9 +66,12 @@ static void vortex_fix_agp_bridge(struct pci_dev *via) * read the config and it is not already set */ - if (!(rc = pci_read_config_byte(via, 0x42, &value)) - && ((value & 0x10) - || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) { + rc = pci_read_config_byte(via, 0x42, &value); + if (!rc) { + if (!(value & 0x10)) + rc = pci_write_config_byte(via, 0x42, value | 0x10); + } + if (!rc) { dev_info(&via->dev, "bridge config is 0x%x\n", value | 0x10); } else { dev_warn(&via->dev, @@ -102,14 +106,16 @@ static void snd_vortex_workaround(struct pci_dev *vortex, int fix) } else { if (fix & 0x1) vortex_fix_latency(vortex); - if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_8365_1, NULL))) - vortex_fix_agp_bridge(via); - if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA, - PCI_DEVICE_ID_VIA_82C598_1, NULL))) - vortex_fix_agp_bridge(via); - if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL))) + if (fix & 0x2) + via = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_8365_1, NULL); + else if (fix & 0x4) + via = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C598_1, NULL); + else if (fix & 0x8) + via = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL); + if (via) vortex_fix_agp_bridge(via); } pci_dev_put(via); @@ -147,7 +153,8 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) *rchip = NULL; // check PCI availability (DMA). - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { dev_err(card->dev, "error to set DMA mask\n"); @@ -174,7 +181,8 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) // (1) PCI resource allocation // Get MMIO area // - if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) + err = pci_request_regions(pci, CARD_NAME_SHORT); + if (err) goto regions_out; chip->mmio = pci_ioremap_bar(pci, 0); @@ -187,14 +195,15 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) /* Init audio core. * This must be done before we do request_irq otherwise we can get spurious * interrupts that we do not handle properly and make a mess of things */ - if ((err = vortex_core_init(chip)) != 0) { + err = vortex_core_init(chip); + if (err) { dev_err(card->dev, "hw core init failed\n"); goto core_out; } - if ((err = request_irq(pci->irq, vortex_interrupt, - IRQF_SHARED, KBUILD_MODNAME, - chip)) != 0) { + err = request_irq(pci->irq, vortex_interrupt, + IRQF_SHARED, KBUILD_MODNAME, chip); + if (err) { dev_err(card->dev, "cannot grab irq\n"); goto irq_out; } @@ -205,9 +214,9 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) // End of PCI setup. // Register alsa root device. - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) goto alloc_out; - } *rchip = chip; @@ -252,7 +261,8 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return err; // (3) - if ((err = snd_vortex_create(card, pci, &chip)) < 0) { + err = snd_vortex_create(card, pci, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -278,12 +288,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) } #ifndef CHIP_AU8820 // ADB SPDIF - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) { + err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1); + if (err < 0) { snd_card_free(card); return err; } // A3D - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) { + err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D); + if (err < 0) { snd_card_free(card); return err; } @@ -297,12 +309,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) */ #ifndef CHIP_AU8810 // WT pcm. - if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) { + err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT); + if (err < 0) { snd_card_free(card); return err; } #endif - if ((err = snd_vortex_midi(chip)) < 0) { + err = snd_vortex_midi(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -327,13 +341,13 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #endif // (5) - if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, - &(chip->device))) < 0) { + err = pci_read_config_word(pci, PCI_DEVICE_ID, &chip->device); + if (err < 0) { snd_card_free(card); return err; } - if ((err = pci_read_config_word(pci, PCI_VENDOR_ID, - &(chip->vendor))) < 0) { + err = pci_read_config_word(pci, PCI_VENDOR_ID, &chip->vendor); + if (err < 0) { snd_card_free(card); return err; } @@ -352,7 +366,8 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) #endif // (6) - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c index 2db183f8826a..eabaee0463fe 100644 --- a/sound/pci/au88x0/au88x0_a3d.c +++ b/sound/pci/au88x0/au88x0_a3d.c @@ -849,46 +849,50 @@ static int vortex_a3d_register_controls(vortex_t *vortex) int err, i; /* HRTF controls. */ for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) + kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); + if (!kcontrol) return -ENOMEM; kcontrol->id.numid = CTRLID_HRTF; kcontrol->info = snd_vortex_a3d_hrtf_info; kcontrol->put = snd_vortex_a3d_hrtf_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; } /* ITD controls. */ for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) + kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); + if (!kcontrol) return -ENOMEM; kcontrol->id.numid = CTRLID_ITD; kcontrol->info = snd_vortex_a3d_itd_info; kcontrol->put = snd_vortex_a3d_itd_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; } /* ILD (gains) controls. */ for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) + kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); + if (!kcontrol) return -ENOMEM; kcontrol->id.numid = CTRLID_GAINS; kcontrol->info = snd_vortex_a3d_ild_info; kcontrol->put = snd_vortex_a3d_ild_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; } /* Filter controls. */ for (i = 0; i < NR_A3D; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL) + kcontrol = snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i]); + if (!kcontrol) return -ENOMEM; kcontrol->id.numid = CTRLID_FILTER; kcontrol->info = snd_vortex_a3d_filter_info; kcontrol->put = snd_vortex_a3d_filter_put; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; } return 0; diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index 5180f1bd1326..2ed5100b8cae 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -2120,9 +2120,9 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, VORTEX_RESOURCE_DMA); } else { en = 1; - if ((dma = - vortex_adb_checkinout(vortex, NULL, en, - VORTEX_RESOURCE_DMA)) < 0) + dma = vortex_adb_checkinout(vortex, NULL, en, + VORTEX_RESOURCE_DMA); + if (dma < 0) return -EBUSY; } @@ -2140,18 +2140,20 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, /* Get SRC and MIXER hardware resources. */ if (stream->type != VORTEX_PCM_SPDIF) { for (i = 0; i < nr_ch; i++) { - if ((src[i] = vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { + src[i] = vortex_adb_checkinout(vortex, + stream->resources, en, + VORTEX_RESOURCE_SRC); + if (src[i] < 0) { memset(stream->resources, 0, sizeof(stream->resources)); return -EBUSY; } if (stream->type != VORTEX_PCM_A3D) { - if ((mix[i] = vortex_adb_checkinout(vortex, - stream->resources, - en, - VORTEX_RESOURCE_MIXIN)) < 0) { + mix[i] = vortex_adb_checkinout(vortex, + stream->resources, + en, + VORTEX_RESOURCE_MIXIN); + if (mix[i] < 0) { memset(stream->resources, 0, sizeof(stream->resources)); @@ -2162,10 +2164,10 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, } #ifndef CHIP_AU8820 if (stream->type == VORTEX_PCM_A3D) { - if ((a3d = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_A3D)) < 0) { + a3d = vortex_adb_checkinout(vortex, + stream->resources, en, + VORTEX_RESOURCE_A3D); + if (a3d < 0) { memset(stream->resources, 0, sizeof(stream->resources)); dev_err(vortex->card->dev, @@ -2278,19 +2280,18 @@ vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir, /* Get SRC and MIXER hardware resources. */ for (i = 0; i < nr_ch; i++) { - if ((mix[i] = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_MIXOUT)) - < 0) { + mix[i] = vortex_adb_checkinout(vortex, + stream->resources, en, + VORTEX_RESOURCE_MIXOUT); + if (mix[i] < 0) { memset(stream->resources, 0, sizeof(stream->resources)); return -EBUSY; } - if ((src[i] = - vortex_adb_checkinout(vortex, - stream->resources, en, - VORTEX_RESOURCE_SRC)) < 0) { + src[i] = vortex_adb_checkinout(vortex, + stream->resources, en, + VORTEX_RESOURCE_SRC); + if (src[i] < 0) { memset(stream->resources, 0, sizeof(stream->resources)); return -EBUSY; diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 58e92f2a72c0..71c13100d7ef 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c @@ -873,29 +873,33 @@ static int vortex_eq_init(vortex_t *vortex) vortex_Eqlzr_init(vortex); - if ((kcontrol = - snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL) + kcontrol = snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex); + if (!kcontrol) return -ENOMEM; kcontrol->private_value = 0; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; /* EQ gain controls */ for (i = 0; i < 10; i++) { - if ((kcontrol = - snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL) + kcontrol = snd_ctl_new1(&vortex_eq_kcontrol, vortex); + if (!kcontrol) return -ENOMEM; snprintf(kcontrol->id.name, sizeof(kcontrol->id.name), "%s Playback Volume", EqBandLabels[i]); kcontrol->private_value = i; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; //vortex->eqctrl[i] = kcontrol; } /* EQ band levels */ - if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL) + kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex); + if (!kcontrol) return -ENOMEM; - if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) + err = snd_ctl_add(vortex->card, kcontrol); + if (err < 0) return err; return 0; diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c index 5b647682b683..aeba684b8d18 100644 --- a/sound/pci/au88x0/au88x0_mixer.c +++ b/sound/pci/au88x0/au88x0_mixer.c @@ -30,7 +30,8 @@ static int snd_vortex_mixer(vortex_t *vortex) .read = vortex_codec_read, }; - if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); // Initialize AC97 codec stuff. diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 603494e7d30e..164f6b7039ab 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c @@ -68,9 +68,9 @@ static int snd_vortex_midi(vortex_t *vortex) /* Create MPU401 instance. */ #ifdef VORTEX_MPU401_LEGACY - if ((temp = - snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330, - MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { + temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330, + MPU401_INFO_IRQ_HOOK, -1, &rmidi); + if (temp) { hwwrite(vortex->mmio, VORTEX_CTRL, (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); @@ -78,10 +78,10 @@ static int snd_vortex_midi(vortex_t *vortex) } #else port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); - if ((temp = - snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, - MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO | - MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) { + temp = snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, + MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO | + MPU401_INFO_IRQ_HOOK, -1, &rmidi); + if (temp) { hwwrite(vortex->mmio, VORTEX_CTRL, (hwread(vortex->mmio, VORTEX_CTRL) & ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index d019aa566de3..546f71220604 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -130,14 +130,14 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream) int err; /* Force equal size periods */ - if ((err = - snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; /* Avoid PAGE_SIZE boundary to fall inside of a period. */ - if ((err = - snd_pcm_hw_constraint_pow2(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0) + err = snd_pcm_hw_constraint_pow2(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES); + if (err < 0) return err; snd_pcm_hw_constraint_step(runtime, 0, @@ -658,7 +658,8 @@ static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr) kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip); if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(chip->card, kctl)) < 0) + err = snd_ctl_add(chip->card, kctl); + if (err < 0) return err; } } diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 51dcf1bc4c0c..4ee7ab409807 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1194,7 +1194,8 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) sw = snd_azf3328_mixer_controls; for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); ++idx, ++sw) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip)); + if (err < 0) return err; } snd_component_add(card, "AZF3328 mixer"); diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 91512b345d19..39bcfb81e81c 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -719,7 +719,8 @@ static int snd_bt87x_create(struct snd_card *card, chip->irq = -1; spin_lock_init(&chip->reg_lock); - if ((err = pci_request_regions(pci, "Bt87x audio")) < 0) { + err = pci_request_regions(pci, "Bt87x audio"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index bee4710916c4..99778711006a 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -575,9 +575,11 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) + err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); + if (err < 0) return err; snd_pcm_set_sync(substream); @@ -668,10 +670,12 @@ static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substre */ //channel->interrupt = snd_ca0106_pcm_channel_interrupt; channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; //snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes); - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) + err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); + if (err < 0) return err; return 0; } @@ -1166,7 +1170,8 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip) .read = snd_ca0106_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; pbus->no_vra = 1; /* we don't need VRA */ @@ -1759,7 +1764,8 @@ static int snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel) midi->dev_id = chip; - if ((err = ca_midi_init(chip, midi, 0, name)) < 0) + err = ca_midi_init(chip, midi, 0, name); + if (err < 0) return err; return 0; diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c index 18524e0a9102..957e60f64821 100644 --- a/sound/pci/ca0106/ca_midi.c +++ b/sound/pci/ca0106/ca_midi.c @@ -276,7 +276,8 @@ int ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi); + if (err < 0) return err; midi->dev_id = dev_id; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 598446348da6..f44f118aacad 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -1225,9 +1225,11 @@ static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *sub rate = subs->runtime->rate; - if (up && do_ac3) - if ((err = save_mixer_state(cm)) < 0) + if (up && do_ac3) { + err = save_mixer_state(cm); + if (err < 0) return err; + } spin_lock_irq(&cm->reg_lock); cm->spdif_playback_avail = up; @@ -1276,7 +1278,8 @@ static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) substream->runtime->channels == 2); if (do_spdif && cm->can_ac3_hw) do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO; - if ((err = setup_spdif_playback(cm, substream, do_spdif, do_ac3)) < 0) + err = setup_spdif_playback(cm, substream, do_spdif, do_ac3); + if (err < 0) return err; return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); } @@ -1291,7 +1294,8 @@ static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO; else do_ac3 = 1; /* doesn't matter */ - if ((err = setup_spdif_playback(cm, substream, 1, do_ac3)) < 0) + err = setup_spdif_playback(cm, substream, 1, do_ac3); + if (err < 0) return err; return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); } @@ -1639,7 +1643,8 @@ static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) + err = open_device_check(cm, CM_OPEN_PLAYBACK, substream); + if (err < 0) return err; runtime->hw = snd_cmipci_playback; if (cm->chip_version == 68) { @@ -1665,7 +1670,8 @@ static int snd_cmipci_capture_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0) + err = open_device_check(cm, CM_OPEN_CAPTURE, substream); + if (err < 0) return err; runtime->hw = snd_cmipci_capture; if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording @@ -1689,7 +1695,9 @@ static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ + /* use channel B */ + err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream); + if (err < 0) return err; runtime->hw = snd_cmipci_playback2; mutex_lock(&cm->open_mutex); @@ -1727,7 +1735,9 @@ static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = open_device_check(cm, CM_OPEN_SPDIF_PLAYBACK, substream)) < 0) /* use channel A */ + /* use channel A */ + err = open_device_check(cm, CM_OPEN_SPDIF_PLAYBACK, substream); + if (err < 0) return err; if (cm->can_ac3_hw) { runtime->hw = snd_cmipci_playback_spdif; @@ -1754,7 +1764,9 @@ static int snd_cmipci_capture_spdif_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */ + /* use channel B */ + err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream); + if (err < 0) return err; runtime->hw = snd_cmipci_capture_spdif; if (cm->can_96k && !(cm->chip_version == 68)) { @@ -2650,7 +2662,8 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) "PCM Playback Volume")) continue; } - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm)); + if (err < 0) return err; } @@ -2675,13 +2688,19 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) return err; } if (cm->can_ac3_hw) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm))) < 0) + kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm))) < 0) + kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm))) < 0) + kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; kctl->id.device = pcm_spdif_device; } @@ -2955,7 +2974,8 @@ static int snd_cmipci_create_fm(struct cmipci *cm, long fm_port) goto disable_fm; } } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { dev_err(cm->card->dev, "cannot create OPL3 hwdep\n"); return err; } @@ -2987,7 +3007,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, *rcmipci = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; cm = kzalloc(sizeof(*cm), GFP_KERNEL); @@ -3006,7 +3027,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, cm->channel[1].ch = 1; cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */ - if ((err = pci_request_regions(pci, card->driver)) < 0) { + err = pci_request_regions(pci, card->driver); + if (err < 0) { kfree(cm); pci_disable_device(pci); return err; @@ -3120,7 +3142,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, sprintf(card->longname, "%s%s at %#lx, irq %i", card->shortname, modelstr, cm->iobase, cm->irq); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops); + if (err < 0) { snd_cmipci_free(cm); return err; } @@ -3172,32 +3195,36 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, /* create pcm devices */ pcm_index = pcm_spdif_index = 0; - if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) + err = snd_cmipci_pcm_new(cm, pcm_index); + if (err < 0) return err; pcm_index++; - if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) + err = snd_cmipci_pcm2_new(cm, pcm_index); + if (err < 0) return err; pcm_index++; if (cm->can_ac3_hw || cm->can_ac3_sw) { pcm_spdif_index = pcm_index; - if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) + err = snd_cmipci_pcm_spdif_new(cm, pcm_index); + if (err < 0) return err; } /* create mixer interface & switches */ - if ((err = snd_cmipci_mixer_new(cm, pcm_spdif_index)) < 0) + err = snd_cmipci_mixer_new(cm, pcm_spdif_index); + if (err < 0) return err; if (iomidi > 0) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - iomidi, - (integrated_midi ? - MPU401_INFO_INTEGRATED : 0) | - MPU401_INFO_IRQ_HOOK, - -1, &cm->rmidi)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, + iomidi, + (integrated_midi ? + MPU401_INFO_INTEGRATED : 0) | + MPU401_INFO_IRQ_HOOK, + -1, &cm->rmidi); + if (err < 0) dev_err(cm->card->dev, "no UART401 device at 0x%lx\n", iomidi); - } } #ifdef USE_VAR48KRATE diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index bf3bb70ffaf9..e122a168c148 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1068,23 +1068,28 @@ static int snd_cs4281_mixer(struct cs4281 *chip) .read = snd_cs4281_ac97_read, }; - if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_cs4281_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; if (chip->dual_codec) { ac97.num = 1; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_secondary); + if (err < 0) return err; } - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_fm_vol, chip)); + if (err < 0) return err; - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4281_pcm_vol, chip)); + if (err < 0) return err; return 0; } @@ -1308,7 +1313,8 @@ static int snd_cs4281_create(struct snd_card *card, }; *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) { @@ -1326,7 +1332,8 @@ static int snd_cs4281_create(struct snd_card *card, } chip->dual_codec = dual_codec; - if ((err = pci_request_regions(pci, "CS4281")) < 0) { + err = pci_request_regions(pci, "CS4281"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1356,7 +1363,8 @@ static int snd_cs4281_create(struct snd_card *card, return tmp; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_cs4281_free(chip); return err; } @@ -1395,12 +1403,14 @@ static int snd_cs4281_chip_init(struct cs4281 *chip) * space between 0e4h and 0ffh to be written. */ snd_cs4281_pokeBA0(chip, BA0_CWPR, 0x4281); - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC1)) != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { + tmp = snd_cs4281_peekBA0(chip, BA0_SERC1); + if (tmp != (BA0_SERC1_SO1EN | BA0_SERC1_AC97)) { dev_err(chip->card->dev, "SERC1 AC'97 check failed (0x%x)\n", tmp); return -EIO; } - if ((tmp = snd_cs4281_peekBA0(chip, BA0_SERC2)) != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { + tmp = snd_cs4281_peekBA0(chip, BA0_SERC2); + if (tmp != (BA0_SERC2_SI1EN | BA0_SERC2_AC97)) { dev_err(chip->card->dev, "SERC2 AC'97 check failed (0x%x)\n", tmp); return -EIO; @@ -1748,7 +1758,8 @@ static int snd_cs4281_midi(struct cs4281 *chip, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi); + if (err < 0) return err; strcpy(rmidi->name, "CS4281"); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs4281_midi_output); @@ -1881,32 +1892,38 @@ static int snd_cs4281_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_cs4281_create(card, pci, &chip, dual_codec[dev])) < 0) { + err = snd_cs4281_create(card, pci, &chip, dual_codec[dev]); + if (err < 0) { snd_card_free(card); return err; } card->private_data = chip; - if ((err = snd_cs4281_mixer(chip)) < 0) { + err = snd_cs4281_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_cs4281_pcm(chip, 0)) < 0) { + err = snd_cs4281_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_cs4281_midi(chip, 0)) < 0) { + err = snd_cs4281_midi(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3)) < 0) { + err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3); + if (err < 0) { snd_card_free(card); return err; } opl3->private_data = chip; opl3->command = snd_cs4281_opl3_command; snd_opl3_init(opl3); - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { snd_card_free(card); return err; } @@ -1918,7 +1935,8 @@ static int snd_cs4281_probe(struct pci_dev *pci, chip->ba0_addr, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 1db7b4112840..358ca84cbdea 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -70,45 +70,53 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, 0, &card); if (err < 0) return err; - if ((err = snd_cs46xx_create(card, pci, - external_amp[dev], thinkpad[dev], - &chip)) < 0) { + err = snd_cs46xx_create(card, pci, + external_amp[dev], thinkpad[dev], + &chip); + if (err < 0) { snd_card_free(card); return err; } card->private_data = chip; chip->accept_valid = mmap_valid[dev]; - if ((err = snd_cs46xx_pcm(chip, 0)) < 0) { + err = snd_cs46xx_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } #ifdef CONFIG_SND_CS46XX_NEW_DSP - if ((err = snd_cs46xx_pcm_rear(chip, 1)) < 0) { + err = snd_cs46xx_pcm_rear(chip, 1); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_cs46xx_pcm_iec958(chip, 2)) < 0) { + err = snd_cs46xx_pcm_iec958(chip, 2); + if (err < 0) { snd_card_free(card); return err; } #endif - if ((err = snd_cs46xx_mixer(chip, 2)) < 0) { + err = snd_cs46xx_mixer(chip, 2); + if (err < 0) { snd_card_free(card); return err; } #ifdef CONFIG_SND_CS46XX_NEW_DSP if (chip->nr_ac97_codecs ==2) { - if ((err = snd_cs46xx_pcm_center_lfe(chip, 3)) < 0) { + err = snd_cs46xx_pcm_center_lfe(chip, 3); + if (err < 0) { snd_card_free(card); return err; } } #endif - if ((err = snd_cs46xx_midi(chip, 0)) < 0) { + err = snd_cs46xx_midi(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_cs46xx_start_dsp(chip)) < 0) { + err = snd_cs46xx_start_dsp(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -124,7 +132,8 @@ static int snd_card_cs46xx_probe(struct pci_dev *pci, chip->ba1_addr, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 37f516e6a5c2..1e1eb17f8e07 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -1058,9 +1058,10 @@ static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46x int unlinked = cpcm->pcm_channel->unlinked; cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel); - if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, - cpcm->hw_buf.addr, - cpcm->pcm_channel_id)) == NULL) { + cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel(chip, sample_rate, cpcm, + cpcm->hw_buf.addr, + cpcm->pcm_channel_id); + if (!cpcm->pcm_channel) { dev_err(chip->card->dev, "failed to re-create virtual PCM channel\n"); return -ENOMEM; @@ -1147,7 +1148,8 @@ static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream, runtime->dma_addr = 0; runtime->dma_bytes = 0; } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) { + err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + if (err < 0) { #ifdef CONFIG_SND_CS46XX_NEW_DSP mutex_unlock(&chip->spos_mutex); #endif @@ -1295,7 +1297,8 @@ static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream, runtime->dma_addr = 0; runtime->dma_bytes = 0; } - if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) + err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + if (err < 0) return err; substream->ops = &snd_cs46xx_capture_indirect_ops; } @@ -1760,7 +1763,8 @@ int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1787,7 +1791,8 @@ int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) + err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1811,7 +1816,8 @@ int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0) + err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1835,7 +1841,8 @@ int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0) + err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -2414,7 +2421,8 @@ static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97) /* test if we can write to the record gain volume register */ snd_ac97_write(ac97, AC97_REC_GAIN, 0x8a05); - if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) + err = snd_ac97_read(ac97, AC97_REC_GAIN); + if (err == 0x8a05) return; msleep(10); @@ -2476,7 +2484,8 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) /* detect primary codec */ chip->nr_ac97_codecs = 0; dev_dbg(chip->card->dev, "detecting primary codec\n"); - if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus; @@ -2497,7 +2506,8 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip); if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM) kctl->id.device = spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } @@ -2684,7 +2694,8 @@ int snd_cs46xx_midi(struct snd_cs46xx *chip, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi); + if (err < 0) return err; strcpy(rmidi->name, "CS46XX"); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output); @@ -3526,7 +3537,8 @@ static void hercules_mixer_init (struct snd_cs46xx *chip) struct snd_kcontrol *kctl; kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip); - if ((err = snd_ctl_add(card, kctl)) < 0) { + err = snd_ctl_add(card, kctl); + if (err < 0) { dev_err(card->dev, "failed to initialize Hercules mixer (%d)\n", err); @@ -3871,7 +3883,8 @@ int snd_cs46xx_create(struct snd_card *card, *rchip = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -3965,8 +3978,9 @@ int snd_cs46xx_create(struct snd_card *card, for (idx = 0; idx < 5; idx++) { region = &chip->region.idx[idx]; - if ((region->resource = request_mem_region(region->base, region->size, - region->name)) == NULL) { + region->resource = request_mem_region(region->base, region->size, + region->name); + if (!region->resource) { dev_err(chip->card->dev, "unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1); @@ -4005,7 +4019,8 @@ int snd_cs46xx_create(struct snd_card *card, return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_cs46xx_free(chip); return err; } diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 05f3f6dc918d..1db6bc58d6a6 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -617,7 +617,8 @@ static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry, col = 0; } - if ( (symbol = cs46xx_dsp_lookup_symbol_addr (chip,i / sizeof(u32), SYMBOL_PARAMETER)) != NULL) { + symbol = cs46xx_dsp_lookup_symbol_addr(chip, i / sizeof(u32), SYMBOL_PARAMETER); + if (symbol) { col = 0; snd_iprintf (buffer,"\n%s:\n",symbol->symbol_name); } diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 9b716b56d739..e048b45d9e7e 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -143,7 +143,8 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) .read = snd_cs5535audio_ac97_codec_read, }; - if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); @@ -155,7 +156,8 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) /* set any OLPC-specific scaps */ olpc_prequirks(card, &ac97); - if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97); + if (err < 0) { dev_err(card->dev, "mixer failed\n"); return err; } @@ -266,7 +268,8 @@ static int snd_cs5535audio_create(struct snd_card *card, }; *rcs5535au = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) { @@ -286,7 +289,8 @@ static int snd_cs5535audio_create(struct snd_card *card, cs5535au->pci = pci; cs5535au->irq = -1; - if ((err = pci_request_regions(pci, "CS5535 Audio")) < 0) { + err = pci_request_regions(pci, "CS5535 Audio"); + if (err < 0) { kfree(cs5535au); goto pcifail; } @@ -304,8 +308,8 @@ static int snd_cs5535audio_create(struct snd_card *card, card->sync_irq = cs5535au->irq; pci_set_master(pci); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - cs5535au, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cs5535au, &ops); + if (err < 0) goto sndfail; *rcs5535au = cs5535au; @@ -340,15 +344,18 @@ static int snd_cs5535audio_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) + err = snd_cs5535audio_create(card, pci, &cs5535au); + if (err < 0) goto probefail_out; card->private_data = cs5535au; - if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) + err = snd_cs5535audio_mixer(cs5535au); + if (err < 0) goto probefail_out; - if ((err = snd_cs5535audio_pcm(cs5535au)) < 0) + err = snd_cs5535audio_pcm(cs5535au); + if (err < 0) goto probefail_out; strcpy(card->driver, DRIVER_NAME); @@ -358,7 +365,8 @@ static int snd_cs5535audio_probe(struct pci_dev *pci, card->shortname, card->driver, cs5535au->port, cs5535au->irq); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto probefail_out; pci_set_drvdata(pci, card); diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 4032b89b1fc1..5ff10fec7b90 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -87,8 +87,9 @@ static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream) snd_pcm_limit_hw_rates(runtime); cs5535au->playback_substream = substream; runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]); - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; @@ -342,8 +343,9 @@ static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream) snd_pcm_limit_hw_rates(runtime); cs5535au->capture_substream = substream; runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]); - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; olpc_capture_open(cs5535au->ac97); return 0; diff --git a/sound/pci/echoaudio/darla20_dsp.c b/sound/pci/echoaudio/darla20_dsp.c index 320837ba7bab..0356efad7528 100644 --- a/sound/pci/echoaudio/darla20_dsp.c +++ b/sound/pci/echoaudio/darla20_dsp.c @@ -36,7 +36,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA20)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw: could not initialize DSP comm page\n"); return err; @@ -53,7 +54,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/darla24_dsp.c b/sound/pci/echoaudio/darla24_dsp.c index 8736b5e81ca3..b96300772aee 100644 --- a/sound/pci/echoaudio/darla24_dsp.c +++ b/sound/pci/echoaudio/darla24_dsp.c @@ -36,7 +36,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA24)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw: could not initialize DSP comm page\n"); return err; @@ -52,7 +53,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_ESYNC; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c index 6deb80c42f11..9e1f2cad0909 100644 --- a/sound/pci/echoaudio/echo3g_dsp.c +++ b/sound/pci/echoaudio/echo3g_dsp.c @@ -49,7 +49,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != ECHO3G)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 9bd67ac33657..a62e5581ad14 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -301,38 +301,42 @@ static int pcm_open(struct snd_pcm_substream *substream, snd_pcm_set_sync(substream); /* Only mono and any even number of channels are allowed */ - if ((err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &pipe->constr)) < 0) + err = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &pipe->constr); + if (err < 0) return err; /* All periods should have the same size */ - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; /* The hw accesses memory in chunks 32 frames long and they should be 32-bytes-aligned. It's not a requirement, but it seems that IRQs are generated with a resolution of 32 frames. Thus we need the following */ - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 32)) < 0) + err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32); + if (err < 0) return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 32)) < 0) + err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32); + if (err < 0) return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - hw_rule_sample_rate, chip, - SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + hw_rule_sample_rate, chip, + SNDRV_PCM_HW_PARAM_RATE, -1); + if (err < 0) return err; /* Allocate a page for the scatter-gather list */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - &chip->pci->dev, - PAGE_SIZE, &pipe->sgpage)) < 0) { + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + &chip->pci->dev, + PAGE_SIZE, &pipe->sgpage); + if (err < 0) { dev_err(chip->card->dev, "s-g list allocation failed\n"); return err; } @@ -358,18 +362,21 @@ static int pcm_analog_in_open(struct snd_pcm_substream *substream) struct echoaudio *chip = snd_pcm_substream_chip(substream); int err; - if ((err = pcm_open(substream, num_analog_busses_in(chip) - - substream->number)) < 0) + err = pcm_open(substream, + num_analog_busses_in(chip) - substream->number); + if (err < 0) return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_capture_channels_by_format, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (err < 0) return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_capture_format_by_channels, NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (err < 0) return err; return 0; @@ -387,19 +394,22 @@ static int pcm_analog_out_open(struct snd_pcm_substream *substream) #else max_channels = num_analog_busses_out(chip); #endif - if ((err = pcm_open(substream, max_channels - substream->number)) < 0) + err = pcm_open(substream, max_channels - substream->number); + if (err < 0) return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_playback_channels_by_format, + NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (err < 0) return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_playback_format_by_channels, + NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (err < 0) return err; return 0; @@ -426,15 +436,17 @@ static int pcm_digital_in_open(struct snd_pcm_substream *substream) if (err < 0) goto din_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_capture_channels_by_format, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1); + if (err < 0) goto din_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_capture_format_by_channels, NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1); + if (err < 0) goto din_exit; din_exit: @@ -463,17 +475,19 @@ static int pcm_digital_out_open(struct snd_pcm_substream *substream) if (err < 0) goto dout_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, SNDRV_PCM_HW_PARAM_FORMAT, - -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_playback_channels_by_format, + NULL, SNDRV_PCM_HW_PARAM_FORMAT, + -1); + if (err < 0) goto dout_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, SNDRV_PCM_HW_PARAM_CHANNELS, - -1)) < 0) + err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_playback_format_by_channels, + NULL, SNDRV_PCM_HW_PARAM_CHANNELS, + -1); + if (err < 0) goto dout_exit; dout_exit: @@ -907,8 +921,9 @@ static int snd_echo_new_pcm(struct echoaudio *chip) separated */ /* PCM#0 Virtual outputs and analog inputs */ - if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) + err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip), + num_analog_busses_in(chip), &pcm); + if (err < 0) return err; pcm->private_data = chip; chip->analog_pcm = pcm; @@ -919,8 +934,9 @@ static int snd_echo_new_pcm(struct echoaudio *chip) #ifdef ECHOCARD_HAS_DIGITAL_IO /* PCM#1 Digital inputs, no outputs */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0, - num_digital_busses_in(chip), &pcm)) < 0) + err = snd_pcm_new(chip->card, "Digital PCM", 1, 0, + num_digital_busses_in(chip), &pcm); + if (err < 0) return err; pcm->private_data = chip; chip->digital_pcm = pcm; @@ -937,9 +953,10 @@ static int snd_echo_new_pcm(struct echoaudio *chip) register two PCM devices: */ /* PCM#0 Analog i/o */ - if ((err = snd_pcm_new(chip->card, "Analog PCM", 0, - num_analog_busses_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) + err = snd_pcm_new(chip->card, "Analog PCM", 0, + num_analog_busses_out(chip), + num_analog_busses_in(chip), &pcm); + if (err < 0) return err; pcm->private_data = chip; chip->analog_pcm = pcm; @@ -950,9 +967,10 @@ static int snd_echo_new_pcm(struct echoaudio *chip) #ifdef ECHOCARD_HAS_DIGITAL_IO /* PCM#1 Digital i/o */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, - num_digital_busses_out(chip), - num_digital_busses_in(chip), &pcm)) < 0) + err = snd_pcm_new(chip->card, "Digital PCM", 1, + num_digital_busses_out(chip), + num_digital_busses_in(chip), &pcm); + if (err < 0) return err; pcm->private_data = chip; chip->digital_pcm = pcm; @@ -1567,7 +1585,8 @@ static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, if (chip->input_clock != dclock) { mutex_lock(&chip->mode_mutex); spin_lock_irq(&chip->lock); - if ((changed = set_input_clock(chip, dclock)) == 0) + changed = set_input_clock(chip, dclock); + if (!changed) changed = 1; /* no errors */ spin_unlock_irq(&chip->lock); mutex_unlock(&chip->mode_mutex); @@ -1911,7 +1930,8 @@ static int snd_echo_create(struct snd_card *card, pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0); - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; pci_set_master(pci); @@ -1943,8 +1963,9 @@ static int snd_echo_create(struct snd_card *card, if (sz > PAGE_SIZE) sz = PAGE_SIZE; /* We map only the required part */ - if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz, - ECHOCARD_NAME)) == NULL) { + chip->iores = request_mem_region(chip->dsp_registers_phys, sz, + ECHOCARD_NAME); + if (!chip->iores) { dev_err(chip->card->dev, "cannot get memory region\n"); snd_echo_free(chip); return -EBUSY; @@ -1988,7 +2009,8 @@ static int snd_echo_create(struct snd_card *card, return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_echo_free(chip); return err; } @@ -2024,7 +2046,8 @@ static int snd_echo_probe(struct pci_dev *pci, return err; chip = NULL; /* Tells snd_echo_create to allocate chip */ - if ((err = snd_echo_create(card, pci, &chip)) < 0) { + err = snd_echo_create(card, pci, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -2040,7 +2063,8 @@ static int snd_echo_probe(struct pci_dev *pci, card->shortname, pci_id->subdevice & 0x000f, dsp, chip->dsp_registers_phys, chip->irq); - if ((err = snd_echo_new_pcm(chip)) < 0) { + err = snd_echo_new_pcm(chip); + if (err < 0) { dev_err(chip->card->dev, "new pcm error %d\n", err); snd_card_free(card); return err; @@ -2048,7 +2072,8 @@ static int snd_echo_probe(struct pci_dev *pci, #ifdef ECHOCARD_HAS_MIDI if (chip->has_midi) { /* Some Mia's do not have midi */ - if ((err = snd_echo_midi_create(card, chip)) < 0) { + err = snd_echo_midi_create(card, chip); + if (err < 0) { dev_err(chip->card->dev, "new midi error %d\n", err); snd_card_free(card); return err; @@ -2058,7 +2083,8 @@ static int snd_echo_probe(struct pci_dev *pci, #ifdef ECHOCARD_HAS_VMIXER snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip)); + if (err < 0) goto ctl_error; #ifdef ECHOCARD_HAS_LINE_OUT_GAIN err = snd_ctl_add(chip->card, @@ -2074,39 +2100,48 @@ static int snd_echo_probe(struct pci_dev *pci, #endif /* ECHOCARD_HAS_VMIXER */ #ifdef ECHOCARD_HAS_INPUT_GAIN - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip)); + if (err < 0) goto ctl_error; #endif #ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL - if (!chip->hasnt_input_nominal_level) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0) + if (!chip->hasnt_input_nominal_level) { + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip)); + if (err < 0) goto ctl_error; + } #endif #ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip)); + if (err < 0) goto ctl_error; #endif - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip)); + if (err < 0) goto ctl_error; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip)); + if (err < 0) goto ctl_error; #ifdef ECHOCARD_HAS_MONITOR snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip)); + if (err < 0) goto ctl_error; #endif #ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip)); + if (err < 0) goto ctl_error; #endif - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip)); + if (err < 0) goto ctl_error; #ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH @@ -2116,7 +2151,8 @@ static int snd_echo_probe(struct pci_dev *pci, if (chip->digital_modes & (1 << i)) chip->digital_mode_list[chip->num_digital_modes++] = i; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip)); + if (err < 0) goto ctl_error; #endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ @@ -2129,20 +2165,24 @@ static int snd_echo_probe(struct pci_dev *pci, if (chip->num_clock_sources > 1) { chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip); - if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0) + err = snd_ctl_add(chip->card, chip->clock_src_ctl); + if (err < 0) goto ctl_error; } #endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ #ifdef ECHOCARD_HAS_DIGITAL_IO - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip)); + if (err < 0) goto ctl_error; #endif #ifdef ECHOCARD_HAS_PHANTOM_POWER - if (chip->has_phantom_power) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0) + if (chip->has_phantom_power) { + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip)); + if (err < 0) goto ctl_error; + } #endif err = snd_card_register(card); diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c index d10d0e460f0b..2a40091d472c 100644 --- a/sound/pci/echoaudio/echoaudio_dsp.c +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -349,7 +349,8 @@ static int load_dsp(struct echoaudio *chip, u16 *code) /* If this board requires a resident loader, install it. */ #ifdef DSP_56361 - if ((i = install_resident_loader(chip)) < 0) + i = install_resident_loader(chip); + if (i < 0) return i; #endif @@ -495,7 +496,8 @@ static int load_firmware(struct echoaudio *chip) /* See if the ASIC is present and working - only if the DSP is already loaded */ if (chip->dsp_code) { - if ((box_type = check_asic_status(chip)) >= 0) + box_type = check_asic_status(chip); + if (box_type >= 0) return box_type; /* ASIC check failed; force the DSP to reload */ chip->dsp_code = NULL; @@ -509,7 +511,8 @@ static int load_firmware(struct echoaudio *chip) if (err < 0) return err; - if ((box_type = load_asic(chip)) < 0) + box_type = load_asic(chip); + if (box_type < 0) return box_type; /* error */ return box_type; @@ -667,7 +670,8 @@ static int restore_dsp_rettings(struct echoaudio *chip) { int i, o, err; - if ((err = check_asic_status(chip)) < 0) + err = check_asic_status(chip); + if (err < 0) return err; /* Gina20/Darla20 only. Should be harmless for other cards. */ diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c index eea6fe530ab4..248983fa2959 100644 --- a/sound/pci/echoaudio/echoaudio_gml.c +++ b/sound/pci/echoaudio/echoaudio_gml.c @@ -194,7 +194,8 @@ static int set_professional_spdif(struct echoaudio *chip, char prof) } } - if ((err = write_control_reg(chip, control_reg, false))) + err = write_control_reg(chip, control_reg, false); + if (err) return err; chip->professional_spdif = prof; dev_dbg(chip->card->dev, "set_professional_spdif to %s\n", diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c index b2377573de09..c93939850357 100644 --- a/sound/pci/echoaudio/gina20_dsp.c +++ b/sound/pci/echoaudio/gina20_dsp.c @@ -40,7 +40,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -58,7 +59,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c index 8eff2b4f5ceb..56e9d1b9b330 100644 --- a/sound/pci/echoaudio/gina24_dsp.c +++ b/sound/pci/echoaudio/gina24_dsp.c @@ -44,7 +44,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -74,7 +75,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM; } - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c index c97dc83bbbdf..16eb082df56a 100644 --- a/sound/pci/echoaudio/indigo_dsp.c +++ b/sound/pci/echoaudio/indigo_dsp.c @@ -41,7 +41,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -56,7 +57,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c index 2428b35f45d6..17a1d888d0b9 100644 --- a/sound/pci/echoaudio/indigodj_dsp.c +++ b/sound/pci/echoaudio/indigodj_dsp.c @@ -41,7 +41,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJ)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -56,7 +57,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c index 79b68ba70936..791787aa0744 100644 --- a/sound/pci/echoaudio/indigoio_dsp.c +++ b/sound/pci/echoaudio/indigoio_dsp.c @@ -41,7 +41,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_IO)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -56,7 +57,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->asic_loaded = true; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c index 5e5b6e288a2d..5fb5c4a4598b 100644 --- a/sound/pci/echoaudio/layla20_dsp.c +++ b/sound/pci/echoaudio/layla20_dsp.c @@ -43,7 +43,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -60,7 +61,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->output_clock_types = ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c index c02bc1dcc170..ef27805d63f6 100644 --- a/sound/pci/echoaudio/layla24_dsp.c +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -43,7 +43,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA24)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -62,11 +63,13 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; - if ((err = init_line_levels(chip)) < 0) + err = init_line_levels(chip); + if (err < 0) return err; return err; diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c index 8f612a09c5d0..8a4dffc68889 100644 --- a/sound/pci/echoaudio/mia_dsp.c +++ b/sound/pci/echoaudio/mia_dsp.c @@ -44,7 +44,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -62,7 +63,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c index 6045a115cffe..cb72d27e809e 100644 --- a/sound/pci/echoaudio/midi.c +++ b/sound/pci/echoaudio/midi.c @@ -308,8 +308,8 @@ static int snd_echo_midi_create(struct snd_card *card, { int err; - if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, - &chip->rmidi)) < 0) + err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, &chip->rmidi); + if (err < 0) return err; strcpy(chip->rmidi->name, card->shortname); diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c index f77db83dd73d..f8e7bb6ce040 100644 --- a/sound/pci/echoaudio/mona_dsp.c +++ b/sound/pci/echoaudio/mona_dsp.c @@ -44,7 +44,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) if (snd_BUG_ON((subdevice_id & 0xfff0) != MONA)) return -ENODEV; - if ((err = init_dsp_comm_page(chip))) { + err = init_dsp_comm_page(chip); + if (err) { dev_err(chip->card->dev, "init_hw - could not initialize DSP comm page\n"); return err; @@ -67,7 +68,8 @@ static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) else chip->dsp_code_to_load = FW_MONA_301_DSP; - if ((err = load_firmware(chip)) < 0) + err = load_firmware(chip); + if (err < 0) return err; chip->bad_board = false; diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 45833bc2a7e7..887bfb3c1e17 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -107,18 +107,22 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, max_buffer_size[dev] = 32; else if (max_buffer_size[dev] > 1024) max_buffer_size[dev] = 1024; - if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], - (long)max_buffer_size[dev] * 1024 * 1024, - enable_ir[dev], subsystem[dev], - &emu)) < 0) + err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], + (long)max_buffer_size[dev] * 1024 * 1024, + enable_ir[dev], subsystem[dev], + &emu); + if (err < 0) goto error; card->private_data = emu; emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f; - if ((err = snd_emu10k1_pcm(emu, 0)) < 0) + err = snd_emu10k1_pcm(emu, 0); + if (err < 0) goto error; - if ((err = snd_emu10k1_pcm_mic(emu, 1)) < 0) + err = snd_emu10k1_pcm_mic(emu, 1); + if (err < 0) goto error; - if ((err = snd_emu10k1_pcm_efx(emu, 2)) < 0) + err = snd_emu10k1_pcm_efx(emu, 2); + if (err < 0) goto error; /* This stores the periods table. */ if (emu->card_capabilities->ca0151_chip) { /* P16V */ @@ -128,26 +132,33 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, goto error; } - if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) + err = snd_emu10k1_mixer(emu, 0, 3); + if (err < 0) goto error; - if ((err = snd_emu10k1_timer(emu, 0)) < 0) + err = snd_emu10k1_timer(emu, 0); + if (err < 0) goto error; - if ((err = snd_emu10k1_pcm_multi(emu, 3)) < 0) + err = snd_emu10k1_pcm_multi(emu, 3); + if (err < 0) goto error; if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_pcm(emu, 4)) < 0) + err = snd_p16v_pcm(emu, 4); + if (err < 0) goto error; } if (emu->audigy) { - if ((err = snd_emu10k1_audigy_midi(emu)) < 0) + err = snd_emu10k1_audigy_midi(emu); + if (err < 0) goto error; } else { - if ((err = snd_emu10k1_midi(emu)) < 0) + err = snd_emu10k1_midi(emu); + if (err < 0) goto error; } - if ((err = snd_emu10k1_fx8010_new(emu, 0)) < 0) + err = snd_emu10k1_fx8010_new(emu, 0); + if (err < 0) goto error; #ifdef ENABLE_SYNTH if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, @@ -174,7 +185,8 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci, "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto error; if (emu->card_capabilities->emu_model) diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index 07471c3dcbed..dba1e9fc2eec 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c @@ -90,7 +90,8 @@ snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw) if (best[i].voice >= 0) { int ch; vp = &emu->voices[best[i].voice]; - if ((ch = vp->ch) < 0) { + ch = vp->ch; + if (ch < 0) { /* dev_warn(emu->card->dev, "synth_get_voice: ch < 0 (%d) ??", i); diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index d9a12cd01647..89b0f3884067 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -349,7 +349,8 @@ static void snd_emu10k1x_pcm_interrupt(struct emu10k1x *emu, struct emu10k1x_voi { struct emu10k1x_pcm *epcm; - if ((epcm = voice->epcm) == NULL) + epcm = voice->epcm; + if (!epcm) return; if (epcm->substream == NULL) return; @@ -371,10 +372,11 @@ static int snd_emu10k1x_playback_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; - } - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) + err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); + if (err < 0) return err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); @@ -550,10 +552,12 @@ static int snd_emu10k1x_pcm_open_capture(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) - return err; + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) + return err; + err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); + if (err < 0) + return err; epcm = kzalloc(sizeof(*epcm), GFP_KERNEL); if (epcm == NULL) @@ -722,7 +726,8 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip) .read = snd_emu10k1x_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; pbus->no_vra = 1; /* we don't need VRA */ @@ -838,7 +843,8 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device) if (device == 0) capture = 1; - if ((err = snd_pcm_new(emu->card, "emu10k1x", device, 1, capture, &pcm)) < 0) + err = snd_pcm_new(emu->card, "emu10k1x", device, 1, capture, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -891,7 +897,8 @@ static int snd_emu10k1x_create(struct snd_card *card, *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28)) < 0) { @@ -914,8 +921,8 @@ static int snd_emu10k1x_create(struct snd_card *card, spin_lock_init(&chip->voice_lock); chip->port = pci_resource_start(pci, 0); - if ((chip->res_port = request_region(chip->port, 8, - "EMU10K1X")) == NULL) { + chip->res_port = request_region(chip->port, 8, "EMU10K1X"); + if (!chip->res_port) { dev_err(card->dev, "cannot allocate the port 0x%lx\n", chip->port); snd_emu10k1x_free(chip); @@ -991,8 +998,8 @@ static int snd_emu10k1x_create(struct snd_card *card, outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_emu10k1x_free(chip); return err; } @@ -1171,17 +1178,23 @@ static int snd_emu10k1x_mixer(struct emu10k1x *emu) struct snd_kcontrol *kctl; struct snd_card *card = emu->card; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_shared_spdif, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1x_shared_spdif, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_control, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1x_spdif_control, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; return 0; @@ -1488,7 +1501,8 @@ static int emu10k1x_midi_init(struct emu10k1x *emu, struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi); + if (err < 0) return err; midi->emu = emu; spin_lock_init(&midi->open_lock); @@ -1511,7 +1525,8 @@ static int snd_emu10k1x_midi(struct emu10k1x *emu) struct emu10k1x_midi *midi = &emu->midi; int err; - if ((err = emu10k1x_midi_init(emu, midi, 0, "EMU10K1X MPU-401 (UART)")) < 0) + err = emu10k1x_midi_init(emu, midi, 0, "EMU10K1X MPU-401 (UART)"); + if (err < 0) return err; midi->tx_enable = INTE_MIDITXENABLE; @@ -1543,35 +1558,42 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_emu10k1x_create(card, pci, &chip)) < 0) { + err = snd_emu10k1x_create(card, pci, &chip); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_pcm(chip, 0)) < 0) { + err = snd_emu10k1x_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_pcm(chip, 1)) < 0) { + err = snd_emu10k1x_pcm(chip, 1); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_pcm(chip, 2)) < 0) { + err = snd_emu10k1x_pcm(chip, 2); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_ac97(chip)) < 0) { + err = snd_emu10k1x_ac97(chip); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_mixer(chip)) < 0) { + err = snd_emu10k1x_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_emu10k1x_midi(chip)) < 0) { + err = snd_emu10k1x_midi(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1583,7 +1605,8 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->port, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 80ef62a4a7c0..6cf7c8b1de47 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -436,7 +436,8 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu, unsigned long flags; spin_lock_irqsave(&emu->fx8010.irq_lock, flags); - if ((tmp = emu->fx8010.irq_handlers) == irq) { + tmp = emu->fx8010.irq_handlers; + if (tmp == irq) { emu->fx8010.irq_handlers = tmp->next; if (emu->fx8010.irq_handlers == NULL) { snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); @@ -871,7 +872,9 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, } knew.private_value = (unsigned long)ctl; *ctl = *nctl; - if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { + kctl = snd_ctl_new1(&knew, emu); + err = snd_ctl_add(emu->card, kctl); + if (err < 0) { kfree(ctl); kfree(knew.tlv.p); goto __error; @@ -2403,7 +2406,8 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) while (ptr < 0x200) OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000); - if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) + err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size); + if (err < 0) goto __err; icode->gpr_add_control_count = i; icode->gpr_add_controls = controls; @@ -2681,7 +2685,8 @@ int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device) struct snd_hwdep *hw; int err; - if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0) + err = snd_hwdep_new(emu->card, "FX8010", device, &hw); + if (err < 0) return err; strcpy(hw->name, "EMU10K1 (FX8010)"); hw->iface = SNDRV_HWDEP_IFACE_EMU10K1; diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 8a6cbe67e29d..e9c0fe3b8446 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c @@ -1119,7 +1119,8 @@ static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); tmp = reg & ~A_SPDIF_RATE_MASK; tmp |= val; - if ((change = (tmp != reg))) + change = (tmp != reg); + if (change) snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); spin_unlock_irqrestore(&emu->reg_lock, flags); return change; @@ -1903,7 +1904,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, .read = snd_emu10k1_ac97_read, }; - if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; pbus->no_vra = 1; /* we don't need VRA */ @@ -1911,7 +1913,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, ac97.private_data = emu; ac97.private_free = snd_emu10k1_mixer_free_ac97; ac97.scaps = AC97_SCAP_NO_SPDIF; - if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &emu->ac97); + if (err < 0) { if (emu->card_capabilities->ac97_chip == 1) return err; dev_info(emu->card->dev, @@ -1991,38 +1994,50 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume"); rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume"); } - if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL) + kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL) + kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL) + kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = pcm_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) + kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) + kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) + kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu); + if (!kctl) return -ENOMEM; kctl->id.device = multi_device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; /* initialize the routing and volume table for each pcm playback stream */ @@ -2069,42 +2084,53 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu, if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ /* sb live! and audigy */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu); + if (!kctl) return -ENOMEM; if (!emu->audigy) kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; - if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu); + if (!kctl) return -ENOMEM; if (!emu->audigy) kctl->id.device = emu->pcm_efx->device; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; } if (emu->card_capabilities->emu_model) { ; /* Disable the snd_audigy_spdif_shared_spdif */ } else if (emu->audigy) { - if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) + kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; #if 0 - if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) + kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; #endif } else if (! emu->card_capabilities->ecard) { /* sb live! */ - if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) + kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu); + if (!kctl) return -ENOMEM; - if ((err = snd_ctl_add(card, kctl))) + err = snd_ctl_add(card, kctl); + if (err) return err; } if (emu->card_capabilities->ca0151_chip) { /* P16V */ - if ((err = snd_p16v_mixer(emu))) + err = snd_p16v_mixer(emu); + if (err) return err; } diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c index b62c95150702..3ce9b2129ce6 100644 --- a/sound/pci/emu10k1/emumpu401.c +++ b/sound/pci/emu10k1/emumpu401.c @@ -319,7 +319,8 @@ static int emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *m struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi); + if (err < 0) return err; midi->emu = emu; spin_lock_init(&midi->open_lock); @@ -342,7 +343,8 @@ int snd_emu10k1_midi(struct snd_emu10k1 *emu) struct snd_emu10k1_midi *midi = &emu->midi; int err; - if ((err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)")) < 0) + err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)"); + if (err < 0) return err; midi->tx_enable = INTE_MIDITXENABLE; @@ -360,7 +362,8 @@ int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) int err; midi = &emu->midi; - if ((err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)")) < 0) + err = emu10k1_midi_init(emu, midi, 0, "Audigy MPU-401 (UART)"); + if (err < 0) return err; midi->tx_enable = INTE_MIDITXENABLE; @@ -371,7 +374,8 @@ int snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu) midi->interrupt = snd_emu10k1_midi_interrupt; midi = &emu->midi2; - if ((err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2")) < 0) + err = emu10k1_midi_init(emu, midi, 1, "Audigy MPU-401 #2"); + if (err < 0) return err; midi->tx_enable = INTE_A_MIDITXENABLE2; diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index b2ddabb99438..b2701a4452d8 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -25,7 +25,8 @@ static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu, { struct snd_emu10k1_pcm *epcm; - if ((epcm = voice->epcm) == NULL) + epcm = voice->epcm; + if (!epcm) return; if (epcm->substream == NULL) return; @@ -399,7 +400,8 @@ static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream, size_t alloc_size; int err; - if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0) + err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params)); + if (err < 0) return err; alloc_size = params_buffer_bytes(hw_params); @@ -1124,11 +1126,13 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream) runtime->private_data = epcm; runtime->private_free = snd_emu10k1_pcm_free_substream; runtime->hw = snd_emu10k1_playback; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) { + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) { kfree(epcm); return err; } - if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) { + err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX); + if (err < 0) { kfree(epcm); return err; } @@ -1380,7 +1384,8 @@ int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0) + err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -1412,7 +1417,8 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device) struct snd_pcm_substream *substream; int err; - if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0) + err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -1446,7 +1452,8 @@ int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0) + err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -1774,7 +1781,8 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device) struct snd_kcontrol *kctl; int err; - if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0) + err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm); + if (err < 0) return err; pcm->private_data = emu; diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 288e0fd2e47d..9d26535f3fa3 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -169,16 +169,20 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk) struct snd_emu10k1_memblk *q; /* calculate the expected size of empty region */ - if ((p = blk->mapped_link.prev) != &emu->mapped_link_head) { + p = blk->mapped_link.prev; + if (p != &emu->mapped_link_head) { q = get_emu10k1_memblk(p, mapped_link); start_page = q->mapped_page + q->pages; - } else + } else { start_page = 1; - if ((p = blk->mapped_link.next) != &emu->mapped_link_head) { + } + p = blk->mapped_link.next; + if (p != &emu->mapped_link_head) { q = get_emu10k1_memblk(p, mapped_link); end_page = q->mapped_page; - } else + } else { end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0); + } /* remove links */ list_del(&blk->mapped_link); @@ -267,7 +271,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b spin_unlock_irqrestore(&emu->memblk_lock, flags); return 0; } - if ((err = map_memblk(emu, blk)) < 0) { + err = map_memblk(emu, blk); + if (err < 0) { /* no enough page - try to unmap some blocks */ /* starting from the oldest block */ p = emu->mapped_order_link_head.next; @@ -454,13 +459,15 @@ static void get_single_page_range(struct snd_util_memhdr *hdr, struct snd_emu10k1_memblk *q; int first_page, last_page; first_page = blk->first_page; - if ((p = blk->mem.list.prev) != &hdr->block) { + p = blk->mem.list.prev; + if (p != &hdr->block) { q = get_emu10k1_memblk(p, mem.list); if (q->last_page == first_page) first_page++; /* first page was already allocated */ } last_page = blk->last_page; - if ((p = blk->mem.list.next) != &hdr->block) { + p = blk->mem.list.next; + if (p != &hdr->block) { q = get_emu10k1_memblk(p, mem.list); if (q->first_page == last_page) last_page--; /* last page was already allocated */ diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 1099f102b365..ff2a3974c824 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -194,7 +194,8 @@ static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substrea #endif /* debug */ /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; runtime->sync.id32[0] = substream->pcm->card->number; @@ -242,7 +243,8 @@ static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream #endif /* debug */ /* channel->interrupt = snd_p16v_pcm_channel_interrupt; */ channel->epcm = epcm; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; @@ -589,7 +591,8 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device) /* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */ emu->p16v_device_offset = device; - if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) + err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm); + if (err < 0) return err; pcm->private_data = emu; @@ -808,8 +811,8 @@ int snd_p16v_mixer(struct snd_emu10k1 *emu) struct snd_card *card = emu->card; for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) { - if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i], - emu))) < 0) + err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i], emu)); + if (err < 0) return err; } return 0; diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c index c2803000aace..2435d3ba68f7 100644 --- a/sound/pci/emu10k1/timer.c +++ b/sound/pci/emu10k1/timer.c @@ -72,7 +72,8 @@ int snd_emu10k1_timer(struct snd_emu10k1 *emu, int device) tid.card = emu->card->number; tid.device = device; tid.subdevice = 0; - if ((err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer)) >= 0) { + err = snd_timer_new(emu->card, "EMU10K1", &tid, &timer); + if (err >= 0) { strcpy(timer->name, "EMU10K1 timer"); timer->private_data = emu; timer->hw = snd_emu10k1_timer_hw; diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 3ccccdbc0029..728b69dad21b 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -672,7 +672,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97, } /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { - if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { + x = inl(ES_REG(ensoniq, 1371_CODEC)); + if (x & ES_1371_CODEC_RDY) { if (is_ev1938(ensoniq)) { for (t = 0; t < 100; t++) inl(ES_REG(ensoniq, CONTROL)); @@ -1594,7 +1595,8 @@ static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, .wait = snd_es1371_codec_wait, }; - if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); @@ -1602,7 +1604,8 @@ static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, ac97.private_free = snd_ensoniq_mixer_free_ac97; ac97.pci = ensoniq->pci; ac97.scaps = AC97_SCAP_AUDIO; - if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) + err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97); + if (err < 0) return err; if (has_spdif > 0 || (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) { @@ -1722,7 +1725,8 @@ static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq) ak4531.write = snd_es1370_codec_write; ak4531.private_data = ensoniq; ak4531.private_free = snd_ensoniq_mixer_free_ak4531; - if ((err = snd_ak4531_mixer(card, &ak4531, &ensoniq->u.es1370.ak4531)) < 0) + err = snd_ak4531_mixer(card, &ak4531, &ensoniq->u.es1370.ak4531); + if (err < 0) return err; for (idx = 0; idx < ES1370_CONTROLS; idx++) { err = snd_ctl_add(card, snd_ctl_new1(&snd_es1370_controls[idx], ensoniq)); @@ -2038,7 +2042,8 @@ static int snd_ensoniq_create(struct snd_card *card, }; *rensoniq = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; ensoniq = kzalloc(sizeof(*ensoniq), GFP_KERNEL); if (ensoniq == NULL) { @@ -2050,7 +2055,8 @@ static int snd_ensoniq_create(struct snd_card *card, ensoniq->card = card; ensoniq->pci = pci; ensoniq->irq = -1; - if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) { + err = pci_request_regions(pci, "Ensoniq AudioPCI"); + if (err < 0) { kfree(ensoniq); pci_disable_device(pci); return err; @@ -2095,7 +2101,8 @@ static int snd_ensoniq_create(struct snd_card *card, snd_ensoniq_chip_init(ensoniq); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops); + if (err < 0) { snd_ensoniq_free(ensoniq); return err; } @@ -2286,7 +2293,8 @@ static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device) struct snd_rawmidi *rmidi; int err; - if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) + err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi); + if (err < 0) return err; strcpy(rmidi->name, CHIP_NAME); snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); @@ -2357,33 +2365,39 @@ static int snd_audiopci_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_ensoniq_create(card, pci, &ensoniq)) < 0) { + err = snd_ensoniq_create(card, pci, &ensoniq); + if (err < 0) { snd_card_free(card); return err; } card->private_data = ensoniq; #ifdef CHIP1370 - if ((err = snd_ensoniq_1370_mixer(ensoniq)) < 0) { + err = snd_ensoniq_1370_mixer(ensoniq); + if (err < 0) { snd_card_free(card); return err; } #endif #ifdef CHIP1371 - if ((err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev])) < 0) { + err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev]); + if (err < 0) { snd_card_free(card); return err; } #endif - if ((err = snd_ensoniq_pcm(ensoniq, 0)) < 0) { + err = snd_ensoniq_pcm(ensoniq, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_ensoniq_pcm2(ensoniq, 1)) < 0) { + err = snd_ensoniq_pcm2(ensoniq, 1); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_ensoniq_midi(ensoniq, 0)) < 0) { + err = snd_ensoniq_midi(ensoniq, 0); + if (err < 0) { snd_card_free(card); return err; } @@ -2399,7 +2413,8 @@ static int snd_audiopci_probe(struct pci_dev *pci, ensoniq->port, ensoniq->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index afc66347d162..33b1eb347a27 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -293,7 +293,8 @@ static void snd_es1938_write_cmd(struct es1938 *chip, unsigned char cmd) int i; unsigned char v; for (i = 0; i < WRITE_LOOP_TIMEOUT; i++) { - if (!(v = inb(SLSB_REG(chip, READSTATUS)) & 0x80)) { + v = inb(SLSB_REG(chip, READSTATUS)); + if (!(v & 0x80)) { outb(cmd, SLSB_REG(chip, WRITEDATA)); return; } @@ -309,9 +310,11 @@ static int snd_es1938_get_byte(struct es1938 *chip) { int i; unsigned char v; - for (i = GET_LOOP_TIMEOUT; i; i--) - if ((v = inb(SLSB_REG(chip, STATUS))) & 0x80) + for (i = GET_LOOP_TIMEOUT; i; i--) { + v = inb(SLSB_REG(chip, STATUS)); + if (v & 0x80) return inb(SLSB_REG(chip, READDATA)); + } dev_err(chip->card->dev, "get_byte timeout: status 0x02%x\n", v); return -ENODEV; } @@ -993,7 +996,8 @@ static int snd_es1938_new_pcm(struct es1938 *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm); + if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1938_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1938_capture_ops); @@ -1553,7 +1557,8 @@ static int snd_es1938_create(struct snd_card *card, *rchip = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { @@ -1573,7 +1578,8 @@ static int snd_es1938_create(struct snd_card *card, chip->card = card; chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) { + err = pci_request_regions(pci, "ESS Solo-1"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1599,7 +1605,8 @@ static int snd_es1938_create(struct snd_card *card, snd_es1938_chip_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_es1938_free(chip); return err; } @@ -1731,7 +1738,8 @@ static int snd_es1938_mixer(struct es1938 *chip) kctl->private_free = snd_es1938_hwv_free; break; } - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } return 0; @@ -1765,7 +1773,8 @@ static int snd_es1938_probe(struct pci_dev *pci, return -ENODEV; } } - if ((err = snd_es1938_create(card, pci, &chip)) < 0) { + err = snd_es1938_create(card, pci, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1778,11 +1787,13 @@ static int snd_es1938_probe(struct pci_dev *pci, chip->revision, chip->irq); - if ((err = snd_es1938_new_pcm(chip, 0)) < 0) { + err = snd_es1938_new_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_es1938_mixer(chip)) < 0) { + err = snd_es1938_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1793,11 +1804,13 @@ static int snd_es1938_probe(struct pci_dev *pci, dev_err(card->dev, "OPL3 not detected at 0x%lx\n", SLSB_REG(chip, FMLOWADDR)); } else { - if ((err = snd_opl3_timer_new(opl3, 0, 1)) < 0) { + err = snd_opl3_timer_new(opl3, 0, 1); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { snd_card_free(card); return err; } @@ -1815,7 +1828,8 @@ static int snd_es1938_probe(struct pci_dev *pci, snd_es1938_create_gameport(chip); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5fa1861236f5..c038c1035c39 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1600,7 +1600,8 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) es->mode = ESM_MODE_CAPTURE; /* get mixbuffer */ - if ((es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE)) == NULL) { + es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE); + if (!es->mixbuf) { snd_es1968_free_apu_pair(chip, apu1); snd_es1968_free_apu_pair(chip, apu2); kfree(es); @@ -1695,11 +1696,13 @@ static void es1968_measure_clock(struct es1968 *chip) chip->clock = 48000; /* default clock value */ /* search 2 APUs (although one apu is enough) */ - if ((apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY)) < 0) { + apu = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY); + if (apu < 0) { dev_err(chip->card->dev, "Hmm, cannot find empty APU pair!?\n"); return; } - if ((memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE)) == NULL) { + memory = snd_es1968_new_memory(chip, CLOCK_MEASURE_BUFSIZE); + if (!memory) { dev_warn(chip->card->dev, "cannot allocate dma buffer - using default clock %d\n", chip->clock); @@ -1791,7 +1794,8 @@ snd_es1968_pcm(struct es1968 *chip, int device) int err; /* get DMA buffer */ - if ((err = snd_es1968_init_dmabuf(chip)) < 0) + err = snd_es1968_init_dmabuf(chip); + if (err < 0) return err; /* set PCMBAR */ @@ -1800,9 +1804,10 @@ snd_es1968_pcm(struct es1968 *chip, int device) wave_set_register(chip, 0x01FE, chip->dma.addr >> 12); wave_set_register(chip, 0x01FF, chip->dma.addr >> 12); - if ((err = snd_pcm_new(chip->card, "ESS Maestro", device, - chip->playback_streams, - chip->capture_streams, &pcm)) < 0) + err = snd_pcm_new(chip->card, "ESS Maestro", device, + chip->playback_streams, + chip->capture_streams, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1953,7 +1958,8 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id) struct es1968 *chip = dev_id; u32 event; - if (!(event = inb(chip->io_port + 0x1A))) + event = inb(chip->io_port + 0x1A); + if (!event) return IRQ_NONE; outw(inw(chip->io_port + 4) & 1, chip->io_port + 4); @@ -2008,13 +2014,15 @@ snd_es1968_mixer(struct es1968 *chip) .read = snd_es1968_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; pbus->no_vra = 1; /* ES1968 doesn't need VRA */ memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); + if (err < 0) return err; #ifndef CONFIG_SND_ES1968_INPUT @@ -2661,7 +2669,8 @@ static int snd_es1968_create(struct snd_card *card, *chip_ret = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 28 bits */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) { @@ -2692,7 +2701,8 @@ static int snd_es1968_create(struct snd_card *card, chip->playback_streams = play_streams; chip->capture_streams = capt_streams; - if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) { + err = pci_request_regions(pci, "ESS Maestro"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -2739,7 +2749,8 @@ static int snd_es1968_create(struct snd_card *card, snd_es1968_chip_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_es1968_free(chip); return err; } @@ -2804,14 +2815,15 @@ static int snd_es1968_probe(struct pci_dev *pci, total_bufsize[dev] = 128; if (total_bufsize[dev] > 4096) total_bufsize[dev] = 4096; - if ((err = snd_es1968_create(card, pci, - total_bufsize[dev] * 1024, /* in bytes */ - pcm_substreams_p[dev], - pcm_substreams_c[dev], - pci_id->driver_data, - use_pm[dev], - radio_nr[dev], - &chip)) < 0) { + err = snd_es1968_create(card, pci, + total_bufsize[dev] * 1024, /* in bytes */ + pcm_substreams_p[dev], + pcm_substreams_c[dev], + pci_id->driver_data, + use_pm[dev], + radio_nr[dev], + &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -2832,12 +2844,14 @@ static int snd_es1968_probe(struct pci_dev *pci, break; } - if ((err = snd_es1968_pcm(chip, 0)) < 0) { + err = snd_es1968_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_es1968_mixer(chip)) < 0) { + err = snd_es1968_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -2855,13 +2869,13 @@ static int snd_es1968_probe(struct pci_dev *pci, } } if (enable_mpu[dev]) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->io_port + ESM_MPU401_PORT, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, + chip->io_port + ESM_MPU401_PORT, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); + if (err < 0) dev_warn(card->dev, "skipping MPU-401 MIDI support..\n"); - } } snd_es1968_create_gameport(chip, dev); @@ -2882,7 +2896,8 @@ static int snd_es1968_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->io_port, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 6279eb156e36..ed9dae87145b 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -659,7 +659,8 @@ static int snd_fm801_playback_open(struct snd_pcm_substream *substream) SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels); } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; } @@ -674,7 +675,8 @@ static int snd_fm801_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_fm801_capture; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; return 0; } @@ -717,7 +719,8 @@ static int snd_fm801_pcm(struct fm801 *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm); + if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_fm801_playback_ops); @@ -985,7 +988,8 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol, struct fm801 *chip = snd_kcontrol_chip(kcontrol); unsigned short val; - if ((val = ucontrol->value.enumerated.item[0]) > 4) + val = ucontrol->value.enumerated.item[0]; + if (val > 4) return -EINVAL; return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); } @@ -1050,19 +1054,22 @@ static int snd_fm801_mixer(struct fm801 *chip) .read = snd_fm801_codec_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_fm801_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; if (chip->secondary) { ac97.num = 1; ac97.addr = chip->secondary_addr; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec); + if (err < 0) return err; } for (i = 0; i < FM801_CONTROLS; i++) { @@ -1213,7 +1220,8 @@ static int snd_fm801_create(struct snd_card *card, }; *rchip = NULL; - if ((err = pcim_enable_device(pci)) < 0) + err = pcim_enable_device(pci); + if (err < 0) return err; chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL); if (chip == NULL) @@ -1223,7 +1231,8 @@ static int snd_fm801_create(struct snd_card *card, chip->dev = &pci->dev; chip->irq = -1; chip->tea575x_tuner = tea575x_tuner; - if ((err = pci_request_regions(pci, "FM801")) < 0) + err = pci_request_regions(pci, "FM801"); + if (err < 0) return err; chip->port = pci_resource_start(pci, 0); @@ -1254,7 +1263,8 @@ static int snd_fm801_create(struct snd_card *card, snd_fm801_chip_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_fm801_free(chip); return err; } @@ -1327,7 +1337,8 @@ static int snd_card_fm801_probe(struct pci_dev *pci, 0, &card); if (err < 0) return err; - if ((err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip)) < 0) { + err = snd_fm801_create(card, pci, tea575x_tuner[dev], radio_nr[dev], &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1342,35 +1353,41 @@ static int snd_card_fm801_probe(struct pci_dev *pci, if (chip->tea575x_tuner & TUNER_ONLY) goto __fm801_tuner_only; - if ((err = snd_fm801_pcm(chip, 0)) < 0) { + err = snd_fm801_pcm(chip, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_fm801_mixer(chip)) < 0) { + err = snd_fm801_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, - chip->port + FM801_MPU401_DATA, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rmidi)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, + chip->port + FM801_MPU401_DATA, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rmidi); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0, - chip->port + FM801_OPL3_BANK1, - OPL3_HW_OPL3_FM801, 1, &opl3)) < 0) { + err = snd_opl3_create(card, chip->port + FM801_OPL3_BANK0, + chip->port + FM801_OPL3_BANK1, + OPL3_HW_OPL3_FM801, 1, &opl3); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { snd_card_free(card); return err; } __fm801_tuner_only: - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 17a25e453f60..e8dee24c309d 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -167,8 +167,11 @@ static void hda_codec_driver_shutdown(struct device *dev) { struct hda_codec *codec = dev_to_hda_codec(dev); - if (!pm_runtime_suspended(dev) && codec->patch_ops.reboot_notify) - codec->patch_ops.reboot_notify(codec); + if (!pm_runtime_suspended(dev)) { + if (codec->patch_ops.reboot_notify) + codec->patch_ops.reboot_notify(codec); + snd_hda_codec_display_power(codec, false); + } } int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5462f771c2f9..7a717e151156 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -798,7 +798,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); /* enable/disable display power per codec */ -static void codec_display_power(struct hda_codec *codec, bool enable) +void snd_hda_codec_display_power(struct hda_codec *codec, bool enable) { if (codec->display_power_control) snd_hdac_display_power(&codec->bus->core, codec->addr, enable); @@ -810,7 +810,7 @@ void snd_hda_codec_register(struct hda_codec *codec) if (codec->registered) return; if (device_is_registered(hda_codec_dev(codec))) { - codec_display_power(codec, true); + snd_hda_codec_display_power(codec, true); pm_runtime_enable(hda_codec_dev(codec)); /* it was powered up in snd_hda_codec_new(), now all done */ snd_hda_power_down(codec); @@ -836,7 +836,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) */ if (codec->core.type == HDA_DEV_LEGACY) snd_hdac_device_unregister(&codec->core); - codec_display_power(codec, false); + snd_hda_codec_display_power(codec, false); /* * In the case of ASoC HD-audio bus, the device refcount is released in @@ -2893,7 +2893,7 @@ static int hda_codec_runtime_suspend(struct device *dev) (codec_has_clkstop(codec) && codec_has_epss(codec) && (state & AC_PWRST_CLK_STOP_OK))) snd_hdac_codec_link_down(&codec->core); - codec_display_power(codec, false); + snd_hda_codec_display_power(codec, false); return 0; } @@ -2905,7 +2905,7 @@ static int hda_codec_runtime_resume(struct device *dev) if (!codec->card) return 0; - codec_display_power(codec, true); + snd_hda_codec_display_power(codec, true); snd_hdac_codec_link_up(&codec->core); hda_call_codec_resume(codec); pm_runtime_mark_last_busy(dev); diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 1f8018f9ce57..e97d00585e8e 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -1433,7 +1433,7 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, path = snd_hda_add_new_path(codec, dac, pin, 0); } if (!path) { - dac = dacs[i] = 0; + dacs[i] = 0; badness += bad->no_dac; } else { /* print_nid_path(codec, "output", path); */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 470753b36c8a..0322b289505e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -883,6 +883,14 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev) return azx_get_pos_posbuf(chip, azx_dev); } +static void azx_shutdown_chip(struct azx *chip) +{ + azx_stop_chip(chip); + azx_enter_link_reset(chip); + azx_clear_irq_pending(chip); + display_power(chip, false); +} + #ifdef CONFIG_PM static DEFINE_MUTEX(card_list_lock); static LIST_HEAD(card_list); @@ -942,14 +950,6 @@ static bool azx_is_pm_ready(struct snd_card *card) return true; } -static void __azx_runtime_suspend(struct azx *chip) -{ - azx_stop_chip(chip); - azx_enter_link_reset(chip); - azx_clear_irq_pending(chip); - display_power(chip, false); -} - static void __azx_runtime_resume(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); @@ -1028,7 +1028,7 @@ static int azx_suspend(struct device *dev) chip = card->private_data; bus = azx_bus(chip); - __azx_runtime_suspend(chip); + azx_shutdown_chip(chip); if (bus->irq >= 0) { free_irq(bus->irq, chip); bus->irq = -1; @@ -1107,7 +1107,7 @@ static int azx_runtime_suspend(struct device *dev) /* enable controller wake up event */ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK); - __azx_runtime_suspend(chip); + azx_shutdown_chip(chip); trace_azx_runtime_suspend(chip); return 0; } @@ -2385,7 +2385,7 @@ static void azx_shutdown(struct pci_dev *pci) return; chip = card->private_data; if (chip && chip->running) - azx_stop_chip(chip); + azx_shutdown_chip(chip); } /* PCI IDs */ diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 4c5589c10f1d..8d2503e8dad8 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -709,6 +709,8 @@ void snd_hdmi_write_eld_info(struct hdmi_eld *eld, #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); +void snd_hda_codec_display_power(struct hda_codec *codec, bool enable); + /* */ #define codec_err(codec, fmt, args...) \ diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 6f2b743b9d75..ea700395bef4 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -235,11 +235,9 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) { struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); - struct device *dev = hda->dev; struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hda->regs = devm_ioremap_resource(dev, res); + hda->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(hda->regs)) return PTR_ERR(hda->regs); @@ -262,6 +260,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) const char *sname, *drv_name = "tegra-hda"; struct device_node *np = pdev->dev.of_node; + if (irq_id < 0) + return irq_id; + err = hda_tegra_init_chip(chip, pdev); if (err) return err; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 49b4fdd2feab..b66e7bdbf483 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -7598,7 +7598,7 @@ static void ca0132_alt_free_active_dma_channels(struct hda_codec *codec) */ static void ca0132_alt_start_dsp_audio_streams(struct hda_codec *codec) { - const unsigned int dsp_dma_stream_ids[] = { 0x0c, 0x03, 0x04 }; + static const unsigned int dsp_dma_stream_ids[] = { 0x0c, 0x03, 0x04 }; struct ca0132_spec *spec = codec->spec; unsigned int i, tmp; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ab5113cccffa..1389cfd5e0db 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -385,6 +385,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); fallthrough; case 0x10ec0215: + case 0x10ec0230: case 0x10ec0233: case 0x10ec0235: case 0x10ec0236: @@ -3054,6 +3055,7 @@ enum { ALC269_TYPE_ALC257, ALC269_TYPE_ALC215, ALC269_TYPE_ALC225, + ALC269_TYPE_ALC287, ALC269_TYPE_ALC294, ALC269_TYPE_ALC300, ALC269_TYPE_ALC623, @@ -3090,6 +3092,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC257: case ALC269_TYPE_ALC215: case ALC269_TYPE_ALC225: + case ALC269_TYPE_ALC287: case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC300: case ALC269_TYPE_ALC623: @@ -3153,6 +3156,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec) alc_update_coef_idx(codec, 0x49, 0x0045, 0x0); alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x48, 0x0); @@ -3180,6 +3184,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec) alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x48, 0xd011); @@ -3558,12 +3563,70 @@ static void alc256_shutup(struct hda_codec *codec) } } +static void alc285_hp_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = alc_get_hp_pin(spec); + int i, val; + int coef38, coef0d, coef36; + + alc_update_coef_idx(codec, 0x4a, 1<<15, 1<<15); /* Reset HP JD */ + coef38 = alc_read_coef_idx(codec, 0x38); /* Amp control */ + coef0d = alc_read_coef_idx(codec, 0x0d); /* Digital Misc control */ + coef36 = alc_read_coef_idx(codec, 0x36); /* Passthrough Control */ + alc_update_coef_idx(codec, 0x38, 1<<4, 0x0); + alc_update_coef_idx(codec, 0x0d, 0x110, 0x0); + + alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); + + if (hp_pin) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + msleep(130); + alc_update_coef_idx(codec, 0x36, 1<<14, 1<<14); + alc_update_coef_idx(codec, 0x36, 1<<13, 0x0); + + if (hp_pin) + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + msleep(10); + alc_write_coef_idx(codec, 0x67, 0x0); /* Set HP depop to manual mode */ + alc_write_coefex_idx(codec, 0x58, 0x00, 0x7880); + alc_write_coefex_idx(codec, 0x58, 0x0f, 0xf049); + alc_update_coefex_idx(codec, 0x58, 0x03, 0x00f0, 0x00c0); + + alc_write_coefex_idx(codec, 0x58, 0x00, 0xf888); /* HP depop procedure start */ + val = alc_read_coefex_idx(codec, 0x58, 0x00); + for (i = 0; i < 20 && val & 0x8000; i++) { + msleep(50); + val = alc_read_coefex_idx(codec, 0x58, 0x00); + } /* Wait for depop procedure finish */ + + alc_write_coefex_idx(codec, 0x58, 0x00, val); /* write back the result */ + alc_update_coef_idx(codec, 0x38, 1<<4, coef38); + alc_update_coef_idx(codec, 0x0d, 0x110, coef0d); + alc_update_coef_idx(codec, 0x36, 3<<13, coef36); + + msleep(50); + alc_update_coef_idx(codec, 0x4a, 1<<15, 0); +} + static void alc225_init(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; hda_nid_t hp_pin = alc_get_hp_pin(spec); bool hp1_pin_sense, hp2_pin_sense; + if (spec->codec_variant != ALC269_TYPE_ALC287) + /* required only at boot or S3 and S4 resume time */ + if (!spec->done_hp_init || + is_s3_resume(codec) || + is_s4_resume(codec)) { + alc285_hp_init(codec); + spec->done_hp_init = true; + } + if (!hp_pin) hp_pin = 0x21; msleep(30); @@ -4744,6 +4807,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -4858,6 +4922,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, alc_process_coef_fw(codec, coef0255); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x45, 0xc489); @@ -5007,6 +5072,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x1b, 0x0e4b); @@ -5105,6 +5171,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -5218,6 +5285,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -5318,6 +5386,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x0070) == 0x0070; break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x1b, 0x0e4b); @@ -5611,6 +5680,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, alc255fw); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, alc256fw); @@ -6211,6 +6281,7 @@ static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec) alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */ alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15); break; + case 0x10ec0230: case 0x10ec0235: case 0x10ec0236: case 0x10ec0255: @@ -6343,6 +6414,24 @@ static void alc_fixup_no_int_mic(struct hda_codec *codec, } } +static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + static const hda_nid_t conn[] = { 0x02 }; + static const struct hda_pintbl pincfgs[] = { + { 0x14, 0x90170110 }, /* rear speaker */ + { } + }; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + snd_hda_apply_pincfgs(codec, pincfgs); + /* force front speaker to DAC1 */ + snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); + break; + } +} + /* for hda_fixup_thinkpad_acpi() */ #include "thinkpad_helper.c" @@ -7810,6 +7899,8 @@ static const struct hda_fixup alc269_fixups[] = { { 0x20, AC_VERB_SET_PROC_COEF, 0x4e4b }, { } }, + .chained = true, + .chain_id = ALC289_FIXUP_ASUS_GA401, }, [ALC285_FIXUP_HP_GPIO_LED] = { .type = HDA_FIXUP_FUNC, @@ -8127,13 +8218,8 @@ static const struct hda_fixup alc269_fixups[] = { .chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED, }, [ALC285_FIXUP_HP_SPECTRE_X360] = { - .type = HDA_FIXUP_PINS, - .v.pins = (const struct hda_pintbl[]) { - { 0x14, 0x90170110 }, /* enable top speaker */ - {} - }, - .chained = true, - .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1, + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360, }, [ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = { .type = HDA_FIXUP_FUNC, @@ -8319,6 +8405,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN), SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), + SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), @@ -8336,19 +8423,26 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP), + SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -8425,7 +8519,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK), SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), @@ -8460,11 +8554,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[5|7][0-9]RZ[Q]", ALC269_FIXUP_DMIC), + SND_PCI_QUIRK(0x1558, 0x8550, "Clevo NH[57][0-9][ER][ACDH]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8551, "Clevo NH[57][0-9][ER][ACDH]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8560, "Clevo NH[57][0-9][ER][ACDH]Q", ALC269_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1558, 0x8561, "Clevo NH[57][0-9][ER][ACDH]Q", ALC269_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[57][0-9]RZ[Q]", ALC269_FIXUP_DMIC), SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), @@ -8475,8 +8569,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x9600, "Clevo N960K[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL5XNU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL5[03]RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), @@ -9341,6 +9435,7 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: spec->codec_variant = ALC269_TYPE_ALC256; @@ -9357,7 +9452,6 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0215: case 0x10ec0245: case 0x10ec0285: - case 0x10ec0287: case 0x10ec0289: spec->codec_variant = ALC269_TYPE_ALC215; spec->shutup = alc225_shutup; @@ -9372,6 +9466,12 @@ static int patch_alc269(struct hda_codec *codec) spec->init_hook = alc225_init; spec->gen.mixer_nid = 0; /* no loopback on ALC225, ALC295 and ALC299 */ break; + case 0x10ec0287: + spec->codec_variant = ALC269_TYPE_ALC287; + spec->shutup = alc225_shutup; + spec->init_hook = alc225_init; + spec->gen.mixer_nid = 0; /* no loopback on ALC287 */ + break; case 0x10ec0234: case 0x10ec0274: case 0x10ec0294: @@ -10632,6 +10732,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269), HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0230, "ALC236", patch_alc269), HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269), HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269), diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c index 1d2a0287284b..08adf4dd1303 100644 --- a/sound/pci/ice1712/delta.c +++ b/sound/pci/ice1712/delta.c @@ -676,13 +676,15 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice) case ICE1712_SUBDEVICE_DELTA1010LT: case ICE1712_SUBDEVICE_VX442: case ICE1712_SUBDEVICE_DELTA66E: - if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { + err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c); + if (err < 0) { dev_err(ice->card->dev, "unable to create I2C bus\n"); return err; } ice->i2c->private_data = ice; ice->i2c->ops = &ap_cs8427_i2c_ops; - if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0) + err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR); + if (err < 0) return err; break; case ICE1712_SUBDEVICE_DELTA1010: diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 3794308313bf..8bb86b3c894e 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c @@ -442,7 +442,8 @@ static int snd_ice1712_ews_init(struct snd_ice1712 *ice) ice->spec = spec; /* create i2c */ - if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) { + err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c); + if (err < 0) { dev_err(ice->card->dev, "unable to create I2C bus\n"); return err; } @@ -483,7 +484,8 @@ static int snd_ice1712_ews_init(struct snd_ice1712 *ice) if (err < 0) return err; /* Check if the front module is connected */ - if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0) + err = snd_ice1712_ews88mt_chip_select(ice, 0x0f); + if (err < 0) return err; break; case ICE1712_SUBDEVICE_EWS88D: @@ -498,12 +500,14 @@ static int snd_ice1712_ews_init(struct snd_ice1712 *ice) /* set up SPDIF interface */ switch (ice->eeprom.subvendor) { case ICE1712_SUBDEVICE_EWX2496: - if ((err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR)) < 0) + err = snd_ice1712_init_cs8427(ice, CS8427_BASE_ADDR); + if (err < 0) return err; snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR); break; case ICE1712_SUBDEVICE_DMX6FIRE: - if ((err = snd_ice1712_init_cs8427(ice, ICE1712_6FIRE_CS8427_ADDR)) < 0) + err = snd_ice1712_init_cs8427(ice, ICE1712_6FIRE_CS8427_ADDR); + if (err < 0) return err; snd_cs8427_reg_write(ice->cs8427, CS8427_REG_RECVERRMASK, CS8427_UNLOCK | CS8427_CONF | CS8427_BIP | CS8427_PAR); break; @@ -853,7 +857,8 @@ static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct s int invert = (kcontrol->private_value >> 8) & 1; int data; - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) + data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT); + if (data < 0) return data; data = (data >> shift) & 1; if (invert) @@ -869,7 +874,8 @@ static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct s int invert = (kcontrol->private_value >> 8) & 1; int data, ndata; - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) + data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT); + if (data < 0) return data; ndata = data & ~(1 << shift); if (ucontrol->value.integer.value[0]) @@ -896,7 +902,8 @@ static int snd_ice1712_6fire_select_input_get(struct snd_kcontrol *kcontrol, str struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int data; - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) + data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT); + if (data < 0) return data; ucontrol->value.integer.value[0] = data & 3; return 0; @@ -907,7 +914,8 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); int data, ndata; - if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0) + data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT); + if (data < 0) return data; ndata = data & ~3; ndata |= (ucontrol->value.integer.value[0] & 3); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5b124c4ad572..df3ba5c70de9 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -79,7 +79,7 @@ enum { \ ICH_REG_##name##_PICB = base + 0x08, /* word - position in current buffer */ \ ICH_REG_##name##_PIV = base + 0x0a, /* byte - prefetched index value */ \ ICH_REG_##name##_CR = base + 0x0b, /* byte - control register */ \ -}; +} /* busmaster blocks */ DEFINE_REGSET(OFF, 0); /* offset */ @@ -538,7 +538,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { + tmp = igetdword(chip, ICHREG(GLOB_STA)); + if (tmp & ICH_RCS) { /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & ~(chip->codec_ready_bits | ICH_GSCI)); @@ -559,7 +560,8 @@ static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) { iagetword(chip, codec * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { + tmp = igetdword(chip, ICHREG(GLOB_STA)); + if (tmp & ICH_RCS) { /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & ~(chip->codec_ready_bits | ICH_GSCI)); @@ -692,7 +694,7 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich int status, civ, i, step; int ack = 0; - if (!ichdev->prepared || ichdev->suspended) + if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended) return; spin_lock_irqsave(&chip->reg_lock, flags); @@ -1105,7 +1107,8 @@ static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ich runtime->hw.buffer_bytes_max = 64*1024; runtime->hw.period_bytes_max = 64*1024; } - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; runtime->private_data = ichdev; return 0; @@ -2190,7 +2193,8 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, udelay(1); } } - if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus); + if (err < 0) goto __err; pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; if (ac97_clock >= 8000 && ac97_clock <= 48000) @@ -2206,7 +2210,8 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, ac97.pci = chip->pci; for (i = 0; i < codecs; i++) { ac97.num = i; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i]); + if (err < 0) { if (err != -EACCES) dev_err(chip->card->dev, "Unable to initialize codec #%d\n", i); @@ -2491,11 +2496,13 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) int err; if (chip->device_type != DEVICE_ALI) { - if ((err = snd_intel8x0_ich_chip_init(chip, probing)) < 0) + err = snd_intel8x0_ich_chip_init(chip, probing); + if (err < 0) return err; iagetword(chip, 0); /* clear semaphore flag */ } else { - if ((err = snd_intel8x0_ali_chip_init(chip, probing)) < 0) + err = snd_intel8x0_ali_chip_init(chip, probing); + if (err < 0) return err; } @@ -2918,7 +2925,8 @@ static int snd_intel8x0_create(struct snd_card *card, *r_intel8x0 = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -2950,7 +2958,8 @@ static int snd_intel8x0_create(struct snd_card *card, pci->device == PCI_DEVICE_ID_INTEL_440MX) chip->fix_nocache = 1; /* enable workaround */ - if ((err = pci_request_regions(pci, card->shortname)) < 0) { + err = pci_request_regions(pci, card->shortname); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -3064,7 +3073,8 @@ static int snd_intel8x0_create(struct snd_card *card, for (i = 0; i < chip->max_codecs; i++) chip->codec_isr_bits |= chip->codec_bit[i]; - if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { + err = snd_intel8x0_chip_init(chip, 1); + if (err < 0) { snd_intel8x0_free(chip); return err; } @@ -3079,7 +3089,8 @@ static int snd_intel8x0_create(struct snd_card *card, chip->irq = pci->irq; card->sync_irq = chip->irq; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_intel8x0_free(chip); return err; } @@ -3186,18 +3197,20 @@ static int snd_intel8x0_probe(struct pci_dev *pci, buggy_irq = 0; } - if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, - &chip)) < 0) { + err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip); + if (err < 0) { snd_card_free(card); return err; } card->private_data = chip; - if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) { + err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_intel8x0_pcm(chip)) < 0) { + err = snd_intel8x0_pcm(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -3217,7 +3230,8 @@ static int snd_intel8x0_probe(struct pci_dev *pci, } } - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 13ef838b26c1..b96fce6cbd83 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -57,7 +57,7 @@ enum { \ ICH_REG_##name##_PICB = base + 0x08, /* word - position in current buffer */ \ ICH_REG_##name##_PIV = base + 0x0a, /* byte - prefetched index value */ \ ICH_REG_##name##_CR = base + 0x0b, /* byte - control register */ \ -}; +} /* busmaster blocks */ DEFINE_REGSET(OFF, 0); /* offset */ @@ -342,7 +342,8 @@ static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); - if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { + tmp = igetdword(chip, ICHREG(GLOB_STA)); + if (tmp & ICH_RCS) { /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); @@ -800,7 +801,8 @@ static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock) glob_sta = igetdword(chip, ICHREG(GLOB_STA)); - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus); + if (err < 0) goto __err; pbus->private_free = snd_intel8x0m_mixer_free_ac97_bus; if (ac97_clock >= 8000 && ac97_clock <= 48000) @@ -809,7 +811,8 @@ static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock) ac97.pci = chip->pci; ac97.num = glob_sta & ICH_SCR ? 1 : 0; - if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) { + err = snd_ac97_mixer(pbus, &ac97, &x97); + if (err < 0) { dev_err(chip->card->dev, "Unable to initialize codec #%d\n", ac97.num); if (ac97.num == 0) @@ -927,7 +930,8 @@ static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing) unsigned int i; int err; - if ((err = snd_intel8x0m_ich_chip_init(chip, probing)) < 0) + err = snd_intel8x0m_ich_chip_init(chip, probing); + if (err < 0) return err; iagetword(chip, 0); /* clear semaphore flag */ @@ -1075,7 +1079,8 @@ static int snd_intel8x0m_create(struct snd_card *card, *r_intel8x0m = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1089,7 +1094,8 @@ static int snd_intel8x0m_create(struct snd_card *card, chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, card->shortname)) < 0) { + err = pci_request_regions(pci, card->shortname); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1167,7 +1173,8 @@ port_inited: pci_set_master(pci); - if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) { + err = snd_intel8x0m_chip_init(chip, 1); + if (err < 0) { snd_intel8x0m_free(chip); return err; } @@ -1181,7 +1188,8 @@ port_inited: chip->irq = pci->irq; card->sync_irq = chip->irq; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_intel8x0m_free(chip); return err; } @@ -1238,17 +1246,20 @@ static int snd_intel8x0m_probe(struct pci_dev *pci, } strcat(card->shortname," Modem"); - if ((err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip)) < 0) { + err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip); + if (err < 0) { snd_card_free(card); return err; } card->private_data = chip; - if ((err = snd_intel8x0m_mixer(chip, ac97_clock)) < 0) { + err = snd_intel8x0m_mixer(chip, ac97_clock); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_intel8x0m_pcm(chip)) < 0) { + err = snd_intel8x0m_pcm(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1258,7 +1269,8 @@ static int snd_intel8x0m_probe(struct pci_dev *pci, sprintf(card->longname, "%s at irq %i", card->shortname, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 80ac3c6152ad..030e01b062e4 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1527,7 +1527,8 @@ static int snd_korg1212_hw_params(struct snd_pcm_substream *substream, return 0; } - if ((err = snd_korg1212_SetRate(korg1212, params_rate(params))) < 0) { + err = snd_korg1212_SetRate(korg1212, params_rate(params)); + if (err < 0) { spin_unlock_irqrestore(&korg1212->lock, flags); return err; } @@ -2159,7 +2160,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, }; * rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL); @@ -2196,7 +2198,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, for (i=0; i<kAudioChannels; i++) korg1212->volumePhase[i] = 0; - if ((err = pci_request_regions(pci, "korg1212")) < 0) { + err = pci_request_regions(pci, "korg1212"); + if (err < 0) { kfree(korg1212); pci_disable_device(pci); return err; @@ -2220,7 +2223,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, korg1212->iomem2, iomem2_size, stateName[korg1212->cardState]); - if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { + korg1212->iobase = ioremap(korg1212->iomem, iomem_size); + if (!korg1212->iobase) { snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, korg1212->iomem + iomem_size - 1); snd_korg1212_free(korg1212); @@ -2360,7 +2364,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops); + if (err < 0) { snd_korg1212_free(korg1212); return err; } @@ -2385,7 +2390,8 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, korg1212->RoutingTablePhy, LowerWordSwap(korg1212->RoutingTablePhy), korg1212->AdatTimeCodePhy, LowerWordSwap(korg1212->AdatTimeCodePhy)); - if ((err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm)) < 0) + err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm); + if (err < 0) return err; korg1212->pcm->private_data = korg1212; @@ -2436,7 +2442,8 @@ snd_korg1212_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { + err = snd_korg1212_create(card, pci, &korg1212); + if (err < 0) { snd_card_free(card); return err; } @@ -2448,7 +2455,8 @@ snd_korg1212_probe(struct pci_dev *pci, K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c index f884f5a6a61c..d3f58a3d17fb 100644 --- a/sound/pci/lx6464es/lx_core.c +++ b/sound/pci/lx6464es/lx_core.c @@ -674,10 +674,6 @@ int lx_stream_set_format(struct lx6464es *chip, struct snd_pcm_runtime *runtime, u32 pipe_cmd = PIPE_INFO_TO_CMD(is_capture, pipe); u32 channels = runtime->channels; - if (runtime->channels != channels) - dev_err(chip->card->dev, "channel count mismatch: %d vs %d", - runtime->channels, channels); - mutex_lock(&chip->msg_lock); lx_message_init(&chip->rmh, CMD_0C_DEF_STREAM); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index cdc4b6106252..77a484bc8c0d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1765,7 +1765,8 @@ snd_m3_playback_open(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; int err; - if ((err = snd_m3_substream_open(chip, subs)) < 0) + err = snd_m3_substream_open(chip, subs); + if (err < 0) return err; runtime->hw = snd_m3_playback; @@ -1789,7 +1790,8 @@ snd_m3_capture_open(struct snd_pcm_substream *subs) struct snd_pcm_runtime *runtime = subs->runtime; int err; - if ((err = snd_m3_substream_open(chip, subs)) < 0) + err = snd_m3_substream_open(chip, subs); + if (err < 0) return err; runtime->hw = snd_m3_capture; @@ -2036,12 +2038,14 @@ static int snd_m3_mixer(struct snd_m3 *chip) .read = snd_m3_ac97_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); + if (err < 0) return err; /* seems ac97 PCM needs initialization.. hack hack.. */ @@ -2642,16 +2646,19 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, if (err < 0) goto free_chip; - if ((err = snd_m3_mixer(chip)) < 0) + err = snd_m3_mixer(chip); + if (err < 0) return err; for (i = 0; i < chip->num_substreams; i++) { struct m3_dma *s = &chip->substreams[i]; - if ((err = snd_m3_assp_client_init(chip, s, i)) < 0) + err = snd_m3_assp_client_init(chip, s, i); + if (err < 0) return err; } - if ((err = snd_m3_pcm(chip, 0)) < 0) + err = snd_m3_pcm(chip, 0); + if (err < 0) return err; #ifdef CONFIG_SND_MAESTRO3_INPUT diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index a0bbb386dc25..1b078b789604 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -954,9 +954,10 @@ static int snd_mixart_pcm_analog(struct snd_mixart *chip) char name[32]; sprintf(name, "miXart analog %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { + err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG, + MIXART_PLAYBACK_STREAMS, + MIXART_CAPTURE_STREAMS, &pcm); + if (err < 0) { dev_err(chip->card->dev, "cannot create the analog pcm %d\n", chip->chip_idx); return err; @@ -987,9 +988,10 @@ static int snd_mixart_pcm_digital(struct snd_mixart *chip) char name[32]; sprintf(name, "miXart AES/EBU %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL, - MIXART_PLAYBACK_STREAMS, - MIXART_CAPTURE_STREAMS, &pcm)) < 0) { + err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL, + MIXART_PLAYBACK_STREAMS, + MIXART_CAPTURE_STREAMS, &pcm); + if (err < 0) { dev_err(chip->card->dev, "cannot create the digital pcm %d\n", chip->chip_idx); return err; @@ -1042,7 +1044,8 @@ static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int chip->mgr = mgr; card->sync_irq = mgr->irq; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_mixart_chip_free(chip); return err; } @@ -1243,7 +1246,8 @@ static int snd_mixart_probe(struct pci_dev *pci, } /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; pci_set_master(pci); @@ -1267,7 +1271,8 @@ static int snd_mixart_probe(struct pci_dev *pci, mgr->irq = -1; /* resource assignment */ - if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { + err = pci_request_regions(pci, CARD_NAME); + if (err < 0) { kfree(mgr); pci_disable_device(pci); return err; @@ -1332,7 +1337,8 @@ static int snd_mixart_probe(struct pci_dev *pci, "Digigram miXart at 0x%lx & 0x%lx, irq %i [PCM #%d]", mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq, i); - if ((err = snd_mixart_create(mgr, card, i)) < 0) { + err = snd_mixart_create(mgr, card, i); + if (err < 0) { snd_card_free(card); snd_mixart_free(mgr); return err; @@ -1343,7 +1349,8 @@ static int snd_mixart_probe(struct pci_dev *pci, snd_mixart_proc_init(mgr->chip[i]); } - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_mixart_free(mgr); return err; } diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index f579f7698bba..689c0f995a9c 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -306,9 +306,13 @@ static int mixart_first_init(struct mixart_mgr *mgr) int err; struct mixart_msg request; - if((err = mixart_enum_connectors(mgr)) < 0) return err; + err = mixart_enum_connectors(mgr); + if (err < 0) + return err; - if((err = mixart_enum_physio(mgr)) < 0) return err; + err = mixart_enum_physio(mgr); + if (err < 0) + return err; /* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */ /* though why not here */ @@ -528,15 +532,18 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw for (card_index = 0; card_index < mgr->num_cards; card_index++) { struct snd_mixart *chip = mgr->chip[card_index]; - if ((err = snd_mixart_create_pcm(chip)) < 0) + err = snd_mixart_create_pcm(chip); + if (err < 0) return err; if (card_index == 0) { - if ((err = snd_mixart_create_mixer(chip->mgr)) < 0) + err = snd_mixart_create_mixer(chip->mgr); + if (err < 0) return err; } - if ((err = snd_card_register(chip->card)) < 0) + err = snd_card_register(chip->card); + if (err < 0) return err; } diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index d2e7c3381267..2727f3345795 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -1114,10 +1114,12 @@ int snd_mixart_create_mixer(struct mixart_mgr *mgr) temp = mixart_control_analog_level; temp.name = "Master Playback Volume"; temp.private_value = 0; /* playback */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; /* output mute controls */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_output_switch, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_output_switch, chip)); + if (err < 0) return err; /* analog input level control only on first two chips !*/ @@ -1125,7 +1127,8 @@ int snd_mixart_create_mixer(struct mixart_mgr *mgr) temp = mixart_control_analog_level; temp.name = "Master Capture Volume"; temp.private_value = 1; /* capture */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } @@ -1133,45 +1136,53 @@ int snd_mixart_create_mixer(struct mixart_mgr *mgr) temp.name = "PCM Playback Volume"; temp.count = MIXART_PLAYBACK_STREAMS; temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; temp.name = "PCM Capture Volume"; temp.count = 1; temp.private_value = MIXART_VOL_REC_MASK; /* capture analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { temp.name = "AES Playback Volume"; temp.count = MIXART_PLAYBACK_STREAMS; temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; temp.name = "AES Capture Volume"; temp.count = 0; temp.private_value = MIXART_VOL_REC_MASK | MIXART_VOL_AES_MASK; /* capture AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } temp = mixart_control_pcm_switch; temp.name = "PCM Playback Switch"; temp.private_value = 0; /* playback analog */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; if(mgr->board_type == MIXART_DAUGHTER_TYPE_AES) { temp.name = "AES Playback Switch"; temp.private_value = MIXART_VOL_AES_MASK; /* playback AES/EBU */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip)); + if (err < 0) return err; } /* monitoring */ - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_vol, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_vol, chip)); + if (err < 0) return err; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_sw, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&mixart_control_monitor_sw, chip)); + if (err < 0) return err; /* init all mixer data and program the master volumes/switches */ diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 6cb689aa28c2..12d02d7d3b51 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1318,7 +1318,8 @@ snd_nm256_mixer(struct nm256 *chip) if (! chip->ac97_regs) return -ENOMEM; - if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus); + if (err < 0) return err; memset(&ac97, 0, sizeof(ac97)); @@ -1476,7 +1477,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, *chip_ret = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -1568,7 +1570,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, chip->buffer_end = buffer_top; else { /* get buffer end pointer from signature */ - if ((err = snd_nm256_peek_for_sig(chip)) < 0) + err = snd_nm256_peek_for_sig(chip); + if (err < 0) goto __error; } @@ -1618,7 +1621,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, // pci_set_master(pci); /* needed? */ - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) goto __error; *chip_ret = chip; @@ -1700,7 +1704,8 @@ static int snd_nm256_probe(struct pci_dev *pci, capture_bufsize = 4; if (capture_bufsize > 128) capture_bufsize = 128; - if ((err = snd_nm256_create(card, pci, &chip)) < 0) { + err = snd_nm256_create(card, pci, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1716,8 +1721,13 @@ static int snd_nm256_probe(struct pci_dev *pci, chip->reset_workaround_2 = 1; } - if ((err = snd_nm256_pcm(chip, 0)) < 0 || - (err = snd_nm256_mixer(chip)) < 0) { + err = snd_nm256_pcm(chip, 0); + if (err < 0) { + snd_card_free(card); + return err; + } + err = snd_nm256_mixer(chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1727,7 +1737,8 @@ static int snd_nm256_probe(struct pci_dev *pci, card->shortname, chip->buffer_addr, chip->cport_addr, chip->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 751f9744b089..96b9371c201a 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1134,9 +1134,10 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip) char name[32]; snprintf(name, sizeof(name), "pcxhr %d", chip->chip_idx); - if ((err = snd_pcm_new(chip->card, name, 0, - chip->nb_streams_play, - chip->nb_streams_capt, &pcm)) < 0) { + err = snd_pcm_new(chip->card, name, 0, + chip->nb_streams_play, + chip->nb_streams_capt, &pcm); + if (err < 0) { dev_err(chip->card->dev, "cannot create pcm %s\n", name); return err; } @@ -1202,7 +1203,8 @@ static int pcxhr_create(struct pcxhr_mgr *mgr, chip->nb_streams_capt = 1; /* or 1 stereo stream */ } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { pcxhr_chip_free(chip); return err; } @@ -1492,7 +1494,8 @@ static int pcxhr_probe(struct pci_dev *pci, } /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; pci_set_master(pci); @@ -1537,7 +1540,8 @@ static int pcxhr_probe(struct pci_dev *pci, mgr->granularity = PCXHR_GRANULARITY; /* resource assignment */ - if ((err = pci_request_regions(pci, card_name)) < 0) { + err = pci_request_regions(pci, card_name); + if (err < 0) { kfree(mgr); pci_disable_device(pci); return err; @@ -1608,7 +1612,8 @@ static int pcxhr_probe(struct pci_dev *pci, snprintf(card->longname, sizeof(card->longname), "%s [PCM #%d]", mgr->name, i); - if ((err = pcxhr_create(mgr, card, i)) < 0) { + err = pcxhr_create(mgr, card, i); + if (err < 0) { snd_card_free(card); pcxhr_free(mgr); return err; @@ -1618,7 +1623,8 @@ static int pcxhr_probe(struct pci_dev *pci, /* init proc interface only for chip0 */ pcxhr_proc_init(mgr->chip[i]); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { pcxhr_free(mgr); return err; } diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index 2258bd698844..249805065f61 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c @@ -322,14 +322,17 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, for (card_index = 0; card_index < mgr->num_cards; card_index++) { struct snd_pcxhr *chip = mgr->chip[card_index]; - if ((err = pcxhr_create_pcm(chip)) < 0) + err = pcxhr_create_pcm(chip); + if (err < 0) return err; if (card_index == 0) { - if ((err = pcxhr_create_mixer(chip->mgr)) < 0) + err = pcxhr_create_mixer(chip->mgr); + if (err < 0) return err; } - if ((err = snd_card_register(chip->card)) < 0) + err = snd_card_register(chip->card); + if (err < 0) return err; } err = pcxhr_start_pipes(mgr); diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 56827db97239..709a1a2cde20 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1087,9 +1087,15 @@ static irqreturn_t riptide_handleirq(int irq, void *dev_id) substream[i] = chip->playback_substream[i]; substream[i] = chip->capture_substream; for (i = 0; i < PLAYBACK_SUBSTREAMS + 1; i++) { - if (substream[i] && - (runtime = substream[i]->runtime) && - (data = runtime->private_data) && data->state != ST_STOP) { + if (!substream[i]) + continue; + runtime = substream[i]->runtime; + if (!runtime) + continue; + data = runtime->private_data; + if (!data) + continue; + if (data->state != ST_STOP) { pos = 0; for (j = 0; j < data->pages; j++) { c = &data->sgdbuf[j]; @@ -1549,10 +1555,10 @@ snd_riptide_hw_params(struct snd_pcm_substream *substream, (int)sgdlist->bytes); if (sgdlist->area) snd_dma_free_pages(sgdlist); - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - &chip->pci->dev, - sizeof(struct sgd) * (DESC_MAX_MASK + 1), - sgdlist)) < 0) { + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev, + sizeof(struct sgd) * (DESC_MAX_MASK + 1), + sgdlist); + if (err < 0) { snd_printk(KERN_ERR "Riptide: failed to alloc %d dma bytes\n", (int)sizeof(struct sgd) * (DESC_MAX_MASK + 1)); return err; @@ -1677,9 +1683,9 @@ static int snd_riptide_pcm(struct snd_riptide *chip, int device) struct snd_pcm *pcm; int err; - if ((err = - snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, - &pcm)) < 0) + err = snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1, + &pcm); + if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_riptide_playback_ops); @@ -1766,14 +1772,16 @@ static int snd_riptide_initialize(struct snd_riptide *chip) cif = chip->cif; if (!cif) { - if ((cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL)) == NULL) + cif = kzalloc(sizeof(struct cmdif), GFP_KERNEL); + if (!cif) return -ENOMEM; cif->hwport = (struct riptideport *)chip->port; spin_lock_init(&cif->lock); chip->cif = cif; } cif->is_reset = 0; - if ((err = riptide_reset(cif, chip)) != 0) + err = riptide_reset(cif, chip); + if (err) return err; device_id = chip->device_id; switch (device_id) { @@ -1797,7 +1805,8 @@ static int snd_riptide_free(struct snd_riptide *chip) if (!chip) return 0; - if ((cif = chip->cif)) { + cif = chip->cif; + if (cif) { SET_GRESET(cif->hwport); udelay(100); UNSET_GRESET(cif->hwport); @@ -1830,9 +1839,11 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, }; *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; - if (!(chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL))) + chip = kzalloc(sizeof(struct snd_riptide), GFP_KERNEL); + if (!chip) return -ENOMEM; spin_lock_init(&chip->lock); @@ -1845,8 +1856,8 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, chip->handled_irqs = 0; chip->cif = NULL; - if ((chip->res_port = - request_region(chip->port, 64, "RIPTIDE")) == NULL) { + chip->res_port = request_region(chip->port, 64, "RIPTIDE"); + if (!chip->res_port) { snd_printk(KERN_ERR "Riptide: unable to grab region 0x%lx-0x%lx\n", chip->port, chip->port + 64 - 1); @@ -1868,12 +1879,14 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, card->sync_irq = chip->irq; chip->device_id = pci->device; pci_set_master(pci); - if ((err = snd_riptide_initialize(chip)) < 0) { + err = snd_riptide_initialize(chip); + if (err < 0) { snd_riptide_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_riptide_free(chip); return err; } @@ -1903,7 +1916,8 @@ snd_riptide_proc_read(struct snd_info_entry *entry, for (i = 0; i < 64; i += 4) snd_iprintf(buffer, "%c%02x: %08x", (i % 16) ? ' ' : '\n', i, inl(chip->port + i)); - if ((cif = chip->cif)) { + cif = chip->cif; + if (cif) { snd_iprintf(buffer, "\nVersion: ASIC: %d CODEC: %d AUXDSP: %d PROG: %d", chip->firmware.firmware.ASIC, @@ -1922,10 +1936,11 @@ snd_riptide_proc_read(struct snd_info_entry *entry, } snd_iprintf(buffer, "\nOpen streams %d:\n", chip->openstreams); for (i = 0; i < PLAYBACK_SUBSTREAMS; i++) { - if (chip->playback_substream[i] - && chip->playback_substream[i]->runtime - && (data = - chip->playback_substream[i]->runtime->private_data)) { + if (!chip->playback_substream[i] || + !chip->playback_substream[i]->runtime) + continue; + data = chip->playback_substream[i]->runtime->private_data; + if (data) { snd_iprintf(buffer, "stream: %d mixer: %d source: %d (%d,%d)\n", data->id, data->mixer, data->source, @@ -1934,15 +1949,16 @@ snd_riptide_proc_read(struct snd_info_entry *entry, snd_iprintf(buffer, "rate: %d\n", rate); } } - if (chip->capture_substream - && chip->capture_substream->runtime - && (data = chip->capture_substream->runtime->private_data)) { - snd_iprintf(buffer, - "stream: %d mixer: %d source: %d (%d,%d)\n", - data->id, data->mixer, - data->source, data->intdec[0], data->intdec[1]); - if (!(getsamplerate(cif, data->intdec, &rate))) - snd_iprintf(buffer, "rate: %d\n", rate); + if (chip->capture_substream && chip->capture_substream->runtime) { + data = chip->capture_substream->runtime->private_data; + if (data) { + snd_iprintf(buffer, + "stream: %d mixer: %d source: %d (%d,%d)\n", + data->id, data->mixer, + data->source, data->intdec[0], data->intdec[1]); + if (!(getsamplerate(cif, data->intdec, &rate))) + snd_iprintf(buffer, "rate: %d\n", rate); + } } snd_iprintf(buffer, "Paths:\n"); i = getpaths(cif, p); @@ -1973,12 +1989,14 @@ static int snd_riptide_mixer(struct snd_riptide *chip) ac97.private_data = chip; ac97.scaps = AC97_SCAP_SKIP_MODEM; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus); + if (err < 0) return err; chip->ac97_bus = pbus; ac97.pci = chip->pci; - if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(pbus, &ac97, &chip->ac97); + if (err < 0) return err; return err; } diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 54f3e39f97f5..b5b357853c94 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -668,18 +668,24 @@ snd_rme32_playback_hw_params(struct snd_pcm_substream *substream, } spin_lock_irq(&rme32->lock); - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { + rate = 0; + if (rme32->rcreg & RME32_RCR_KMODE) + rate = snd_rme32_capture_getrate(rme32, &dummy); + if (rate > 0) { /* AutoSync */ if ((int)params_rate(params) != rate) { spin_unlock_irq(&rme32->lock); return -EIO; } - } else if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { - spin_unlock_irq(&rme32->lock); - return err; + } else { + err = snd_rme32_playback_setrate(rme32, params_rate(params)); + if (err < 0) { + spin_unlock_irq(&rme32->lock); + return err; + } } - if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { + err = snd_rme32_setformat(rme32, params_format(params)); + if (err < 0) { spin_unlock_irq(&rme32->lock); return err; } @@ -723,15 +729,18 @@ snd_rme32_capture_hw_params(struct snd_pcm_substream *substream, rme32->wcreg |= RME32_WCR_AUTOSYNC; writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); - if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { + err = snd_rme32_setformat(rme32, params_format(params)); + if (err < 0) { spin_unlock_irq(&rme32->lock); return err; } - if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { + err = snd_rme32_playback_setrate(rme32, params_rate(params)); + if (err < 0) { spin_unlock_irq(&rme32->lock); return err; } - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { + rate = snd_rme32_capture_getrate(rme32, &isadat); + if (rate > 0) { if ((int)params_rate(params) != rate) { spin_unlock_irq(&rme32->lock); return -EIO; @@ -854,8 +863,10 @@ static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; runtime->hw.rate_max = 96000; } - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { + rate = 0; + if (rme32->rcreg & RME32_RCR_KMODE) + rate = snd_rme32_capture_getrate(rme32, &dummy); + if (rate > 0) { /* AutoSync */ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); runtime->hw.rate_min = rate; @@ -895,7 +906,8 @@ static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; runtime->hw.rate_max = 96000; } - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { + rate = snd_rme32_capture_getrate(rme32, &isadat); + if (rate > 0) { if (isadat) { return -EIO; } @@ -932,8 +944,10 @@ snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) runtime->hw = snd_rme32_adat_fd_info; else runtime->hw = snd_rme32_adat_info; - if ((rme32->rcreg & RME32_RCR_KMODE) && - (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { + rate = 0; + if (rme32->rcreg & RME32_RCR_KMODE) + rate = snd_rme32_capture_getrate(rme32, &dummy); + if (rate > 0) { /* AutoSync */ runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); runtime->hw.rate_min = rate; @@ -955,7 +969,8 @@ snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) runtime->hw = snd_rme32_adat_fd_info; else runtime->hw = snd_rme32_adat_info; - if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { + rate = snd_rme32_capture_getrate(rme32, &isadat); + if (rate > 0) { if (!isadat) { return -EIO; } @@ -1307,10 +1322,12 @@ static int snd_rme32_create(struct rme32 *rme32) rme32->irq = -1; spin_lock_init(&rme32->lock); - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; - if ((err = pci_request_regions(pci, "RME32")) < 0) + err = pci_request_regions(pci, "RME32"); + if (err < 0) return err; rme32->port = pci_resource_start(rme32->pci, 0); @@ -1334,9 +1351,9 @@ static int snd_rme32_create(struct rme32 *rme32) pci_read_config_byte(pci, 8, &rme32->rev); /* set up ALSA pcm device for S/PDIF */ - if ((err = snd_pcm_new(rme32->card, "Digi32 IEC958", 0, 1, 1, &rme32->spdif_pcm)) < 0) { + err = snd_pcm_new(rme32->card, "Digi32 IEC958", 0, 1, 1, &rme32->spdif_pcm); + if (err < 0) return err; - } rme32->spdif_pcm->private_data = rme32; rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm; strcpy(rme32->spdif_pcm->name, "Digi32 IEC958"); @@ -1363,11 +1380,10 @@ static int snd_rme32_create(struct rme32 *rme32) rme32->adat_pcm = NULL; } else { - if ((err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1, - 1, 1, &rme32->adat_pcm)) < 0) - { + err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1, + 1, 1, &rme32->adat_pcm); + if (err < 0) return err; - } rme32->adat_pcm->private_data = rme32; rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm; strcpy(rme32->adat_pcm->name, "Digi32 ADAT"); @@ -1410,9 +1426,9 @@ static int snd_rme32_create(struct rme32 *rme32) /* init switch interface */ - if ((err = snd_rme32_create_switches(rme32->card, rme32)) < 0) { + err = snd_rme32_create_switches(rme32->card, rme32); + if (err < 0) return err; - } /* init proc interface */ snd_rme32_proc_init(rme32); @@ -1855,7 +1871,9 @@ static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32 struct snd_kcontrol *kctl; for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0) + kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ rme32->spdif_ctl = kctl; @@ -1899,7 +1917,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) rme32->pci = pci; if (fullduplex[dev]) rme32->fullduplex_mode = 1; - if ((err = snd_rme32_create(rme32)) < 0) { + err = snd_rme32_create(rme32); + if (err < 0) { snd_card_free(card); return err; } @@ -1919,7 +1938,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) sprintf(card->longname, "%s (Rev. %d) at 0x%lx, irq %d", card->shortname, rme32->rev, rme32->port, rme32->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 66082e9f526d..fc7ac077559c 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -666,12 +666,14 @@ snd_rme96_playback_getrate(struct rme96 *rme96) int rate, dummy; if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - return rate; + snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { + rate = snd_rme96_capture_getrate(rme96, &dummy); + if (rate > 0) { + /* slave clock */ + return rate; + } } + rate = ((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_0) & 1) + (((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_1) & 1) << 1); switch (rate) { @@ -984,10 +986,11 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, runtime->dma_bytes = RME96_BUFFER_SIZE; spin_lock_irq(&rme96->lock); + rate = 0; if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { + snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) + rate = snd_rme96_capture_getrate(rme96, &dummy); + if (rate > 0) { /* slave clock */ if ((int)params_rate(params) != rate) { err = -EIO; @@ -1046,28 +1049,30 @@ snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, runtime->dma_bytes = RME96_BUFFER_SIZE; spin_lock_irq(&rme96->lock); - if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) { + err = snd_rme96_capture_setformat(rme96, params_format(params)); + if (err < 0) { spin_unlock_irq(&rme96->lock); return err; } if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { - if ((err = snd_rme96_capture_analog_setrate(rme96, - params_rate(params))) < 0) - { + err = snd_rme96_capture_analog_setrate(rme96, params_rate(params)); + if (err < 0) { spin_unlock_irq(&rme96->lock); return err; } - } else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { - if ((int)params_rate(params) != rate) { - spin_unlock_irq(&rme96->lock); - return -EIO; - } - if ((isadat && runtime->hw.channels_min == 2) || - (!isadat && runtime->hw.channels_min == 8)) - { - spin_unlock_irq(&rme96->lock); - return -EIO; - } + } else { + rate = snd_rme96_capture_getrate(rme96, &isadat); + if (rate > 0) { + if ((int)params_rate(params) != rate) { + spin_unlock_irq(&rme96->lock); + return -EIO; + } + if ((isadat && runtime->hw.channels_min == 2) || + (!isadat && runtime->hw.channels_min == 8)) { + spin_unlock_irq(&rme96->lock); + return -EIO; + } + } } snd_rme96_setframelog(rme96, params_channels(params), 0); if (rme96->playback_periodsize != 0) { @@ -1160,8 +1165,10 @@ rme96_set_buffer_size_constraint(struct rme96 *rme96, snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE); - if ((size = rme96->playback_periodsize) != 0 || - (size = rme96->capture_periodsize) != 0) + size = rme96->playback_periodsize; + if (!size) + size = rme96->capture_periodsize; + if (size) snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, size); @@ -1191,13 +1198,14 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) runtime->hw = snd_rme96_playback_spdif_info; if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; + snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { + rate = snd_rme96_capture_getrate(rme96, &dummy); + if (rate > 0) { + /* slave clock */ + runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); + runtime->hw.rate_min = rate; + runtime->hw.rate_max = rate; + } } rme96_set_buffer_size_constraint(rme96, runtime); @@ -1217,16 +1225,16 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) snd_pcm_set_sync(substream); runtime->hw = snd_rme96_capture_spdif_info; - if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) - { - if (isadat) { - return -EIO; - } - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } + if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { + rate = snd_rme96_capture_getrate(rme96, &isadat); + if (rate > 0) { + if (isadat) + return -EIO; + runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); + runtime->hw.rate_min = rate; + runtime->hw.rate_max = rate; + } + } spin_lock_irq(&rme96->lock); if (rme96->capture_substream) { @@ -1260,14 +1268,16 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) runtime->hw = snd_rme96_playback_adat_info; if (!(rme96->wcreg & RME96_WCR_MASTER) && - snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && - (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) - { - /* slave clock */ - runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); - runtime->hw.rate_min = rate; - runtime->hw.rate_max = rate; - } + snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { + rate = snd_rme96_capture_getrate(rme96, &dummy); + if (rate > 0) { + /* slave clock */ + runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); + runtime->hw.rate_min = rate; + runtime->hw.rate_max = rate; + } + } + rme96_set_buffer_size_constraint(rme96, runtime); return 0; } @@ -1286,7 +1296,8 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) expension cards AEB4/8-I are RME96_INPUT_INTERNAL */ return -EIO; } - if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { + rate = snd_rme96_capture_getrate(rme96, &isadat); + if (rate > 0) { if (!isadat) { return -EIO; } @@ -1603,10 +1614,12 @@ snd_rme96_create(struct rme96 *rme96) rme96->irq = -1; spin_lock_init(&rme96->lock); - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; - if ((err = pci_request_regions(pci, "RME96")) < 0) + err = pci_request_regions(pci, "RME96"); + if (err < 0) return err; rme96->port = pci_resource_start(rme96->pci, 0); @@ -1630,11 +1643,11 @@ snd_rme96_create(struct rme96 *rme96) pci_read_config_byte(pci, 8, &rme96->rev); /* set up ALSA pcm device for S/PDIF */ - if ((err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, - 1, 1, &rme96->spdif_pcm)) < 0) - { + err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, + 1, 1, &rme96->spdif_pcm); + if (err < 0) return err; - } + rme96->spdif_pcm->private_data = rme96; rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm; strcpy(rme96->spdif_pcm->name, "Digi96 IEC958"); @@ -1648,11 +1661,10 @@ snd_rme96_create(struct rme96 *rme96) /* ADAT is not available on the base model */ rme96->adat_pcm = NULL; } else { - if ((err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, - 1, 1, &rme96->adat_pcm)) < 0) - { + err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, + 1, 1, &rme96->adat_pcm); + if (err < 0) return err; - } rme96->adat_pcm->private_data = rme96; rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm; strcpy(rme96->adat_pcm->name, "Digi96 ADAT"); @@ -1701,9 +1713,9 @@ snd_rme96_create(struct rme96 *rme96) } /* init switch interface */ - if ((err = snd_rme96_create_switches(rme96->card, rme96)) < 0) { + err = snd_rme96_create_switches(rme96->card, rme96); + if (err < 0) return err; - } /* init proc interface */ snd_rme96_proc_init(rme96); @@ -2336,16 +2348,20 @@ snd_rme96_create_switches(struct snd_card *card, struct snd_kcontrol *kctl; for (idx = 0; idx < 7; idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) + kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ rme96->spdif_ctl = kctl; } if (RME96_HAS_ANALOG_OUT(rme96)) { - for (idx = 7; idx < 10; idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) + for (idx = 7; idx < 10; idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_rme96_controls[idx], rme96)); + if (err < 0) return err; + } } return 0; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 720297cbdf87..8457a4bbc3df 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -289,7 +289,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin"); return 104857600000000 / rate; // 100 MHz return 110100480000000 / rate; // 105 MHz */ -#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */ +#define DDS_NUMERATOR 104857600000000ULL /* = 2^20 * 10^8 */ #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) @@ -1318,11 +1318,13 @@ static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) spin_lock_irqsave (&hmidi->lock, flags); if (hmidi->output) { if (!snd_rawmidi_transmit_empty (hmidi->output)) { - if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { + n_pending = snd_hdsp_midi_output_possible(hmidi->hdsp, hmidi->id); + if (n_pending > 0) { if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); - if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { + to_write = snd_rawmidi_transmit(hmidi->output, buf, n_pending); + if (to_write > 0) { for (i = 0; i < to_write; ++i) snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); } @@ -1341,7 +1343,8 @@ static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi) int i; spin_lock_irqsave (&hmidi->lock, flags); - if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) { + n_pending = snd_hdsp_midi_input_available(hmidi->hdsp, hmidi->id); + if (n_pending > 0) { if (hmidi->input) { if (n_pending > (int)sizeof (buf)) n_pending = sizeof (buf); @@ -3322,7 +3325,9 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) } for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) + kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ hdsp->spdif_ctl = kctl; @@ -3331,12 +3336,16 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) /* ADAT SyncCheck status */ snd_hdsp_adat_sync_check.name = "ADAT Lock Status"; snd_hdsp_adat_sync_check.index = 1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) + kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { for (idx = 1; idx < 3; ++idx) { snd_hdsp_adat_sync_check.index = idx+1; - if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) + kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } } @@ -3344,7 +3353,9 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ if (hdsp->io_type == H9632) { for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) + kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; } } @@ -3362,8 +3373,10 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp) /* AEB control for H96xx card */ if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) - return err; + kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp); + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; } return 0; @@ -3942,7 +3955,8 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels)) return NULL; - if ((mapped_channel = hdsp->channel_map[channel]) < 0) + mapped_channel = hdsp->channel_map[channel]; + if (mapped_channel < 0) return NULL; if (stream == SNDRV_PCM_STREAM_CAPTURE) @@ -4114,7 +4128,8 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, spin_lock_irq(&hdsp->lock); if (! hdsp->clock_source_locked) { - if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { + err = hdsp_set_rate(hdsp, params_rate(params), 0); + if (err < 0) { spin_unlock_irq(&hdsp->lock); _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return err; @@ -4122,7 +4137,8 @@ static int snd_hdsp_hw_params(struct snd_pcm_substream *substream, } spin_unlock_irq(&hdsp->lock); - if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { + err = hdsp_set_interrupt_interval(hdsp, params_period_size(params)); + if (err < 0) { _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); return err; } @@ -4854,14 +4870,15 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) + err = hdsp_get_iobox_version(hdsp); + if (err < 0) return err; } memset(&hdsp_version, 0, sizeof(hdsp_version)); hdsp_version.io_type = hdsp->io_type; hdsp_version.firmware_rev = hdsp->firmware_rev; - if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) - return -EFAULT; + if (copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))) + return -EFAULT; break; } case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { @@ -4900,17 +4917,20 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne hdsp->state |= HDSP_FirmwareCached; - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) + err = snd_hdsp_load_firmware_from_cache(hdsp); + if (err < 0) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) + err = snd_hdsp_enable_io(hdsp); + if (err < 0) return err; snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating alsa devices\n"); return err; @@ -4960,7 +4980,8 @@ static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) struct snd_hwdep *hw; int err; - if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) + err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw); + if (err < 0) return err; hdsp->hwdep = hw; @@ -4978,7 +4999,8 @@ static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm); + if (err < 0) return err; hdsp->pcm = pcm; @@ -5084,28 +5106,32 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp { int err; - if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { + err = snd_hdsp_create_pcm(card, hdsp); + if (err < 0) { dev_err(card->dev, "Error creating pcm interface\n"); return err; } - if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { + err = snd_hdsp_create_midi(card, hdsp, 0); + if (err < 0) { dev_err(card->dev, "Error creating first midi interface\n"); return err; } if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { - if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { + err = snd_hdsp_create_midi(card, hdsp, 1); + if (err < 0) { dev_err(card->dev, "Error creating second midi interface\n"); return err; } } - if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { + err = snd_hdsp_create_controls(card, hdsp); + if (err < 0) { dev_err(card->dev, "Error creating ctl interface\n"); return err; @@ -5119,7 +5145,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp hdsp->capture_substream = NULL; hdsp->playback_substream = NULL; - if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { + err = snd_hdsp_set_defaults(hdsp); + if (err < 0) { dev_err(card->dev, "Error setting default values\n"); return err; @@ -5130,7 +5157,8 @@ static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, hdsp->port, hdsp->irq); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { dev_err(card->dev, "error registering card\n"); return err; @@ -5151,7 +5179,8 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if (hdsp->io_type == Undefined) { - if ((err = hdsp_get_iobox_version(hdsp)) < 0) + err = hdsp_get_iobox_version(hdsp); + if (err < 0) return err; if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; @@ -5197,21 +5226,25 @@ static int hdsp_request_fw_loader(struct hdsp *hdsp) hdsp->state |= HDSP_FirmwareCached; - if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) + err = snd_hdsp_load_firmware_from_cache(hdsp); + if (err < 0) return err; if (!(hdsp->state & HDSP_InitializationComplete)) { - if ((err = snd_hdsp_enable_io(hdsp)) < 0) + err = snd_hdsp_enable_io(hdsp); + if (err < 0) return err; - if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_hwdep(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating hwdep device\n"); return err; } snd_hdsp_initialize_channels(hdsp); snd_hdsp_initialize_midi_flush(hdsp); - if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { + err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp); + if (err < 0) { dev_err(hdsp->card->dev, "error creating alsa devices\n"); return err; @@ -5280,15 +5313,18 @@ static int snd_hdsp_create(struct snd_card *card, is_9632 = 1; } - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; pci_set_master(hdsp->pci); - if ((err = pci_request_regions(pci, "hdsp")) < 0) + err = pci_request_regions(pci, "hdsp"); + if (err < 0) return err; hdsp->port = pci_resource_start(pci, 0); - if ((hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT)) == NULL) { + hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT); + if (!hdsp->iobase) { dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; @@ -5306,7 +5342,8 @@ static int snd_hdsp_create(struct snd_card *card, hdsp->use_midi_work = 1; hdsp->dds_value = 0; - if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) + err = snd_hdsp_initialize_memory(hdsp); + if (err < 0) return err; if (!is_9652 && !is_9632) { @@ -5318,7 +5355,8 @@ static int snd_hdsp_create(struct snd_card *card, return err; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { - if ((err = hdsp_request_fw_loader(hdsp)) < 0) + err = hdsp_request_fw_loader(hdsp); + if (err < 0) /* we don't fail as this can happen if userspace is not ready for firmware upload @@ -5331,7 +5369,8 @@ static int snd_hdsp_create(struct snd_card *card, /* we defer initialization */ dev_info(hdsp->card->dev, "card initialization pending : waiting for firmware\n"); - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) + err = snd_hdsp_create_hwdep(card, hdsp); + if (err < 0) return err; return 0; } else { @@ -5346,7 +5385,8 @@ static int snd_hdsp_create(struct snd_card *card, } } - if ((err = snd_hdsp_enable_io(hdsp)) != 0) + err = snd_hdsp_enable_io(hdsp); + if (err) return err; if (is_9652) @@ -5355,7 +5395,8 @@ static int snd_hdsp_create(struct snd_card *card, if (is_9632) hdsp->io_type = H9632; - if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) + err = snd_hdsp_create_hwdep(card, hdsp); + if (err < 0) return err; snd_hdsp_initialize_channels(hdsp); @@ -5363,7 +5404,8 @@ static int snd_hdsp_create(struct snd_card *card, hdsp->state |= HDSP_FirmwareLoaded; - if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) + err = snd_hdsp_create_alsa_devices(card, hdsp); + if (err < 0) return err; return 0; diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 7a4d395abcee..f1aad38760d6 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -433,9 +433,9 @@ static int rme9652_set_interrupt_interval(struct snd_rme9652 *s, spin_lock_irq(&s->lock); - if ((restart = s->running)) { + restart = s->running; + if (restart) rme9652_stop(s); - } frames >>= 7; n = 0; @@ -518,16 +518,15 @@ static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) return -EBUSY; } - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652->control_register &= ~(RME9652_freq | RME9652_DS); rme9652->control_register |= rate; rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } if (rate & RME9652_DS) { if (rme9652->ss_channels == RME9652_NCHANNELS) { @@ -878,15 +877,14 @@ static int rme9652_set_adat1_input(struct snd_rme9652 *rme9652, int internal) /* XXX do we actually need to stop the card when we do this ? */ - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } return 0; } @@ -943,15 +941,14 @@ static int rme9652_set_spdif_input(struct snd_rme9652 *rme9652, int in) rme9652->control_register &= ~RME9652_inp; rme9652->control_register |= rme9652_encode_spdif_in(in); - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } return 0; } @@ -1010,15 +1007,14 @@ static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out) rme9652->control_register &= ~RME9652_opt_out; } - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } return 0; } @@ -1086,15 +1082,14 @@ static int rme9652_set_sync_mode(struct snd_rme9652 *rme9652, int mode) break; } - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } return 0; } @@ -1173,15 +1168,14 @@ static int rme9652_set_sync_pref(struct snd_rme9652 *rme9652, int pref) break; } - if ((restart = rme9652->running)) { + restart = rme9652->running; + if (restart) rme9652_stop(rme9652); - } rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); - if (restart) { + if (restart) rme9652_start(rme9652); - } return 0; } @@ -1513,19 +1507,27 @@ static int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 struct snd_kcontrol *kctl; for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652))) < 0) + kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; if (idx == 1) /* IEC958 (S/PDIF) Stream */ rme9652->spdif_ctl = kctl; } - if (rme9652->ss_channels == RME9652_NCHANNELS) - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_adat3_check, rme9652))) < 0) + if (rme9652->ss_channels == RME9652_NCHANNELS) { + kctl = snd_ctl_new1(&snd_rme9652_adat3_check, rme9652); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } - if (rme9652->hw_rev >= 15) - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_adat1_input, rme9652))) < 0) + if (rme9652->hw_rev >= 15) { + kctl = snd_ctl_new1(&snd_rme9652_adat1_input, rme9652); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; + } return 0; } @@ -1842,9 +1844,9 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, if (snd_BUG_ON(channel < 0 || channel >= RME9652_NCHANNELS)) return NULL; - if ((mapped_channel = rme9652->channel_map[channel]) < 0) { + mapped_channel = rme9652->channel_map[channel]; + if (mapped_channel < 0) return NULL; - } if (stream == SNDRV_PCM_STREAM_CAPTURE) { return rme9652->capture_buffer + @@ -2021,12 +2023,14 @@ static int snd_rme9652_hw_params(struct snd_pcm_substream *substream, /* how to make sure that the rate matches an externally-set one ? */ - if ((err = rme9652_set_rate(rme9652, params_rate(params))) < 0) { + err = rme9652_set_rate(rme9652, params_rate(params)); + if (err < 0) { _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); return err; } - if ((err = rme9652_set_interrupt_interval(rme9652, params_period_size(params))) < 0) { + err = rme9652_set_interrupt_interval(rme9652, params_period_size(params)); + if (err < 0) { _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); return err; } @@ -2406,11 +2410,9 @@ static int snd_rme9652_create_pcm(struct snd_card *card, struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, - rme9652->card_name, - 0, 1, 1, &pcm)) < 0) { + err = snd_pcm_new(card, rme9652->card_name, 0, 1, 1, &pcm); + if (err < 0) return err; - } rme9652->pcm = pcm; pcm->private_data = rme9652; @@ -2450,12 +2452,14 @@ static int snd_rme9652_create(struct snd_card *card, return -ENODEV; } - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; spin_lock_init(&rme9652->lock); - if ((err = pci_request_regions(pci, "rme9652")) < 0) + err = pci_request_regions(pci, "rme9652"); + if (err < 0) return err; rme9652->port = pci_resource_start(pci, 0); rme9652->iobase = ioremap(rme9652->port, RME9652_IO_EXTENT); @@ -2528,17 +2532,17 @@ static int snd_rme9652_create(struct snd_card *card, pci_set_master(rme9652->pci); - if ((err = snd_rme9652_initialize_memory(rme9652)) < 0) { + err = snd_rme9652_initialize_memory(rme9652); + if (err < 0) return err; - } - if ((err = snd_rme9652_create_pcm(card, rme9652)) < 0) { + err = snd_rme9652_create_pcm(card, rme9652); + if (err < 0) return err; - } - if ((err = snd_rme9652_create_controls(card, rme9652)) < 0) { + err = snd_rme9652_create_controls(card, rme9652); + if (err < 0) return err; - } snd_rme9652_proc_init(rme9652); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 7de10997775f..03a48da897e3 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -852,7 +852,8 @@ static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0) + err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm); + if (err < 0) return err; if (snd_BUG_ON(!pcm)) return -EINVAL; @@ -1093,7 +1094,9 @@ static int snd_sonicvibes_mixer(struct sonicvibes *sonic) strcpy(card->mixername, "S3 SonicVibes"); for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0) + kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic); + err = snd_ctl_add(card, kctl); + if (err < 0) return err; switch (idx) { case 0: @@ -1226,7 +1229,8 @@ static int snd_sonicvibes_create(struct snd_card *card, *rsonic = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 24 bits */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) { @@ -1246,7 +1250,8 @@ static int snd_sonicvibes_create(struct snd_card *card, sonic->pci = pci; sonic->irq = -1; - if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) { + err = pci_request_regions(pci, "S3 SonicVibes"); + if (err < 0) { kfree(sonic); pci_disable_device(pci); return err; @@ -1289,14 +1294,16 @@ static int snd_sonicvibes_create(struct snd_card *card, pci_write_config_dword(pci, 0x40, dmaa); pci_write_config_dword(pci, 0x48, dmac); - if ((sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A")) == NULL) { + sonic->res_dmaa = request_region(dmaa, 0x10, "S3 SonicVibes DDMA-A"); + if (!sonic->res_dmaa) { snd_sonicvibes_free(sonic); dev_err(card->dev, "unable to grab DDMA-A port at 0x%x-0x%x\n", dmaa, dmaa + 0x10 - 1); return -EBUSY; } - if ((sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C")) == NULL) { + sonic->res_dmac = request_region(dmac, 0x10, "S3 SonicVibes DDMA-C"); + if (!sonic->res_dmac) { snd_sonicvibes_free(sonic); dev_err(card->dev, "unable to grab DDMA-C port at 0x%x-0x%x\n", @@ -1358,7 +1365,8 @@ static int snd_sonicvibes_create(struct snd_card *card, #endif sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops); + if (err < 0) { snd_sonicvibes_free(sonic); return err; } @@ -1405,9 +1413,11 @@ static int snd_sonicvibes_midi(struct sonicvibes *sonic, mpu->private_data = sonic; mpu->open_input = snd_sonicvibes_midi_input_open; mpu->close_input = snd_sonicvibes_midi_input_close; - for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++) - if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0) + for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic)); + if (err < 0) return err; + } return 0; } @@ -1439,10 +1449,11 @@ static int snd_sonic_probe(struct pci_dev *pci, return -ENODEV; } } - if ((err = snd_sonicvibes_create(card, pci, - reverb[dev] ? 1 : 0, - mge[dev] ? 1 : 0, - &sonic)) < 0) { + err = snd_sonicvibes_create(card, pci, + reverb[dev] ? 1 : 0, + mge[dev] ? 1 : 0, + &sonic); + if (err < 0) { snd_card_free(card); return err; } @@ -1455,30 +1466,35 @@ static int snd_sonic_probe(struct pci_dev *pci, (unsigned long long)pci_resource_start(pci, 1), sonic->irq); - if ((err = snd_sonicvibes_pcm(sonic, 0)) < 0) { + err = snd_sonicvibes_pcm(sonic, 0); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_sonicvibes_mixer(sonic)) < 0) { + err = snd_sonicvibes_mixer(sonic); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, - sonic->midi_port, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &midi_uart)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, + sonic->midi_port, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &midi_uart); + if (err < 0) { snd_card_free(card); return err; } snd_sonicvibes_midi(sonic, midi_uart); - if ((err = snd_opl3_create(card, sonic->synth_port, - sonic->synth_port + 2, - OPL3_HW_OPL3_SV, 1, &opl3)) < 0) { + err = snd_opl3_create(card, sonic->synth_port, + sonic->synth_port + 2, + OPL3_HW_OPL3_SV, 1, &opl3); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { snd_card_free(card); return err; } @@ -1489,7 +1505,8 @@ static int snd_sonic_probe(struct pci_dev *pci, return err; } - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index a51041205f7c..60e4dca28c2b 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -67,11 +67,12 @@ static int snd_trident_probe(struct pci_dev *pci, if (err < 0) return err; - if ((err = snd_trident_create(card, pci, - pcm_channels[dev], - ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2, - wavetable_size[dev], - &trident)) < 0) { + err = snd_trident_create(card, pci, + pcm_channels[dev], + ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2, + wavetable_size[dev], + &trident); + if (err < 0) { snd_card_free(card); return err; } @@ -100,38 +101,44 @@ static int snd_trident_probe(struct pci_dev *pci, sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", card->shortname, trident->port, trident->irq); - if ((err = snd_trident_pcm(trident, pcm_dev++)) < 0) { + err = snd_trident_pcm(trident, pcm_dev++); + if (err < 0) { snd_card_free(card); return err; } switch (trident->device) { case TRIDENT_DEVICE_ID_DX: case TRIDENT_DEVICE_ID_NX: - if ((err = snd_trident_foldback_pcm(trident, pcm_dev++)) < 0) { + err = snd_trident_foldback_pcm(trident, pcm_dev++); + if (err < 0) { snd_card_free(card); return err; } break; } if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_trident_spdif_pcm(trident, pcm_dev++)) < 0) { + err = snd_trident_spdif_pcm(trident, pcm_dev++); + if (err < 0) { snd_card_free(card); return err; } } - if (trident->device != TRIDENT_DEVICE_ID_SI7018 && - (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, - trident->midi_port, - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &trident->rmidi)) < 0) { - snd_card_free(card); - return err; + if (trident->device != TRIDENT_DEVICE_ID_SI7018) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, + trident->midi_port, + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &trident->rmidi); + if (err < 0) { + snd_card_free(card); + return err; + } } snd_trident_create_gameport(trident); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h index c7567edbe4c4..c579a44bb9ae 100644 --- a/sound/pci/trident/trident.h +++ b/sound/pci/trident/trident.h @@ -251,7 +251,6 @@ struct snd_trident_memblk_arg { struct snd_trident_tlb { __le32 *entries; /* 16k-aligned TLB table */ dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */ - unsigned long * shadow_entries; /* shadow entries with virtual addresses */ struct snd_dma_buffer buffer; struct snd_util_memhdr * memhdr; /* page allocation list */ struct snd_dma_buffer silent_page; diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 20145143f6a6..cfbca3bd60ed 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2119,7 +2119,8 @@ int snd_trident_pcm(struct snd_trident *trident, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0) + err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm); + if (err < 0) return err; pcm->private_data = trident; @@ -2178,7 +2179,8 @@ int snd_trident_foldback_pcm(struct snd_trident *trident, int device) if (trident->device == TRIDENT_DEVICE_ID_NX) num_chan = 4; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0) + err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback); + if (err < 0) return err; foldback->private_data = trident; @@ -2228,7 +2230,8 @@ int snd_trident_spdif_pcm(struct snd_trident *trident, int device) struct snd_pcm *spdif; int err; - if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0) + err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif); + if (err < 0) return err; spdif->private_data = trident; @@ -2921,7 +2924,8 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) if (!uctl) return -ENOMEM; - if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0) + err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus); + if (err < 0) goto __out; memset(&_ac97, 0, sizeof(_ac97)); @@ -2929,9 +2933,11 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) trident->ac97_detect = 1; __again: - if ((err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97)) < 0) { + err = snd_ac97_mixer(trident->ac97_bus, &_ac97, &trident->ac97); + if (err < 0) { if (trident->device == TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_trident_sis_reset(trident)) < 0) + err = snd_trident_sis_reset(trident); + if (err < 0) goto __out; if (retries-- > 0) goto __again; @@ -2962,10 +2968,14 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) trident->ac97_detect = 0; if (trident->device != TRIDENT_DEVICE_ID_SI7018) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident))) < 0) + kctl = snd_ctl_new1(&snd_trident_vol_wave_control, trident); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl->put(kctl, uctl); - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident))) < 0) + kctl = snd_ctl_new1(&snd_trident_vol_music_control, trident); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl->put(kctl, uctl); outl(trident->musicvol_wavevol = 0x00000000, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL)); @@ -2979,28 +2989,38 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) tmix = &trident->pcm_mixer[idx]; tmix->voice = NULL; } - if ((trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident)) == NULL) + trident->ctl_vol = snd_ctl_new1(&snd_trident_pcm_vol_control, trident); + if (!trident->ctl_vol) goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_vol))) + err = snd_ctl_add(card, trident->ctl_vol); + if (err) goto __out; - if ((trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident)) == NULL) + trident->ctl_pan = snd_ctl_new1(&snd_trident_pcm_pan_control, trident); + if (!trident->ctl_pan) goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_pan))) + err = snd_ctl_add(card, trident->ctl_pan); + if (err) goto __out; - if ((trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident)) == NULL) + trident->ctl_rvol = snd_ctl_new1(&snd_trident_pcm_rvol_control, trident); + if (!trident->ctl_rvol) goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_rvol))) + err = snd_ctl_add(card, trident->ctl_rvol); + if (err) goto __out; - if ((trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident)) == NULL) + trident->ctl_cvol = snd_ctl_new1(&snd_trident_pcm_cvol_control, trident); + if (!trident->ctl_cvol) goto __nomem; - if ((err = snd_ctl_add(card, trident->ctl_cvol))) + err = snd_ctl_add(card, trident->ctl_cvol); + if (err) goto __out; if (trident->device == TRIDENT_DEVICE_ID_NX) { - if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident))) < 0) + kctl = snd_ctl_new1(&snd_trident_ac97_rear_control, trident); + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl->put(kctl, uctl); } @@ -3016,7 +3036,8 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) if (trident->ac97_sec && (trident->ac97_sec->ext_id & AC97_EI_SPDIF)) kctl->id.index++; idx = kctl->id.index; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl->put(kctl, uctl); @@ -3027,7 +3048,8 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) } kctl->id.index = idx; kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl = snd_ctl_new1(&snd_trident_spdif_mask, trident); @@ -3037,7 +3059,8 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) } kctl->id.index = idx; kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; kctl = snd_ctl_new1(&snd_trident_spdif_stream, trident); @@ -3047,7 +3070,8 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device) } kctl->id.index = idx; kctl->id.device = pcm_spdif_device; - if ((err = snd_ctl_add(card, kctl)) < 0) + err = snd_ctl_add(card, kctl); + if (err < 0) goto __out; trident->spdif_pcm_ctl = kctl; } @@ -3307,12 +3331,6 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) } trident->tlb.entries = (__le32 *)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4); trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4); - /* allocate shadow TLB page table (virtual addresses) */ - trident->tlb.shadow_entries = - vmalloc(array_size(SNDRV_TRIDENT_MAX_PAGES, - sizeof(unsigned long))); - if (!trident->tlb.shadow_entries) - return -ENOMEM; /* allocate and setup silent page and initialise TLB entries */ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &trident->pci->dev, @@ -3321,10 +3339,8 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident) return -ENOMEM; } memset(trident->tlb.silent_page.area, 0, SNDRV_TRIDENT_PAGE_SIZE); - for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) { + for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page.addr & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); - trident->tlb.shadow_entries[i] = (unsigned long)trident->tlb.silent_page.area; - } /* use emu memory block manager code to manage tlb page allocation */ trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE * SNDRV_TRIDENT_MAX_PAGES); @@ -3449,7 +3465,8 @@ static int snd_trident_sis_init(struct snd_trident *trident) { int err; - if ((err = snd_trident_sis_reset(trident)) < 0) + err = snd_trident_sis_reset(trident); + if (err < 0) return err; snd_trident_stop_all_voices(trident); @@ -3494,7 +3511,8 @@ int snd_trident_create(struct snd_card *card, *rtrident = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; /* check, if we can restrict PCI DMA transfers to 30 bits */ if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) { @@ -3528,7 +3546,8 @@ int snd_trident_create(struct snd_card *card, trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE); pci_set_master(pci); - if ((err = pci_request_regions(pci, "Trident Audio")) < 0) { + err = pci_request_regions(pci, "Trident Audio"); + if (err < 0) { kfree(trident); pci_disable_device(pci); return err; @@ -3548,7 +3567,8 @@ int snd_trident_create(struct snd_card *card, trident->tlb.entries = NULL; trident->tlb.buffer.area = NULL; if (trident->device == TRIDENT_DEVICE_ID_NX) { - if ((err = snd_trident_tlb_alloc(trident)) < 0) { + err = snd_trident_tlb_alloc(trident); + if (err < 0) { snd_trident_free(trident); return err; } @@ -3576,12 +3596,14 @@ int snd_trident_create(struct snd_card *card, return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, trident, &ops); + if (err < 0) { snd_trident_free(trident); return err; } - if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0) + err = snd_trident_mixer(trident, pcm_spdif_device); + if (err < 0) return err; /* initialise synth voices */ @@ -3635,7 +3657,6 @@ static int snd_trident_free(struct snd_trident *trident) snd_util_memhdr_free(trident->tlb.memhdr); if (trident->tlb.silent_page.area) snd_dma_free_pages(&trident->tlb.silent_page); - vfree(trident->tlb.shadow_entries); snd_dma_free_pages(&trident->tlb.buffer); } pci_release_regions(trident->pci); diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index bb24dbf0530d..4ad3855101c9 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c @@ -19,11 +19,8 @@ /* page arguments of these two macros are Trident page (4096 bytes), not like * aligned pages in others */ -#define __set_tlb_bus(trident,page,ptr,addr) \ - do { (trident)->tlb.entries[page] = cpu_to_le32((addr) & ~(SNDRV_TRIDENT_PAGE_SIZE-1)); \ - (trident)->tlb.shadow_entries[page] = (ptr); } while (0) -#define __tlb_to_ptr(trident,page) \ - (void*)((trident)->tlb.shadow_entries[page]) +#define __set_tlb_bus(trident,page,addr) \ + (trident)->tlb.entries[page] = cpu_to_le32((addr) & ~(SNDRV_TRIDENT_PAGE_SIZE-1)) #define __tlb_to_addr(trident,page) \ (dma_addr_t)le32_to_cpu((trident->tlb.entries[page]) & ~(SNDRV_TRIDENT_PAGE_SIZE - 1)) @@ -32,15 +29,13 @@ #define ALIGN_PAGE_SIZE PAGE_SIZE /* minimum page size for allocation */ #define MAX_ALIGN_PAGES SNDRV_TRIDENT_MAX_PAGES /* maxmium aligned pages */ /* fill TLB entrie(s) corresponding to page with ptr */ -#define set_tlb_bus(trident,page,ptr,addr) __set_tlb_bus(trident,page,ptr,addr) +#define set_tlb_bus(trident,page,addr) __set_tlb_bus(trident,page,addr) /* fill TLB entrie(s) corresponding to page with silence pointer */ -#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr) +#define set_silent_tlb(trident,page) __set_tlb_bus(trident, page, trident->tlb.silent_page.addr) /* get aligned page from offset address */ #define get_aligned_page(offset) ((offset) >> 12) /* get offset address from aligned page */ #define aligned_page_offset(page) ((page) << 12) -/* get buffer address from aligned page */ -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, page) /* get PCI physical address from aligned page */ #define page_to_addr(trident,page) __tlb_to_addr(trident, page) @@ -50,22 +45,21 @@ #define MAX_ALIGN_PAGES (SNDRV_TRIDENT_MAX_PAGES / 2) #define get_aligned_page(offset) ((offset) >> 13) #define aligned_page_offset(page) ((page) << 13) -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) << 1) #define page_to_addr(trident,page) __tlb_to_addr(trident, (page) << 1) /* fill TLB entries -- we need to fill two entries */ static inline void set_tlb_bus(struct snd_trident *trident, int page, - unsigned long ptr, dma_addr_t addr) + dma_addr_t addr) { page <<= 1; - __set_tlb_bus(trident, page, ptr, addr); - __set_tlb_bus(trident, page+1, ptr + SNDRV_TRIDENT_PAGE_SIZE, addr + SNDRV_TRIDENT_PAGE_SIZE); + __set_tlb_bus(trident, page, addr); + __set_tlb_bus(trident, page+1, addr + SNDRV_TRIDENT_PAGE_SIZE); } static inline void set_silent_tlb(struct snd_trident *trident, int page) { page <<= 1; - __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); - __set_tlb_bus(trident, page+1, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); + __set_tlb_bus(trident, page, trident->tlb.silent_page.addr); + __set_tlb_bus(trident, page+1, trident->tlb.silent_page.addr); } #else @@ -80,18 +74,16 @@ static inline void set_silent_tlb(struct snd_trident *trident, int page) */ #define get_aligned_page(offset) ((offset) / ALIGN_PAGE_SIZE) #define aligned_page_offset(page) ((page) * ALIGN_PAGE_SIZE) -#define page_to_ptr(trident,page) __tlb_to_ptr(trident, (page) * UNIT_PAGES) #define page_to_addr(trident,page) __tlb_to_addr(trident, (page) * UNIT_PAGES) /* fill TLB entries -- UNIT_PAGES entries must be filled */ static inline void set_tlb_bus(struct snd_trident *trident, int page, - unsigned long ptr, dma_addr_t addr) + dma_addr_t addr) { int i; page *= UNIT_PAGES; for (i = 0; i < UNIT_PAGES; i++, page++) { - __set_tlb_bus(trident, page, ptr, addr); - ptr += SNDRV_TRIDENT_PAGE_SIZE; + __set_tlb_bus(trident, page, addr); addr += SNDRV_TRIDENT_PAGE_SIZE; } } @@ -100,20 +92,11 @@ static inline void set_silent_tlb(struct snd_trident *trident, int page) int i; page *= UNIT_PAGES; for (i = 0; i < UNIT_PAGES; i++, page++) - __set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr); + __set_tlb_bus(trident, page, trident->tlb.silent_page.addr); } #endif /* PAGE_SIZE */ -/* calculate buffer pointer from offset address */ -static inline void *offset_ptr(struct snd_trident *trident, int offset) -{ - char *ptr; - ptr = page_to_ptr(trident, get_aligned_page(offset)); - ptr += offset % ALIGN_PAGE_SIZE; - return (void*)ptr; -} - /* first and last (aligned) pages of memory block */ #define firstpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->first_page) #define lastpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->last_page) @@ -201,14 +184,12 @@ snd_trident_alloc_sg_pages(struct snd_trident *trident, for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) { unsigned long ofs = idx << PAGE_SHIFT; dma_addr_t addr = snd_pcm_sgbuf_get_addr(substream, ofs); - unsigned long ptr = (unsigned long) - snd_pcm_sgbuf_get_ptr(substream, ofs); if (! is_valid_page(addr)) { __snd_util_mem_free(hdr, blk); mutex_unlock(&hdr->block_mutex); return NULL; } - set_tlb_bus(trident, page, ptr, addr); + set_tlb_bus(trident, page, addr); } mutex_unlock(&hdr->block_mutex); return blk; @@ -226,7 +207,6 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, int page; struct snd_pcm_runtime *runtime = substream->runtime; dma_addr_t addr; - unsigned long ptr; if (snd_BUG_ON(runtime->dma_bytes <= 0 || runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES * @@ -245,15 +225,14 @@ snd_trident_alloc_cont_pages(struct snd_trident *trident, /* set TLB entries */ addr = runtime->dma_addr; - ptr = (unsigned long)runtime->dma_area; for (page = firstpg(blk); page <= lastpg(blk); page++, - ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) { + addr += SNDRV_TRIDENT_PAGE_SIZE) { if (! is_valid_page(addr)) { __snd_util_mem_free(hdr, blk); mutex_unlock(&hdr->block_mutex); return NULL; } - set_tlb_bus(trident, page, ptr, addr); + set_tlb_bus(trident, page, addr); } mutex_unlock(&hdr->block_mutex); return blk; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index fd1f2f9cfbc3..943813a06abc 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -515,7 +515,8 @@ static int snd_via82xx_codec_ready(struct via82xx *chip, int secondary) while (timeout-- > 0) { udelay(1); - if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) + val = snd_via82xx_codec_xread(chip); + if (!(val & VIA_REG_AC97_BUSY)) return val & 0xffff; } dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n", @@ -1023,7 +1024,8 @@ static int snd_via8233_playback_prepare(struct snd_pcm_substream *substream) int rate_changed; u32 rbits; - if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0) + rate_changed = via_lock_rate(&chip->rates[0], ac97_rate); + if (rate_changed < 0) return rate_changed; if (rate_changed) snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, @@ -1197,7 +1199,8 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev, /* we may remove following constaint when we modify table entries in interrupt */ - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; if (use_src) { @@ -1222,7 +1225,8 @@ static int snd_via686_playback_open(struct snd_pcm_substream *substream) struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number]; int err; - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) + err = snd_via82xx_pcm_open(chip, viadev, substream); + if (err < 0) return err; return 0; } @@ -1238,7 +1242,8 @@ static int snd_via8233_playback_open(struct snd_pcm_substream *substream) int err; viadev = &chip->devs[chip->playback_devno + substream->number]; - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) + err = snd_via82xx_pcm_open(chip, viadev, substream); + if (err < 0) return err; stream = viadev->reg_offset / 0x10; if (chip->dxs_controls[stream]) { @@ -1275,7 +1280,8 @@ static int snd_via8233_multi_open(struct snd_pcm_substream *substream) .mask = 0, }; - if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) + err = snd_via82xx_pcm_open(chip, viadev, substream); + if (err < 0) return err; substream->runtime->hw.channels_max = 6; if (chip->revision == VIA_REV_8233A) @@ -1875,7 +1881,8 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid .wait = snd_via82xx_codec_wait, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; @@ -1885,7 +1892,8 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid ac97.private_free = snd_via82xx_mixer_free_ac97; ac97.pci = chip->pci; ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override); @@ -2054,9 +2062,9 @@ static int snd_via686_init_misc(struct via82xx *chip) break; } } - if (mpu_port >= 0x200 && - (chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401")) - != NULL) { + if (mpu_port >= 0x200) + chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401"); + if (chip->mpu_res) { if (rev_h) legacy |= VIA_FUNC_MIDI_PNP; /* enable PCI I/O 2 */ legacy |= VIA_FUNC_ENABLE_MIDI; @@ -2173,7 +2181,8 @@ static int snd_via82xx_chip_init(struct via82xx *chip) schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_BUSY) dev_err(chip->card->dev, "AC'97 codec is not ready [0x%x]\n", val); @@ -2186,7 +2195,8 @@ static int snd_via82xx_chip_init(struct via82xx *chip) VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); do { - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_SECONDARY_VALID) { chip->ac97_secondary = 1; goto __ac97_ok2; } @@ -2337,10 +2347,12 @@ static int snd_via82xx_create(struct snd_card *card, .dev_free = snd_via82xx_dev_free, }; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) { pci_disable_device(pci); return -ENOMEM; } @@ -2360,7 +2372,8 @@ static int snd_via82xx_create(struct snd_card *card, pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM)); - if ((err = pci_request_regions(pci, card->driver)) < 0) { + err = pci_request_regions(pci, card->driver); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -2380,12 +2393,14 @@ static int snd_via82xx_create(struct snd_card *card, if (ac97_clock >= 8000 && ac97_clock <= 48000) chip->ac97_clock = ac97_clock; - if ((err = snd_via82xx_chip_init(chip)) < 0) { + err = snd_via82xx_chip_init(chip); + if (err < 0) { snd_via82xx_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_via82xx_free(chip); return err; } @@ -2541,24 +2556,31 @@ static int snd_via82xx_probe(struct pci_dev *pci, goto __error; } - if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision, - ac97_clock, &chip)) < 0) + err = snd_via82xx_create(card, pci, chip_type, pci->revision, + ac97_clock, &chip); + if (err < 0) goto __error; card->private_data = chip; - if ((err = snd_via82xx_mixer_new(chip, ac97_quirk)) < 0) + err = snd_via82xx_mixer_new(chip, ac97_quirk); + if (err < 0) goto __error; if (chip_type == TYPE_VIA686) { - if ((err = snd_via686_pcm_new(chip)) < 0 || - (err = snd_via686_init_misc(chip)) < 0) + err = snd_via686_pcm_new(chip); + if (err < 0) + goto __error; + err = snd_via686_init_misc(chip); + if (err < 0) goto __error; } else { if (chip_type == TYPE_VIA8233A) { - if ((err = snd_via8233a_pcm_new(chip)) < 0) + err = snd_via8233a_pcm_new(chip); + if (err < 0) goto __error; // chip->dxs_fixed = 1; /* FIXME: use 48k for DXS #3? */ } else { - if ((err = snd_via8233_pcm_new(chip)) < 0) + err = snd_via8233_pcm_new(chip); + if (err < 0) goto __error; if (dxs_support == VIA_DXS_48K) chip->dxs_fixed = 1; @@ -2569,7 +2591,8 @@ static int snd_via82xx_probe(struct pci_dev *pci, chip->dxs_src = 1; } } - if ((err = snd_via8233_init_misc(chip)) < 0) + err = snd_via8233_init_misc(chip); + if (err < 0) goto __error; } @@ -2583,7 +2606,8 @@ static int snd_via82xx_probe(struct pci_dev *pci, snd_via82xx_proc_init(chip); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 30253306f67c..07278a3dc8c1 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -369,7 +369,8 @@ static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary) while (timeout-- > 0) { udelay(1); - if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)) + val = snd_via82xx_codec_xread(chip); + if (!(val & VIA_REG_AC97_BUSY)) return val & 0xffff; } dev_err(chip->card->dev, "codec_ready: codec %i is not ready [0x%x]\n", @@ -738,13 +739,15 @@ static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev runtime->hw = snd_via82xx_hw; - if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - &hw_constraints_rates)) < 0) + err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &hw_constraints_rates); + if (err < 0) return err; /* we may remove following constaint when we modify table entries in interrupt */ - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (err < 0) return err; runtime->private_data = viadev; @@ -878,7 +881,8 @@ static int snd_via82xx_mixer_new(struct via82xx_modem *chip) .wait = snd_via82xx_codec_wait, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus; chip->ac97_bus->clock = chip->ac97_clock; @@ -890,7 +894,8 @@ static int snd_via82xx_mixer_new(struct via82xx_modem *chip) ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; ac97.num = chip->ac97_secondary; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; return 0; @@ -971,7 +976,8 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) schedule_timeout_uninterruptible(1); } while (time_before(jiffies, end_time)); - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_BUSY) dev_err(chip->card->dev, "AC'97 codec is not ready [0x%x]\n", val); @@ -983,7 +989,8 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) VIA_REG_AC97_SECONDARY_VALID | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); do { - if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) { + val = snd_via82xx_codec_xread(chip); + if (val & VIA_REG_AC97_SECONDARY_VALID) { chip->ac97_secondary = 1; goto __ac97_ok2; } @@ -1079,10 +1086,12 @@ static int snd_via82xx_create(struct snd_card *card, .dev_free = snd_via82xx_dev_free, }; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; - if ((chip = kzalloc(sizeof(*chip), GFP_KERNEL)) == NULL) { + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) { pci_disable_device(pci); return -ENOMEM; } @@ -1092,7 +1101,8 @@ static int snd_via82xx_create(struct snd_card *card, chip->pci = pci; chip->irq = -1; - if ((err = pci_request_regions(pci, card->driver)) < 0) { + err = pci_request_regions(pci, card->driver); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; @@ -1109,12 +1119,14 @@ static int snd_via82xx_create(struct snd_card *card, if (ac97_clock >= 8000 && ac97_clock <= 48000) chip->ac97_clock = ac97_clock; - if ((err = snd_via82xx_chip_init(chip)) < 0) { + err = snd_via82xx_chip_init(chip); + if (err < 0) { snd_via82xx_free(chip); return err; } - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_via82xx_free(chip); return err; } @@ -1154,14 +1166,17 @@ static int snd_via82xx_probe(struct pci_dev *pci, goto __error; } - if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision, - ac97_clock, &chip)) < 0) + err = snd_via82xx_create(card, pci, chip_type, pci->revision, + ac97_clock, &chip); + if (err < 0) goto __error; card->private_data = chip; - if ((err = snd_via82xx_mixer_new(chip)) < 0) + err = snd_via82xx_mixer_new(chip); + if (err < 0) goto __error; - if ((err = snd_via686_pcm_new(chip)) < 0 ) + err = snd_via686_pcm_new(chip); + if (err < 0) goto __error; /* disable interrupts */ @@ -1173,7 +1188,8 @@ static int snd_via82xx_probe(struct pci_dev *pci, snd_via82xx_proc_init(chip); - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 2a9e1a77a81a..04c7204cb7bc 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -133,7 +133,8 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, const struct snd_vx_ops *vx_ops; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; pci_set_master(pci); @@ -147,7 +148,8 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, vx = to_vx222(chip); vx->pci = pci; - if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { + err = pci_request_regions(pci, CARD_NAME); + if (err < 0) { snd_vx222_free(chip); return err; } @@ -164,7 +166,8 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, chip->irq = pci->irq; card->sync_irq = chip->irq; - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) { snd_vx222_free(chip); return err; } @@ -207,7 +210,8 @@ static int snd_vx222_probe(struct pci_dev *pci, hw = &vx222_v2_hw; break; } - if ((err = snd_vx222_create(card, pci, hw, &vx)) < 0) { + err = snd_vx222_create(card, pci, hw, &vx); + if (err < 0) { snd_card_free(card); return err; } @@ -223,12 +227,14 @@ static int snd_vx222_probe(struct pci_dev *pci, vx->core.dev = &pci->dev; #endif - if ((err = snd_vx_setup_firmware(&vx->core)) < 0) { + err = snd_vx_setup_firmware(&vx->core); + if (err < 0) { snd_card_free(card); return err; } - if ((err = snd_card_register(card)) < 0) { + err = snd_card_register(card); + if (err < 0) { snd_card_free(card); return err; } diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index a05537202738..3e7e928b24f8 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -408,9 +408,11 @@ static int vx2_load_dsp(struct vx_core *vx, int index, const struct firmware *ds switch (index) { case 1: /* xilinx image */ - if ((err = vx2_load_xilinx_binary(vx, dsp)) < 0) + err = vx2_load_xilinx_binary(vx, dsp); + if (err < 0) return err; - if ((err = vx2_test_xilinx(vx)) < 0) + err = vx2_test_xilinx(vx); + if (err < 0) return err; return 0; case 2: @@ -972,9 +974,11 @@ static int vx2_add_mic_controls(struct vx_core *_chip) vx2_set_input_level(chip); /* controls */ - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_input_level, chip))) < 0) + err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_input_level, chip)); + if (err < 0) return err; - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) + err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip)); + if (err < 0) return err; return 0; diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 99be1490ef0e..7e32d57147ff 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -72,7 +72,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, if (io_port == 1) { /* auto-detect */ - if (!(io_port = pci_resource_start(chip->pci, 2))) + io_port = pci_resource_start(chip->pci, 2); + if (!io_port) return -ENODEV; } } else { @@ -81,7 +82,8 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, for (io_port = 0x201; io_port <= 0x205; io_port++) { if (io_port == 0x203) continue; - if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL) + r = request_region(io_port, 1, "YMFPCI gameport"); + if (r) break; } if (!r) { @@ -102,10 +104,13 @@ static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, } } - if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) { - dev_err(chip->card->dev, - "joystick port %#x is in use.\n", io_port); - return -EBUSY; + if (!r) { + r = request_region(io_port, 1, "YMFPCI gameport"); + if (!r) { + dev_err(chip->card->dev, + "joystick port %#x is in use.\n", io_port); + return -EBUSY; + } } chip->gameport = gp = gameport_allocate_port(); @@ -193,8 +198,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, /* auto-detect */ fm_port[dev] = pci_resource_start(pci, 1); } - if (fm_port[dev] > 0 && - (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { + if (fm_port[dev] > 0) + fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3"); + if (fm_res) { legacy_ctrl |= YMFPCI_LEGACY_FMEN; pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]); } @@ -202,8 +208,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, /* auto-detect */ mpu_port[dev] = pci_resource_start(pci, 1) + 0x20; } - if (mpu_port[dev] > 0 && - (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { + if (mpu_port[dev] > 0) + mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401"); + if (mpu_res) { legacy_ctrl |= YMFPCI_LEGACY_MEN; pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]); } @@ -215,8 +222,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, case 0x3a8: legacy_ctrl2 |= 3; break; default: fm_port[dev] = 0; break; } - if (fm_port[dev] > 0 && - (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { + if (fm_port[dev] > 0) + fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3"); + if (fm_res) { legacy_ctrl |= YMFPCI_LEGACY_FMEN; } else { legacy_ctrl2 &= ~YMFPCI_LEGACY2_FMIO; @@ -229,8 +237,9 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, case 0x334: legacy_ctrl2 |= 3 << 4; break; default: mpu_port[dev] = 0; break; } - if (mpu_port[dev] > 0 && - (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { + if (mpu_port[dev] > 0) + mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401"); + if (mpu_res) { legacy_ctrl |= YMFPCI_LEGACY_MEN; } else { legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO; @@ -244,9 +253,8 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl); pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); - if ((err = snd_ymfpci_create(card, pci, - old_legacy_ctrl, - &chip)) < 0) { + err = snd_ymfpci_create(card, pci, old_legacy_ctrl, &chip); + if (err < 0) { release_and_free_resource(mpu_res); release_and_free_resource(fm_res); goto free_card; @@ -287,11 +295,12 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, goto free_card; if (chip->mpu_res) { - if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, - mpu_port[dev], - MPU401_INFO_INTEGRATED | - MPU401_INFO_IRQ_HOOK, - -1, &chip->rawmidi)) < 0) { + err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, + mpu_port[dev], + MPU401_INFO_INTEGRATED | + MPU401_INFO_IRQ_HOOK, + -1, &chip->rawmidi); + if (err < 0) { dev_warn(card->dev, "cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); @@ -300,18 +309,22 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci, } } if (chip->fm_res) { - if ((err = snd_opl3_create(card, - fm_port[dev], - fm_port[dev] + 2, - OPL3_HW_OPL3, 1, &opl3)) < 0) { + err = snd_opl3_create(card, + fm_port[dev], + fm_port[dev] + 2, + OPL3_HW_OPL3, 1, &opl3); + if (err < 0) { dev_warn(card->dev, "cannot initialize FM OPL3 at 0x%lx, skipping...\n", fm_port[dev]); legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); - } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { - dev_err(card->dev, "cannot create opl3 hwdep\n"); - goto free_card; + } else { + err = snd_opl3_hwdep_new(opl3, 0, 1, NULL); + if (err < 0) { + dev_err(card->dev, "cannot create opl3 hwdep\n"); + goto free_card; + } } } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index cacc6a9d14c8..8fd060769882 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -292,7 +292,8 @@ static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_ struct snd_ymfpci_pcm *ypcm; u32 pos, delta; - if ((ypcm = voice->ypcm) == NULL) + ypcm = voice->ypcm; + if (!ypcm) return; if (ypcm->substream == NULL) return; @@ -628,7 +629,8 @@ static int snd_ymfpci_playback_hw_params(struct snd_pcm_substream *substream, struct snd_ymfpci_pcm *ypcm = runtime->private_data; int err; - if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0) + err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params)); + if (err < 0) return err; return 0; } @@ -932,7 +934,8 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) struct snd_ymfpci_pcm *ypcm; int err; - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) + err = snd_ymfpci_playback_open_1(substream); + if (err < 0) return err; ypcm = runtime->private_data; ypcm->output_front = 1; @@ -954,7 +957,8 @@ static int snd_ymfpci_playback_spdif_open(struct snd_pcm_substream *substream) struct snd_ymfpci_pcm *ypcm; int err; - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) + err = snd_ymfpci_playback_open_1(substream); + if (err < 0) return err; ypcm = runtime->private_data; ypcm->output_front = 0; @@ -982,7 +986,8 @@ static int snd_ymfpci_playback_4ch_open(struct snd_pcm_substream *substream) struct snd_ymfpci_pcm *ypcm; int err; - if ((err = snd_ymfpci_playback_open_1(substream)) < 0) + err = snd_ymfpci_playback_open_1(substream); + if (err < 0) return err; ypcm = runtime->private_data; ypcm->output_front = 0; @@ -1124,7 +1129,8 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1157,7 +1163,8 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0) + err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1190,7 +1197,8 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0) + err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1230,7 +1238,8 @@ int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0) + err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm); + if (err < 0) return err; pcm->private_data = chip; @@ -1785,7 +1794,8 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) .read = snd_ymfpci_codec_read, }; - if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0) + err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus); + if (err < 0) return err; chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus; chip->ac97_bus->no_vra = 1; /* YMFPCI doesn't need VRA */ @@ -1793,7 +1803,8 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) memset(&ac97, 0, sizeof(ac97)); ac97.private_data = chip; ac97.private_free = snd_ymfpci_mixer_free_ac97; - if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) + err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97); + if (err < 0) return err; /* to be sure */ @@ -1801,7 +1812,8 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) AC97_EA_VRA|AC97_EA_VRM, 0); for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip)); + if (err < 0) return err; } if (chip->ac97->ext_id & AC97_EI_SDAC) { @@ -1814,27 +1826,37 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) /* add S/PDIF control */ if (snd_BUG_ON(!chip->pcm_spdif)) return -ENXIO; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip))) < 0) + kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip); + err = snd_ctl_add(chip->card, kctl); + if (err < 0) return err; kctl->id.device = chip->pcm_spdif->device; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip))) < 0) + kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip); + err = snd_ctl_add(chip->card, kctl); + if (err < 0) return err; kctl->id.device = chip->pcm_spdif->device; - if ((err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip))) < 0) + kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip); + err = snd_ctl_add(chip->card, kctl); + if (err < 0) return err; kctl->id.device = chip->pcm_spdif->device; chip->spdif_pcm_ctl = kctl; /* direct recording source */ - if (chip->device_id == PCI_DEVICE_ID_YAMAHA_754 && - (err = snd_ctl_add(chip->card, kctl = snd_ctl_new1(&snd_ymfpci_drec_source, chip))) < 0) - return err; + if (chip->device_id == PCI_DEVICE_ID_YAMAHA_754) { + kctl = snd_ctl_new1(&snd_ymfpci_drec_source, chip); + err = snd_ctl_add(chip->card, kctl); + if (err < 0) + return err; + } /* * shared rear/line-in */ if (rear_switch) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_rear_shared, chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_rear_shared, chip)); + if (err < 0) return err; } @@ -1847,7 +1869,8 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) kctl->id.device = chip->pcm->device; kctl->id.subdevice = idx; kctl->private_value = (unsigned long)substream; - if ((err = snd_ctl_add(chip->card, kctl)) < 0) + err = snd_ctl_add(chip->card, kctl); + if (err < 0) return err; chip->pcm_mixer[idx].left = 0x8000; chip->pcm_mixer[idx].right = 0x8000; @@ -1928,7 +1951,8 @@ int snd_ymfpci_timer(struct snd_ymfpci *chip, int device) tid.card = chip->card->number; tid.device = device; tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "YMFPCI", &tid, &timer)) >= 0) { + err = snd_timer_new(chip->card, "YMFPCI", &tid, &timer); + if (err >= 0) { strcpy(timer->name, "YMFPCI timer"); timer->private_data = chip; timer->hw = snd_ymfpci_timer_hw; @@ -2334,7 +2358,8 @@ int snd_ymfpci_create(struct snd_card *card, *rchip = NULL; /* enable PCI device */ - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); @@ -2357,7 +2382,8 @@ int snd_ymfpci_create(struct snd_card *card, pci_set_master(pci); chip->src441_used = -1; - if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { + chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI"); + if (!chip->res_reg_area) { dev_err(chip->card->dev, "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 144582350a05..8363ec08df5d 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -170,7 +170,8 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq if (err < 0) return err; - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) return err; return 0; diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c index 0f59e4cca56d..bc2114475810 100644 --- a/sound/pcmcia/vx/vxp_mixer.c +++ b/sound/pcmcia/vx/vxp_mixer.c @@ -124,11 +124,13 @@ int vxp_add_mic_controls(struct vx_core *_chip) /* mic level */ switch (_chip->type) { case VX_TYPE_VXPOCKET: - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip))) < 0) + err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_level, chip)); + if (err < 0) return err; break; case VX_TYPE_VXP440: - if ((err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip))) < 0) + err = snd_ctl_add(_chip->card, snd_ctl_new1(&vx_control_mic_boost, chip)); + if (err < 0) return err; break; } diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 45eeb0f57d59..4176abd73799 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -237,9 +237,11 @@ static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw switch (index) { case 0: /* xilinx boot */ - if ((err = vx_check_magic(vx)) < 0) + err = vx_check_magic(vx); + if (err < 0) return err; - if ((err = snd_vx_load_boot_image(vx, fw)) < 0) + err = snd_vx_load_boot_image(vx, fw); + if (err < 0) return err; return 0; case 1: diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 636320489805..0dfb6a943b60 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -183,7 +183,8 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq chip->irq = irq; card->sync_irq = chip->irq; - if ((err = snd_vx_setup_firmware(chip)) < 0) + err = snd_vx_setup_firmware(chip); + if (err < 0) return err; return 0; diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index 6bc586a5db0f..0f4bce1c0d4f 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c @@ -105,7 +105,10 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, } chip = input_get_drvdata(dev); - if (! chip || (beep = chip->beep) == NULL) + if (!chip) + return -1; + beep = chip->beep; + if (!beep) return -1; if (! hz) { diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 1eb698dafd93..4da9278dd58a 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -84,7 +84,8 @@ static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0; return 0; @@ -97,7 +98,8 @@ static int daca_put_deemphasis(struct snd_kcontrol *kcontrol, struct pmac_daca *mix; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; change = mix->deemphasis != ucontrol->value.integer.value[0]; if (change) { @@ -123,7 +125,8 @@ static int daca_get_volume(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->left_vol; ucontrol->value.integer.value[1] = mix->right_vol; @@ -138,7 +141,8 @@ static int daca_put_volume(struct snd_kcontrol *kcontrol, unsigned int vol[2]; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; vol[0] = ucontrol->value.integer.value[0]; vol[1] = ucontrol->value.integer.value[1]; @@ -162,7 +166,8 @@ static int daca_get_amp(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_daca *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0; return 0; @@ -175,7 +180,8 @@ static int daca_put_amp(struct snd_kcontrol *kcontrol, struct pmac_daca *mix; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; change = mix->amp_on != ucontrol->value.integer.value[0]; if (change) { @@ -248,7 +254,8 @@ int snd_pmac_daca_init(struct snd_pmac *chip) mix->i2c.addr = DACA_I2C_ADDR; mix->i2c.init_client = daca_init_client; mix->i2c.name = "DACA"; - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) + err = snd_pmac_keywest_init(&mix->i2c); + if (err < 0) return err; /* @@ -257,7 +264,8 @@ int snd_pmac_daca_init(struct snd_pmac *chip) strcpy(chip->card->mixername, "PowerMac DACA"); for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip)); + if (err < 0) return err; } diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index a8915100d6bb..6e5daae18f9d 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -114,7 +114,8 @@ int snd_pmac_tumbler_post_init(void) if (!keywest_ctx || !keywest_ctx->client) return -ENXIO; - if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) { + err = keywest_ctx->init_client(keywest_ctx); + if (err < 0) { snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); return err; } @@ -136,7 +137,8 @@ int snd_pmac_keywest_init(struct pmac_keywest *i2c) keywest_ctx = i2c; - if ((err = i2c_add_driver(&keywest_driver))) { + err = i2c_add_driver(&keywest_driver); + if (err) { snd_printk(KERN_ERR "cannot register keywest i2c driver\n"); i2c_put_adapter(adap); return err; diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 2e750b317be1..84058bbf9d12 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -1160,7 +1160,8 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->playback.stream = SNDRV_PCM_STREAM_PLAYBACK; chip->capture.stream = SNDRV_PCM_STREAM_CAPTURE; - if ((err = snd_pmac_detect(chip)) < 0) + err = snd_pmac_detect(chip); + if (err < 0) goto __error; if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || @@ -1299,7 +1300,8 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) /* Reset dbdma channels */ snd_pmac_dbdma_reset(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); + if (err < 0) goto __error; *chip_return = chip; diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 9fb51ebafde1..db414b61157e 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -48,7 +48,8 @@ static int snd_pmac_probe(struct platform_device *devptr) if (err < 0) return err; - if ((err = snd_pmac_new(card, &chip)) < 0) + err = snd_pmac_new(card, &chip); + if (err < 0) goto __error; card->private_data = chip; @@ -58,7 +59,8 @@ static int snd_pmac_probe(struct platform_device *devptr) strcpy(card->shortname, "PowerMac Burgundy"); sprintf(card->longname, "%s (Dev %d) Sub-frame %d", card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_burgundy_init(chip)) < 0) + err = snd_pmac_burgundy_init(chip); + if (err < 0) goto __error; break; case PMAC_DACA: @@ -66,7 +68,8 @@ static int snd_pmac_probe(struct platform_device *devptr) strcpy(card->shortname, "PowerMac DACA"); sprintf(card->longname, "%s (Dev %d) Sub-frame %d", card->shortname, chip->device_id, chip->subframe); - if ((err = snd_pmac_daca_init(chip)) < 0) + err = snd_pmac_daca_init(chip); + if (err < 0) goto __error; break; case PMAC_TUMBLER: @@ -76,7 +79,11 @@ static int snd_pmac_probe(struct platform_device *devptr) sprintf(card->shortname, "PowerMac %s", name_ext); sprintf(card->longname, "%s (Dev %d) Sub-frame %d", card->shortname, chip->device_id, chip->subframe); - if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) + err = snd_pmac_tumbler_init(chip); + if (err < 0) + goto __error; + err = snd_pmac_tumbler_post_init(); + if (err < 0) goto __error; break; case PMAC_AWACS: @@ -92,7 +99,8 @@ static int snd_pmac_probe(struct platform_device *devptr) name_ext = ""; sprintf(card->longname, "%s%s Rev %d", card->shortname, name_ext, chip->revision); - if ((err = snd_pmac_awacs_init(chip)) < 0) + err = snd_pmac_awacs_init(chip); + if (err < 0) goto __error; break; default: @@ -101,14 +109,16 @@ static int snd_pmac_probe(struct platform_device *devptr) goto __error; } - if ((err = snd_pmac_pcm_new(chip)) < 0) + err = snd_pmac_pcm_new(chip); + if (err < 0) goto __error; chip->initialized = 1; if (enable_beep) snd_pmac_attach_beep(chip); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto __error; platform_set_drvdata(devptr, card); @@ -162,7 +172,8 @@ static int __init alsa_card_pmac_init(void) { int err; - if ((err = platform_driver_register(&snd_pmac_driver)) < 0) + err = platform_driver_register(&snd_pmac_driver); + if (err < 0) return err; device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); return 0; diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 6e5bdaa262b0..c65e74d7cd0a 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -402,7 +402,8 @@ static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->drc_range; return 0; @@ -416,7 +417,8 @@ static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol, unsigned int val; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; val = ucontrol->value.integer.value[0]; if (chip->model == PMAC_TUMBLER) { @@ -442,7 +444,8 @@ static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol, { struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->drc_enable; return 0; @@ -455,7 +458,8 @@ static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol, struct pmac_tumbler *mix; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; change = mix->drc_enable != ucontrol->value.integer.value[0]; if (change) { @@ -524,7 +528,8 @@ static int tumbler_get_mono(struct snd_kcontrol *kcontrol, struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value; struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->mono_vol[info->index]; return 0; @@ -539,7 +544,8 @@ static int tumbler_put_mono(struct snd_kcontrol *kcontrol, unsigned int vol; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; vol = ucontrol->value.integer.value[0]; if (vol >= info->max) @@ -669,7 +675,8 @@ static int snapper_get_mix(struct snd_kcontrol *kcontrol, int idx = (int)kcontrol->private_value; struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; ucontrol->value.integer.value[0] = mix->mix_vol[idx][0]; ucontrol->value.integer.value[1] = mix->mix_vol[idx][1]; @@ -685,7 +692,8 @@ static int snapper_put_mix(struct snd_kcontrol *kcontrol, unsigned int vol[2]; int change; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; vol[0] = ucontrol->value.integer.value[0]; vol[1] = ucontrol->value.integer.value[1]; @@ -716,7 +724,8 @@ static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol, struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); struct pmac_tumbler *mix; struct pmac_gpio *gp; - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; switch(kcontrol->private_value) { case TUMBLER_MUTE_HP: @@ -745,7 +754,8 @@ static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol, if (chip->update_automute && chip->auto_mute) return 0; /* don't touch in the auto-mute mode */ #endif - if (! (mix = chip->mixer_data)) + mix = chip->mixer_data; + if (!mix) return -ENODEV; switch(kcontrol->private_value) { case TUMBLER_MUTE_HP: @@ -1361,7 +1371,8 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) break; } } - if ((err = tumbler_init(chip)) < 0) + err = tumbler_init(chip); + if (err < 0) return err; /* set up TAS */ @@ -1392,7 +1403,8 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) chipname = "Snapper"; } - if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) + err = snd_pmac_keywest_init(&mix->i2c); + if (err < 0) return err; /* @@ -1402,28 +1414,34 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) if (chip->model == PMAC_TUMBLER) { for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip)); + if (err < 0) return err; } } else { for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) { - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0) + err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip)); + if (err < 0) return err; } } chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) + err = snd_ctl_add(chip->card, chip->master_sw_ctl); + if (err < 0) return err; chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) + err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); + if (err < 0) return err; if (mix->line_mute.addr != 0) { chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) + err = snd_ctl_add(chip->card, chip->lineout_sw_ctl); + if (err < 0) return err; } chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); - if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) + err = snd_ctl_add(chip->card, chip->drc_sw_ctl); + if (err < 0) return err; /* set initial DRC range to 60% */ @@ -1446,9 +1464,11 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) device_change_chip = chip; #ifdef PMAC_SUPPORT_AUTOMUTE - if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) - && (err = snd_pmac_add_automute(chip)) < 0) - return err; + if (mix->headphone_irq >= 0 || mix->lineout_irq >= 0) { + err = snd_pmac_add_automute(chip); + if (err < 0) + return err; + } chip->detect_headphone = tumbler_detect_headphone; chip->update_automute = tumbler_update_automute; tumbler_update_automute(chip, 0); /* update the status only */ @@ -1456,8 +1476,9 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) /* activate headphone status interrupts */ if (mix->headphone_irq >= 0) { unsigned char val; - if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, - "Sound Headphone Detection", chip)) < 0) + err = request_irq(mix->headphone_irq, headphone_intr, 0, + "Sound Headphone Detection", chip); + if (err < 0) return 0; /* activate headphone status interrupts */ val = do_gpio_read(&mix->hp_detect); @@ -1465,8 +1486,9 @@ int snd_pmac_tumbler_init(struct snd_pmac *chip) } if (mix->lineout_irq >= 0) { unsigned char val; - if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, - "Sound Lineout Detection", chip)) < 0) + err = request_irq(mix->lineout_irq, headphone_intr, 0, + "Sound Lineout Detection", chip); + if (err < 0) return 0; /* activate headphone status interrupts */ val = do_gpio_read(&mix->line_detect); diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index ba5a85bf7412..49ff5e73e9ba 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -52,3 +52,12 @@ config SND_SOC_AMD_RENOIR_MACH depends on SND_SOC_AMD_RENOIR help This option enables machine driver for DMIC + +config SND_SOC_AMD_ACP5x + tristate "AMD Audio Coprocessor-v5.x I2S support" + depends on X86 && PCI + help + This option enables ACP v5.x support on AMD platform + + By enabling this flag build will trigger for ACP PCI driver, + ACP DMA driver, CPU DAI driver. diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index e6df2f72a2a1..07150d26f315 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/ obj-$(CONFIG_SND_SOC_AMD_RV_RT5682_MACH) += snd-soc-acp-rt5682-mach.o obj-$(CONFIG_SND_SOC_AMD_RENOIR) += renoir/ +obj-$(CONFIG_SND_SOC_AMD_ACP5x) += vangogh/ diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 3c60c5f96dcb..b3df98a9f9f3 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -756,15 +756,9 @@ static int cz_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, machine); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "devm_snd_soc_register_card(%s) failed: %d\n", - card->name, ret); - else - dev_dbg(&pdev->dev, - "devm_snd_soc_register_card(%s) probe deferred: %d\n", - card->name, ret); - return ret; + return dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card(%s) failed\n", + card->name); } bt_uart_enable = !device_property_read_bool(&pdev->dev, "bt-pad-enable"); diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index cc1ce6f22caa..11b3c4f39eba 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -156,7 +156,7 @@ static void config_acp_dma_channel(void __iomem *acp_mmio, u8 ch_num, acp_reg_write(priority_level, acp_mmio, mmACP_DMA_PRIO_0 + ch_num); } -/* Initialize a dma descriptor in SRAM based on descritor information passed */ +/* Initialize a dma descriptor in SRAM based on descriptor information passed */ static void config_dma_descriptor_in_sram(void __iomem *acp_mmio, u16 descr_idx, acp_dma_dscr_transfer_t *descr_info) @@ -288,7 +288,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem *acp_mmio, u32 size, &dmadscr[i]); } pre_config_reset(acp_mmio, ch); - /* Configure the DMA channel with the above descriptore */ + /* Configure the DMA channel with the above descriptor */ config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1, NUM_DSCRS_PER_CHANNEL, ACP_DMA_PRIORITY_LEVEL_NORMAL); @@ -322,7 +322,7 @@ static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr, high |= BIT(31); acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data); - /* Move to next physically contiguos page */ + /* Move to next physically contiguous page */ addr += PAGE_SIZE; } } @@ -602,11 +602,11 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type) acp_reg_write(val, acp_mmio, mmACP_BT_UART_PAD_SEL); } - /* initiailize Onion control DAGB register */ + /* initialize Onion control DAGB register */ acp_reg_write(ACP_ONION_CNTL_DEFAULT, acp_mmio, mmACP_AXI2DAGB_ONION_CNTL); - /* initiailize Garlic control DAGB registers */ + /* initialize Garlic control DAGB registers */ acp_reg_write(ACP_GARLIC_CNTL_DEFAULT, acp_mmio, mmACP_AXI2DAGB_GARLIC_CNTL); @@ -621,7 +621,7 @@ static int acp_init(void __iomem *acp_mmio, u32 asic_type) acp_reg_write(ACP_SRAM_BASE_ADDRESS, acp_mmio, mmACP_DMA_DESC_BASE_ADDR); - /* Num of descriptiors in SRAM 0x4, means 256 descriptors;(64 * 4) */ + /* Num of descriptors in SRAM 0x4, means 256 descriptors;(64 * 4) */ acp_reg_write(0x4, acp_mmio, mmACP_DMA_DESC_MAX_NUM_DSCR); acp_reg_write(ACP_EXTERNAL_INTR_CNTL__DMAIOCMask_MASK, acp_mmio, mmACP_EXTERNAL_INTR_CNTL); @@ -1035,13 +1035,6 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, return bytes_to_frames(runtime, pos); } -static int acp_dma_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return snd_pcm_lib_default_mmap(substream, vma); -} - static int acp_dma_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -1205,7 +1198,6 @@ static const struct snd_soc_component_driver acp_asoc_platform = { .hw_params = acp_dma_hw_params, .trigger = acp_dma_trigger, .pointer = acp_dma_pointer, - .mmap = acp_dma_mmap, .prepare = acp_dma_prepare, .pcm_construct = acp_dma_new, }; diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index d9980aba2910..e561464f7d60 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -512,17 +512,11 @@ static int acp3x_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "devm_snd_soc_register_card(%s) failed: %d\n", - card->name, ret); - else - dev_dbg(&pdev->dev, - "devm_snd_soc_register_card(%s) probe deferred: %d\n", - card->name, ret); + return dev_err_probe(&pdev->dev, ret, + "devm_snd_soc_register_card(%s) failed\n", + card->name); } - - return ret; + return 0; } static const struct acpi_device_id acp3x_audio_acpi_match[] = { diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 597d7c4b2a6b..75c06697fa09 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -147,7 +147,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) high |= BIT(31); rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val + 4); - /* Move to next physically contiguos page */ + /* Move to next physically contiguous page */ val += 8; addr += PAGE_SIZE; } @@ -320,13 +320,6 @@ static int acp3x_dma_new(struct snd_soc_component *component, return 0; } -static int acp3x_dma_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return snd_pcm_lib_default_mmap(substream, vma); -} - static int acp3x_dma_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -370,7 +363,6 @@ static const struct snd_soc_component_driver acp3x_i2s_component = { .close = acp3x_dma_close, .hw_params = acp3x_dma_hw_params, .pointer = acp3x_dma_pointer, - .mmap = acp3x_dma_mmap, .pcm_construct = acp3x_dma_new, }; diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 0391c28dd078..9dd22a2fa2e5 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -291,13 +291,6 @@ static int acp_pdm_dma_new(struct snd_soc_component *component, return 0; } -static int acp_pdm_dma_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - return snd_pcm_lib_default_mmap(substream, vma); -} - static int acp_pdm_dma_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -375,7 +368,6 @@ static const struct snd_soc_component_driver acp_pdm_component = { .close = acp_pdm_dma_close, .hw_params = acp_pdm_dma_hw_params, .pointer = acp_pdm_dma_pointer, - .mmap = acp_pdm_dma_mmap, .pcm_construct = acp_pdm_dma_new, }; diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c index 306134b89a82..5d979a7b77fb 100644 --- a/sound/soc/amd/renoir/acp3x-rn.c +++ b/sound/soc/amd/renoir/acp3x-rn.c @@ -54,10 +54,9 @@ static int acp_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, machine); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - dev_err(&pdev->dev, - "snd_soc_register_card(%s) failed: %d\n", - acp_card.name, ret); - return ret; + return dev_err_probe(&pdev->dev, ret, + "snd_soc_register_card(%s) failed\n", + card->name); } return 0; } diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile new file mode 100644 index 000000000000..3353f93dc610 --- /dev/null +++ b/sound/soc/amd/vangogh/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Vangogh platform Support +snd-pci-acp5x-objs := pci-acp5x.o +snd-acp5x-i2s-objs := acp5x-i2s.o +snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o + +obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o +obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-i2s.o +obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-pcm-dma.o diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c new file mode 100644 index 000000000000..2705e57eb713 --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x-i2s.c @@ -0,0 +1,427 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dai.h> +#include <linux/dma-mapping.h> + +#include "acp5x.h" + +#define DRV_NAME "acp5x_i2s_playcap" + +static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct i2s_dev_data *adata; + int mode; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + switch (mode) { + case SND_SOC_DAIFMT_I2S: + adata->tdm_mode = TDM_DISABLE; + break; + case SND_SOC_DAIFMT_DSP_A: + adata->tdm_mode = TDM_ENABLE; + break; + default: + return -EINVAL; + } + mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; + switch (mode) { + case SND_SOC_DAIFMT_CBC_CFC: + adata->master_mode = I2S_MASTER_MODE_ENABLE; + break; + case SND_SOC_DAIFMT_CBP_CFP: + adata->master_mode = I2S_MASTER_MODE_DISABLE; + break; + } + return 0; +} + +static int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, + u32 tx_mask, u32 rx_mask, + int slots, int slot_width) +{ + struct i2s_dev_data *adata; + u32 frm_len; + u16 slot_len; + + adata = snd_soc_dai_get_drvdata(cpu_dai); + + /* These values are as per Hardware Spec */ + switch (slot_width) { + case SLOT_WIDTH_8: + slot_len = 8; + break; + case SLOT_WIDTH_16: + slot_len = 16; + break; + case SLOT_WIDTH_24: + slot_len = 24; + break; + case SLOT_WIDTH_32: + slot_len = 0; + break; + default: + return -EINVAL; + } + frm_len = FRM_LEN | (slots << 15) | (slot_len << 18); + adata->tdm_fmt = frm_len; + return 0; +} + +static int acp5x_i2s_hwparams(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp5x_platform_info *pinfo; + struct i2s_dev_data *adata; + union acp_i2stdm_mstrclkgen mclkgen; + + u32 val; + u32 reg_val, frmt_reg, master_reg; + u32 lrclk_div_val, bclk_div_val; + + lrclk_div_val = 0; + bclk_div_val = 0; + prtd = asoc_substream_to_rtd(substream); + rtd = substream->runtime->private_data; + card = prtd->card; + adata = snd_soc_dai_get_drvdata(dai); + pinfo = snd_soc_card_get_drvdata(card); + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rtd->i2s_instance = pinfo->play_i2s_instance; + else + rtd->i2s_instance = pinfo->cap_i2s_instance; + } + + /* These values are as per Hardware Spec */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: + rtd->xfer_resolution = 0x0; + break; + case SNDRV_PCM_FORMAT_S16_LE: + rtd->xfer_resolution = 0x02; + break; + case SNDRV_PCM_FORMAT_S24_LE: + rtd->xfer_resolution = 0x04; + break; + case SNDRV_PCM_FORMAT_S32_LE: + rtd->xfer_resolution = 0x05; + break; + default: + return -EINVAL; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + frmt_reg = ACP_HSTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_ITER; + frmt_reg = ACP_I2STDM_TXFRMT; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + frmt_reg = ACP_HSTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_IRER; + frmt_reg = ACP_I2STDM_RXFRMT; + } + } + if (adata->tdm_mode) { + val = acp_readl(rtd->acp5x_base + reg_val); + acp_writel(val | 0x2, rtd->acp5x_base + reg_val); + acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg); + } + val = acp_readl(rtd->acp5x_base + reg_val); + val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK; + val = val | (rtd->xfer_resolution << 3); + acp_writel(val, rtd->acp5x_base + reg_val); + + if (adata->master_mode) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + master_reg = ACP_I2STDM2_MSTRCLKGEN; + break; + case I2S_SP_INSTANCE: + default: + master_reg = ACP_I2STDM0_MSTRCLKGEN; + break; + } + mclkgen.bits.i2stdm_master_mode = 0x1; + if (adata->tdm_mode) + mclkgen.bits.i2stdm_format_mode = 0x01; + else + mclkgen.bits.i2stdm_format_mode = 0x0; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 768; + break; + case 16000: + bclk_div_val = 384; + break; + case 24000: + bclk_div_val = 256; + break; + case 32000: + bclk_div_val = 192; + break; + case 44100: + case 48000: + bclk_div_val = 128; + break; + case 88200: + case 96000: + bclk_div_val = 64; + break; + case 192000: + bclk_div_val = 32; + break; + default: + return -EINVAL; + } + lrclk_div_val = 32; + break; + case SNDRV_PCM_FORMAT_S32_LE: + switch (params_rate(params)) { + case 8000: + bclk_div_val = 384; + break; + case 16000: + bclk_div_val = 192; + break; + case 24000: + bclk_div_val = 128; + break; + case 32000: + bclk_div_val = 96; + break; + case 44100: + case 48000: + bclk_div_val = 64; + break; + case 88200: + case 96000: + bclk_div_val = 32; + break; + case 192000: + bclk_div_val = 16; + break; + default: + return -EINVAL; + } + lrclk_div_val = 64; + break; + default: + return -EINVAL; + } + mclkgen.bits.i2stdm_bclk_div_val = bclk_div_val; + mclkgen.bits.i2stdm_lrclk_div_val = lrclk_div_val; + acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg); + } + return 0; +} + +static int acp5x_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct i2s_stream_instance *rtd; + u32 ret, val, period_bytes, reg_val, ier_val, water_val; + u32 buf_size, buf_reg; + + rtd = substream->runtime->private_data; + period_bytes = frames_to_bytes(substream->runtime, + substream->runtime->period_size); + buf_size = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + rtd->bytescount = acp_get_byte_count(rtd, + substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + water_val = + ACP_HS_TX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_ITER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_TX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + ACP_I2S_TX_INTR_WATERMARK_SIZE; + reg_val = ACP_I2STDM_ITER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_TX_RINGBUFSIZE; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + water_val = + ACP_HS_RX_INTR_WATERMARK_SIZE; + reg_val = ACP_HSTDM_IRER; + ier_val = ACP_HSTDM_IER; + buf_reg = ACP_HS_RX_RINGBUFSIZE; + break; + case I2S_SP_INSTANCE: + default: + water_val = + ACP_I2S_RX_INTR_WATERMARK_SIZE; + reg_val = ACP_I2STDM_IRER; + ier_val = ACP_I2STDM_IER; + buf_reg = ACP_I2S_RX_RINGBUFSIZE; + } + } + acp_writel(period_bytes, rtd->acp5x_base + water_val); + acp_writel(buf_size, rtd->acp5x_base + buf_reg); + val = acp_readl(rtd->acp5x_base + reg_val); + val = val | BIT(0); + acp_writel(val, rtd->acp5x_base + reg_val); + acp_writel(1, rtd->acp5x_base + ier_val); + ret = 0; + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_ITER; + } + + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_IRER; + } + } + val = acp_readl(rtd->acp5x_base + reg_val); + val = val & ~BIT(0); + acp_writel(val, rtd->acp5x_base + reg_val); + + if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) && + !(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0))) + acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER); + if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) && + !(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0))) + acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER); + ret = 0; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static struct snd_soc_dai_ops acp5x_i2s_dai_ops = { + .hw_params = acp5x_i2s_hwparams, + .trigger = acp5x_i2s_trigger, + .set_fmt = acp5x_i2s_set_fmt, + .set_tdm_slot = acp5x_i2s_set_tdm_slot, +}; + +static const struct snd_soc_component_driver acp5x_dai_component = { + .name = "acp5x-i2s", +}; + +static struct snd_soc_dai_driver acp5x_i2s_dai = { + .playback = { + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 96000, + }, + .capture = { + .rates = SNDRV_PCM_RATE_8000_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 96000, + }, + .ops = &acp5x_i2s_dai_ops, +}; + +static int acp5x_dai_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + int ret; + + adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data), + GFP_KERNEL); + if (!adata) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENOMEM; + } + adata->acp5x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp5x_base) + return -ENOMEM; + + adata->master_mode = I2S_MASTER_MODE_ENABLE; + dev_set_drvdata(&pdev->dev, adata); + ret = devm_snd_soc_register_component(&pdev->dev, + &acp5x_dai_component, + &acp5x_i2s_dai, 1); + if (ret) + dev_err(&pdev->dev, "Fail to register acp i2s dai\n"); + return ret; +} + +static struct platform_driver acp5x_dai_driver = { + .probe = acp5x_dai_probe, + .driver = { + .name = "acp5x_i2s_playcap", + }, +}; + +module_platform_driver(acp5x_dai_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver"); +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/vangogh/acp5x-pcm-dma.c b/sound/soc/amd/vangogh/acp5x-pcm-dma.c new file mode 100644 index 000000000000..f10de38976cb --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x-pcm-dma.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD ALSA SoC PCM Driver +// +// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/pm_runtime.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-dai.h> + +#include "acp5x.h" + +#define DRV_NAME "acp5x_i2s_dma" + +static const struct snd_pcm_hardware acp5x_pcm_hardware_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE, + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = PLAYBACK_MIN_NUM_PERIODS, + .periods_max = PLAYBACK_MAX_NUM_PERIODS, +}; + +static const struct snd_pcm_hardware acp5x_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 96000, + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, +}; + +static irqreturn_t i2s_irq_handler(int irq, void *dev_id) +{ + struct i2s_dev_data *vg_i2s_data; + u16 irq_flag; + u32 val; + + vg_i2s_data = dev_id; + if (!vg_i2s_data) + return IRQ_NONE; + + irq_flag = 0; + val = acp_readl(vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + if ((val & BIT(HS_TX_THRESHOLD)) && vg_i2s_data->play_stream) { + acp_writel(BIT(HS_TX_THRESHOLD), vg_i2s_data->acp5x_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->play_stream); + irq_flag = 1; + } + if ((val & BIT(I2S_TX_THRESHOLD)) && vg_i2s_data->i2ssp_play_stream) { + acp_writel(BIT(I2S_TX_THRESHOLD), + vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->i2ssp_play_stream); + irq_flag = 1; + } + + if ((val & BIT(HS_RX_THRESHOLD)) && vg_i2s_data->capture_stream) { + acp_writel(BIT(HS_RX_THRESHOLD), vg_i2s_data->acp5x_base + + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->capture_stream); + irq_flag = 1; + } + if ((val & BIT(I2S_RX_THRESHOLD)) && vg_i2s_data->i2ssp_capture_stream) { + acp_writel(BIT(I2S_RX_THRESHOLD), + vg_i2s_data->acp5x_base + ACP_EXTERNAL_INTR_STAT); + snd_pcm_period_elapsed(vg_i2s_data->i2ssp_capture_stream); + irq_flag = 1; + } + + if (irq_flag) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static void config_acp5x_dma(struct i2s_stream_instance *rtd, int direction) +{ + u16 page_idx; + u32 low, high, val, acp_fifo_addr, reg_fifo_addr; + u32 reg_dma_size, reg_fifo_size; + dma_addr_t addr; + + addr = rtd->dma_addr; + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + val = ACP_SRAM_HS_PB_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_PB_PTE_OFFSET; + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + val = ACP_SRAM_HS_CP_PTE_OFFSET; + break; + case I2S_SP_INSTANCE: + default: + val = ACP_SRAM_SP_CP_PTE_OFFSET; + } + } + /* Group Enable */ + acp_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp5x_base + + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); + acp_writel(PAGE_SIZE_4K_ENABLE, rtd->acp5x_base + + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); + + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { + /* Load the low address of page int ACP SRAM through SRBM */ + low = lower_32_bits(addr); + high = upper_32_bits(addr); + + acp_writel(low, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val); + high |= BIT(31); + acp_writel(high, rtd->acp5x_base + ACP_SCRATCH_REG_0 + val + 4); + /* Move to next physically contiguous page */ + val += 8; + addr += PAGE_SIZE; + } + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_dma_size = ACP_HS_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + HS_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_TX_FIFOADDR; + reg_fifo_size = ACP_HS_TX_FIFOSIZE; + acp_writel(I2S_HS_TX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_HS_TX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = ACP_I2S_TX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_PB_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR; + reg_fifo_size = ACP_I2S_TX_FIFOSIZE; + acp_writel(I2S_SP_TX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_I2S_TX_RINGBUFADDR); + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_dma_size = ACP_HS_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + HS_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_HS_RX_FIFOADDR; + reg_fifo_size = ACP_HS_RX_FIFOSIZE; + acp_writel(I2S_HS_RX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_HS_RX_RINGBUFADDR); + break; + + case I2S_SP_INSTANCE: + default: + reg_dma_size = ACP_I2S_RX_DMA_SIZE; + acp_fifo_addr = ACP_SRAM_PTE_OFFSET + + SP_CAPT_FIFO_ADDR_OFFSET; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR; + reg_fifo_size = ACP_I2S_RX_FIFOSIZE; + acp_writel(I2S_SP_RX_MEM_WINDOW_START, + rtd->acp5x_base + ACP_I2S_RX_RINGBUFADDR); + } + } + acp_writel(DMA_SIZE, rtd->acp5x_base + reg_dma_size); + acp_writel(acp_fifo_addr, rtd->acp5x_base + reg_fifo_addr); + acp_writel(FIFO_SIZE, rtd->acp5x_base + reg_fifo_size); + acp_writel(BIT(I2S_RX_THRESHOLD) | BIT(HS_RX_THRESHOLD) + | BIT(I2S_TX_THRESHOLD) | BIT(HS_TX_THRESHOLD), + rtd->acp5x_base + ACP_EXTERNAL_INTR_CNTL); +} + +static int acp5x_dma_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *i2s_data; + int ret; + + runtime = substream->runtime; + prtd = asoc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + + i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL); + if (!i2s_data) + return -ENOMEM; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp5x_pcm_hardware_playback; + else + runtime->hw = acp5x_pcm_hardware_capture; + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(component->dev, "set integer constraint failed\n"); + kfree(i2s_data); + return ret; + } + i2s_data->acp5x_base = adata->acp5x_base; + runtime->private_data = i2s_data; + return ret; +} + +static int acp5x_dma_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct i2s_stream_instance *rtd; + struct snd_soc_pcm_runtime *prtd; + struct snd_soc_card *card; + struct acp5x_platform_info *pinfo; + struct i2s_dev_data *adata; + u64 size; + + prtd = asoc_substream_to_rtd(substream); + card = prtd->card; + pinfo = snd_soc_card_get_drvdata(card); + adata = dev_get_drvdata(component->dev); + rtd = substream->runtime->private_data; + + if (!rtd) + return -EINVAL; + + if (pinfo) { + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + rtd->i2s_instance = pinfo->play_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + adata->play_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = substream; + } + } else { + rtd->i2s_instance = pinfo->cap_i2s_instance; + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + adata->capture_stream = substream; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = substream; + } + } + } else { + dev_err(component->dev, "pinfo failed\n"); + return -EINVAL; + } + size = params_buffer_bytes(params); + rtd->dma_addr = substream->dma_buffer.addr; + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); + config_acp5x_dma(rtd, substream->stream); + return 0; +} + +static snd_pcm_uframes_t acp5x_dma_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct i2s_stream_instance *rtd; + u32 pos; + u32 buffersize; + u64 bytescount; + + rtd = substream->runtime->private_data; + buffersize = frames_to_bytes(substream->runtime, + substream->runtime->buffer_size); + bytescount = acp_get_byte_count(rtd, substream->stream); + if (bytescount > rtd->bytescount) + bytescount -= rtd->bytescount; + pos = do_div(bytescount, buffersize); + return bytes_to_frames(substream->runtime, pos); +} + +static int acp5x_dma_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct device *parent = component->dev->parent; + + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + parent, MIN_BUFFER, MAX_BUFFER); + return 0; +} + +static int acp5x_dma_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *prtd; + struct i2s_dev_data *adata; + struct i2s_stream_instance *ins; + + prtd = asoc_substream_to_rtd(substream); + component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); + adata = dev_get_drvdata(component->dev); + ins = substream->runtime->private_data; + if (!ins) + return -EINVAL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (ins->i2s_instance) { + case I2S_HS_INSTANCE: + adata->play_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = NULL; + } + } else { + switch (ins->i2s_instance) { + case I2S_HS_INSTANCE: + adata->capture_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = NULL; + } + } + kfree(ins); + return 0; +} + +static const struct snd_soc_component_driver acp5x_i2s_component = { + .name = DRV_NAME, + .open = acp5x_dma_open, + .close = acp5x_dma_close, + .hw_params = acp5x_dma_hw_params, + .pointer = acp5x_dma_pointer, + .pcm_construct = acp5x_dma_new, +}; + +static int acp5x_audio_probe(struct platform_device *pdev) +{ + struct resource *res; + struct i2s_dev_data *adata; + unsigned int irqflags; + int status; + + if (!pdev->dev.platform_data) { + dev_err(&pdev->dev, "platform_data not retrieved\n"); + return -ENODEV; + } + irqflags = *((unsigned int *)(pdev->dev.platform_data)); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); + return -ENODEV; + } + + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); + if (!adata) + return -ENOMEM; + + adata->acp5x_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!adata->acp5x_base) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); + return -ENODEV; + } + + adata->i2s_irq = res->start; + dev_set_drvdata(&pdev->dev, adata); + status = devm_snd_soc_register_component(&pdev->dev, + &acp5x_i2s_component, + NULL, 0); + if (status) { + dev_err(&pdev->dev, "Fail to register acp i2s component\n"); + return status; + } + status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler, + irqflags, "ACP5x_I2S_IRQ", adata); + if (status) { + dev_err(&pdev->dev, "ACP5x I2S IRQ request failed\n"); + return status; + } + pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_allow(&pdev->dev); + + return 0; +} + +static int acp5x_audio_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + return 0; +} + +static int __maybe_unused acp5x_pcm_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + u32 val, reg_val, frmt_val; + + reg_val = 0; + frmt_val = 0; + adata = dev_get_drvdata(dev); + + if (adata->play_stream && adata->play_stream->runtime) { + struct i2s_stream_instance *rtd = + adata->play_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK); + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_ITER; + frmt_val = ACP_HSTDM_TXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_ITER; + frmt_val = ACP_I2STDM_TXFRMT; + } + acp_writel((rtd->xfer_resolution << 3), + rtd->acp5x_base + reg_val); + } + + if (adata->capture_stream && adata->capture_stream->runtime) { + struct i2s_stream_instance *rtd = + adata->capture_stream->runtime->private_data; + config_acp5x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + reg_val = ACP_HSTDM_IRER; + frmt_val = ACP_HSTDM_RXFRMT; + break; + case I2S_SP_INSTANCE: + default: + reg_val = ACP_I2STDM_IRER; + frmt_val = ACP_I2STDM_RXFRMT; + } + acp_writel((rtd->xfer_resolution << 3), + rtd->acp5x_base + reg_val); + } + if (adata->tdm_mode == TDM_ENABLE) { + acp_writel(adata->tdm_fmt, adata->acp5x_base + frmt_val); + val = acp_readl(adata->acp5x_base + reg_val); + acp_writel(val | 0x2, adata->acp5x_base + reg_val); + } + acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int __maybe_unused acp5x_pcm_suspend(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp_writel(0, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static int __maybe_unused acp5x_pcm_runtime_resume(struct device *dev) +{ + struct i2s_dev_data *adata; + + adata = dev_get_drvdata(dev); + acp_writel(1, adata->acp5x_base + ACP_EXTERNAL_INTR_ENB); + return 0; +} + +static const struct dev_pm_ops acp5x_pm_ops = { + SET_RUNTIME_PM_OPS(acp5x_pcm_suspend, + acp5x_pcm_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(acp5x_pcm_suspend, acp5x_pcm_resume) +}; + +static struct platform_driver acp5x_dma_driver = { + .probe = acp5x_audio_probe, + .remove = acp5x_audio_remove, + .driver = { + .name = "acp5x_i2s_dma", + .pm = &acp5x_pm_ops, + }, +}; + +module_platform_driver(acp5x_dma_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP 5.x PCM Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/amd/vangogh/acp5x.h b/sound/soc/amd/vangogh/acp5x.h new file mode 100644 index 000000000000..a808635f9740 --- /dev/null +++ b/sound/soc/amd/vangogh/acp5x.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ALSA SoC PCM Driver + * + * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include "vg_chip_offset_byte.h" +#include <sound/pcm.h> + +#define ACP5x_PHY_BASE_ADDRESS 0x1240000 +#define ACP_DEVICE_ID 0x15E2 +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 + +#define ACP_ERR_INTR_MASK 0x20000000 +#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF + +#define ACP5x_DEVS 3 +#define ACP5x_REG_START 0x1240000 +#define ACP5x_REG_END 0x1250200 +#define ACP5x_I2STDM_REG_START 0x1242400 +#define ACP5x_I2STDM_REG_END 0x1242410 +#define ACP5x_HS_TDM_REG_START 0x1242814 +#define ACP5x_HS_TDM_REG_END 0x1242824 +#define I2S_MODE 0 +#define ACP5x_I2S_MODE 1 +#define ACP5x_RES 4 +#define I2S_RX_THRESHOLD 27 +#define I2S_TX_THRESHOLD 28 +#define HS_TX_THRESHOLD 24 +#define HS_RX_THRESHOLD 23 + +#define I2S_SP_INSTANCE 1 +#define I2S_HS_INSTANCE 2 + +#define ACP_SRAM_PTE_OFFSET 0x02050000 +#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 +#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 +#define ACP_SRAM_HS_PB_PTE_OFFSET 0x200 +#define ACP_SRAM_HS_CP_PTE_OFFSET 0x300 +#define PAGE_SIZE_4K_ENABLE 0x2 +#define I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define I2S_SP_RX_MEM_WINDOW_START 0x4020000 +#define I2S_HS_TX_MEM_WINDOW_START 0x4040000 +#define I2S_HS_RX_MEM_WINDOW_START 0x4060000 + +#define SP_PB_FIFO_ADDR_OFFSET 0x500 +#define SP_CAPT_FIFO_ADDR_OFFSET 0x700 +#define HS_PB_FIFO_ADDR_OFFSET 0x900 +#define HS_CAPT_FIFO_ADDR_OFFSET 0xB00 +#define PLAYBACK_MIN_NUM_PERIODS 2 +#define PLAYBACK_MAX_NUM_PERIODS 8 +#define PLAYBACK_MAX_PERIOD_SIZE 8192 +#define PLAYBACK_MIN_PERIOD_SIZE 1024 +#define CAPTURE_MIN_NUM_PERIODS 2 +#define CAPTURE_MAX_NUM_PERIODS 8 +#define CAPTURE_MAX_PERIOD_SIZE 8192 +#define CAPTURE_MIN_PERIOD_SIZE 1024 + +#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) +#define MIN_BUFFER MAX_BUFFER +#define FIFO_SIZE 0x100 +#define DMA_SIZE 0x40 +#define FRM_LEN 0x100 + +#define I2S_MASTER_MODE_ENABLE 1 +#define I2S_MASTER_MODE_DISABLE 0 + +#define SLOT_WIDTH_8 8 +#define SLOT_WIDTH_16 16 +#define SLOT_WIDTH_24 24 +#define SLOT_WIDTH_32 32 +#define TDM_ENABLE 1 +#define TDM_DISABLE 0 +#define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38 + +struct i2s_dev_data { + bool tdm_mode; + bool master_mode; + unsigned int i2s_irq; + u16 i2s_instance; + u32 tdm_fmt; + void __iomem *acp5x_base; + struct snd_pcm_substream *play_stream; + struct snd_pcm_substream *capture_stream; + struct snd_pcm_substream *i2ssp_play_stream; + struct snd_pcm_substream *i2ssp_capture_stream; +}; + +struct i2s_stream_instance { + u16 num_pages; + u16 i2s_instance; + u16 direction; + u16 channels; + u32 xfer_resolution; + u32 val; + dma_addr_t dma_addr; + u64 bytescount; + void __iomem *acp5x_base; +}; + +union acp_dma_count { + struct { + u32 low; + u32 high; + } bcount; + u64 bytescount; +}; + +struct acp5x_platform_info { + u16 play_i2s_instance; + u16 cap_i2s_instance; +}; + +union acp_i2stdm_mstrclkgen { + struct { + u32 i2stdm_master_mode : 1; + u32 i2stdm_format_mode : 1; + u32 i2stdm_lrclk_div_val : 9; + u32 i2stdm_bclk_div_val : 11; + u32:10; + } bitfields, bits; + u32 u32_all; +}; + +/* common header file uses exact offset rather than relative + * offset which requires subtraction logic from base_addr + * for accessing ACP5x MMIO space registers + */ +static inline u32 acp_readl(void __iomem *base_addr) +{ + return readl(base_addr - ACP5x_PHY_BASE_ADDRESS); +} + +static inline void acp_writel(u32 val, void __iomem *base_addr) +{ + writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS); +} + +static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, + int direction) +{ + union acp_dma_count byte_count; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_HS_TX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_HS_TX_LINEARPOSCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_I2S_TX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_I2S_TX_LINEARPOSCNTR_LOW); + } + } else { + switch (rtd->i2s_instance) { + case I2S_HS_INSTANCE: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_HS_RX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_HS_RX_LINEARPOSCNTR_LOW); + break; + case I2S_SP_INSTANCE: + default: + byte_count.bcount.high = + acp_readl(rtd->acp5x_base + + ACP_I2S_RX_LINEARPOSCNTR_HIGH); + byte_count.bcount.low = + acp_readl(rtd->acp5x_base + + ACP_I2S_RX_LINEARPOSCNTR_LOW); + } + } + return byte_count.bytescount; +} diff --git a/sound/soc/amd/vangogh/pci-acp5x.c b/sound/soc/amd/vangogh/pci-acp5x.c new file mode 100644 index 000000000000..a57b762d9f2e --- /dev/null +++ b/sound/soc/amd/vangogh/pci-acp5x.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// AMD Vangogh ACP PCI Driver +// +// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. + +#include <linux/pci.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/pm_runtime.h> + +#include "acp5x.h" + +struct acp5x_dev_data { + void __iomem *acp5x_base; + bool acp5x_audio_mode; + struct resource *res; + struct platform_device *pdev[ACP5x_DEVS]; +}; + +static int acp5x_power_on(void __iomem *acp5x_base) +{ + u32 val; + int timeout; + + val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if ((val & ACP_PGFSM_STATUS_MASK) != + ACP_POWER_ON_IN_PROGRESS) + acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp5x_base + ACP_PGFSM_CONTROL); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); + if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static int acp5x_reset(void __iomem *acp5x_base) +{ + u32 val; + int timeout; + + acp_writel(1, acp5x_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_SOFT_RESET); + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) + break; + cpu_relax(); + } + acp_writel(0, acp5x_base + ACP_SOFT_RESET); + timeout = 0; + while (++timeout < 500) { + val = acp_readl(acp5x_base + ACP_SOFT_RESET); + if (!val) + return 0; + cpu_relax(); + } + return -ETIMEDOUT; +} + +static void acp5x_enable_interrupts(void __iomem *acp5x_base) +{ + acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB); +} + +static void acp5x_disable_interrupts(void __iomem *acp5x_base) +{ + acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base + + ACP_EXTERNAL_INTR_STAT); + acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL); + acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB); +} + +static int acp5x_init(void __iomem *acp5x_base) +{ + int ret; + + /* power on */ + ret = acp5x_power_on(acp5x_base); + if (ret) { + pr_err("ACP5x power on failed\n"); + return ret; + } + /* Reset */ + ret = acp5x_reset(acp5x_base); + if (ret) { + pr_err("ACP5x reset failed\n"); + return ret; + } + acp5x_enable_interrupts(acp5x_base); + return 0; +} + +static int acp5x_deinit(void __iomem *acp5x_base) +{ + int ret; + + acp5x_disable_interrupts(acp5x_base); + /* Reset */ + ret = acp5x_reset(acp5x_base); + if (ret) { + pr_err("ACP5x reset failed\n"); + return ret; + } + return 0; +} + +static int snd_acp5x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp5x_dev_data *adata; + struct platform_device_info pdevinfo[ACP5x_DEVS]; + unsigned int irqflags; + int ret, i; + u32 addr, val; + + irqflags = IRQF_SHARED; + if (pci->revision != 0x50) + return -ENODEV; + + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP5x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + + adata = devm_kzalloc(&pci->dev, sizeof(struct acp5x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + addr = pci_resource_start(pci, 0); + adata->acp5x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp5x_base) { + ret = -ENOMEM; + goto release_regions; + } + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = acp5x_init(adata->acp5x_base); + if (ret) + goto release_regions; + + val = acp_readl(adata->acp5x_base + ACP_PIN_CONFIG); + switch (val) { + case I2S_MODE: + adata->res = devm_kzalloc(&pci->dev, + sizeof(struct resource) * ACP5x_RES, + GFP_KERNEL); + if (!adata->res) { + ret = -ENOMEM; + goto de_init; + } + + adata->res[0].name = "acp5x_i2s_iomem"; + adata->res[0].flags = IORESOURCE_MEM; + adata->res[0].start = addr; + adata->res[0].end = addr + (ACP5x_REG_END - ACP5x_REG_START); + + adata->res[1].name = "acp5x_i2s_sp"; + adata->res[1].flags = IORESOURCE_MEM; + adata->res[1].start = addr + ACP5x_I2STDM_REG_START; + adata->res[1].end = addr + ACP5x_I2STDM_REG_END; + + adata->res[2].name = "acp5x_i2s_hs"; + adata->res[2].flags = IORESOURCE_MEM; + adata->res[2].start = addr + ACP5x_HS_TDM_REG_START; + adata->res[2].end = addr + ACP5x_HS_TDM_REG_END; + + adata->res[3].name = "acp5x_i2s_irq"; + adata->res[3].flags = IORESOURCE_IRQ; + adata->res[3].start = pci->irq; + adata->res[3].end = adata->res[3].start; + + adata->acp5x_audio_mode = ACP5x_I2S_MODE; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo[0].name = "acp5x_i2s_dma"; + pdevinfo[0].id = 0; + pdevinfo[0].parent = &pci->dev; + pdevinfo[0].num_res = 4; + pdevinfo[0].res = &adata->res[0]; + pdevinfo[0].data = &irqflags; + pdevinfo[0].size_data = sizeof(irqflags); + + pdevinfo[1].name = "acp5x_i2s_playcap"; + pdevinfo[1].id = 0; + pdevinfo[1].parent = &pci->dev; + pdevinfo[1].num_res = 1; + pdevinfo[1].res = &adata->res[1]; + + pdevinfo[2].name = "acp5x_i2s_playcap"; + pdevinfo[2].id = 1; + pdevinfo[2].parent = &pci->dev; + pdevinfo[2].num_res = 1; + pdevinfo[2].res = &adata->res[2]; + + for (i = 0; i < ACP5x_DEVS; i++) { + adata->pdev[i] = + platform_device_register_full(&pdevinfo[i]); + if (IS_ERR(adata->pdev[i])) { + dev_err(&pci->dev, "cannot register %s device\n", + pdevinfo[i].name); + ret = PTR_ERR(adata->pdev[i]); + goto unregister_devs; + } + } + break; + default: + dev_info(&pci->dev, "ACP audio mode : %d\n", val); + } + pm_runtime_set_autosuspend_delay(&pci->dev, 2000); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +unregister_devs: + for (--i; i >= 0; i--) + platform_device_unregister(adata->pdev[i]); +de_init: + if (acp5x_deinit(adata->acp5x_base)) + dev_err(&pci->dev, "ACP de-init failed\n"); +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int __maybe_unused snd_acp5x_suspend(struct device *dev) +{ + int ret; + struct acp5x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp5x_deinit(adata->acp5x_base); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + else + dev_dbg(dev, "ACP de-initialized\n"); + + return ret; +} + +static int __maybe_unused snd_acp5x_resume(struct device *dev) +{ + int ret; + struct acp5x_dev_data *adata; + + adata = dev_get_drvdata(dev); + ret = acp5x_init(adata->acp5x_base); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static const struct dev_pm_ops acp5x_pm = { + SET_RUNTIME_PM_OPS(snd_acp5x_suspend, + snd_acp5x_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(snd_acp5x_suspend, snd_acp5x_resume) +}; + +static void snd_acp5x_remove(struct pci_dev *pci) +{ + struct acp5x_dev_data *adata; + int i, ret; + + adata = pci_get_drvdata(pci); + if (adata->acp5x_audio_mode == ACP5x_I2S_MODE) { + for (i = 0; i < ACP5x_DEVS; i++) + platform_device_unregister(adata->pdev[i]); + } + ret = acp5x_deinit(adata->acp5x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp5x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp5x_ids); + +static struct pci_driver acp5x_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp5x_ids, + .probe = snd_acp5x_probe, + .remove = snd_acp5x_remove, + .driver = { + .pm = &acp5x_pm, + } +}; + +module_pci_driver(acp5x_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD Vangogh ACP PCI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/vangogh/vg_chip_offset_byte.h b/sound/soc/amd/vangogh/vg_chip_offset_byte.h new file mode 100644 index 000000000000..b1165ae142b7 --- /dev/null +++ b/sound/soc/amd/vangogh/vg_chip_offset_byte.h @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 5.x Register Documentation + * + * Copyright 2021 Advanced Micro Devices, Inc. + */ + +#ifndef _acp_ip_OFFSET_HEADER +#define _acp_ip_OFFSET_HEADER + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_CNTL_1 0x1240004 +#define ACP_DMA_CNTL_2 0x1240008 +#define ACP_DMA_CNTL_3 0x124000C +#define ACP_DMA_CNTL_4 0x1240010 +#define ACP_DMA_CNTL_5 0x1240014 +#define ACP_DMA_CNTL_6 0x1240018 +#define ACP_DMA_CNTL_7 0x124001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x1240024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x1240028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x124002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x1240030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x1240034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x1240038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x124003C +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_DSCR_CNT_1 0x1240044 +#define ACP_DMA_DSCR_CNT_2 0x1240048 +#define ACP_DMA_DSCR_CNT_3 0x124004C +#define ACP_DMA_DSCR_CNT_4 0x1240050 +#define ACP_DMA_DSCR_CNT_5 0x1240054 +#define ACP_DMA_DSCR_CNT_6 0x1240058 +#define ACP_DMA_DSCR_CNT_7 0x124005C +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_PRIO_1 0x1240064 +#define ACP_DMA_PRIO_2 0x1240068 +#define ACP_DMA_PRIO_3 0x124006C +#define ACP_DMA_PRIO_4 0x1240070 +#define ACP_DMA_PRIO_5 0x1240074 +#define ACP_DMA_PRIO_6 0x1240078 +#define ACP_DMA_PRIO_7 0x124007C +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_DSCR_1 0x1240084 +#define ACP_DMA_CUR_DSCR_2 0x1240088 +#define ACP_DMA_CUR_DSCR_3 0x124008C +#define ACP_DMA_CUR_DSCR_4 0x1240090 +#define ACP_DMA_CUR_DSCR_5 0x1240094 +#define ACP_DMA_CUR_DSCR_6 0x1240098 +#define ACP_DMA_CUR_DSCR_7 0x124009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x12400A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x12400A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x12400AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x12400B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x12400B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x12400B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x12400BC +#define ACP_DMA_ERR_STS_0 0x12400C0 +#define ACP_DMA_ERR_STS_1 0x12400C4 +#define ACP_DMA_ERR_STS_2 0x12400C8 +#define ACP_DMA_ERR_STS_3 0x12400CC +#define ACP_DMA_ERR_STS_4 0x12400D0 +#define ACP_DMA_ERR_STS_5 0x12400D4 +#define ACP_DMA_ERR_STS_6 0x12400D8 +#define ACP_DMA_ERR_STS_7 0x12400DC +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +/* Registers from ACP_AXI2AXIATU block */ +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C +#define ACPAXI2AXI_ATU_CTRL 0x1240C40 + +/* Registers from ACP_CLKRST block */ +#define ACP_SOFT_RESET 0x1241000 +#define ACP_CONTROL 0x1241004 +#define ACP_STATUS 0x1241008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010 + +/* Registers from ACP_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_CNTL 0x1241804 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_ERROR_STATUS 0x12418C4 +#define ACP_SW_I2S_ERROR_REASON 0x12418C8 +#define ACP_MEM_PG_STS 0x12418CC +#define ACP_PGMEM_DEEP_SLEEP_CTRL 0x12418D0 +#define ACP_PGMEM_SHUT_DOWN_CTRL 0x12418D4 + +/* Registers from ACP_PGFSM block */ +#define ACP_PIN_CONFIG 0x1241400 +#define ACP_PAD_PULLUP_CTRL 0x1241404 +#define ACP_PAD_PULLDOWN_CTRL 0x1241408 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x124140C +#define ACP_PAD_SCHMEN_CTRL 0x1241410 +#define ACP_SW_PAD_KEEPER_EN 0x1241414 +#define ACP_SW_WAKE_EN 0x1241418 +#define ACP_I2S_WAKE_EN 0x124141C +#define ACP_PME_EN 0x1241420 +#define ACP_PGFSM_CONTROL 0x1241424 +#define ACP_PGFSM_STATUS 0x1241428 +#define ACP_CLKMUX_SEL 0x124142C +#define ACP_DEVICE_STATE 0x1241430 +#define AZ_DEVICE_STATE 0x1241434 +#define ACP_INTR_URGENCY_TIMER 0x1241438 +#define AZ_INTR_URGENCY_TIMER 0x124143C +#define ACP_AON_SW_INTR_TRIG 0x1241440 + +/* Registers from ACP_SCRATCH block */ +#define ACP_SCRATCH_REG_0 0x1250000 +#define ACP_SCRATCH_REG_1 0x1250004 +#define ACP_SCRATCH_REG_2 0x1250008 +#define ACP_SCRATCH_REG_3 0x125000C +#define ACP_SCRATCH_REG_4 0x1250010 +#define ACP_SCRATCH_REG_5 0x1250014 +#define ACP_SCRATCH_REG_6 0x1250018 +#define ACP_SCRATCH_REG_7 0x125001C +#define ACP_SCRATCH_REG_8 0x1250020 +#define ACP_SCRATCH_REG_9 0x1250024 +#define ACP_SCRATCH_REG_10 0x1250028 +#define ACP_SCRATCH_REG_11 0x125002C +#define ACP_SCRATCH_REG_12 0x1250030 +#define ACP_SCRATCH_REG_13 0x1250034 +#define ACP_SCRATCH_REG_14 0x1250038 +#define ACP_SCRATCH_REG_15 0x125003C +#define ACP_SCRATCH_REG_16 0x1250040 +#define ACP_SCRATCH_REG_17 0x1250044 +#define ACP_SCRATCH_REG_18 0x1250048 +#define ACP_SCRATCH_REG_19 0x125004C +#define ACP_SCRATCH_REG_20 0x1250050 +#define ACP_SCRATCH_REG_21 0x1250054 +#define ACP_SCRATCH_REG_22 0x1250058 +#define ACP_SCRATCH_REG_23 0x125005C +#define ACP_SCRATCH_REG_24 0x1250060 +#define ACP_SCRATCH_REG_25 0x1250064 +#define ACP_SCRATCH_REG_26 0x1250068 +#define ACP_SCRATCH_REG_27 0x125006C +#define ACP_SCRATCH_REG_28 0x1250070 +#define ACP_SCRATCH_REG_29 0x1250074 +#define ACP_SCRATCH_REG_30 0x1250078 +#define ACP_SCRATCH_REG_31 0x125007C +#define ACP_SCRATCH_REG_32 0x1250080 +#define ACP_SCRATCH_REG_33 0x1250084 +#define ACP_SCRATCH_REG_34 0x1250088 +#define ACP_SCRATCH_REG_35 0x125008C +#define ACP_SCRATCH_REG_36 0x1250090 +#define ACP_SCRATCH_REG_37 0x1250094 +#define ACP_SCRATCH_REG_38 0x1250098 +#define ACP_SCRATCH_REG_39 0x125009C +#define ACP_SCRATCH_REG_40 0x12500A0 +#define ACP_SCRATCH_REG_41 0x12500A4 +#define ACP_SCRATCH_REG_42 0x12500A8 +#define ACP_SCRATCH_REG_43 0x12500AC +#define ACP_SCRATCH_REG_44 0x12500B0 +#define ACP_SCRATCH_REG_45 0x12500B4 +#define ACP_SCRATCH_REG_46 0x12500B8 +#define ACP_SCRATCH_REG_47 0x12500BC +#define ACP_SCRATCH_REG_48 0x12500C0 +#define ACP_SCRATCH_REG_49 0x12500C4 +#define ACP_SCRATCH_REG_50 0x12500C8 +#define ACP_SCRATCH_REG_51 0x12500CC +#define ACP_SCRATCH_REG_52 0x12500D0 +#define ACP_SCRATCH_REG_53 0x12500D4 +#define ACP_SCRATCH_REG_54 0x12500D8 +#define ACP_SCRATCH_REG_55 0x12500DC +#define ACP_SCRATCH_REG_56 0x12500E0 +#define ACP_SCRATCH_REG_57 0x12500E4 +#define ACP_SCRATCH_REG_58 0x12500E8 +#define ACP_SCRATCH_REG_59 0x12500EC +#define ACP_SCRATCH_REG_60 0x12500F0 +#define ACP_SCRATCH_REG_61 0x12500F4 +#define ACP_SCRATCH_REG_62 0x12500F8 +#define ACP_SCRATCH_REG_63 0x12500FC +#define ACP_SCRATCH_REG_64 0x1250100 +#define ACP_SCRATCH_REG_65 0x1250104 +#define ACP_SCRATCH_REG_66 0x1250108 +#define ACP_SCRATCH_REG_67 0x125010C +#define ACP_SCRATCH_REG_68 0x1250110 +#define ACP_SCRATCH_REG_69 0x1250114 +#define ACP_SCRATCH_REG_70 0x1250118 +#define ACP_SCRATCH_REG_71 0x125011C +#define ACP_SCRATCH_REG_72 0x1250120 +#define ACP_SCRATCH_REG_73 0x1250124 +#define ACP_SCRATCH_REG_74 0x1250128 +#define ACP_SCRATCH_REG_75 0x125012C +#define ACP_SCRATCH_REG_76 0x1250130 +#define ACP_SCRATCH_REG_77 0x1250134 +#define ACP_SCRATCH_REG_78 0x1250138 +#define ACP_SCRATCH_REG_79 0x125013C +#define ACP_SCRATCH_REG_80 0x1250140 +#define ACP_SCRATCH_REG_81 0x1250144 +#define ACP_SCRATCH_REG_82 0x1250148 +#define ACP_SCRATCH_REG_83 0x125014C +#define ACP_SCRATCH_REG_84 0x1250150 +#define ACP_SCRATCH_REG_85 0x1250154 +#define ACP_SCRATCH_REG_86 0x1250158 +#define ACP_SCRATCH_REG_87 0x125015C +#define ACP_SCRATCH_REG_88 0x1250160 +#define ACP_SCRATCH_REG_89 0x1250164 +#define ACP_SCRATCH_REG_90 0x1250168 +#define ACP_SCRATCH_REG_91 0x125016C +#define ACP_SCRATCH_REG_92 0x1250170 +#define ACP_SCRATCH_REG_93 0x1250174 +#define ACP_SCRATCH_REG_94 0x1250178 +#define ACP_SCRATCH_REG_95 0x125017C +#define ACP_SCRATCH_REG_96 0x1250180 +#define ACP_SCRATCH_REG_97 0x1250184 +#define ACP_SCRATCH_REG_98 0x1250188 +#define ACP_SCRATCH_REG_99 0x125018C +#define ACP_SCRATCH_REG_100 0x1250190 +#define ACP_SCRATCH_REG_101 0x1250194 +#define ACP_SCRATCH_REG_102 0x1250198 +#define ACP_SCRATCH_REG_103 0x125019C +#define ACP_SCRATCH_REG_104 0x12501A0 +#define ACP_SCRATCH_REG_105 0x12501A4 +#define ACP_SCRATCH_REG_106 0x12501A8 +#define ACP_SCRATCH_REG_107 0x12501AC +#define ACP_SCRATCH_REG_108 0x12501B0 +#define ACP_SCRATCH_REG_109 0x12501B4 +#define ACP_SCRATCH_REG_110 0x12501B8 +#define ACP_SCRATCH_REG_111 0x12501BC +#define ACP_SCRATCH_REG_112 0x12501C0 +#define ACP_SCRATCH_REG_113 0x12501C4 +#define ACP_SCRATCH_REG_114 0x12501C8 +#define ACP_SCRATCH_REG_115 0x12501CC +#define ACP_SCRATCH_REG_116 0x12501D0 +#define ACP_SCRATCH_REG_117 0x12501D4 +#define ACP_SCRATCH_REG_118 0x12501D8 +#define ACP_SCRATCH_REG_119 0x12501DC +#define ACP_SCRATCH_REG_120 0x12501E0 +#define ACP_SCRATCH_REG_121 0x12501E4 +#define ACP_SCRATCH_REG_122 0x12501E8 +#define ACP_SCRATCH_REG_123 0x12501EC +#define ACP_SCRATCH_REG_124 0x12501F0 +#define ACP_SCRATCH_REG_125 0x12501F4 +#define ACP_SCRATCH_REG_126 0x12501F8 +#define ACP_SCRATCH_REG_127 0x12501FC +#define ACP_SCRATCH_REG_128 0x1250200 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM1_MSTRCLKGEN 0x1242418 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C +#define ACP_I2STDM_REFCLKGEN 0x1242420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 +#endif diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index ec04e3386bc0..8617793ed955 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -11,7 +11,6 @@ if SND_ATMEL_SOC config SND_ATMEL_SOC_PDC bool - depends on HAS_DMA config SND_ATMEL_SOC_DMA bool diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index e8fe1a7a4d83..6b3d9c05eaf2 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -200,6 +200,7 @@ struct atmel_i2s_dev { unsigned int fmt; const struct atmel_i2s_gck_param *gck_param; const struct atmel_i2s_caps *caps; + int clk_use_no; }; static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id) @@ -321,9 +322,16 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, { struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - unsigned int mr = 0; + unsigned int mr = 0, mr_mask; int ret; + mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK | + ATMEL_I2SC_MR_DATALENGTH_MASK; + if (is_playback) + mr_mask |= ATMEL_I2SC_MR_TXMONO; + else + mr_mask |= ATMEL_I2SC_MR_RXMONO; + switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: mr |= ATMEL_I2SC_MR_FORMAT_I2S; @@ -402,7 +410,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr); + return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr); } static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev, @@ -495,18 +503,28 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd, is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER; /* If master starts, enable the audio clock. */ - if (is_master && mck_enabled) - err = atmel_i2s_switch_mck_generator(dev, true); - if (err) - return err; + if (is_master && mck_enabled) { + if (!dev->clk_use_no) { + err = atmel_i2s_switch_mck_generator(dev, true); + if (err) + return err; + } + dev->clk_use_no++; + } err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr); if (err) return err; /* If master stops, disable the audio clock. */ - if (is_master && !mck_enabled) - err = atmel_i2s_switch_mck_generator(dev, false); + if (is_master && !mck_enabled) { + if (dev->clk_use_no == 1) { + err = atmel_i2s_switch_mck_generator(dev, false); + if (err) + return err; + } + dev->clk_use_no--; + } return err; } @@ -542,6 +560,7 @@ static struct snd_soc_dai_driver atmel_i2s_dai = { }, .ops = &atmel_i2s_dai_ops, .symmetric_rate = 1, + .symmetric_sample_bits = 1, }; static const struct snd_soc_component_driver atmel_i2s_component = { diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c index e6ded6f8453f..bcd4f3e4fb0f 100644 --- a/sound/soc/atmel/mchp-spdifrx.c +++ b/sound/soc/atmel/mchp-spdifrx.c @@ -56,7 +56,7 @@ /* Validity Bit Mode */ #define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1) #define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \ - (0 << 1) /* Load sample regardles of validity bit value */ + (0 << 1) /* Load sample regardless of validity bit value */ #define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \ (1 << 1) /* Load sample only if validity bit is 0 */ @@ -519,7 +519,7 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev, /* check for new data available */ ret = wait_for_completion_interruptible_timeout(&ch_stat->done, msecs_to_jiffies(100)); - /* IP might not be started or valid stream might not be prezent */ + /* IP might not be started or valid stream might not be present */ if (ret < 0) { dev_dbg(dev->dev, "channel status for channel %d timeout\n", channel); @@ -571,7 +571,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev, mchp_spdifrx_isr_blockend_en(dev); ret = wait_for_completion_interruptible_timeout(&user_data->done, msecs_to_jiffies(100)); - /* IP might not be started or valid stream might not be prezent */ + /* IP might not be started or valid stream might not be present */ if (ret <= 0) { dev_dbg(dev->dev, "user data for channel %d timeout\n", channel); diff --git a/sound/soc/atmel/mchp-spdiftx.c b/sound/soc/atmel/mchp-spdiftx.c index 3bd350afb743..d24380046435 100644 --- a/sound/soc/atmel/mchp-spdiftx.c +++ b/sound/soc/atmel/mchp-spdiftx.c @@ -80,7 +80,7 @@ #define SPDIFTX_MR_VALID1 BIT(24) #define SPDIFTX_MR_VALID2 BIT(25) -/* Disable Null Frame on underrrun */ +/* Disable Null Frame on underrun */ #define SPDIFTX_MR_DNFR_MASK GENMASK(27, 27) #define SPDIFTX_MR_DNFR_INVALID (0 << 27) #define SPDIFTX_MR_DNFR_VALID (1 << 27) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 59e2edb22b3a..50c3dc6936f9 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -23,7 +23,7 @@ // IN2 +---o--+------------+--o---+ OUT2 // loop2 relays // -// The 'loop1' gpio pin controlls two relays, which are either in loop +// The 'loop1' gpio pin controls two relays, which are either in loop // position, meaning that input and output are directly connected, or // they are in mixer position, meaning that the signal is passed through // the 'Sum' mixer. Similarly for 'loop2'. diff --git a/sound/soc/bcm/cygnus-pcm.c b/sound/soc/bcm/cygnus-pcm.c index 56b71b965624..3abeaf0f1b1c 100644 --- a/sound/soc/bcm/cygnus-pcm.c +++ b/sound/soc/bcm/cygnus-pcm.c @@ -729,7 +729,7 @@ static struct snd_soc_component_driver cygnus_soc_platform = { int cygnus_soc_platform_register(struct device *dev, struct cygnus_audio *cygaud) { - int rc = 0; + int rc; dev_dbg(dev, "%s Enter\n", __func__); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index d24edb01c19b..82ee233a269d 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW imply SND_SOC_RT1316_SDW + imply SND_SOC_SDW_MOCKUP imply SND_SOC_SGTL5000 imply SND_SOC_SI476X imply SND_SOC_SIMPLE_AMPLIFIER @@ -693,7 +694,7 @@ config SND_SOC_CS47L15 config SND_SOC_CS47L24 tristate - depends on MFD_CS47L24 + depends on MFD_CS47L24 && MFD_ARIZONA config SND_SOC_CS47L35 tristate @@ -847,7 +848,7 @@ config SND_SOC_HDAC_HDA select SND_HDA config SND_SOC_ICS43432 - tristate + tristate "ICS43423 and compatible i2s microphones" config SND_SOC_INNO_RK3036 tristate "Inno codec driver for RK3036 SoC" @@ -1287,6 +1288,23 @@ config SND_SOC_RT715_SDCA_SDW select REGMAP_SOUNDWIRE select REGMAP_SOUNDWIRE_MBQ +config SND_SOC_SDW_MOCKUP + tristate "SoundWire mockup codec" + depends on EXPERT + depends on SOUNDWIRE + help + This option enables a SoundWire mockup codec that does not drive the + bus, take part in the command/command protocol or generate data on a + Source port. + This option is only intended to be used for tests on a device + with a connector, in combination with a bus analyzer, or to test new + topologies that differ from the actual hardware layout. + This mockup device could be totally virtual but could also be a + real physical one with one key restriction: it is not allowed by the + SoundWire specification to be configured via a sideband mechanism and + generate audio data for capture. However, nothing prevents such a + peripheral device from snooping the bus. + #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate "Freescale SGTL5000 CODEC" @@ -1564,6 +1582,7 @@ config SND_SOC_WCD938X config SND_SOC_WCD938X_SDW tristate "WCD9380/WCD9385 Codec - SDW" select SND_SOC_WCD938X + select SND_SOC_WCD_MBHC depends on SOUNDWIRE select REGMAP_SOUNDWIRE help @@ -1595,11 +1614,11 @@ config SND_SOC_WM5100 config SND_SOC_WM5102 tristate - depends on MFD_WM5102 + depends on MFD_WM5102 && MFD_ARIZONA config SND_SOC_WM5110 tristate - depends on MFD_WM5110 + depends on MFD_WM5110 && MFD_ARIZONA config SND_SOC_WM8350 tristate @@ -1764,11 +1783,11 @@ config SND_SOC_WM8996 config SND_SOC_WM8997 tristate - depends on MFD_WM8997 + depends on MFD_WM8997 && MFD_ARIZONA config SND_SOC_WM8998 tristate - depends on MFD_WM8998 + depends on MFD_WM8998 && MFD_ARIZONA config SND_SOC_WM9081 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7bb38c370842..8dcea2c4604a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -203,6 +203,7 @@ snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o +snd-soc-sdw-mockup-objs := sdw-mockup.o snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o @@ -530,6 +531,7 @@ obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o +obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index f37ab7eda615..278a55af158b 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -316,6 +316,13 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, int word_len = 0, master_rate = 0; struct snd_soc_component *component = dai->component; struct ad193x_priv *ad193x = snd_soc_component_get_drvdata(component); + bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + u8 dacc0; + + dev_dbg(dai->dev, "%s() rate=%u format=%#x width=%u channels=%u\n", + __func__, params_rate(params), params_format(params), + params_width(params), params_channels(params)); + /* bit size */ switch (params_width(params)) { @@ -346,6 +353,25 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream, break; } + if (is_playback) { + switch (params_rate(params)) { + case 48000: + dacc0 = AD193X_DAC_SR_48; + break; + case 96000: + dacc0 = AD193X_DAC_SR_96; + break; + case 192000: + dacc0 = AD193X_DAC_SR_192; + break; + default: + dev_err(dai->dev, "invalid sampling rate: %d\n", params_rate(params)); + return -EINVAL; + } + + regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL0, AD193X_DAC_SR_MASK, dacc0); + } + regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0, AD193X_PLL_INPUT_MASK, master_rate); @@ -385,7 +411,7 @@ static struct snd_soc_dai_driver ad193x_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, }, @@ -407,7 +433,7 @@ static struct snd_soc_dai_driver ad193x_no_adc_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, }, diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 377854712c20..61f4648861d5 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -37,6 +37,10 @@ int ad193x_probe(struct device *dev, struct regmap *regmap, #define AD193X_PLL_CLK_SRC_MCLK (1 << 1) #define AD193X_DAC_CTRL0 0x02 #define AD193X_DAC_POWERDOWN 0x01 +#define AD193X_DAC_SR_MASK 0x06 +#define AD193X_DAC_SR_48 (0 << 1) +#define AD193X_DAC_SR_96 (1 << 1) +#define AD193X_DAC_SR_192 (2 << 1) #define AD193X_DAC_SERFMT_MASK 0xC0 #define AD193X_DAC_SERFMT_STEREO (0 << 6) #define AD193X_DAC_SERFMT_TDM (1 << 6) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 99c022be94a6..fb1e4c33e27d 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -586,6 +586,7 @@ struct cs42l42_pll_params { * Table 4-5 from the Datasheet */ static const struct cs42l42_pll_params pll_ratio_table[] = { + { 1411200, 0, 1, 0x00, 0x80, 0x000000, 0x03, 0x10, 11289600, 128, 2}, { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2}, { 2304000, 0, 1, 0x00, 0x55, 0xC00000, 0x02, 0x10, 12288000, 85, 2}, { 2400000, 0, 1, 0x00, 0x50, 0x000000, 0x03, 0x10, 12000000, 80, 2}, @@ -843,6 +844,13 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, if (channels == 1) cs42l42->bclk *= 2; + /* + * Assume 24-bit samples are in 32-bit slots, to prevent SCLK being + * more than assumed (which would result in overclocking). + */ + if (params_width(params) == 24) + cs42l42->bclk = (cs42l42->bclk / 3) * 4; + switch(substream->stream) { case SNDRV_PCM_STREAM_CAPTURE: if (channels == 2) { @@ -890,10 +898,23 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai, { struct snd_soc_component *component = dai->component; struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); + int i; - cs42l42->sclk = freq; + if (freq == 0) { + cs42l42->sclk = 0; + return 0; + } - return 0; + for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) { + if (pll_ratio_table[i].sclk == freq) { + cs42l42->sclk = freq; + return 0; + } + } + + dev_err(component->dev, "SCLK %u not supported\n", freq); + + return -EINVAL; } static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) @@ -2106,4 +2127,7 @@ MODULE_DESCRIPTION("ASoC CS42L42 driver"); MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>"); MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>"); MODULE_AUTHOR("Michael White, Cirrus Logic Inc, <michael.white@cirrus.com>"); +MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>"); +MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); +MODULE_AUTHOR("Vitaly Rodionov <vitalyr@opensource.cirrus.com>"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 112ffcf938c3..8734f6828f3e 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -79,7 +79,7 @@ #define CS42L42_HP_PDN_SHIFT 3 #define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT) #define CS42L42_ADC_PDN_SHIFT 2 -#define CS42L42_ADC_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT) +#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT) #define CS42L42_PDN_ALL_SHIFT 0 #define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT) diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index 61dfa86d444d..13258f3ca9aa 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -206,7 +206,7 @@ static int cx20442_write(struct snd_soc_component *component, unsigned int reg, */ /* Modem init: echo off, digital speaker off, quiet off, voice mode */ -static const char *v253_init = "ate0m0q0+fclass=8\r"; +static const char v253_init[] = "ate0m0q0+fclass=8\r"; /* Line discipline .open() */ static int v253_open(struct tty_struct *tty) @@ -259,8 +259,8 @@ static int v253_hangup(struct tty_struct *tty) } /* Line discipline .receive_buf() */ -static void v253_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) +static void v253_receive(struct tty_struct *tty, const unsigned char *cp, + const char *fp, int count) { struct snd_soc_component *component = tty->disc_data; struct cx20442_priv *cx20442; @@ -279,11 +279,6 @@ static void v253_receive(struct tty_struct *tty, } } -/* Line discipline .write_wakeup() */ -static void v253_wakeup(struct tty_struct *tty) -{ -} - struct tty_ldisc_ops v253_ops = { .name = "cx20442", .owner = THIS_MODULE, @@ -291,7 +286,6 @@ struct tty_ldisc_ops v253_ops = { .close = v253_close, .hangup = v253_hangup, .receive_buf = v253_receive, - .write_wakeup = v253_wakeup, }; EXPORT_SYMBOL_GPL(v253_ops); diff --git a/sound/soc/codecs/ics43432.c b/sound/soc/codecs/ics43432.c index 47e749f03940..de4c8460ab3d 100644 --- a/sound/soc/codecs/ics43432.c +++ b/sound/soc/codecs/ics43432.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * I2S MEMS microphone driver for InvenSense ICS-43432 + * I2S MEMS microphone driver for InvenSense ICS-43432 and similar + * MEMS-based microphones. * * - Non configurable. * - I2S interface, 64 BCLs per frame, 32 bits per channel, 24 bit data @@ -53,6 +54,7 @@ static int ics43432_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id ics43432_ids[] = { { .compatible = "invensense,ics43432", }, + { .compatible = "cui,cmm-4030d-261", }, { } }; MODULE_DEVICE_TABLE(of, ics43432_ids); diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 3622961f7c2c..196b06898eeb 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -1722,42 +1722,43 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) case RX_MACRO_AIF2_PB: case RX_MACRO_AIF3_PB: case RX_MACRO_AIF4_PB: - for (j = 0; j < INTERP_MAX; j++) { - reg = CDC_RX_RXn_RX_PATH_CTL(j); - mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); - dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j); - - if (mute) { - snd_soc_component_update_bits(component, reg, - CDC_RX_PATH_PGA_MUTE_MASK, - CDC_RX_PATH_PGA_MUTE_ENABLE); - snd_soc_component_update_bits(component, mix_reg, - CDC_RX_PATH_PGA_MUTE_MASK, - CDC_RX_PATH_PGA_MUTE_ENABLE); - } else { - snd_soc_component_update_bits(component, reg, - CDC_RX_PATH_PGA_MUTE_MASK, 0x0); - snd_soc_component_update_bits(component, mix_reg, - CDC_RX_PATH_PGA_MUTE_MASK, 0x0); - } - - if (j == INTERP_AUX) - dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; + for (j = 0; j < INTERP_MAX; j++) { + reg = CDC_RX_RXn_RX_PATH_CTL(j); + mix_reg = CDC_RX_RXn_RX_PATH_MIX_CTL(j); + dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(j); + + if (mute) { + snd_soc_component_update_bits(component, reg, + CDC_RX_PATH_PGA_MUTE_MASK, + CDC_RX_PATH_PGA_MUTE_ENABLE); + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_PATH_PGA_MUTE_MASK, + CDC_RX_PATH_PGA_MUTE_ENABLE); + } else { + snd_soc_component_update_bits(component, reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x0); + snd_soc_component_update_bits(component, mix_reg, + CDC_RX_PATH_PGA_MUTE_MASK, 0x0); + } - int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8; - int_mux_cfg1 = int_mux_cfg0 + 4; - int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0); - int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1); + if (j == INTERP_AUX) + dsm_reg = CDC_RX_RX2_RX_PATH_DSM_CTL; - if (snd_soc_component_read(component, dsm_reg) & 0x01) { - if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0)) - snd_soc_component_update_bits(component, reg, 0x20, 0x20); - if (int_mux_cfg1_val & 0x0F) { - snd_soc_component_update_bits(component, reg, 0x20, 0x20); - snd_soc_component_update_bits(component, mix_reg, 0x20, 0x20); + int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8; + int_mux_cfg1 = int_mux_cfg0 + 4; + int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0); + int_mux_cfg1_val = snd_soc_component_read(component, int_mux_cfg1); + + if (snd_soc_component_read(component, dsm_reg) & 0x01) { + if (int_mux_cfg0_val || (int_mux_cfg1_val & 0xF0)) + snd_soc_component_update_bits(component, reg, 0x20, 0x20); + if (int_mux_cfg1_val & 0x0F) { + snd_soc_component_update_bits(component, reg, 0x20, 0x20); + snd_soc_component_update_bits(component, mix_reg, 0x20, + 0x20); + } } } - } break; default: break; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index bc30a1dc7530..b45ec35cd63c 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2158,13 +2158,11 @@ static void max98090_jack_work(struct work_struct *work) msleep(50); - reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); + snd_soc_component_read(component, M98090_REG_JACK_STATUS); /* Weak pull up allows only insertion detection */ snd_soc_component_update_bits(component, M98090_REG_JACK_DETECT, M98090_JDWK_MASK, M98090_JDWK_MASK); - } else { - reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); } reg = snd_soc_component_read(component, M98090_REG_JACK_STATUS); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index f3a12205cd48..dc520effc61c 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -271,7 +271,7 @@ static __maybe_unused int max98373_resume(struct device *dev) struct max98373_priv *max98373 = dev_get_drvdata(dev); unsigned long time; - if (!max98373->hw_init) + if (!max98373->first_hw_init) return 0; if (!slave->unattach_request) @@ -362,7 +362,7 @@ static int max98373_io_init(struct sdw_slave *slave) struct device *dev = &slave->dev; struct max98373_priv *max98373 = dev_get_drvdata(dev); - if (max98373->pm_init_once) { + if (max98373->first_hw_init) { regcache_cache_only(max98373->regmap, false); regcache_cache_bypass(max98373->regmap, true); } @@ -370,7 +370,7 @@ static int max98373_io_init(struct sdw_slave *slave) /* * PM runtime is only enabled when a Slave reports as Attached */ - if (!max98373->pm_init_once) { + if (!max98373->first_hw_init) { /* set autosuspend parameters */ pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); @@ -462,12 +462,12 @@ static int max98373_io_init(struct sdw_slave *slave) regmap_write(max98373->regmap, MAX98373_R20B5_BDE_EN, 1); regmap_write(max98373->regmap, MAX98373_R20E2_LIMITER_EN, 1); - if (max98373->pm_init_once) { + if (max98373->first_hw_init) { regcache_cache_bypass(max98373->regmap, false); regcache_mark_dirty(max98373->regmap); } - max98373->pm_init_once = true; + max98373->first_hw_init = true; max98373->hw_init = true; pm_runtime_mark_last_busy(dev); @@ -787,6 +787,8 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) max98373->cache = devm_kcalloc(dev, max98373->cache_num, sizeof(*max98373->cache), GFP_KERNEL); + if (!max98373->cache) + return -ENOMEM; for (i = 0; i < max98373->cache_num; i++) max98373->cache[i].reg = max98373_sdw_cache_reg[i]; @@ -795,7 +797,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) max98373_slot_config(dev, max98373); max98373->hw_init = false; - max98373->pm_init_once = false; + max98373->first_hw_init = false; /* codec registration */ ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98373_sdw, diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 73a2cf69d84a..e1810b3b1620 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -226,7 +226,7 @@ struct max98373_priv { /* variables to support soundwire */ struct sdw_slave *slave; bool hw_init; - bool pm_init_once; + bool first_hw_init; int slot; unsigned int rx_mask; }; diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 94773ccee9d5..b392567c2b3e 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -765,17 +765,26 @@ static int max98390_dsm_init(struct snd_soc_component *component) vendor = dmi_get_system_info(DMI_SYS_VENDOR); product = dmi_get_system_info(DMI_PRODUCT_NAME); - if (vendor && product) { - snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin", - vendor, product); + if (!strcmp(max98390->dsm_param_name, "default")) { + if (vendor && product) { + snprintf(filename, sizeof(filename), + "dsm_param_%s_%s.bin", vendor, product); + } else { + sprintf(filename, "dsm_param.bin"); + } } else { - sprintf(filename, "dsm_param.bin"); + snprintf(filename, sizeof(filename), "%s", + max98390->dsm_param_name); } ret = request_firmware(&fw, filename, component->dev); if (ret) { ret = request_firmware(&fw, "dsm_param.bin", component->dev); - if (ret) - goto err; + if (ret) { + ret = request_firmware(&fw, "dsmparam.bin", + component->dev); + if (ret) + goto err; + } } dev_dbg(component->dev, @@ -1047,6 +1056,11 @@ static int max98390_i2c_probe(struct i2c_client *i2c, __func__, max98390->ref_rdc_value, max98390->ambient_temp_value); + ret = device_property_read_string(&i2c->dev, "maxim,dsm_param_name", + &max98390->dsm_param_name); + if (ret) + max98390->dsm_param_name = "default"; + /* voltage/current slot configuration */ max98390_slot_config(i2c, max98390); diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h index e31516717d3b..c250740f73a2 100644 --- a/sound/soc/codecs/max98390.h +++ b/sound/soc/codecs/max98390.h @@ -662,5 +662,6 @@ struct max98390_priv { unsigned int i_l_slot; unsigned int ref_rdc_value; unsigned int ambient_temp_value; + const char *dsm_param_name; }; #endif diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c index 78314187d37e..6d3d170144a0 100644 --- a/sound/soc/codecs/mt6359-accdet.c +++ b/sound/soc/codecs/mt6359-accdet.c @@ -234,7 +234,7 @@ static void recover_eint_setting(struct mt6359_accdet *priv) static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv) { - int ret = 0; + int ret; unsigned int value = 0; regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, @@ -461,7 +461,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data) { struct mt6359_accdet *priv = data; unsigned int irq_val = 0, val = 0, value = 0; - int ret = 0; + int ret; mutex_lock(&priv->res_lock); regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val); @@ -551,7 +551,7 @@ static irqreturn_t mt6359_accdet_irq(int irq, void *data) static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv) { - int ret = 0; + int ret; struct device *dev = priv->dev; struct device_node *node = NULL; int pwm_deb[15] = {0}; @@ -926,7 +926,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev) { struct mt6359_accdet *priv; struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); - int ret = 0; + int ret; dev_dbg(&pdev->dev, "%s(), dev name %s\n", __func__, dev_name(&pdev->dev)); @@ -1057,22 +1057,7 @@ static struct platform_driver mt6359_accdet_driver = { .probe = mt6359_accdet_probe, }; -static int __init mt6359_accdet_driver_init(void) -{ - int ret = 0; - - ret = platform_driver_register(&mt6359_accdet_driver); - if (ret) - return -ENODEV; - return 0; -} - -static void __exit mt6359_accdet_driver_exit(void) -{ - platform_driver_unregister(&mt6359_accdet_driver); -} -module_init(mt6359_accdet_driver_init); -module_exit(mt6359_accdet_driver_exit); +module_platform_driver(mt6359_accdet_driver) /* Module information */ MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver"); diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 9238f12999aa..c0c5952cdff7 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -547,31 +547,6 @@ static int rt1015_bypass_boost_put(struct snd_kcontrol *kcontrol, return 0; } -static void rt1015_flush_work(struct work_struct *work) -{ - struct rt1015_priv *rt1015 = container_of(work, struct rt1015_priv, - flush_work.work); - struct snd_soc_component *component = rt1015->component; - unsigned int val, i; - - for (i = 0; i < 200; ++i) { - usleep_range(1000, 1500); - dev_dbg(component->dev, "Flush DAC (retry:%u)\n", i); - regmap_read(rt1015->regmap, RT1015_CLK_DET, &val); - if (val & 0x800) - break; - } - - regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x0597); - regmap_write(rt1015->regmap, RT1015_SYS_RST1, 0x05f7); - regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x0028); - - if (val & 0x800) - dev_dbg(component->dev, "Flush DAC completed.\n"); - else - dev_warn(component->dev, "Fail to flush DAC data.\n"); -} - static const struct snd_kcontrol_new rt1015_snd_controls[] = { SOC_SINGLE_TLV("DAC Playback Volume", RT1015_DAC1, RT1015_DAC_VOL_SFT, 127, 0, dac_vol_tlv), @@ -630,10 +605,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, } break; - case SND_SOC_DAPM_POST_PMU: - regmap_write(rt1015->regmap, RT1015_MAN_I2C, 0x00a8); - break; - case SND_SOC_DAPM_POST_PMD: if (rt1015->bypass_boost == RT1015_Enable_Boost) { snd_soc_component_write(component, @@ -653,8 +624,6 @@ static int r1015_dac_event(struct snd_soc_dapm_widget *w, RT1015_SYS_RST2, 0x0b9a); } rt1015->dac_is_used = 0; - - cancel_delayed_work_sync(&rt1015->flush_work); break; default: @@ -687,8 +656,6 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: - if (rt1015->hw_config == RT1015_HW_28) - schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10)); msleep(rt1015->pdata.power_up_delay_ms); break; default: @@ -702,7 +669,7 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { NULL, 0), SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, - r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0, rt1015_amp_drv_event, SND_SOC_DAPM_PRE_PMU | @@ -722,7 +689,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - int pre_div, bclk_ms, frame_size, lrck; + int pre_div, frame_size, lrck; unsigned int val_len = 0; lrck = params_rate(params); @@ -739,10 +706,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_ms = frame_size > 32; - - dev_dbg(component->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", - bclk_ms, pre_div, dai->id); + dev_dbg(component->dev, "pre_div is %d for iis %d\n", pre_div, dai->id); dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d\n", lrck, pre_div, dai->id); @@ -1028,7 +992,6 @@ static int rt1015_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); rt1015->component = component; - INIT_DELAYED_WORK(&rt1015->flush_work, rt1015_flush_work); return 0; } @@ -1037,7 +1000,6 @@ static void rt1015_remove(struct snd_soc_component *component) { struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); - cancel_delayed_work_sync(&rt1015->flush_work); regmap_write(rt1015->regmap, RT1015_RESET, 0); } @@ -1180,8 +1142,6 @@ static int rt1015_i2c_probe(struct i2c_client *i2c, return ret; } - rt1015->hw_config = (i2c->addr == 0x29) ? RT1015_HW_29 : RT1015_HW_28; - ret = regmap_read(rt1015->regmap, RT1015_DEVICE_ID, &val); if (ret) { dev_err(&i2c->dev, diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index 14344532048e..c9f636af7fd1 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -444,8 +444,6 @@ struct rt1015_priv { int bypass_boost; int dac_is_used; int cali_done; - int hw_config; - struct delayed_work flush_work; }; #endif /* __RT1015_H__ */ diff --git a/sound/soc/codecs/rt1015p.c b/sound/soc/codecs/rt1015p.c index 40f2063aefbe..415cfb3b2f0d 100644 --- a/sound/soc/codecs/rt1015p.c +++ b/sound/soc/codecs/rt1015p.c @@ -127,6 +127,7 @@ static int rt1015p_platform_probe(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id rt1015p_device_id[] = { { .compatible = "realtek,rt1015p" }, + { .compatible = "realtek,rt1019p" }, {} }; MODULE_DEVICE_TABLE(of, rt1015p_device_id); @@ -135,6 +136,7 @@ MODULE_DEVICE_TABLE(of, rt1015p_device_id); #ifdef CONFIG_ACPI static const struct acpi_device_id rt1015p_acpi_match[] = { { "RTL1015", 0}, + { "RTL1019", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, rt1015p_acpi_match); diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 1c226994aebd..f716668de640 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -709,7 +709,7 @@ static int __maybe_unused rt1308_dev_resume(struct device *dev) struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); unsigned long time; - if (!rt1308->hw_init) + if (!rt1308->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 3b029c56467d..09b4914bba1b 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -701,7 +701,7 @@ static int __maybe_unused rt1316_dev_resume(struct device *dev) struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); unsigned long time; - if (!rt1316->hw_init) + if (!rt1316->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 7081142a355e..4b1ad5054e8d 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -494,7 +494,7 @@ static const struct snd_kcontrol_new rt5514_sto2_dmic_mux = */ static int rt5514_calc_dmic_clk(struct snd_soc_component *component, int rate) { - int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; + static const int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; int i; if (rate < 1000000 * div[0]) { diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 9523f4b5c800..cd1db5caabad 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2093,7 +2093,7 @@ int rt5640_sel_asrc_clk_src(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(rt5640_sel_asrc_clk_src); -static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component) +void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); @@ -2105,8 +2105,9 @@ static void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component) snd_soc_dapm_sync_unlocked(dapm); snd_soc_dapm_mutex_unlock(dapm); } +EXPORT_SYMBOL_GPL(rt5640_enable_micbias1_for_ovcd); -static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component) +void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); @@ -2117,6 +2118,7 @@ static void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component snd_soc_dapm_sync_unlocked(dapm); snd_soc_dapm_mutex_unlock(dapm); } +EXPORT_SYMBOL_GPL(rt5640_disable_micbias1_for_ovcd); static void rt5640_enable_micbias1_ovcd_irq(struct snd_soc_component *component) { @@ -2241,7 +2243,7 @@ static void rt5640_button_press_work(struct work_struct *work) schedule_delayed_work(&rt5640->bp_work, msecs_to_jiffies(BP_POLL_TIME)); } -static int rt5640_detect_headset(struct snd_soc_component *component) +int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio) { int i, headset_count = 0, headphone_count = 0; @@ -2259,8 +2261,13 @@ static int rt5640_detect_headset(struct snd_soc_component *component) msleep(JACK_SETTLE_TIME); /* Check the jack is still connected before checking ovcd */ - if (!rt5640_jack_inserted(component)) - return 0; + if (hp_det_gpio) { + if (gpiod_get_value_cansleep(hp_det_gpio)) + return 0; + } else { + if (!rt5640_jack_inserted(component)) + return 0; + } if (rt5640_micbias1_ovcd(component)) { /* @@ -2285,6 +2292,7 @@ static int rt5640_detect_headset(struct snd_soc_component *component) dev_err(component->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n"); return SND_JACK_HEADPHONE; } +EXPORT_SYMBOL_GPL(rt5640_detect_headset); static void rt5640_jack_work(struct work_struct *work) { @@ -2309,7 +2317,7 @@ static void rt5640_jack_work(struct work_struct *work) /* Jack inserted */ WARN_ON(rt5640->ovcd_irq_enabled); rt5640_enable_micbias1_for_ovcd(component); - status = rt5640_detect_headset(component); + status = rt5640_detect_headset(component, NULL); if (status == SND_JACK_HEADSET) { /* Enable ovcd IRQ for button press detect. */ rt5640_enable_micbias1_ovcd_irq(component); @@ -2362,10 +2370,59 @@ static void rt5640_cancel_work(void *data) cancel_delayed_work_sync(&rt5640->bp_work); } +void rt5640_set_ovcd_params(struct snd_soc_component *component) +{ + struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); + + snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4, + 0xa800 | rt5640->ovcd_sf); + + snd_soc_component_update_bits(component, RT5640_MICBIAS, + RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK, + rt5640->ovcd_th | RT5640_MIC1_OVCD_EN); + + /* + * The over-current-detect is only reliable in detecting the absence + * of over-current, when the mic-contact in the jack is short-circuited, + * the hardware periodically retries if it can apply the bias-current + * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about + * 10% of the time, as we poll the ovcd status bit we might hit that + * 10%, so we enable sticky mode and when checking OVCD we clear the + * status, msleep() a bit and then check to get a reliable reading. + */ + snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2, + RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN); +} +EXPORT_SYMBOL_GPL(rt5640_set_ovcd_params); + +static void rt5640_disable_jack_detect(struct snd_soc_component *component) +{ + struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); + + /* + * soc_remove_component() force-disables jack and thus rt5640->jack + * could be NULL at the time of driver's module unloading. + */ + if (!rt5640->jack) + return; + + free_irq(rt5640->irq, rt5640); + rt5640_cancel_work(rt5640); + + if (rt5640->jack->status & SND_JACK_MICROPHONE) { + rt5640_disable_micbias1_ovcd_irq(component); + rt5640_disable_micbias1_for_ovcd(component); + snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0); + } + + rt5640->jack = NULL; +} + static void rt5640_enable_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *jack) { struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); + int ret; /* Select JD-source */ snd_soc_component_update_bits(component, RT5640_JD_CTRL, @@ -2385,24 +2442,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, /* Enabling jd2 in general control 2 */ snd_soc_component_write(component, RT5640_DUMMY2, 0x4001); - snd_soc_component_write(component, RT5640_PR_BASE + RT5640_BIAS_CUR4, - 0xa800 | rt5640->ovcd_sf); - - snd_soc_component_update_bits(component, RT5640_MICBIAS, - RT5640_MIC1_OVTH_MASK | RT5640_MIC1_OVCD_MASK, - rt5640->ovcd_th | RT5640_MIC1_OVCD_EN); - - /* - * The over-current-detect is only reliable in detecting the absence - * of over-current, when the mic-contact in the jack is short-circuited, - * the hardware periodically retries if it can apply the bias-current - * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about - * 10% of the time, as we poll the ovcd status bit we might hit that - * 10%, so we enable sticky mode and when checking OVCD we clear the - * status, msleep() a bit and then check to get a reliable reading. - */ - snd_soc_component_update_bits(component, RT5640_IRQ_CTRL2, - RT5640_MB1_OC_STKY_MASK, RT5640_MB1_OC_STKY_EN); + rt5640_set_ovcd_params(component); /* * All IRQs get or-ed together, so we need the jack IRQ to report 0 @@ -2423,32 +2463,19 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, rt5640_enable_micbias1_ovcd_irq(component); } - enable_irq(rt5640->irq); - /* sync initial jack state */ - queue_work(system_long_wq, &rt5640->jack_work); -} - -static void rt5640_disable_jack_detect(struct snd_soc_component *component) -{ - struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); - - /* - * soc_remove_component() force-disables jack and thus rt5640->jack - * could be NULL at the time of driver's module unloading. - */ - if (!rt5640->jack) + ret = request_irq(rt5640->irq, rt5640_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "rt5640", rt5640); + if (ret) { + dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret); + rt5640->irq = -ENXIO; + /* Undo above settings */ + rt5640_disable_jack_detect(component); return; - - disable_irq(rt5640->irq); - rt5640_cancel_work(rt5640); - - if (rt5640->jack->status & SND_JACK_MICROPHONE) { - rt5640_disable_micbias1_ovcd_irq(component); - rt5640_disable_micbias1_for_ovcd(component); - snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0); } - rt5640->jack = NULL; + /* sync initial jack state */ + queue_work(system_long_wq, &rt5640->jack_work); } static int rt5640_set_jack(struct snd_soc_component *component, @@ -2836,18 +2863,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, if (ret) return ret; - ret = devm_request_irq(&i2c->dev, rt5640->irq, rt5640_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING - | IRQF_ONESHOT, "rt5640", rt5640); - if (ret == 0) { - /* Gets re-enabled by rt5640_set_jack() */ - disable_irq(rt5640->irq); - } else { - dev_warn(&i2c->dev, "Failed to reguest IRQ %d: %d\n", - rt5640->irq, ret); - rt5640->irq = -ENXIO; - } - return devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_rt5640, rt5640_dai, ARRAY_SIZE(rt5640_dai)); diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 4fd47f2b936b..2c28f83e338a 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -10,6 +10,7 @@ #define _RT5640_H #include <linux/clk.h> +#include <linux/gpio/consumer.h> #include <linux/workqueue.h> #include <dt-bindings/sound/rt5640.h> @@ -2157,4 +2158,9 @@ int rt5640_dmic_enable(struct snd_soc_component *component, int rt5640_sel_asrc_clk_src(struct snd_soc_component *component, unsigned int filter_mask, unsigned int clk_src); +void rt5640_set_ovcd_params(struct snd_soc_component *component); +void rt5640_enable_micbias1_for_ovcd(struct snd_soc_component *component); +void rt5640_disable_micbias1_for_ovcd(struct snd_soc_component *component); +int rt5640_detect_headset(struct snd_soc_component *component, struct gpio_desc *hp_det_gpio); + #endif diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 438fa18bcb55..9408ee63cb26 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3388,44 +3388,30 @@ static int rt5645_probe(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); - int ret = 0; rt5645->component = component; switch (rt5645->codec_type) { case CODEC_TYPE_RT5645: - ret = snd_soc_dapm_new_controls(dapm, + snd_soc_dapm_new_controls(dapm, rt5645_specific_dapm_widgets, ARRAY_SIZE(rt5645_specific_dapm_widgets)); - if (ret < 0) - goto exit; - - ret = snd_soc_dapm_add_routes(dapm, + snd_soc_dapm_add_routes(dapm, rt5645_specific_dapm_routes, ARRAY_SIZE(rt5645_specific_dapm_routes)); - if (ret < 0) - goto exit; - if (rt5645->v_id < 3) { - ret = snd_soc_dapm_add_routes(dapm, + snd_soc_dapm_add_routes(dapm, rt5645_old_dapm_routes, ARRAY_SIZE(rt5645_old_dapm_routes)); - if (ret < 0) - goto exit; } break; case CODEC_TYPE_RT5650: - ret = snd_soc_dapm_new_controls(dapm, + snd_soc_dapm_new_controls(dapm, rt5650_specific_dapm_widgets, ARRAY_SIZE(rt5650_specific_dapm_widgets)); - if (ret < 0) - goto exit; - - ret = snd_soc_dapm_add_routes(dapm, + snd_soc_dapm_add_routes(dapm, rt5650_specific_dapm_routes, ARRAY_SIZE(rt5650_specific_dapm_routes)); - if (ret < 0) - goto exit; break; } @@ -3433,17 +3419,9 @@ static int rt5645_probe(struct snd_soc_component *component) /* for JD function */ if (rt5645->pdata.jd_mode) { - ret = snd_soc_dapm_force_enable_pin(dapm, "JD Power"); - if (ret < 0) - goto exit; - - ret = snd_soc_dapm_force_enable_pin(dapm, "LDO2"); - if (ret < 0) - goto exit; - - ret = snd_soc_dapm_sync(dapm); - if (ret < 0) - goto exit; + snd_soc_dapm_force_enable_pin(dapm, "JD Power"); + snd_soc_dapm_force_enable_pin(dapm, "LDO2"); + snd_soc_dapm_sync(dapm); } if (rt5645->pdata.long_name) @@ -3454,14 +3432,9 @@ static int rt5645_probe(struct snd_soc_component *component) GFP_KERNEL); if (!rt5645->eq_param) - ret = -ENOMEM; -exit: - /* - * If there was an error above, everything will be cleaned up by the - * caller if we return an error here. This will be done with a later - * call to rt5645_remove(). - */ - return ret; + return -ENOMEM; + + return 0; } static void rt5645_remove(struct snd_soc_component *component) diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 4a56a52adab5..b9d5d7a0975b 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -117,6 +117,13 @@ static struct snd_soc_dai_driver rt5682_dai[] = { }, }; +static void rt5682_i2c_disable_regulators(void *data) +{ + struct rt5682_priv *rt5682 = data; + + regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies); +} + static int rt5682_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -157,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c, return ret; } + ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators, + rt5682); + if (ret) + return ret; + ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies); if (ret) { @@ -282,10 +294,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) static int rt5682_i2c_remove(struct i2c_client *client) { - struct rt5682_priv *rt5682 = i2c_get_clientdata(client); - rt5682_i2c_shutdown(client); - regulator_bulk_disable(ARRAY_SIZE(rt5682->supplies), rt5682->supplies); return 0; } diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index e78ba3b064c4..31a4f286043e 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -344,6 +344,8 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap, rt5682->sdw_regmap = regmap; rt5682->is_sdw = true; + mutex_init(&rt5682->disable_irq_lock); + rt5682->regmap = devm_regmap_init(dev, NULL, dev, &rt5682_sdw_indirect_regmap); if (IS_ERR(rt5682->regmap)) { @@ -378,6 +380,8 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) int ret = 0, loop = 10; unsigned int val; + rt5682->disable_irq = false; + if (rt5682->hw_init) return 0; @@ -400,6 +404,11 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) pm_runtime_get_noresume(&slave->dev); + if (rt5682->first_hw_init) { + regcache_cache_only(rt5682->regmap, false); + regcache_cache_bypass(rt5682->regmap, true); + } + while (loop > 0) { regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); if (val == DEVICE_ID) @@ -408,14 +417,11 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) usleep_range(30000, 30005); loop--; } + if (val != DEVICE_ID) { dev_err(dev, "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - - if (rt5682->first_hw_init) { - regcache_cache_only(rt5682->regmap, false); - regcache_cache_bypass(rt5682->regmap, true); + ret = -ENODEV; + goto err_nodev; } rt5682_calibrate(rt5682); @@ -486,10 +492,11 @@ reinit: rt5682->hw_init = true; rt5682->first_hw_init = true; +err_nodev: pm_runtime_mark_last_busy(&slave->dev); pm_runtime_put_autosuspend(&slave->dev); - dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + dev_dbg(&slave->dev, "%s hw_init complete: %d\n", __func__, ret); return ret; } @@ -676,10 +683,12 @@ static int rt5682_interrupt_callback(struct sdw_slave *slave, dev_dbg(&slave->dev, "%s control_port_stat=%x", __func__, status->control_port); - if (status->control_port & 0x4) { + mutex_lock(&rt5682->disable_irq_lock); + if (status->control_port & 0x4 && !rt5682->disable_irq) { mod_delayed_work(system_power_efficient_wq, &rt5682->jack_detect_work, msecs_to_jiffies(rt5682->irq_work_delay_time)); } + mutex_unlock(&rt5682->disable_irq_lock); return 0; } @@ -737,13 +746,41 @@ static int __maybe_unused rt5682_dev_suspend(struct device *dev) return 0; } +static int __maybe_unused rt5682_dev_system_suspend(struct device *dev) +{ + struct rt5682_priv *rt5682 = dev_get_drvdata(dev); + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret; + + if (!rt5682->hw_init) + return 0; + + /* + * prevent new interrupts from being handled after the + * deferred work completes and before the parent disables + * interrupts on the link + */ + mutex_lock(&rt5682->disable_irq_lock); + rt5682->disable_irq = true; + ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1, + SDW_SCP_INT1_IMPL_DEF, 0); + mutex_unlock(&rt5682->disable_irq_lock); + + if (ret < 0) { + /* log but don't prevent suspend from happening */ + dev_dbg(&slave->dev, "%s: could not disable imp-def interrupts\n:", __func__); + } + + return rt5682_dev_suspend(dev); +} + static int __maybe_unused rt5682_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt5682_priv *rt5682 = dev_get_drvdata(dev); unsigned long time; - if (!rt5682->hw_init) + if (!rt5682->first_hw_init) return 0; if (!slave->unattach_request) @@ -765,7 +802,7 @@ regmap_sync: } static const struct dev_pm_ops rt5682_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume) + SET_SYSTEM_SLEEP_PM_OPS(rt5682_dev_system_suspend, rt5682_dev_resume) SET_RUNTIME_PM_OPS(rt5682_dev_suspend, rt5682_dev_resume, NULL) }; diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index abcd6f483788..fcf442b8a732 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2915,10 +2915,46 @@ static void rt5682_remove(struct snd_soc_component *component) static int rt5682_suspend(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); + unsigned int val; if (rt5682->is_sdw) return 0; + cancel_delayed_work_sync(&rt5682->jack_detect_work); + cancel_delayed_work_sync(&rt5682->jd_check_work); + if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) { + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK, + RT5682_CTRL_MB1_REG | RT5682_CTRL_MB2_REG); + val = snd_soc_component_read(component, + RT5682_CBJ_CTRL_2) & RT5682_JACK_TYPE_MASK; + + switch (val) { + case 0x1: + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK, + RT5682_SAR_SEL_MB1_NOSEL | RT5682_SAR_SEL_MB2_SEL); + break; + case 0x2: + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_SEL_MB1_MASK | RT5682_SAR_SEL_MB2_MASK, + RT5682_SAR_SEL_MB1_SEL | RT5682_SAR_SEL_MB2_NOSEL); + break; + default: + break; + } + + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, + RT5682_PWR_CBJ, 0); + + /* enter SAR ADC power saving mode */ + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK, 0); + snd_soc_component_update_bits(component, RT5682_SAR_IL_CMD_1, + RT5682_SAR_BUTT_DET_MASK | RT5682_SAR_BUTDET_MODE_MASK | RT5682_SAR_BUTDET_RST_MASK, + RT5682_SAR_BUTT_DET_EN | RT5682_SAR_BUTDET_POW_SAV | RT5682_SAR_BUTDET_RST_NORMAL); + } + regcache_cache_only(rt5682->regmap, true); regcache_mark_dirty(rt5682->regmap); return 0; @@ -2934,6 +2970,14 @@ static int rt5682_resume(struct snd_soc_component *component) regcache_cache_only(rt5682->regmap, false); regcache_sync(rt5682->regmap); + if (rt5682->hs_jack && rt5682->jack_type == SND_JACK_HEADSET) { + snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, + RT5682_MB1_PATH_MASK | RT5682_MB2_PATH_MASK, + RT5682_CTRL_MB1_FSM | RT5682_CTRL_MB2_FSM); + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, + RT5682_PWR_CBJ, RT5682_PWR_CBJ); + } + mod_delayed_work(system_power_efficient_wq, &rt5682->jack_detect_work, msecs_to_jiffies(250)); diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 74ff66767016..b59221048ebf 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1415,6 +1415,8 @@ struct rt5682_priv { struct regulator_bulk_data supplies[RT5682_NUM_SUPPLIES]; struct delayed_work jack_detect_work; struct delayed_work jd_check_work; + struct mutex disable_irq_lock; /* imp-def irq lock protection */ + bool disable_irq; struct mutex calibrate_mutex; struct sdw_slave *slave; enum sdw_slave_status status; diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index ff9c081fd52a..bda594899664 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -418,10 +418,12 @@ static int rt700_interrupt_callback(struct sdw_slave *slave, dev_dbg(&slave->dev, "%s control_port_stat=%x", __func__, status->control_port); - if (status->control_port & 0x4) { + mutex_lock(&rt700->disable_irq_lock); + if (status->control_port & 0x4 && !rt700->disable_irq) { mod_delayed_work(system_power_efficient_wq, &rt700->jack_detect_work, msecs_to_jiffies(250)); } + mutex_unlock(&rt700->disable_irq_lock); return 0; } @@ -490,6 +492,34 @@ static int __maybe_unused rt700_dev_suspend(struct device *dev) return 0; } +static int __maybe_unused rt700_dev_system_suspend(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt700_priv *rt700 = dev_get_drvdata(dev); + int ret; + + if (!rt700->hw_init) + return 0; + + /* + * prevent new interrupts from being handled after the + * deferred work completes and before the parent disables + * interrupts on the link + */ + mutex_lock(&rt700->disable_irq_lock); + rt700->disable_irq = true; + ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1, + SDW_SCP_INT1_IMPL_DEF, 0); + mutex_unlock(&rt700->disable_irq_lock); + + if (ret < 0) { + /* log but don't prevent suspend from happening */ + dev_dbg(&slave->dev, "%s: could not disable imp-def interrupts\n:", __func__); + } + + return rt700_dev_suspend(dev); +} + #define RT700_PROBE_TIMEOUT 5000 static int __maybe_unused rt700_dev_resume(struct device *dev) @@ -498,7 +528,7 @@ static int __maybe_unused rt700_dev_resume(struct device *dev) struct rt700_priv *rt700 = dev_get_drvdata(dev); unsigned long time; - if (!rt700->hw_init) + if (!rt700->first_hw_init) return 0; if (!slave->unattach_request) @@ -521,7 +551,7 @@ regmap_sync: } static const struct dev_pm_ops rt700_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt700_dev_suspend, rt700_dev_resume) + SET_SYSTEM_SLEEP_PM_OPS(rt700_dev_system_suspend, rt700_dev_resume) SET_RUNTIME_PM_OPS(rt700_dev_suspend, rt700_dev_resume, NULL) }; diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 01af9d9dd3ca..921382724f9c 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -1112,6 +1112,8 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap, rt700->sdw_regmap = sdw_regmap; rt700->regmap = regmap; + mutex_init(&rt700->disable_irq_lock); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1133,6 +1135,8 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave) { struct rt700_priv *rt700 = dev_get_drvdata(dev); + rt700->disable_irq = false; + if (rt700->hw_init) return 0; diff --git a/sound/soc/codecs/rt700.h b/sound/soc/codecs/rt700.h index 794ee2e29051..bed9d1de6d5b 100644 --- a/sound/soc/codecs/rt700.h +++ b/sound/soc/codecs/rt700.h @@ -23,6 +23,8 @@ struct rt700_priv { struct delayed_work jack_detect_work; struct delayed_work jack_btn_check_work; int jack_type; + struct mutex disable_irq_lock; /* imp-def irq lock protection */ + bool disable_irq; }; struct sdw_stream_data { diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index 9685c8905468..aaf5af153d3f 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -75,6 +75,16 @@ static bool rt711_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x5b00000 ... 0x5b000ff: case 0x5f00000 ... 0x5f000ff: case 0x6100000 ... 0x61000ff: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R): return true; default: return false; @@ -246,6 +256,15 @@ static int rt711_sdca_interrupt_callback(struct sdw_slave *slave, scp_sdca_stat2 = rt711->scp_sdca_stat2; } + /* + * The critical section below intentionally protects a rather large piece of code. + * We don't want to allow the system suspend to disable an interrupt while we are + * processing it, which could be problematic given the quirky SoundWire interrupt + * scheme. We do want however to prevent new workqueues from being scheduled if + * the disable_irq flag was set during system suspend. + */ + mutex_lock(&rt711->disable_irq_lock); + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error; @@ -304,13 +323,16 @@ static int rt711_sdca_interrupt_callback(struct sdw_slave *slave, "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, rt711->scp_sdca_stat1, rt711->scp_sdca_stat2); - if (status->sdca_cascade) + if (status->sdca_cascade && !rt711->disable_irq) mod_delayed_work(system_power_efficient_wq, &rt711->jack_detect_work, msecs_to_jiffies(30)); + mutex_unlock(&rt711->disable_irq_lock); + return 0; io_error: + mutex_unlock(&rt711->disable_irq_lock); pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); return ret; } @@ -372,6 +394,36 @@ static int __maybe_unused rt711_sdca_dev_suspend(struct device *dev) return 0; } +static int __maybe_unused rt711_sdca_dev_system_suspend(struct device *dev) +{ + struct rt711_sdca_priv *rt711_sdca = dev_get_drvdata(dev); + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret1, ret2; + + if (!rt711_sdca->hw_init) + return 0; + + /* + * prevent new interrupts from being handled after the + * deferred work completes and before the parent disables + * interrupts on the link + */ + mutex_lock(&rt711_sdca->disable_irq_lock); + rt711_sdca->disable_irq = true; + ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1, + SDW_SCP_SDCA_INTMASK_SDCA_0, 0); + ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_8, 0); + mutex_unlock(&rt711_sdca->disable_irq_lock); + + if (ret1 < 0 || ret2 < 0) { + /* log but don't prevent suspend from happening */ + dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__); + } + + return rt711_sdca_dev_suspend(dev); +} + #define RT711_PROBE_TIMEOUT 5000 static int __maybe_unused rt711_sdca_dev_resume(struct device *dev) @@ -380,7 +432,7 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev) struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); unsigned long time; - if (!rt711->hw_init) + if (!rt711->first_hw_init) return 0; if (!slave->unattach_request) @@ -403,7 +455,7 @@ regmap_sync: } static const struct dev_pm_ops rt711_sdca_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume) + SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_system_suspend, rt711_sdca_dev_resume) SET_RUNTIME_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume, NULL) }; diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 24a084e0b48a..2e992589f1e4 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1411,6 +1411,8 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, rt711->regmap = regmap; rt711->mbq_regmap = mbq_regmap; + mutex_init(&rt711->disable_irq_lock); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1494,12 +1496,16 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) int ret = 0; unsigned int val; + rt711->disable_irq = false; + if (rt711->hw_init) return 0; if (rt711->first_hw_init) { regcache_cache_only(rt711->regmap, false); regcache_cache_bypass(rt711->regmap, true); + regcache_cache_only(rt711->mbq_regmap, false); + regcache_cache_bypass(rt711->mbq_regmap, true); } else { /* * PM runtime is only enabled when a Slave reports as Attached @@ -1565,6 +1571,8 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) if (rt711->first_hw_init) { regcache_cache_bypass(rt711->regmap, false); regcache_mark_dirty(rt711->regmap); + regcache_cache_bypass(rt711->mbq_regmap, false); + regcache_mark_dirty(rt711->mbq_regmap); } else rt711->first_hw_init = true; diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h index 43ae82b7fdb3..498ca687c47b 100644 --- a/sound/soc/codecs/rt711-sdca.h +++ b/sound/soc/codecs/rt711-sdca.h @@ -27,6 +27,8 @@ struct rt711_sdca_priv { struct delayed_work jack_detect_work; struct delayed_work jack_btn_check_work; struct mutex calibrate_mutex; /* for headset calibration */ + struct mutex disable_irq_lock; /* SDCA irq lock protection */ + bool disable_irq; int jack_type, jd_src; unsigned int scp_sdca_stat1, scp_sdca_stat2; int hw_ver; diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 8f5ebe92d407..bda2cc9439c9 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -423,10 +423,12 @@ static int rt711_interrupt_callback(struct sdw_slave *slave, dev_dbg(&slave->dev, "%s control_port_stat=%x", __func__, status->control_port); - if (status->control_port & 0x4) { + mutex_lock(&rt711->disable_irq_lock); + if (status->control_port & 0x4 && !rt711->disable_irq) { mod_delayed_work(system_power_efficient_wq, &rt711->jack_detect_work, msecs_to_jiffies(250)); } + mutex_unlock(&rt711->disable_irq_lock); return 0; } @@ -493,6 +495,34 @@ static int __maybe_unused rt711_dev_suspend(struct device *dev) return 0; } +static int __maybe_unused rt711_dev_system_suspend(struct device *dev) +{ + struct rt711_priv *rt711 = dev_get_drvdata(dev); + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret; + + if (!rt711->hw_init) + return 0; + + /* + * prevent new interrupts from being handled after the + * deferred work completes and before the parent disables + * interrupts on the link + */ + mutex_lock(&rt711->disable_irq_lock); + rt711->disable_irq = true; + ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1, + SDW_SCP_INT1_IMPL_DEF, 0); + mutex_unlock(&rt711->disable_irq_lock); + + if (ret < 0) { + /* log but don't prevent suspend from happening */ + dev_dbg(&slave->dev, "%s: could not disable imp-def interrupts\n:", __func__); + } + + return rt711_dev_suspend(dev); +} + #define RT711_PROBE_TIMEOUT 5000 static int __maybe_unused rt711_dev_resume(struct device *dev) @@ -501,7 +531,7 @@ static int __maybe_unused rt711_dev_resume(struct device *dev) struct rt711_priv *rt711 = dev_get_drvdata(dev); unsigned long time; - if (!rt711->hw_init) + if (!rt711->first_hw_init) return 0; if (!slave->unattach_request) @@ -524,7 +554,7 @@ regmap_sync: } static const struct dev_pm_ops rt711_pm = { - SET_SYSTEM_SLEEP_PM_OPS(rt711_dev_suspend, rt711_dev_resume) + SET_SYSTEM_SLEEP_PM_OPS(rt711_dev_system_suspend, rt711_dev_resume) SET_RUNTIME_PM_OPS(rt711_dev_suspend, rt711_dev_resume, NULL) }; diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index abaf150cc087..a7c5608a0ef8 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1196,6 +1196,8 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, rt711->sdw_regmap = sdw_regmap; rt711->regmap = regmap; + mutex_init(&rt711->disable_irq_lock); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1220,6 +1222,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) { struct rt711_priv *rt711 = dev_get_drvdata(dev); + rt711->disable_irq = false; + if (rt711->hw_init) return 0; diff --git a/sound/soc/codecs/rt711.h b/sound/soc/codecs/rt711.h index 5f2ba1341085..f50f8c8d0934 100644 --- a/sound/soc/codecs/rt711.h +++ b/sound/soc/codecs/rt711.h @@ -25,6 +25,8 @@ struct rt711_priv { struct work_struct calibration_work; struct mutex calibrate_mutex; /* for headset calibration */ int jack_type, jd_src; + struct mutex disable_irq_lock; /* imp-def irq lock protection */ + bool disable_irq; }; struct sdw_stream_data { diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 1350798406f0..a5c673f43d82 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -70,6 +70,7 @@ static bool rt715_sdca_mbq_readable_register(struct device *dev, unsigned int re case 0x2000036: case 0x2000037: case 0x2000039: + case 0x2000044: case 0x6100000: return true; default: @@ -224,7 +225,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev) struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); unsigned long time; - if (!rt715->hw_init) + if (!rt715->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt715-sdca-sdw.h b/sound/soc/codecs/rt715-sdca-sdw.h index cd365bb60747..0cbc14844f8c 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.h +++ b/sound/soc/codecs/rt715-sdca-sdw.h @@ -113,6 +113,7 @@ static const struct reg_default rt715_mbq_reg_defaults_sdca[] = { { 0x2000036, 0x0000 }, { 0x2000037, 0x0000 }, { 0x2000039, 0xaa81 }, + { 0x2000044, 0x0202 }, { 0x6100000, 0x0100 }, { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 7db76c19e048..66e166568c50 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -997,7 +997,7 @@ int rt715_sdca_init(struct device *dev, struct regmap *mbq_regmap, * HW init will be performed when device reports present */ rt715->hw_init = false; - rt715->first_init = false; + rt715->first_hw_init = false; ret = devm_snd_soc_register_component(dev, &soc_codec_dev_rt715_sdca, @@ -1018,7 +1018,7 @@ int rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave) /* * PM runtime is only enabled when a Slave reports as Attached */ - if (!rt715->first_init) { + if (!rt715->first_hw_init) { /* set autosuspend parameters */ pm_runtime_set_autosuspend_delay(&slave->dev, 3000); pm_runtime_use_autosuspend(&slave->dev); @@ -1031,7 +1031,7 @@ int rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave) pm_runtime_enable(&slave->dev); - rt715->first_init = true; + rt715->first_hw_init = true; } pm_runtime_get_noresume(&slave->dev); @@ -1054,6 +1054,9 @@ int rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, RT715_REV_1, 0x40, 0x40); } + /* DFLL Calibration trigger */ + rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, + RT715_DFLL_VAD, 0x1, 0x1); /* trigger mode = VAD enable */ regmap_write(rt715->regmap, SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, diff --git a/sound/soc/codecs/rt715-sdca.h b/sound/soc/codecs/rt715-sdca.h index 85ce4d95e5eb..90881b455ece 100644 --- a/sound/soc/codecs/rt715-sdca.h +++ b/sound/soc/codecs/rt715-sdca.h @@ -27,7 +27,7 @@ struct rt715_sdca_priv { enum sdw_slave_status status; struct sdw_bus_params params; bool hw_init; - bool first_init; + bool first_hw_init; int l_is_unmute; int r_is_unmute; int hw_sdw_ver; @@ -81,6 +81,7 @@ struct rt715_sdca_kcontrol_private { #define RT715_AD_FUNC_EN 0x36 #define RT715_REV_1 0x37 #define RT715_SDW_INPUT_SEL 0x39 +#define RT715_DFLL_VAD 0x44 #define RT715_EXT_DMIC_CLK_CTRL2 0x54 /* Index (NID:61h) */ diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 81a1dd77b6f6..a7b21b03c08b 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -541,7 +541,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev) struct rt715_priv *rt715 = dev_get_drvdata(dev); unsigned long time; - if (!rt715->hw_init) + if (!rt715->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c new file mode 100644 index 000000000000..a4f79eb2c69d --- /dev/null +++ b/sound/soc/codecs/sdw-mockup.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// sdw-mockup.c -- a mockup SoundWire codec for tests where only the host +// drives the bus. +// +// Copyright(c) 2021 Intel Corporation +// +// + +#include <linux/device.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <linux/soundwire/sdw_registers.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> + +struct sdw_mockup_priv { + struct sdw_slave *slave; +}; + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +static int sdw_mockup_component_probe(struct snd_soc_component *component) +{ + return 0; +} + +static void sdw_mockup_component_remove(struct snd_soc_component *component) +{ +} + +static const struct snd_soc_component_driver snd_soc_sdw_mockup_component = { + .probe = sdw_mockup_component_probe, + .remove = sdw_mockup_component_remove, +}; + +static int sdw_mockup_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void sdw_mockup_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int sdw_mockup_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int num_channels; + int port; + int ret; + + stream = snd_soc_dai_get_dma_data(dai, substream); + if (!stream) + return -EINVAL; + + if (!sdw_mockup->slave) + return -EINVAL; + + /* SoundWire specific configuration */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port = 1; + } else { + direction = SDW_DATA_DIR_TX; + port = 8; + } + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = (1 << num_channels) - 1; + port_config.num = port; + + ret = sdw_stream_add_slave(sdw_mockup->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (ret) + dev_err(dai->dev, "Unable to configure port\n"); + + return ret; +} + +static int sdw_mockup_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct sdw_mockup_priv *sdw_mockup = snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!sdw_mockup->slave) + return -EINVAL; + + sdw_stream_remove_slave(sdw_mockup->slave, stream->sdw_stream); + return 0; +} + +static const struct snd_soc_dai_ops sdw_mockup_ops = { + .hw_params = sdw_mockup_pcm_hw_params, + .hw_free = sdw_mockup_pcm_hw_free, + .set_sdw_stream = sdw_mockup_set_sdw_stream, + .shutdown = sdw_mockup_shutdown, +}; + +static struct snd_soc_dai_driver sdw_mockup_dai[] = { + { + .name = "sdw-mockup-aif1", + .id = 1, + .playback = { + .stream_name = "DP1 Playback", + .channels_min = 1, + .channels_max = 2, + }, + .capture = { + .stream_name = "DP8 Capture", + .channels_min = 1, + .channels_max = 2, + }, + .ops = &sdw_mockup_ops, + }, +}; + +static int sdw_mockup_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + return 0; +} + +static int sdw_mockup_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval; + int i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->paging_support = false; + + /* + * first we need to allocate memory for set bits in port lists + * the port allocation is completely arbitrary: + * DP0 is not supported + * DP1 is sink + * DP8 is source + */ + prop->source_ports = BIT(8); + prop->sink_ports = BIT(1); + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = true; + j++; + } + + prop->simple_clk_stop_capable = true; + + /* wake-up event */ + prop->wake_capable = 0; + + return 0; +} + +static int sdw_mockup_bus_config(struct sdw_slave *slave, + struct sdw_bus_params *params) +{ + return 0; +} + +static int sdw_mockup_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + return 0; +} + +static const struct sdw_slave_ops sdw_mockup_slave_ops = { + .read_prop = sdw_mockup_read_prop, + .interrupt_callback = sdw_mockup_interrupt_callback, + .update_status = sdw_mockup_update_status, + .bus_config = sdw_mockup_bus_config, +}; + +static int sdw_mockup_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct device *dev = &slave->dev; + struct sdw_mockup_priv *sdw_mockup; + int ret; + + sdw_mockup = devm_kzalloc(dev, sizeof(*sdw_mockup), GFP_KERNEL); + if (!sdw_mockup) + return -ENOMEM; + + dev_set_drvdata(dev, sdw_mockup); + sdw_mockup->slave = slave; + + ret = devm_snd_soc_register_component(dev, + &snd_soc_sdw_mockup_component, + sdw_mockup_dai, + ARRAY_SIZE(sdw_mockup_dai)); + + return ret; +} + +static int sdw_mockup_sdw_remove(struct sdw_slave *slave) +{ + return 0; +} + +/* + * Intel reserved parts ID with the following mapping expected: + * 0xAAAA: generic full-duplex codec + * 0xAA55: headset codec (mock-up of RT711/RT5682) - full-duplex + * 0x55AA: amplifier (mock-up of RT1308/Maxim 98373) - playback only with + * IV feedback + * 0x5555: mic codec (mock-up of RT715) - capture-only + */ +static const struct sdw_device_id sdw_mockup_id[] = { + SDW_SLAVE_ENTRY_EXT(0x0105, 0xAAAA, 0x0, 0, 0), + SDW_SLAVE_ENTRY_EXT(0x0105, 0xAA55, 0x0, 0, 0), + SDW_SLAVE_ENTRY_EXT(0x0105, 0x55AA, 0x0, 0, 0), + SDW_SLAVE_ENTRY_EXT(0x0105, 0x5555, 0x0, 0, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, sdw_mockup_id); + +static struct sdw_driver sdw_mockup_sdw_driver = { + .driver = { + .name = "sdw-mockup", + .owner = THIS_MODULE, + }, + .probe = sdw_mockup_sdw_probe, + .remove = sdw_mockup_sdw_remove, + .ops = &sdw_mockup_slave_ops, + .id_table = sdw_mockup_id, +}; +module_sdw_driver(sdw_mockup_sdw_driver); + +MODULE_DESCRIPTION("ASoC SDW mockup codec driver"); +MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 2e9175b37dc9..d39c7d52ecfd 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -714,7 +714,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, unsigned long adc_clock_rate, dac_clock_rate; int ret; - struct clk_bulk_data clocks[] = { + static struct clk_bulk_data clocks[] = { { .id = "pll" }, { .id = "nadc" }, { .id = "madc" }, @@ -878,7 +878,7 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, { int ret; - struct clk_bulk_data clocks[] = { + static struct clk_bulk_data clocks[] = { { .id = "madc" }, { .id = "mdac" }, { .id = "bdiv" }, @@ -994,7 +994,7 @@ static int aic32x4_component_probe(struct snd_soc_component *component) u32 tmp_reg; int ret; - struct clk_bulk_data clocks[] = { + static struct clk_bulk_data clocks[] = { { .id = "codec_clkin" }, { .id = "pll" }, { .id = "bdiv" }, @@ -1131,7 +1131,7 @@ static struct snd_soc_dai_driver aic32x4_tas2505_dai = { .playback = { .stream_name = "Playback", .channels_min = 1, - .channels_max = 1, + .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_96000, .formats = AIC32X4_FORMATS,}, .ops = &aic32x4_ops, @@ -1144,7 +1144,7 @@ static int aic32x4_tas2505_component_probe(struct snd_soc_component *component) u32 tmp_reg; int ret; - struct clk_bulk_data clocks[] = { + static struct clk_bulk_data clocks[] = { { .id = "codec_clkin" }, { .id = "pll" }, { .id = "bdiv" }, diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 2fcc97370be2..f0daf8defcf1 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -21,6 +21,7 @@ #include <linux/regulator/consumer.h> #include "wcd-clsh-v2.h" +#include "wcd-mbhc-v2.h" #include "wcd938x.h" #define WCD938X_MAX_MICBIAS (4) @@ -173,6 +174,11 @@ struct wcd938x_priv { struct device *rxdev; struct device_node *rxnode, *txnode; struct regmap *regmap; + struct mutex micb_lock; + /* mbhc module */ + struct wcd_mbhc *wcd_mbhc; + struct wcd_mbhc_config mbhc_cfg; + struct wcd_mbhc_intr intr_ids; struct wcd_clsh_ctrl *clsh_info; struct irq_domain *virq; struct regmap_irq_chip *wcd_regmap_irq_chip; @@ -201,24 +207,70 @@ struct wcd938x_priv { bool bcs_dis; }; -enum { - MIC_BIAS_1 = 1, - MIC_BIAS_2, - MIC_BIAS_3, - MIC_BIAS_4 -}; - -enum { - MICB_PULLUP_ENABLE, - MICB_PULLUP_DISABLE, - MICB_ENABLE, - MICB_DISABLE, -}; - static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800); static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000); static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000); +struct wcd938x_mbhc_zdet_param { + u16 ldo_ctl; + u16 noff; + u16 nshift; + u16 btn5; + u16 btn6; + u16 btn7; +}; + +static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { + WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD938X_ANA_MBHC_MECH, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD938X_ANA_MBHC_MECH, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD938X_ANA_MBHC_MECH, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x30), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD938X_ANA_MBHC_ELECT, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x1F), + WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD938X_ANA_MBHC_MECH, 0x04), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD938X_ANA_MBHC_MECH, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD938X_ANA_MBHC_MECH, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD938X_ANA_MBHC_ELECT, 0x06), + WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD938X_ANA_MBHC_ELECT, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F), + WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD938X_MBHC_NEW_CTL_1, 0x03), + WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD938X_MBHC_NEW_CTL_2, 0x03), + WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD938X_ANA_MBHC_RESULT_3, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD938X_HPH_OCP_CTL, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0x07), + WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD938X_ANA_MBHC_ELECT, 0x70), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD938X_ANA_MBHC_RESULT_3, 0xFF), + WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD938X_ANA_MICB2, 0xC0), + WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD938X_HPH_CNP_WG_TIME, 0xFF), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD938X_ANA_HPH, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD938X_ANA_HPH, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD938X_ANA_HPH, 0xC0), + WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD938X_ANA_MBHC_RESULT_3, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD938X_MBHC_CTL_BCS, 0x02), + WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD938X_MBHC_NEW_CTL_2, 0x70), + WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD938X_MBHC_NEW_FSM_STATUS, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD938X_HPH_PA_CTL2, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD938X_HPH_PA_CTL2, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD938X_HPH_L_TEST, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD938X_HPH_R_TEST, 0x01), + WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD938X_DIGITAL_INTR_STATUS_0, 0x20), + WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD938X_MBHC_NEW_CTL_1, 0x08), + WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD938X_MBHC_NEW_FSM_STATUS, 0x40), + WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD938X_MBHC_NEW_FSM_STATUS, 0x80), + WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD938X_MBHC_NEW_ADC_RESULT, 0xFF), + WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD938X_ANA_MICB2, 0x3F), + WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD938X_MBHC_NEW_CTL_1, 0x10), + WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD938X_MBHC_NEW_CTL_1, 0x04), + WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02), +}; + static const struct reg_default wcd938x_defaults[] = { {WCD938X_ANA_PAGE_REGISTER, 0x00}, {WCD938X_ANA_BIAS, 0x00}, @@ -1360,7 +1412,6 @@ static int wcd938x_io_init(struct wcd938x_priv *wcd938x) static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, struct sdw_port_config *port_config, - u32 mstr_port_num, u8 enable) { u8 ch_mask, port_num; @@ -1380,14 +1431,12 @@ static int wcd938x_sdw_connect_port(struct wcd938x_sdw_ch_info *ch_info, static int wcd938x_connect_port(struct wcd938x_sdw_priv *wcd, u8 ch_id, u8 enable) { - u8 port_num, mstr_port_num; + u8 port_num; port_num = wcd->ch_info[ch_id].port_num; - mstr_port_num = wcd->port_map[port_num - 1]; return wcd938x_sdw_connect_port(&wcd->ch_info[ch_id], &wcd->port_config[port_num], - mstr_port_num, enable); } @@ -1623,7 +1672,6 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); - int ret = 0; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1651,7 +1699,7 @@ static int wcd938x_codec_aux_dac_event(struct snd_soc_dapm_widget *w, WCD938X_ANA_RX_DIV4_CLK_EN_MASK, 0); break; } - return ret; + return 0; } @@ -1728,6 +1776,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); snd_soc_component_write_field(component, WCD938X_ANA_HPH, WCD938X_HPHR_EN_MASK, 0); + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_PRE_HPHR_PA_OFF); set_bit(HPH_PA_DELAY, &wcd938x->status_mask); break; case SND_SOC_DAPM_POST_PMD: @@ -1743,6 +1793,8 @@ static int wcd938x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); } + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_HPHR_PA_OFF); snd_soc_component_write_field(component, WCD938X_ANA_HPH, WCD938X_HPHR_REF_EN_MASK, 0); snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL1, @@ -1830,6 +1882,7 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); snd_soc_component_write_field(component, WCD938X_ANA_HPH, WCD938X_HPHL_EN_MASK, 0); + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, WCD_EVENT_PRE_HPHL_PA_OFF); set_bit(HPH_PA_DELAY, &wcd938x->status_mask); break; case SND_SOC_DAPM_POST_PMD: @@ -1845,6 +1898,8 @@ static int wcd938x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &wcd938x->status_mask); } + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_HPHL_PA_OFF); snd_soc_component_write_field(component, WCD938X_ANA_HPH, WCD938X_HPHL_REF_EN_MASK, 0); snd_soc_component_write_field(component, WCD938X_DIGITAL_PDM_WD_CTL0, @@ -1866,7 +1921,6 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); int hph_mode = wcd938x->hph_mode; - int ret = 0; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1902,7 +1956,7 @@ static int wcd938x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w, WCD938X_EN_CUR_DET_MASK, 1); break; } - return ret; + return 0; } static int wcd938x_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, @@ -2355,7 +2409,14 @@ static int wcd938x_micbias_control(struct snd_soc_component *component, snd_soc_component_write_field(component, micb_reg, WCD938X_MICB_EN_MASK, WCD938X_MICB_ENABLE); + if (micb_num == MIC_BIAS_2) + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_MICBIAS_2_ON); } + if (micb_num == MIC_BIAS_2 && is_dapm) + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_DAPM_MICBIAS_2_ON); + break; case MICB_DISABLE: @@ -2369,10 +2430,19 @@ static int wcd938x_micbias_control(struct snd_soc_component *component, WCD938X_MICB_PULL_UP); else if ((wcd938x->micb_ref[micb_index] == 0) && (wcd938x->pullup_ref[micb_index] == 0)) { + if (micb_num == MIC_BIAS_2) + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_PRE_MICBIAS_2_OFF); snd_soc_component_write_field(component, micb_reg, WCD938X_MICB_EN_MASK, 0); + if (micb_num == MIC_BIAS_2) + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_MICBIAS_2_OFF); } + if (is_dapm && micb_num == MIC_BIAS_2) + wcd_mbhc_event_notify(wcd938x->wcd_mbhc, + WCD_EVENT_POST_DAPM_MICBIAS_2_OFF); break; } @@ -2845,6 +2915,704 @@ static int wcd938x_set_swr_port(struct snd_kcontrol *kcontrol, } +/* MBHC related */ +static void wcd938x_mbhc_clk_setup(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_1, + WCD938X_MBHC_CTL_RCO_EN_MASK, enable); +} + +static void wcd938x_mbhc_mbhc_bias_control(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_ELECT, + WCD938X_ANA_MBHC_BIAS_EN, enable); +} + +static void wcd938x_mbhc_program_btn_thr(struct snd_soc_component *component, + int *btn_low, int *btn_high, + int num_btn, bool is_micbias) +{ + int i, vth; + + if (num_btn > WCD_MBHC_DEF_BUTTONS) { + dev_err(component->dev, "%s: invalid number of buttons: %d\n", + __func__, num_btn); + return; + } + + for (i = 0; i < num_btn; i++) { + vth = ((btn_high[i] * 2) / 25) & 0x3F; + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_BTN0 + i, + WCD938X_MBHC_BTN_VTH_MASK, vth); + dev_dbg(component->dev, "%s: btn_high[%d]: %d, vth: %d\n", + __func__, i, btn_high[i], vth); + } +} + +static bool wcd938x_mbhc_micb_en_status(struct snd_soc_component *component, int micb_num) +{ + u8 val; + + if (micb_num == MIC_BIAS_2) { + val = snd_soc_component_read_field(component, + WCD938X_ANA_MICB2, + WCD938X_ANA_MICB2_ENABLE_MASK); + if (val == WCD938X_MICB_ENABLE) + return true; + } + return false; +} + +static void wcd938x_mbhc_hph_l_pull_up_control(struct snd_soc_component *component, + int pull_up_cur) +{ + /* Default pull up current to 2uA */ + if (pull_up_cur > HS_PULLUP_I_OFF || pull_up_cur < HS_PULLUP_I_3P0_UA) + pull_up_cur = HS_PULLUP_I_2P0_UA; + + snd_soc_component_write_field(component, + WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, + WCD938X_HSDET_PULLUP_C_MASK, pull_up_cur); +} + +static int wcd938x_mbhc_request_micbias(struct snd_soc_component *component, + int micb_num, int req) +{ + return wcd938x_micbias_control(component, micb_num, req, false); +} + +static void wcd938x_mbhc_micb_ramp_control(struct snd_soc_component *component, + bool enable) +{ + if (enable) { + snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, + WCD938X_RAMP_SHIFT_CTRL_MASK, 0x0C); + snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, + WCD938X_RAMP_EN_MASK, 1); + } else { + snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, + WCD938X_RAMP_EN_MASK, 0); + snd_soc_component_write_field(component, WCD938X_ANA_MICB2_RAMP, + WCD938X_RAMP_SHIFT_CTRL_MASK, 0); + } +} + +static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv) +{ + /* min micbias voltage is 1V and maximum is 2.85V */ + if (micb_mv < 1000 || micb_mv > 2850) + return -EINVAL; + + return (micb_mv - 1000) / 50; +} + +static int wcd938x_mbhc_micb_adjust_voltage(struct snd_soc_component *component, + int req_volt, int micb_num) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int cur_vout_ctl, req_vout_ctl, micb_reg, micb_en, ret = 0; + + switch (micb_num) { + case MIC_BIAS_1: + micb_reg = WCD938X_ANA_MICB1; + break; + case MIC_BIAS_2: + micb_reg = WCD938X_ANA_MICB2; + break; + case MIC_BIAS_3: + micb_reg = WCD938X_ANA_MICB3; + break; + case MIC_BIAS_4: + micb_reg = WCD938X_ANA_MICB4; + break; + default: + return -EINVAL; + } + mutex_lock(&wcd938x->micb_lock); + /* + * If requested micbias voltage is same as current micbias + * voltage, then just return. Otherwise, adjust voltage as + * per requested value. If micbias is already enabled, then + * to avoid slow micbias ramp-up or down enable pull-up + * momentarily, change the micbias value and then re-enable + * micbias. + */ + micb_en = snd_soc_component_read_field(component, micb_reg, + WCD938X_MICB_EN_MASK); + cur_vout_ctl = snd_soc_component_read_field(component, micb_reg, + WCD938X_MICB_VOUT_MASK); + + req_vout_ctl = wcd938x_get_micb_vout_ctl_val(req_volt); + if (req_vout_ctl < 0) { + ret = -EINVAL; + goto exit; + } + + if (cur_vout_ctl == req_vout_ctl) { + ret = 0; + goto exit; + } + + if (micb_en == WCD938X_MICB_ENABLE) + snd_soc_component_write_field(component, micb_reg, + WCD938X_MICB_EN_MASK, + WCD938X_MICB_PULL_UP); + + snd_soc_component_write_field(component, micb_reg, + WCD938X_MICB_VOUT_MASK, + req_vout_ctl); + + if (micb_en == WCD938X_MICB_ENABLE) { + snd_soc_component_write_field(component, micb_reg, + WCD938X_MICB_EN_MASK, + WCD938X_MICB_ENABLE); + /* + * Add 2ms delay as per HW requirement after enabling + * micbias + */ + usleep_range(2000, 2100); + } +exit: + mutex_unlock(&wcd938x->micb_lock); + return ret; +} + +static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *component, + int micb_num, bool req_en) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int rc, micb_mv; + + if (micb_num != MIC_BIAS_2) + return -EINVAL; + /* + * If device tree micbias level is already above the minimum + * voltage needed to detect threshold microphone, then do + * not change the micbias, just return. + */ + if (wcd938x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV) + return 0; + + micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd938x->micb2_mv; + + rc = wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2); + + return rc; +} + +static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x, + s16 *d1_a, u16 noff, + int32_t *zdet) +{ + int i; + int val, val1; + s16 c1; + s32 x1, d1; + int32_t denom; + int minCode_param[] = { + 3277, 1639, 820, 410, 205, 103, 52, 26 + }; + + regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x20); + for (i = 0; i < WCD938X_ZDET_NUM_MEASUREMENTS; i++) { + regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_2, &val); + if (val & 0x80) + break; + } + val = val << 0x8; + regmap_read(wcd938x->regmap, WCD938X_ANA_MBHC_RESULT_1, &val1); + val |= val1; + regmap_update_bits(wcd938x->regmap, WCD938X_ANA_MBHC_ZDET, 0x20, 0x00); + x1 = WCD938X_MBHC_GET_X1(val); + c1 = WCD938X_MBHC_GET_C1(val); + /* If ramp is not complete, give additional 5ms */ + if ((c1 < 2) && x1) + usleep_range(5000, 5050); + + if (!c1 || !x1) { + pr_err("%s: Impedance detect ramp error, c1=%d, x1=0x%x\n", + __func__, c1, x1); + goto ramp_down; + } + d1 = d1_a[c1]; + denom = (x1 * d1) - (1 << (14 - noff)); + if (denom > 0) + *zdet = (WCD938X_MBHC_ZDET_CONST * 1000) / denom; + else if (x1 < minCode_param[noff]) + *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE; + + pr_err("%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n", + __func__, d1, c1, x1, *zdet); +ramp_down: + i = 0; + while (x1) { + regmap_read(wcd938x->regmap, + WCD938X_ANA_MBHC_RESULT_1, &val); + regmap_read(wcd938x->regmap, + WCD938X_ANA_MBHC_RESULT_2, &val1); + val = val << 0x08; + val |= val1; + x1 = WCD938X_MBHC_GET_X1(val); + i++; + if (i == WCD938X_ZDET_NUM_MEASUREMENTS) + break; + } +} + +static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component, + struct wcd938x_mbhc_zdet_param *zdet_param, + int32_t *zl, int32_t *zr, s16 *d1_a) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + int32_t zdet = 0; + + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, + WCD938X_ZDET_MAXV_CTL_MASK, zdet_param->ldo_ctl); + snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN5, + WCD938X_VTH_MASK, zdet_param->btn5); + snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN6, + WCD938X_VTH_MASK, zdet_param->btn6); + snd_soc_component_update_bits(component, WCD938X_ANA_MBHC_BTN7, + WCD938X_VTH_MASK, zdet_param->btn7); + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, + WCD938X_ZDET_RANGE_CTL_MASK, zdet_param->noff); + snd_soc_component_update_bits(component, WCD938X_MBHC_NEW_ZDET_RAMP_CTL, + 0x0F, zdet_param->nshift); + + if (!zl) + goto z_right; + /* Start impedance measurement for HPH_L */ + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ZDET, 0x80, 0x80); + dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n", + __func__, zdet_param->noff); + wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet); + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ZDET, 0x80, 0x00); + + *zl = zdet; + +z_right: + if (!zr) + return; + /* Start impedance measurement for HPH_R */ + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ZDET, 0x40, 0x40); + dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n", + __func__, zdet_param->noff); + wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet); + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ZDET, 0x40, 0x00); + + *zr = zdet; +} + +static inline void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component, + int32_t *z_val, int flag_l_r) +{ + s16 q1; + int q1_cal; + + if (*z_val < (WCD938X_ZDET_VAL_400/1000)) + q1 = snd_soc_component_read(component, + WCD938X_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r)); + else + q1 = snd_soc_component_read(component, + WCD938X_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r)); + if (q1 & 0x80) + q1_cal = (10000 - ((q1 & 0x7F) * 25)); + else + q1_cal = (10000 + (q1 * 25)); + if (q1_cal > 0) + *z_val = ((*z_val) * 10000) / q1_cal; +} + +static void wcd938x_wcd_mbhc_calc_impedance(struct snd_soc_component *component, + uint32_t *zl, uint32_t *zr) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + s16 reg0, reg1, reg2, reg3, reg4; + int32_t z1L, z1R, z1Ls; + int zMono, z_diff1, z_diff2; + bool is_fsm_disable = false; + struct wcd938x_mbhc_zdet_param zdet_param[] = { + {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */ + {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */ + {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */ + {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */ + }; + struct wcd938x_mbhc_zdet_param *zdet_param_ptr = NULL; + s16 d1_a[][4] = { + {0, 30, 90, 30}, + {0, 30, 30, 5}, + {0, 30, 30, 5}, + {0, 30, 30, 5}, + }; + s16 *d1 = NULL; + + reg0 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN5); + reg1 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN6); + reg2 = snd_soc_component_read(component, WCD938X_ANA_MBHC_BTN7); + reg3 = snd_soc_component_read(component, WCD938X_MBHC_CTL_CLK); + reg4 = snd_soc_component_read(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL); + + if (snd_soc_component_read(component, WCD938X_ANA_MBHC_ELECT) & 0x80) { + is_fsm_disable = true; + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ELECT, 0x80, 0x00); + } + + /* For NO-jack, disable L_DET_EN before Z-det measurements */ + if (wcd938x->mbhc_cfg.hphl_swh) + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_MECH, 0x80, 0x00); + + /* Turn off 100k pull down on HPHL */ + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_MECH, 0x01, 0x00); + + /* Disable surge protection before impedance detection. + * This is done to give correct value for high impedance. + */ + regmap_update_bits(wcd938x->regmap, + WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); + /* 1ms delay needed after disable surge protection */ + usleep_range(1000, 1010); + + /* First get impedance on Left */ + d1 = d1_a[1]; + zdet_param_ptr = &zdet_param[1]; + wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); + + if (!WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1L)) + goto left_ch_impedance; + + /* Second ramp for left ch */ + if (z1L < WCD938X_ZDET_VAL_32) { + zdet_param_ptr = &zdet_param[0]; + d1 = d1_a[0]; + } else if ((z1L > WCD938X_ZDET_VAL_400) && + (z1L <= WCD938X_ZDET_VAL_1200)) { + zdet_param_ptr = &zdet_param[2]; + d1 = d1_a[2]; + } else if (z1L > WCD938X_ZDET_VAL_1200) { + zdet_param_ptr = &zdet_param[3]; + d1 = d1_a[3]; + } + wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); + +left_ch_impedance: + if ((z1L == WCD938X_ZDET_FLOATING_IMPEDANCE) || + (z1L > WCD938X_ZDET_VAL_100K)) { + *zl = WCD938X_ZDET_FLOATING_IMPEDANCE; + zdet_param_ptr = &zdet_param[1]; + d1 = d1_a[1]; + } else { + *zl = z1L/1000; + wcd938x_wcd_mbhc_qfuse_cal(component, zl, 0); + } + dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n", + __func__, *zl); + + /* Start of right impedance ramp and calculation */ + wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); + if (WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) { + if (((z1R > WCD938X_ZDET_VAL_1200) && + (zdet_param_ptr->noff == 0x6)) || + ((*zl) != WCD938X_ZDET_FLOATING_IMPEDANCE)) + goto right_ch_impedance; + /* Second ramp for right ch */ + if (z1R < WCD938X_ZDET_VAL_32) { + zdet_param_ptr = &zdet_param[0]; + d1 = d1_a[0]; + } else if ((z1R > WCD938X_ZDET_VAL_400) && + (z1R <= WCD938X_ZDET_VAL_1200)) { + zdet_param_ptr = &zdet_param[2]; + d1 = d1_a[2]; + } else if (z1R > WCD938X_ZDET_VAL_1200) { + zdet_param_ptr = &zdet_param[3]; + d1 = d1_a[3]; + } + wcd938x_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); + } +right_ch_impedance: + if ((z1R == WCD938X_ZDET_FLOATING_IMPEDANCE) || + (z1R > WCD938X_ZDET_VAL_100K)) { + *zr = WCD938X_ZDET_FLOATING_IMPEDANCE; + } else { + *zr = z1R/1000; + wcd938x_wcd_mbhc_qfuse_cal(component, zr, 1); + } + dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n", + __func__, *zr); + + /* Mono/stereo detection */ + if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) && + (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE)) { + dev_dbg(component->dev, + "%s: plug type is invalid or extension cable\n", + __func__); + goto zdet_complete; + } + if ((*zl == WCD938X_ZDET_FLOATING_IMPEDANCE) || + (*zr == WCD938X_ZDET_FLOATING_IMPEDANCE) || + ((*zl < WCD_MONO_HS_MIN_THR) && (*zr > WCD_MONO_HS_MIN_THR)) || + ((*zl > WCD_MONO_HS_MIN_THR) && (*zr < WCD_MONO_HS_MIN_THR))) { + dev_dbg(component->dev, + "%s: Mono plug type with one ch floating or shorted to GND\n", + __func__); + wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO); + goto zdet_complete; + } + snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST, + WCD938X_HPHPA_GND_OVR_MASK, 1); + snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, + WCD938X_HPHPA_GND_R_MASK, 1); + if (*zl < (WCD938X_ZDET_VAL_32/1000)) + wcd938x_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, NULL, d1); + else + wcd938x_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, NULL, d1); + snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, + WCD938X_HPHPA_GND_R_MASK, 0); + snd_soc_component_write_field(component, WCD938X_HPH_R_ATEST, + WCD938X_HPHPA_GND_OVR_MASK, 0); + z1Ls /= 1000; + wcd938x_wcd_mbhc_qfuse_cal(component, &z1Ls, 0); + /* Parallel of left Z and 9 ohm pull down resistor */ + zMono = ((*zl) * 9) / ((*zl) + 9); + z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls); + z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl)); + if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) { + dev_dbg(component->dev, "%s: stereo plug type detected\n", + __func__); + wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_STEREO); + } else { + dev_dbg(component->dev, "%s: MONO plug type detected\n", + __func__); + wcd_mbhc_set_hph_type(wcd938x->wcd_mbhc, WCD_MBHC_HPH_MONO); + } + + /* Enable surge protection again after impedance detection */ + regmap_update_bits(wcd938x->regmap, + WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); +zdet_complete: + snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN5, reg0); + snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN6, reg1); + snd_soc_component_write(component, WCD938X_ANA_MBHC_BTN7, reg2); + /* Turn on 100k pull down on HPHL */ + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_MECH, 0x01, 0x01); + + /* For NO-jack, re-enable L_DET_EN after Z-det measurements */ + if (wcd938x->mbhc_cfg.hphl_swh) + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_MECH, 0x80, 0x80); + + snd_soc_component_write(component, WCD938X_MBHC_NEW_ZDET_ANA_CTL, reg4); + snd_soc_component_write(component, WCD938X_MBHC_CTL_CLK, reg3); + if (is_fsm_disable) + regmap_update_bits(wcd938x->regmap, + WCD938X_ANA_MBHC_ELECT, 0x80, 0x80); +} + +static void wcd938x_mbhc_gnd_det_ctrl(struct snd_soc_component *component, + bool enable) +{ + if (enable) { + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, + WCD938X_MBHC_HSG_PULLUP_COMP_EN, 1); + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, + WCD938X_MBHC_GND_DET_EN_MASK, 1); + } else { + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, + WCD938X_MBHC_GND_DET_EN_MASK, 0); + snd_soc_component_write_field(component, WCD938X_ANA_MBHC_MECH, + WCD938X_MBHC_HSG_PULLUP_COMP_EN, 0); + } +} + +static void wcd938x_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, + WCD938X_HPHPA_GND_R_MASK, enable); + snd_soc_component_write_field(component, WCD938X_HPH_PA_CTL2, + WCD938X_HPHPA_GND_L_MASK, enable); +} + +static void wcd938x_mbhc_moisture_config(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + if (wcd938x->mbhc_cfg.moist_rref == R_OFF) { + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, R_OFF); + return; + } + + /* Do not enable moisture detection if jack type is NC */ + if (!wcd938x->mbhc_cfg.hphl_swh) { + dev_dbg(component->dev, "%s: disable moisture detection for NC\n", + __func__); + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, R_OFF); + return; + } + + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref); +} + +static void wcd938x_mbhc_moisture_detect_en(struct snd_soc_component *component, bool enable) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + if (enable) + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, wcd938x->mbhc_cfg.moist_rref); + else + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, R_OFF); +} + +static bool wcd938x_mbhc_get_moisture_status(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + bool ret = false; + + if (wcd938x->mbhc_cfg.moist_rref == R_OFF) { + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, R_OFF); + goto done; + } + + /* Do not enable moisture detection if jack type is NC */ + if (!wcd938x->mbhc_cfg.hphl_swh) { + dev_dbg(component->dev, "%s: disable moisture detection for NC\n", + __func__); + snd_soc_component_write_field(component, WCD938X_MBHC_NEW_CTL_2, + WCD938X_M_RTH_CTL_MASK, R_OFF); + goto done; + } + + /* + * If moisture_en is already enabled, then skip to plug type + * detection. + */ + if (snd_soc_component_read_field(component, WCD938X_MBHC_NEW_CTL_2, WCD938X_M_RTH_CTL_MASK)) + goto done; + + wcd938x_mbhc_moisture_detect_en(component, true); + /* Read moisture comparator status */ + ret = ((snd_soc_component_read(component, WCD938X_MBHC_NEW_FSM_STATUS) + & 0x20) ? 0 : 1); + +done: + return ret; + +} + +static void wcd938x_mbhc_moisture_polling_ctrl(struct snd_soc_component *component, + bool enable) +{ + snd_soc_component_write_field(component, + WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, + WCD938X_MOISTURE_EN_POLLING_MASK, enable); +} + +static const struct wcd_mbhc_cb mbhc_cb = { + .clk_setup = wcd938x_mbhc_clk_setup, + .mbhc_bias = wcd938x_mbhc_mbhc_bias_control, + .set_btn_thr = wcd938x_mbhc_program_btn_thr, + .micbias_enable_status = wcd938x_mbhc_micb_en_status, + .hph_pull_up_control_v2 = wcd938x_mbhc_hph_l_pull_up_control, + .mbhc_micbias_control = wcd938x_mbhc_request_micbias, + .mbhc_micb_ramp_control = wcd938x_mbhc_micb_ramp_control, + .mbhc_micb_ctrl_thr_mic = wcd938x_mbhc_micb_ctrl_threshold_mic, + .compute_impedance = wcd938x_wcd_mbhc_calc_impedance, + .mbhc_gnd_det_ctrl = wcd938x_mbhc_gnd_det_ctrl, + .hph_pull_down_ctrl = wcd938x_mbhc_hph_pull_down_ctrl, + .mbhc_moisture_config = wcd938x_mbhc_moisture_config, + .mbhc_get_moisture_status = wcd938x_mbhc_get_moisture_status, + .mbhc_moisture_polling_ctrl = wcd938x_mbhc_moisture_polling_ctrl, + .mbhc_moisture_detect_en = wcd938x_mbhc_moisture_detect_en, +}; + +static int wcd938x_get_hph_type(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = wcd_mbhc_get_hph_type(wcd938x->wcd_mbhc); + + return 0; +} + +static int wcd938x_hph_impedance_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + uint32_t zl, zr; + bool hphr; + struct soc_mixer_control *mc; + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + + mc = (struct soc_mixer_control *)(kcontrol->private_value); + hphr = mc->shift; + wcd_mbhc_get_impedance(wcd938x->wcd_mbhc, &zl, &zr); + dev_dbg(component->dev, "%s: zl=%u(ohms), zr=%u(ohms)\n", __func__, zl, zr); + ucontrol->value.integer.value[0] = hphr ? zr : zl; + + return 0; +} + +static const struct snd_kcontrol_new hph_type_detect_controls[] = { + SOC_SINGLE_EXT("HPH Type", 0, 0, UINT_MAX, 0, + wcd938x_get_hph_type, NULL), +}; + +static const struct snd_kcontrol_new impedance_detect_controls[] = { + SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0, + wcd938x_hph_impedance_get, NULL), + SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0, + wcd938x_hph_impedance_get, NULL), +}; + +static int wcd938x_mbhc_init(struct snd_soc_component *component) +{ + struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); + struct wcd_mbhc_intr *intr_ids = &wcd938x->intr_ids; + + intr_ids->mbhc_sw_intr = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_MBHC_SW_DET); + intr_ids->mbhc_btn_press_intr = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_MBHC_BUTTON_PRESS_DET); + intr_ids->mbhc_btn_release_intr = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET); + intr_ids->mbhc_hs_ins_intr = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_MBHC_ELECT_INS_REM_LEG_DET); + intr_ids->mbhc_hs_rem_intr = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_MBHC_ELECT_INS_REM_DET); + intr_ids->hph_left_ocp = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_HPHL_OCP_INT); + intr_ids->hph_right_ocp = regmap_irq_get_virq(wcd938x->irq_chip, + WCD938X_IRQ_HPHR_OCP_INT); + + wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true); + + snd_soc_add_component_controls(component, impedance_detect_controls, + ARRAY_SIZE(impedance_detect_controls)); + snd_soc_add_component_controls(component, hph_type_detect_controls, + ARRAY_SIZE(hph_type_detect_controls)); + + return 0; +} +/* END MBHC */ + static const struct snd_kcontrol_new wcd938x_snd_controls[] = { SOC_SINGLE_EXT("HPHL_COMP Switch", WCD938X_COMP_L, 0, 1, 0, wcd938x_get_compander, wcd938x_set_compander), @@ -3225,15 +3993,6 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = { {"EAR", NULL, "EAR PGA"}, }; -static int wcd938x_get_micb_vout_ctl_val(u32 micb_mv) -{ - /* min micbias voltage is 1V and maximum is 2.85V */ - if (micb_mv < 1000 || micb_mv > 2850) - return -EINVAL; - - return (micb_mv - 1000) / 50; -} - static int wcd938x_set_micbias_data(struct wcd938x_priv *wcd938x) { int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4; @@ -3372,10 +4131,27 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component) default: break; } + + ret = wcd938x_mbhc_init(component); + if (ret) + dev_err(component->dev, "mbhc initialization failed\n"); err: return ret; } +static int wcd938x_codec_set_jack(struct snd_soc_component *comp, + struct snd_soc_jack *jack, void *data) +{ + struct wcd938x_priv *wcd = dev_get_drvdata(comp->dev); + + if (!jack) + return wcd_mbhc_start(wcd->wcd_mbhc, &wcd->mbhc_cfg, jack); + + wcd_mbhc_stop(wcd->wcd_mbhc); + + return 0; +} + static const struct snd_soc_component_driver soc_codec_dev_wcd938x = { .name = "wcd938x_codec", .probe = wcd938x_soc_codec_probe, @@ -3385,6 +4161,7 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd938x = { .num_dapm_widgets = ARRAY_SIZE(wcd938x_dapm_widgets), .dapm_routes = wcd938x_audio_map, .num_dapm_routes = ARRAY_SIZE(wcd938x_audio_map), + .set_jack = wcd938x_codec_set_jack, }; static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_priv *wcd) @@ -3420,6 +4197,7 @@ static void wcd938x_dt_parse_micbias_info(struct device *dev, struct wcd938x_pri static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device *dev) { + struct wcd_mbhc_config *cfg = &wcd938x->mbhc_cfg; int ret; wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); @@ -3448,6 +4226,17 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device wcd938x_dt_parse_micbias_info(dev, wcd938x); + cfg->mbhc_micbias = MIC_BIAS_2; + cfg->anc_micbias = MIC_BIAS_2; + cfg->v_hs_max = WCD_MBHC_HS_V_MAX; + cfg->num_btn = WCD938X_MBHC_MAX_BUTTONS; + cfg->micb_mv = wcd938x->micb2_mv; + cfg->linein_th = 5000; + cfg->hs_thr = 1700; + cfg->hph_thr = 50; + + wcd_dt_parse_mbhc_data(dev, cfg); + return 0; } @@ -3679,6 +4468,7 @@ static int wcd938x_probe(struct platform_device *pdev) return -ENOMEM; dev_set_drvdata(dev, wcd938x); + mutex_init(&wcd938x->micb_lock); ret = wcd938x_populate_dt_data(wcd938x, dev); if (ret) { @@ -3703,7 +4493,7 @@ static int wcd938x_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_idle(dev); - return ret; + return 0; } static int wcd938x_remove(struct platform_device *pdev) diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h index 07b08de4cebf..ea82039e7843 100644 --- a/sound/soc/codecs/wcd938x.h +++ b/sound/soc/codecs/wcd938x.h @@ -658,7 +658,6 @@ struct wcd938x_sdw_priv { struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS]; struct wcd938x_sdw_ch_info *ch_info; bool port_enable[WCD938X_MAX_SWR_CH_IDS]; - int port_map[WCD938X_MAX_SWR_PORTS]; int active_ports; int num_ports; bool is_tx; diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 536339e43dc7..e4018ba3b19a 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -912,13 +912,13 @@ void wm8958_dsp2_init(struct snd_soc_component *component) /* We don't *require* firmware and don't want to delay boot */ - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, "wm8958_mbc.wfw", component->dev, GFP_KERNEL, component, wm8958_mbc_loaded); - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, "wm8958_mbc_vss.wfw", component->dev, GFP_KERNEL, component, wm8958_mbc_vss_loaded); - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, "wm8958_enh_eq.wfw", component->dev, GFP_KERNEL, component, wm8958_enh_eq_loaded); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index a4d4cbf716a1..f7c800927cb2 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2031,10 +2031,9 @@ static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp, if (!pos->subname) continue; if (strncmp(pos->subname, name, pos->subname_len) == 0 && - strncmp(pos->fw_name, fw_txt, - SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 && - pos->alg_region.alg == alg && - pos->alg_region.type == type) { + pos->fw_name == fw_txt && + pos->alg_region.alg == alg && + pos->alg_region.type == type) { rslt = pos; break; } diff --git a/sound/soc/dwc/Kconfig b/sound/soc/dwc/Kconfig index 0cd1a15f40aa..71a58f7ac13a 100644 --- a/sound/soc/dwc/Kconfig +++ b/sound/soc/dwc/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SND_DESIGNWARE_I2S tristate "Synopsys I2S Device Driver" - depends on CLKDEV_LOOKUP + depends on HAVE_CLK select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for I2S driver for diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index ea5c973e2e84..d60f4dac6c1b 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -165,25 +165,25 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) } /* Get the optional clocks */ - rpmsg->ipg = devm_clk_get(&pdev->dev, "ipg"); + rpmsg->ipg = devm_clk_get_optional(&pdev->dev, "ipg"); if (IS_ERR(rpmsg->ipg)) - rpmsg->ipg = NULL; + return PTR_ERR(rpmsg->ipg); - rpmsg->mclk = devm_clk_get(&pdev->dev, "mclk"); + rpmsg->mclk = devm_clk_get_optional(&pdev->dev, "mclk"); if (IS_ERR(rpmsg->mclk)) - rpmsg->mclk = NULL; + return PTR_ERR(rpmsg->mclk); - rpmsg->dma = devm_clk_get(&pdev->dev, "dma"); + rpmsg->dma = devm_clk_get_optional(&pdev->dev, "dma"); if (IS_ERR(rpmsg->dma)) - rpmsg->dma = NULL; + return PTR_ERR(rpmsg->dma); - rpmsg->pll8k = devm_clk_get(&pdev->dev, "pll8k"); + rpmsg->pll8k = devm_clk_get_optional(&pdev->dev, "pll8k"); if (IS_ERR(rpmsg->pll8k)) - rpmsg->pll8k = NULL; + return PTR_ERR(rpmsg->pll8k); - rpmsg->pll11k = devm_clk_get(&pdev->dev, "pll11k"); + rpmsg->pll11k = devm_clk_get_optional(&pdev->dev, "pll11k"); if (IS_ERR(rpmsg->pll11k)) - rpmsg->pll11k = NULL; + return PTR_ERR(rpmsg->pll11k); platform_set_drvdata(pdev, rpmsg); pm_runtime_enable(&pdev->dev); diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 2252a4a62fa5..8ffb1a6048d6 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1438,14 +1438,27 @@ static int fsl_spdif_probe(struct platform_device *pdev) &spdif_priv->cpu_dai_drv, 1); if (ret) { dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); - return ret; + goto err_pm_disable; } ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); - if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret); + if (ret) { + dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed\n"); + goto err_pm_disable; + } return ret; + +err_pm_disable: + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int fsl_spdif_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; } #ifdef CONFIG_PM @@ -1454,6 +1467,9 @@ static int fsl_spdif_runtime_suspend(struct device *dev) struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev); int i; + /* Disable all the interrupts */ + regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SIE, 0xffffff, 0); + regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC, &spdif_priv->regcache_srpc); regcache_cache_only(spdif_priv->regmap, true); @@ -1551,6 +1567,7 @@ static struct platform_driver fsl_spdif_driver = { .pm = &fsl_spdif_pm, }, .probe = fsl_spdif_probe, + .remove = fsl_spdif_remove, }; module_platform_driver(fsl_spdif_driver); diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index fb7c29fc39d7..31c5ee641fe7 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1189,10 +1189,8 @@ static int fsl_xcvr_probe(struct platform_device *pdev) /* get IRQs */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "no irq[0]: %d\n", irq); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, irq0_isr, 0, pdev->name, xcvr); if (ret) { diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 677f7da93b4b..10c63b73900c 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -640,8 +640,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, cnf_num += li->num[i].codecs; } - dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); - dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL); + dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); + dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL); if (!dais || !dlcs) return -ENOMEM; diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index a8a9aa0057d3..4e8382097e61 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c @@ -128,7 +128,7 @@ int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx, while (header.p.header_high.part.busy) { if (loop_count > 25) { dev_err(sst_drv_ctx->dev, - "sst: Busy wait failed, cant send this msg\n"); + "sst: Busy wait failed, can't send this msg\n"); retval = -EBUSY; goto out; } diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 7e29b0d911e2..046955bf717c 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -602,6 +602,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_DMIC select SND_SOC_INTEL_HDA_DSP_COMMON select SND_SOC_INTEL_SOF_MAXIM_COMMON + select SND_SOC_SDW_MOCKUP help Add support for Intel SoundWire-based platforms connected to MAX98373, RT700, RT711, RT1308 and RT715 diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index a0af91580184..055248f104b2 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -37,6 +37,7 @@ struct byt_cht_es8316_private { struct clk *mclk; struct snd_soc_jack jack; struct gpio_desc *speaker_en_gpio; + struct device *codec_dev; bool speaker_en; }; @@ -461,6 +462,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) const struct dmi_system_id *dmi_id; struct device *dev = &pdev->dev; struct snd_soc_acpi_mach *mach; + struct fwnode_handle *fwnode; const char *platform_name; struct acpi_device *adev; struct device *codec_dev; @@ -491,6 +493,9 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); byt_cht_es8316_dais[dai_index].codecs->name = codec_name; + } else { + dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); + return -ENXIO; } /* override plaform name, if required */ @@ -535,15 +540,25 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) } /* get speaker enable GPIO */ - codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name); + codec_dev = acpi_get_first_physical_node(adev); if (!codec_dev) return -EPROBE_DEFER; + priv->codec_dev = get_device(codec_dev); if (quirk & BYT_CHT_ES8316_JD_INVERTED) props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted"); if (cnt) { - ret = device_add_properties(codec_dev, props); + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) { + put_device(codec_dev); + return PTR_ERR(fwnode); + } + + ret = device_add_software_node(codec_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); + if (ret) { put_device(codec_dev); return ret; @@ -555,7 +570,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) gpiod_get_index(codec_dev, "speaker-enable", 0, /* see comment in byt_cht_es8316_resume */ GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE); - put_device(codec_dev); if (IS_ERR(priv->speaker_en_gpio)) { ret = PTR_ERR(priv->speaker_en_gpio); @@ -567,7 +581,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) dev_err(dev, "get speaker GPIO failed: %d\n", ret); fallthrough; case -EPROBE_DEFER: - return ret; + goto err_put_codec; } } @@ -605,10 +619,15 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) if (ret) { gpiod_put(priv->speaker_en_gpio); dev_err(dev, "snd_soc_register_card failed: %d\n", ret); - return ret; + goto err_put_codec; } platform_set_drvdata(pdev, &byt_cht_es8316_card); return 0; + +err_put_codec: + device_remove_software_node(priv->codec_dev); + put_device(priv->codec_dev); + return ret; } static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) @@ -617,6 +636,8 @@ static int snd_byt_cht_es8316_mc_remove(struct platform_device *pdev) struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); gpiod_put(priv->speaker_en_gpio); + device_remove_software_node(priv->codec_dev); + put_device(priv->codec_dev); return 0; } diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 91a6d712eb58..05667a33d919 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -18,6 +18,8 @@ #include <linux/clk.h> #include <linux/device.h> #include <linux/dmi.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> #include <linux/input.h> #include <linux/slab.h> #include <sound/pcm.h> @@ -73,6 +75,10 @@ enum { #define BYT_RT5640_MCLK_EN BIT(22) #define BYT_RT5640_MCLK_25MHZ BIT(23) #define BYT_RT5640_NO_SPEAKERS BIT(24) +#define BYT_RT5640_LINEOUT BIT(25) +#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26) +#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27) +#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28) #define BYTCR_INPUT_DEFAULTS \ (BYT_RT5640_IN3_MAP | \ @@ -86,7 +92,10 @@ enum { struct byt_rt5640_private { struct snd_soc_jack jack; + struct snd_soc_jack jack2; + struct gpio_desc *hsmic_detect; struct clk *mclk; + struct device *codec_dev; }; static bool is_bytcr; @@ -125,6 +134,8 @@ static void log_quirks(struct device *dev) dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map); break; } + if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) + dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n"); if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) { dev_info(dev, "quirk realtek,jack-detect-source %ld\n", BYT_RT5640_JDSRC(byt_rt5640_quirk)); @@ -135,10 +146,16 @@ static void log_quirks(struct device *dev) } if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) dev_info(dev, "quirk JD_NOT_INV enabled\n"); + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) + dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) dev_info(dev, "quirk MONO_SPEAKER enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) dev_info(dev, "quirk NO_SPEAKERS enabled\n"); + if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) + dev_info(dev, "quirk LINEOUT enabled\n"); + if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2) + dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC) dev_info(dev, "quirk DIFF_MIC enabled\n"); if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) { @@ -224,6 +241,20 @@ static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai, #define BYT_CODEC_DAI1 "rt5640-aif1" #define BYT_CODEC_DAI2 "rt5640-aif2" +static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm) +{ + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + + codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); + if (!codec_dai) + codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); + if (!codec_dai) + dev_err(card->dev, "Error codec dai not found\n"); + + return codec_dai; +} + static int platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { @@ -233,15 +264,9 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); int ret; - codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1); + codec_dai = byt_rt5640_get_codec_dai(dapm); if (!codec_dai) - codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2); - - if (!codec_dai) { - dev_err(card->dev, - "Codec dai not found; Unable to set platform clock\n"); return -EIO; - } if (SND_SOC_DAPM_EVENT_ON(event)) { if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { @@ -276,23 +301,48 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, return 0; } +static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT; + struct snd_soc_dai *codec_dai; + + if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)) + return 0; + + /* + * On devices which use line-out as a second headphones output, + * the codec's GPIO1 pin is used to enable an external HP-amp. + */ + + codec_dai = byt_rt5640_get_codec_dai(w->dapm); + if (!codec_dai) + return -EIO; + + if (SND_SOC_DAPM_EVENT_ON(event)) + gpio_ctrl3_val |= RT5640_GP1_OUT_HI; + + snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3, + RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val); + + return 0; +} + static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Headset Mic 2", NULL), SND_SOC_DAPM_MIC("Internal Mic", NULL), SND_SOC_DAPM_SPK("Speaker", NULL), + SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - }; static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { {"Headphone", NULL, "Platform Clock"}, {"Headset Mic", NULL, "Platform Clock"}, - {"Internal Mic", NULL, "Platform Clock"}, - {"Speaker", NULL, "Platform Clock"}, - {"Headset Mic", NULL, "MICBIAS1"}, {"IN2P", NULL, "Headset Mic"}, {"Headphone", NULL, "HPOL"}, @@ -300,23 +350,33 @@ static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = { }; static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = { + {"Internal Mic", NULL, "Platform Clock"}, {"DMIC1", NULL, "Internal Mic"}, }; static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = { + {"Internal Mic", NULL, "Platform Clock"}, {"DMIC2", NULL, "Internal Mic"}, }; static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { + {"Internal Mic", NULL, "Platform Clock"}, {"Internal Mic", NULL, "MICBIAS1"}, {"IN1P", NULL, "Internal Mic"}, }; static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = { + {"Internal Mic", NULL, "Platform Clock"}, {"Internal Mic", NULL, "MICBIAS1"}, {"IN3P", NULL, "Internal Mic"}, }; +static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = { + {"Headset Mic 2", NULL, "Platform Clock"}, + {"Headset Mic 2", NULL, "MICBIAS1"}, + {"IN1P", NULL, "Headset Mic 2"}, +}; + static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = { {"ssp2 Tx", NULL, "codec_out0"}, {"ssp2 Tx", NULL, "codec_out1"}, @@ -354,6 +414,7 @@ static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = { }; static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { + {"Speaker", NULL, "Platform Clock"}, {"Speaker", NULL, "SPOLP"}, {"Speaker", NULL, "SPOLN"}, {"Speaker", NULL, "SPORP"}, @@ -361,15 +422,24 @@ static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = { }; static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = { + {"Speaker", NULL, "Platform Clock"}, {"Speaker", NULL, "SPOLP"}, {"Speaker", NULL, "SPOLN"}, }; +static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = { + {"Line Out", NULL, "Platform Clock"}, + {"Line Out", NULL, "LOUTR"}, + {"Line Out", NULL, "LOUTL"}, +}; + static const struct snd_kcontrol_new byt_rt5640_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headset Mic 2"), SOC_DAPM_PIN_SWITCH("Internal Mic"), SOC_DAPM_PIN_SWITCH("Speaker"), + SOC_DAPM_PIN_SWITCH("Line Out"), }; static struct snd_soc_jack_pin rt5640_pins[] = { @@ -383,6 +453,75 @@ static struct snd_soc_jack_pin rt5640_pins[] = { }, }; +static struct snd_soc_jack_pin rt5640_pins2[] = { + { + /* The 2nd headset jack uses lineout with an external HP-amp */ + .pin = "Line Out", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic 2", + .mask = SND_JACK_MICROPHONE, + }, +}; + +struct snd_soc_jack_gpio rt5640_jack_gpio = { + .name = "hp-detect", + .report = SND_JACK_HEADSET, + .invert = true, + .debounce_time = 200, +}; + +struct snd_soc_jack_gpio rt5640_jack2_gpio = { + .name = "hp2-detect", + .report = SND_JACK_HEADSET, + .invert = true, + .debounce_time = 200, +}; + +static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false }; +static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false }; +static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false }; + +static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = { + { "hp-detect-gpios", &acpi_gpio0, 1, }, + { "headset-mic-detect-gpios", &acpi_gpio1, 1, }, + { "hp2-detect-gpios", &acpi_gpio2, 1, }, + { }, +}; + +static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data) +{ + struct byt_rt5640_private *priv = data; + int jack_status, mic_status; + + jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc); + if (jack_status) + return 0; + + mic_status = gpiod_get_value_cansleep(priv->hsmic_detect); + if (mic_status) + return SND_JACK_HEADPHONE; + else + return SND_JACK_HEADSET; +} + +static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data) +{ + struct snd_soc_component *component = data; + int jack_status, report; + + jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc); + if (jack_status) + return 0; + + rt5640_enable_micbias1_for_ovcd(component); + report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc); + rt5640_disable_micbias1_for_ovcd(component); + + return report; +} + static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -590,8 +729,12 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"), }, - .driver_data = (void *)(BYT_RT5640_IN1_MAP | - BYT_RT5640_MCLK_EN), + .driver_data = (void *)(BYT_RT5640_DMIC2_MAP | + BYT_RT5640_MCLK_EN | + BYT_RT5640_LINEOUT | + BYT_RT5640_LINEOUT_AS_HP2 | + BYT_RT5640_HSMIC2_ON_IN1 | + BYT_RT5640_JD_HP_ELITEP_1000G2), }, { /* HP Pavilion x2 10-k0XX, 10-n0XX */ .matches = { @@ -912,15 +1055,13 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) +static int byt_rt5640_add_codec_device_props(struct device *i2c_dev, + struct byt_rt5640_private *priv) { struct property_entry props[MAX_NO_PROPS] = {}; - struct device *i2c_dev; - int ret, cnt = 0; - - i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name); - if (!i2c_dev) - return -EPROBE_DEFER; + struct fwnode_handle *fwnode; + int cnt = 0; + int ret; switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { case BYT_RT5640_DMIC1_MAP: @@ -960,8 +1101,15 @@ static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name) if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV) props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); - ret = device_add_properties(i2c_dev, props); - put_device(i2c_dev); + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) { + /* put_device() is handled in caller */ + return PTR_ERR(fwnode); + } + + ret = device_add_software_node(i2c_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); return ret; } @@ -1021,6 +1169,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; + if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_hsmic2_in1_map, + ARRAY_SIZE(byt_rt5640_hsmic2_in1_map)); + if (ret) + return ret; + } + if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5640_ssp2_aif2_map, @@ -1053,6 +1209,14 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) if (ret) return ret; + if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) { + ret = snd_soc_dapm_add_routes(&card->dapm, + byt_rt5640_lineout_map, + ARRAY_SIZE(byt_rt5640_lineout_map)); + if (ret) + return ret; + } + if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) { /* * The firmware might enable the clock at @@ -1093,9 +1257,53 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) snd_soc_component_set_jack(component, &priv->jack, NULL); } + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { + ret = snd_soc_card_jack_new(card, "Headset", + SND_JACK_HEADSET, + &priv->jack, rt5640_pins, + ARRAY_SIZE(rt5640_pins)); + if (ret) + return ret; + + ret = snd_soc_card_jack_new(card, "Headset 2", + SND_JACK_HEADSET, + &priv->jack2, rt5640_pins2, + ARRAY_SIZE(rt5640_pins2)); + if (ret) + return ret; + + rt5640_jack_gpio.data = priv; + rt5640_jack_gpio.gpiod_dev = priv->codec_dev; + rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check; + ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio); + if (ret) + return ret; + + rt5640_set_ovcd_params(component); + rt5640_jack2_gpio.data = component; + rt5640_jack2_gpio.gpiod_dev = priv->codec_dev; + rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check; + ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio); + if (ret) { + snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio); + return ret; + } + } + return 0; } +static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_card *card = runtime->card; + struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); + + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { + snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio); + snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio); + } +} + static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -1208,6 +1416,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = byt_rt5640_init, + .exit = byt_rt5640_exit, .ops = &byt_rt5640_be_ssp2_ops, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, @@ -1218,7 +1427,7 @@ static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN]; #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */ #endif -static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */ +static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */ static int byt_rt5640_suspend(struct snd_soc_card *card) { @@ -1288,10 +1497,13 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" }; __maybe_unused const char *spk_type; const struct dmi_system_id *dmi_id; + const char *headset2_string = ""; + const char *lineout_string = ""; struct byt_rt5640_private *priv; struct snd_soc_acpi_mach *mach; const char *platform_name; struct acpi_device *adev; + struct device *codec_dev; bool sof_parent; int ret_val = 0; int dai_index = 0; @@ -1324,6 +1536,9 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; + } else { + dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); + return -ENXIO; } /* @@ -1400,10 +1615,29 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_quirk = quirk_override; } + codec_dev = acpi_get_first_physical_node(adev); + if (!codec_dev) + return -EPROBE_DEFER; + priv->codec_dev = get_device(codec_dev); + + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) { + acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev), + byt_rt5640_hp_elitepad_1000g2_gpios); + + priv->hsmic_detect = devm_fwnode_gpiod_get(&pdev->dev, codec_dev->fwnode, + "headset-mic-detect", GPIOD_IN, + "headset-mic-detect"); + if (IS_ERR(priv->hsmic_detect)) { + ret_val = PTR_ERR(priv->hsmic_detect); + dev_err_probe(&pdev->dev, ret_val, "getting hsmic-detect GPIO\n"); + goto err_device; + } + } + /* Must be called before register_card, also see declaration comment. */ - ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name); + ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv); if (ret_val) - return ret_val; + goto err_remove_gpios; log_quirks(&pdev->dev); @@ -1434,7 +1668,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) * for all other errors, including -EPROBE_DEFER */ if (ret_val != -ENOENT) - return ret_val; + goto err; byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN; } } @@ -1450,9 +1684,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) spk_type = "stereo"; } + if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) { + if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2) + lineout_string = " cfg-hp2:lineout"; + else + lineout_string = " cfg-lineout:2"; + } + + if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) + headset2_string = " cfg-hs2:in1"; + snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), - "cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk, - map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif); + "cfg-spk:%d cfg-mic:%s aif:%d%s%s", cfg_spk, + map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif, + lineout_string, headset2_string); byt_rt5640_card.components = byt_rt5640_components; #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), @@ -1467,7 +1712,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, platform_name); if (ret_val) - return ret_val; + goto err; sof_parent = snd_soc_acpi_sof_parent(&pdev->dev); @@ -1489,10 +1734,32 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) if (ret_val) { dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", ret_val); - return ret_val; + goto err; } platform_set_drvdata(pdev, &byt_rt5640_card); return ret_val; + +err: + device_remove_software_node(priv->codec_dev); +err_remove_gpios: + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) + acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev)); +err_device: + put_device(priv->codec_dev); + return ret_val; +} + +static int snd_byt_rt5640_mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); + + if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) + acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev)); + + device_remove_software_node(priv->codec_dev); + put_device(priv->codec_dev); + return 0; } static struct platform_driver snd_byt_rt5640_mc_driver = { @@ -1500,6 +1767,7 @@ static struct platform_driver snd_byt_rt5640_mc_driver = { .name = "bytcr_rt5640", }, .probe = snd_byt_rt5640_mc_probe, + .remove = snd_byt_rt5640_mc_remove, }; module_platform_driver(snd_byt_rt5640_mc_driver); diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index e13c0c63a949..e94c9124d4f4 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -85,6 +85,7 @@ struct byt_rt5651_private { struct gpio_desc *ext_amp_gpio; struct gpio_desc *hp_detect; struct snd_soc_jack jack; + struct device *codec_dev; }; static const struct acpi_gpio_mapping *byt_rt5651_gpios; @@ -527,10 +528,13 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = { * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int byt_rt5651_add_codec_device_props(struct device *i2c_dev) +static int byt_rt5651_add_codec_device_props(struct device *i2c_dev, + struct byt_rt5651_private *priv) { struct property_entry props[MAX_NO_PROPS] = {}; + struct fwnode_handle *fwnode; int cnt = 0; + int ret; props[cnt++] = PROPERTY_ENTRY_U32("realtek,jack-detect-source", BYT_RT5651_JDSRC(byt_rt5651_quirk)); @@ -547,7 +551,17 @@ static int byt_rt5651_add_codec_device_props(struct device *i2c_dev) if (byt_rt5651_quirk & BYT_RT5651_JD_NOT_INV) props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted"); - return device_add_properties(i2c_dev, props); + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) { + /* put_device(i2c_dev) is handled in caller */ + return PTR_ERR(fwnode); + } + + ret = device_add_software_node(i2c_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); + + return ret; } static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) @@ -920,13 +934,13 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name; } else { dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); - return -ENODEV; + return -ENXIO; } - codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, - byt_rt5651_codec_name); + codec_dev = acpi_get_first_physical_node(adev); if (!codec_dev) return -EPROBE_DEFER; + priv->codec_dev = get_device(codec_dev); /* * swap SSP0 if bytcr is detected @@ -994,11 +1008,9 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) } /* Must be called before register_card, also see declaration comment. */ - ret_val = byt_rt5651_add_codec_device_props(codec_dev); - if (ret_val) { - put_device(codec_dev); - return ret_val; - } + ret_val = byt_rt5651_add_codec_device_props(codec_dev, priv); + if (ret_val) + goto err_device; /* Cherry Trail devices use an external amplifier enable gpio */ if (soc_intel_is_cht() && !byt_rt5651_gpios) @@ -1022,8 +1034,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) ret_val); fallthrough; case -EPROBE_DEFER: - put_device(codec_dev); - return ret_val; + goto err; } } priv->hp_detect = devm_fwnode_gpiod_get(&pdev->dev, @@ -1042,14 +1053,11 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) ret_val); fallthrough; case -EPROBE_DEFER: - put_device(codec_dev); - return ret_val; + goto err; } } } - put_device(codec_dev); - log_quirks(&pdev->dev); if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) || @@ -1073,7 +1081,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) * for all other errors, including -EPROBE_DEFER */ if (ret_val != -ENOENT) - return ret_val; + goto err; byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN; } } @@ -1102,7 +1110,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card, platform_name); if (ret_val) - return ret_val; + goto err; sof_parent = snd_soc_acpi_sof_parent(&pdev->dev); @@ -1124,10 +1132,26 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) if (ret_val) { dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", ret_val); - return ret_val; + goto err; } platform_set_drvdata(pdev, &byt_rt5651_card); return ret_val; + +err: + device_remove_software_node(priv->codec_dev); +err_device: + put_device(priv->codec_dev); + return ret_val; +} + +static int snd_byt_rt5651_mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); + + device_remove_software_node(priv->codec_dev); + put_device(priv->codec_dev); + return 0; } static struct platform_driver snd_byt_rt5651_mc_driver = { @@ -1135,6 +1159,7 @@ static struct platform_driver snd_byt_rt5651_mc_driver = { .name = "bytcr_rt5651", }, .probe = snd_byt_rt5651_mc_probe, + .remove = snd_byt_rt5651_mc_remove, }; module_platform_driver(snd_byt_rt5651_mc_driver); diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index a31a7a7bbf66..2b43459adc33 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -199,7 +199,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, } if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x03, 3, 8, 24); + 0x30, 3, 8, 16); if (ret < 0) { dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); @@ -208,10 +208,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, } if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x0C, 3, 8, 24); + 0xC0, 3, 8, 16); if (ret < 0) { dev_err(runtime->dev, - "DEV0 TDM slot err:%d\n", ret); + "DEV1 TDM slot err:%d\n", ret); return ret; } } @@ -311,24 +311,6 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, * The above 2 loops are mutually exclusive based on the stream direction, * thus rtd_dpcm variable will never be overwritten */ - /* - * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE, - * where as kblda7219m98927 & kblmax98927 supports S16_LE by default. - * Skipping the port wise FE and BE configuration for kblda7219m98373 & - * kblmax98373 as the topology (FE & BE) supports S24_LE only. - */ - - if (!strcmp(rtd->card->name, "kblda7219m98373") || - !strcmp(rtd->card->name, "kblmax98373")) { - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = DUAL_CHANNEL; - - /* set SSP to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - return 0; - } /* * The ADSP will convert the FE rate to 48k, stereo, 24 bit @@ -479,31 +461,20 @@ static struct snd_pcm_hw_constraint_list constraints_channels_quad = { static int kbl_fe_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); /* * On this platform for PCM device we support, * 48Khz * stereo + * 16 bit audio */ runtime->hw.channels_max = DUAL_CHANNEL; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &constraints_channels); - /* - * Setup S24_LE (32 bit container and 24 bit valid data) for - * kblda7219m98373 & kblmax98373. For kblda7219m98927 & - * kblmax98927 keeping it as 16/16 due to topology FW dependency. - */ - if (!strcmp(soc_rt->card->name, "kblda7219m98373") || - !strcmp(soc_rt->card->name, "kblmax98373")) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - - } else { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); - } + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); @@ -536,23 +507,11 @@ static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_dmic_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_rt = asoc_substream_to_rtd(substream); runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &constraints_channels_quad); - /* - * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE. - * The DMIC also configured for S24_LE. Forcing the DMIC format to - * S24_LE due to the topology FW dependency. - */ - if (!strcmp(soc_rt->card->name, "kblda7219m98373") || - !strcmp(soc_rt->card->name, "kblmax98373")) { - runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_LE; - snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - } - return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); } diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 42aadf801f72..ce78c1879887 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -16,6 +16,7 @@ #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> +#include <sound/sof.h> #include <sound/soc-acpi.h> #include <dt-bindings/sound/cs42l42.h> #include "../../codecs/hdac_hdmi.h" @@ -36,7 +37,20 @@ #define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7)) #define SOF_CS42L42_NUM_HDMIDEV(quirk) \ (((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK) -#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(10) +#define SOF_CS42L42_DAILINK_SHIFT 10 +#define SOF_CS42L42_DAILINK_MASK (GENMASK(24, 10)) +#define SOF_CS42L42_DAILINK(link1, link2, link3, link4, link5) \ + ((((link1) | ((link2) << 3) | ((link3) << 6) | ((link4) << 9) | ((link5) << 12)) << SOF_CS42L42_DAILINK_SHIFT) & SOF_CS42L42_DAILINK_MASK) +#define SOF_MAX98357A_SPEAKER_AMP_PRESENT BIT(25) +#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(26) + +enum { + LINK_NONE = 0, + LINK_HP = 1, + LINK_SPK = 2, + LINK_DMIC = 3, + LINK_HDMI = 4, +}; /* Default: SSP2 */ static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2); @@ -122,7 +136,12 @@ static int sof_cs42l42_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_freq, ret; - clk_freq = 3072000; /* BCLK freq */ + clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */ + + if (clk_freq <= 0) { + dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq); + return -EINVAL; + } /* Configure sysclk for codec */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, @@ -259,133 +278,168 @@ static struct snd_soc_dai_link_component dmic_component[] = { } }; -static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, - int ssp_codec, - int ssp_amp, - int dmic_be_num, - int hdmi_num) +static int create_spk_amp_dai_links(struct device *dev, + struct snd_soc_dai_link *links, + struct snd_soc_dai_link_component *cpus, + int *id, int ssp_amp) { - struct snd_soc_dai_link_component *idisp_components; - struct snd_soc_dai_link_component *cpus; - struct snd_soc_dai_link *links; - int i, id = 0; - - links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * - sof_audio_card_cs42l42.num_links, GFP_KERNEL); - cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) * - sof_audio_card_cs42l42.num_links, GFP_KERNEL); - if (!links || !cpus) - goto devm_err; + int ret = 0; /* speaker amp */ - if (sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT) { - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d-Codec", ssp_amp); - if (!links[id].name) - goto devm_err; + if (!(sof_cs42l42_quirk & SOF_SPEAKER_AMP_PRESENT)) + return 0; - links[id].id = id; + links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", + ssp_amp); + if (!links[*id].name) { + ret = -ENOMEM; + goto devm_err; + } - if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) { - max_98357a_dai_link(&links[id]); - } else { - dev_err(dev, "no amp defined\n"); - goto devm_err; - } + links[*id].id = *id; - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].dpcm_playback = 1; - links[id].no_pcm = 1; - links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_amp); - if (!links[id].cpus->dai_name) - goto devm_err; + if (sof_cs42l42_quirk & SOF_MAX98357A_SPEAKER_AMP_PRESENT) { + max_98357a_dai_link(&links[*id]); + } else if (sof_cs42l42_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) { + max_98360a_dai_link(&links[*id]); + } else { + dev_err(dev, "no amp defined\n"); + ret = -EINVAL; + goto devm_err; + } - id++; + links[*id].platforms = platform_component; + links[*id].num_platforms = ARRAY_SIZE(platform_component); + links[*id].dpcm_playback = 1; + links[*id].no_pcm = 1; + links[*id].cpus = &cpus[*id]; + links[*id].num_cpus = 1; + + links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", ssp_amp); + if (!links[*id].cpus->dai_name) { + ret = -ENOMEM; + goto devm_err; } + (*id)++; + +devm_err: + return ret; +} + +static int create_hp_codec_dai_links(struct device *dev, + struct snd_soc_dai_link *links, + struct snd_soc_dai_link_component *cpus, + int *id, int ssp_codec) +{ /* codec SSP */ - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d-Codec", ssp_codec); - if (!links[id].name) + links[*id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", + ssp_codec); + if (!links[*id].name) goto devm_err; - links[id].id = id; - links[id].codecs = cs42l42_component; - links[id].num_codecs = ARRAY_SIZE(cs42l42_component); - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].init = sof_cs42l42_init; - links[id].exit = sof_cs42l42_exit; - links[id].ops = &sof_cs42l42_ops; - links[id].dpcm_playback = 1; - links[id].dpcm_capture = 1; - links[id].no_pcm = 1; - links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "SSP%d Pin", - ssp_codec); - if (!links[id].cpus->dai_name) + links[*id].id = *id; + links[*id].codecs = cs42l42_component; + links[*id].num_codecs = ARRAY_SIZE(cs42l42_component); + links[*id].platforms = platform_component; + links[*id].num_platforms = ARRAY_SIZE(platform_component); + links[*id].init = sof_cs42l42_init; + links[*id].exit = sof_cs42l42_exit; + links[*id].ops = &sof_cs42l42_ops; + links[*id].dpcm_playback = 1; + links[*id].dpcm_capture = 1; + links[*id].no_pcm = 1; + links[*id].cpus = &cpus[*id]; + links[*id].num_cpus = 1; + + links[*id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", + ssp_codec); + if (!links[*id].cpus->dai_name) goto devm_err; - id++; + (*id)++; + + return 0; + +devm_err: + return -ENOMEM; +} + +static int create_dmic_dai_links(struct device *dev, + struct snd_soc_dai_link *links, + struct snd_soc_dai_link_component *cpus, + int *id, int dmic_be_num) +{ + int i; /* dmic */ - if (dmic_be_num > 0) { - /* at least we have dmic01 */ - links[id].name = "dmic01"; - links[id].cpus = &cpus[id]; - links[id].cpus->dai_name = "DMIC01 Pin"; - links[id].init = dmic_init; - if (dmic_be_num > 1) { - /* set up 2 BE links at most */ - links[id + 1].name = "dmic16k"; - links[id + 1].cpus = &cpus[id + 1]; - links[id + 1].cpus->dai_name = "DMIC16k Pin"; - dmic_be_num = 2; - } + if (dmic_be_num <= 0) + return 0; + + /* at least we have dmic01 */ + links[*id].name = "dmic01"; + links[*id].cpus = &cpus[*id]; + links[*id].cpus->dai_name = "DMIC01 Pin"; + links[*id].init = dmic_init; + if (dmic_be_num > 1) { + /* set up 2 BE links at most */ + links[*id + 1].name = "dmic16k"; + links[*id + 1].cpus = &cpus[*id + 1]; + links[*id + 1].cpus->dai_name = "DMIC16k Pin"; + dmic_be_num = 2; } for (i = 0; i < dmic_be_num; i++) { - links[id].id = id; - links[id].num_cpus = 1; - links[id].codecs = dmic_component; - links[id].num_codecs = ARRAY_SIZE(dmic_component); - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].ignore_suspend = 1; - links[id].dpcm_capture = 1; - links[id].no_pcm = 1; - id++; + links[*id].id = *id; + links[*id].num_cpus = 1; + links[*id].codecs = dmic_component; + links[*id].num_codecs = ARRAY_SIZE(dmic_component); + links[*id].platforms = platform_component; + links[*id].num_platforms = ARRAY_SIZE(platform_component); + links[*id].ignore_suspend = 1; + links[*id].dpcm_capture = 1; + links[*id].no_pcm = 1; + + (*id)++; } + return 0; +} + +static int create_hdmi_dai_links(struct device *dev, + struct snd_soc_dai_link *links, + struct snd_soc_dai_link_component *cpus, + int *id, int hdmi_num) +{ + struct snd_soc_dai_link_component *idisp_components; + int i; + /* HDMI */ - if (hdmi_num > 0) { - idisp_components = devm_kzalloc(dev, - sizeof(struct snd_soc_dai_link_component) * - hdmi_num, GFP_KERNEL); - if (!idisp_components) - goto devm_err; - } + if (hdmi_num <= 0) + return 0; + + idisp_components = devm_kzalloc(dev, + sizeof(struct snd_soc_dai_link_component) * + hdmi_num, GFP_KERNEL); + if (!idisp_components) + goto devm_err; + for (i = 1; i <= hdmi_num; i++) { - links[id].name = devm_kasprintf(dev, GFP_KERNEL, - "iDisp%d", i); - if (!links[id].name) + links[*id].name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d", i); + if (!links[*id].name) goto devm_err; - links[id].id = id; - links[id].cpus = &cpus[id]; - links[id].num_cpus = 1; - links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, - "iDisp%d Pin", i); - if (!links[id].cpus->dai_name) + links[*id].id = *id; + links[*id].cpus = &cpus[*id]; + links[*id].num_cpus = 1; + links[*id].cpus->dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "iDisp%d Pin", + i); + if (!links[*id].cpus->dai_name) goto devm_err; idisp_components[i - 1].name = "ehdaudio0D2"; @@ -396,14 +450,86 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, if (!idisp_components[i - 1].dai_name) goto devm_err; - links[id].codecs = &idisp_components[i - 1]; - links[id].num_codecs = 1; - links[id].platforms = platform_component; - links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].init = sof_hdmi_init; - links[id].dpcm_playback = 1; - links[id].no_pcm = 1; - id++; + links[*id].codecs = &idisp_components[i - 1]; + links[*id].num_codecs = 1; + links[*id].platforms = platform_component; + links[*id].num_platforms = ARRAY_SIZE(platform_component); + links[*id].init = sof_hdmi_init; + links[*id].dpcm_playback = 1; + links[*id].no_pcm = 1; + + (*id)++; + } + + return 0; + +devm_err: + return -ENOMEM; +} + +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, + int ssp_codec, + int ssp_amp, + int dmic_be_num, + int hdmi_num) +{ + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link *links; + int ret, id = 0, link_seq; + + links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * + sof_audio_card_cs42l42.num_links, GFP_KERNEL); + cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) * + sof_audio_card_cs42l42.num_links, GFP_KERNEL); + if (!links || !cpus) + goto devm_err; + + link_seq = (sof_cs42l42_quirk & SOF_CS42L42_DAILINK_MASK) >> SOF_CS42L42_DAILINK_SHIFT; + + while (link_seq) { + int link_type = link_seq & 0x07; + + switch (link_type) { + case LINK_HP: + ret = create_hp_codec_dai_links(dev, links, cpus, &id, ssp_codec); + if (ret < 0) { + dev_err(dev, "fail to create hp codec dai links, ret %d\n", + ret); + goto devm_err; + } + break; + case LINK_SPK: + ret = create_spk_amp_dai_links(dev, links, cpus, &id, ssp_amp); + if (ret < 0) { + dev_err(dev, "fail to create spk amp dai links, ret %d\n", + ret); + goto devm_err; + } + break; + case LINK_DMIC: + ret = create_dmic_dai_links(dev, links, cpus, &id, dmic_be_num); + if (ret < 0) { + dev_err(dev, "fail to create dmic dai links, ret %d\n", + ret); + goto devm_err; + } + break; + case LINK_HDMI: + ret = create_hdmi_dai_links(dev, links, cpus, &id, hdmi_num); + if (ret < 0) { + dev_err(dev, "fail to create hdmi dai links, ret %d\n", + ret); + goto devm_err; + } + break; + case LINK_NONE: + /* caught here if it's not used as terminator in macro */ + default: + dev_err(dev, "invalid link type %d\n", link_type); + goto devm_err; + } + + link_seq >>= 3; } return links; @@ -484,7 +610,16 @@ static const struct platform_device_id board_ids[] = { .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) | SOF_SPEAKER_AMP_PRESENT | SOF_MAX98357A_SPEAKER_AMP_PRESENT | - SOF_CS42L42_SSP_AMP(1)), + SOF_CS42L42_SSP_AMP(1)) | + SOF_CS42L42_DAILINK(LINK_SPK, LINK_HP, LINK_DMIC, LINK_HDMI, LINK_NONE), + }, + { + .name = "jsl_cs4242_mx98360a", + .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_CS42L42_SSP_AMP(1)) | + SOF_CS42L42_DAILINK(LINK_HP, LINK_DMIC, LINK_HDMI, LINK_SPK, LINK_NONE), }, { } }; diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index e9c52f8b6428..e66dfe666915 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -134,7 +134,7 @@ void max_98373_set_codec_conf(struct snd_soc_card *card) EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON); /* - * Maxim MAX98357A + * Maxim MAX98357A/MAX98360A */ static const struct snd_kcontrol_new max_98357a_kcontrols[] = { SOC_DAPM_PIN_SWITCH("Spk"), @@ -156,6 +156,13 @@ static struct snd_soc_dai_link_component max_98357a_components[] = { } }; +static struct snd_soc_dai_link_component max_98360a_components[] = { + { + .name = MAX_98360A_DEV0_NAME, + .dai_name = MAX_98357A_CODEC_DAI, + } +}; + static int max_98357a_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -193,5 +200,13 @@ void max_98357a_dai_link(struct snd_soc_dai_link *link) } EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); +void max_98360a_dai_link(struct snd_soc_dai_link *link) +{ + link->codecs = max_98360a_components; + link->num_codecs = ARRAY_SIZE(max_98360a_components); + link->init = max_98357a_init; +} +EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); + MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 2674f1e373ef..3ff5e8fec4de 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -25,11 +25,13 @@ void max_98373_set_codec_conf(struct snd_soc_card *card); int max_98373_trigger(struct snd_pcm_substream *substream, int cmd); /* - * Maxim MAX98357A + * Maxim MAX98357A/MAX98360A */ #define MAX_98357A_CODEC_DAI "HiFi" #define MAX_98357A_DEV0_NAME "MX98357A:00" +#define MAX_98360A_DEV0_NAME "MX98360A:00" void max_98357a_dai_link(struct snd_soc_dai_link *link); +void max_98360a_dai_link(struct snd_soc_dai_link *link); #endif /* __SOF_MAXIM_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index 2ec9c62366e2..6815204e58d5 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -26,11 +26,16 @@ #define SOF_PCM512X_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0)) #define SOF_PCM512X_SSP_CODEC_MASK (GENMASK(3, 0)) +#define SOF_PCM512X_ENABLE_SSP_CAPTURE BIT(4) +#define SOF_PCM512X_ENABLE_DMIC BIT(5) #define IDISP_CODEC_MASK 0x4 /* Default: SSP5 */ -static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5); +static unsigned long sof_pcm512x_quirk = + SOF_PCM512X_SSP_CODEC(5) | + SOF_PCM512X_ENABLE_SSP_CAPTURE | + SOF_PCM512X_ENABLE_DMIC; static bool is_legacy_cpu; @@ -244,8 +249,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].dpcm_playback = 1; /* * capture only supported with specific versions of the Hifiberry DAC+ - * links[id].dpcm_capture = 1; */ + if (sof_pcm512x_quirk & SOF_PCM512X_ENABLE_SSP_CAPTURE) + links[id].dpcm_capture = 1; links[id].no_pcm = 1; links[id].cpus = &cpus[id]; links[id].num_cpus = 1; @@ -380,6 +386,9 @@ static int sof_audio_probe(struct platform_device *pdev) ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK; + if (!(sof_pcm512x_quirk & SOF_PCM512X_ENABLE_DMIC)) + dmic_be_num = 0; + /* compute number of dai links */ sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num; diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 39217223d50c..f096bd6d69be 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -162,6 +162,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_RT5682_SSP_AMP(2) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), + DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"), + }, + .driver_data = (void *)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98373_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(2) | + SOF_RT5682_NUM_HDMIDEV(4)), + }, {} }; @@ -456,10 +470,6 @@ static const struct snd_kcontrol_new sof_controls[] = { }; -static const struct snd_kcontrol_new speaker_controls[] = { - SOC_DAPM_PIN_SWITCH("Spk"), -}; - static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), @@ -467,10 +477,6 @@ static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_SPK("Right Spk", NULL), }; -static const struct snd_soc_dapm_widget speaker_widgets[] = { - SND_SOC_DAPM_SPK("Spk", NULL), -}; - static const struct snd_soc_dapm_widget dmic_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; @@ -484,11 +490,6 @@ static const struct snd_soc_dapm_route sof_map[] = { { "IN1P", NULL, "Headset Mic" }, }; -static const struct snd_soc_dapm_route speaker_map[] = { - /* speaker */ - { "Spk", NULL, "Speaker" }, -}; - static const struct snd_soc_dapm_route speaker_map_lr[] = { { "Left Spk", NULL, "Left SPO" }, { "Right Spk", NULL, "Right SPO" }, @@ -505,34 +506,6 @@ static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd) ARRAY_SIZE(speaker_map_lr)); } -static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - int ret; - - ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets, - ARRAY_SIZE(speaker_widgets)); - if (ret) { - dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret); - /* Don't need to add routes if widget addition failed */ - return ret; - } - - ret = snd_soc_add_card_controls(card, speaker_controls, - ARRAY_SIZE(speaker_controls)); - if (ret) { - dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map, - ARRAY_SIZE(speaker_map)); - - if (ret) - dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); - return ret; -} - static int dmic_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -594,13 +567,6 @@ static struct snd_soc_dai_link_component dmic_component[] = { } }; -static struct snd_soc_dai_link_component max98360a_component[] = { - { - .name = "MX98360A:00", - .dai_name = "HiFi", - } -}; - static struct snd_soc_dai_link_component rt1015_components[] = { { .name = "i2c-10EC1015:00", @@ -775,9 +741,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].dpcm_capture = 1; } else if (sof_rt5682_quirk & SOF_MAX98360A_SPEAKER_AMP_PRESENT) { - links[id].codecs = max98360a_component; - links[id].num_codecs = ARRAY_SIZE(max98360a_component); - links[id].init = speaker_codec_init; + max_98360a_dai_link(&links[id]); } else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT) { sof_rt1011_dai_link(&links[id]); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e9118234b30e..6602eda89e8e 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -13,8 +13,9 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include "sof_sdw_common.h" +#include "../../codecs/rt711.h" -unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1; +unsigned long sof_sdw_quirk = RT711_JD1; static int quirk_override = -1; module_param_named(quirk, quirk_override, int, 0444); MODULE_PARM_DESC(quirk, "Board-specific quirk override"); @@ -63,7 +64,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(RT711_JD2 | SOF_RT715_DAI_ID_FIX), }, { @@ -73,7 +74,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(RT711_JD2 | SOF_RT715_DAI_ID_FIX), }, { @@ -82,7 +83,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(RT711_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, @@ -92,7 +93,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + .driver_data = (void *)(RT711_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, @@ -114,7 +115,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { "Tiger Lake Client Platform"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD1 | + RT711_JD1 | SOF_SDW_PCH_DMIC | SOF_SSP_PORT(SOF_I2S_SSP2)), }, @@ -125,17 +126,29 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | + RT711_JD2 | SOF_RT715_DAI_ID_FIX), }, { + /* Dell XPS 9710 */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), + }, + { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | + RT711_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, @@ -175,7 +188,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | - SOF_RT711_JD_SRC_JD2), + RT711_JD2), + }, + { + /* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"), + DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + RT711_JD1), }, /* TigerLake-SDCA devices */ { @@ -185,7 +209,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | + RT711_JD2 | SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, @@ -196,7 +220,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), }, - .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | + .driver_data = (void *)(RT711_JD2_100K | SOF_SDW_TGL_HDMI | SOF_RT715_DAI_ID_FIX | SOF_BT_OFFLOAD_SSP(2) | @@ -328,6 +352,20 @@ static const struct snd_soc_ops sdw_ops = { .shutdown = sdw_shutdown, }; +static int sof_sdw_mic_codec_mockup_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * force DAI link to use same ID as RT715 and DMIC + * to reuse topologies + */ + dai_links->id = SDW_DMIC_DAI_ID; + return 0; +} + static struct sof_sdw_codec_info codec_info_list[] = { { .part_id = 0x700, @@ -410,6 +448,34 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt5682-sdw", .init = sof_sdw_rt5682_init, }, + { + .part_id = 0xaaaa, /* generic codec mockup */ + .version_id = 0, + .direction = {true, true}, + .dai_name = "sdw-mockup-aif1", + .init = NULL, + }, + { + .part_id = 0xaa55, /* headset codec mockup */ + .version_id = 0, + .direction = {true, true}, + .dai_name = "sdw-mockup-aif1", + .init = NULL, + }, + { + .part_id = 0x55aa, /* amplifier mockup */ + .version_id = 0, + .direction = {true, false}, + .dai_name = "sdw-mockup-aif1", + .init = NULL, + }, + { + .part_id = 0x5555, + .version_id = 0, + .direction = {false, true}, + .dai_name = "sdw-mockup-aif1", + .init = sof_sdw_mic_codec_mockup_init, + }, }; static inline int find_codec_info_part(u64 adr) @@ -600,13 +666,13 @@ static int create_codec_dai_name(struct device *dev, comp_index = i + offset; if (is_unique_device(link, sdw_version, mfg_id, part_id, class_id, i)) { - codec_str = "sdw:%x:%x:%x:%x"; + codec_str = "sdw:%01x:%04x:%04x:%02x"; codec[comp_index].name = devm_kasprintf(dev, GFP_KERNEL, codec_str, link_id, mfg_id, part_id, class_id); } else { - codec_str = "sdw:%x:%x:%x:%x:%x"; + codec_str = "sdw:%01x:%04x:%04x:%02x:%01x"; codec[comp_index].name = devm_kasprintf(dev, GFP_KERNEL, codec_str, link_id, mfg_id, part_id, @@ -632,7 +698,8 @@ static int create_codec_dai_name(struct device *dev, return 0; } -static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, +static int set_codec_init_func(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, bool playback, int group_id) { @@ -655,7 +722,8 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, if (link->adr_d[i].endpoints->group_id != group_id) continue; if (codec_info_list[codec_index].init) - codec_info_list[codec_index].init(link, + codec_info_list[codec_index].init(card, + link, dai_links, &codec_info_list[codec_index], playback); @@ -740,7 +808,8 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } -static int create_sdw_dailink(struct device *dev, int *be_index, +static int create_sdw_dailink(struct snd_soc_card *card, + struct device *dev, int *be_index, struct snd_soc_dai_link *dai_links, int sdw_be_num, int sdw_cpu_dai_num, struct snd_soc_dai_link_component *cpus, @@ -861,7 +930,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, codecs, codec_num, NULL, &sdw_ops); - ret = set_codec_init_func(link, dai_links + (*be_index)++, + ret = set_codec_init_func(card, link, dai_links + (*be_index)++, playback, group_id); if (ret < 0) { dev_err(dev, "failed to init codec %d", codec_index); @@ -1042,7 +1111,7 @@ static int sof_card_dai_links_create(struct device *dev, group_generated[endpoint->group_id]) continue; - ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num, + ret = create_sdw_dailink(card, dev, &be_id, links, sdw_be_num, sdw_cpu_dai_num, cpus, adr_link, &cpu_id, group_generated, codec_conf, codec_conf_count, @@ -1105,7 +1174,7 @@ SSP: ssp_components, 1, NULL, info->ops); - ret = info->init(NULL, links + link_id, info, 0); + ret = info->init(card, NULL, links + link_id, info, 0); if (ret < 0) return ret; @@ -1328,7 +1397,7 @@ static int mc_remove(struct platform_device *pdev) for_each_card_prelinks(card, j, link) { if (!strcmp(link->codecs[0].dai_name, codec_info_list[i].dai_name)) { - ret = codec_info_list[i].exit(&pdev->dev, link); + ret = codec_info_list[i].exit(card, link); if (ret) dev_warn(&pdev->dev, "codec exit failed %d\n", diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index ec5740486b75..b35f5a9b96f5 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -23,11 +23,6 @@ #define SDW_MAX_GROUPS 9 enum { - SOF_RT711_JD_SRC_JD1 = 1, - SOF_RT711_JD_SRC_JD2 = 2, -}; - -enum { SOF_PRE_TGL_HDMI_COUNT = 3, SOF_TGL_HDMI_COUNT = 4, }; @@ -41,21 +36,21 @@ enum { SOF_I2S_SSP5 = BIT(5), }; -#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(1, 0)) -#define SOF_SDW_FOUR_SPK BIT(2) -#define SOF_SDW_TGL_HDMI BIT(3) -#define SOF_SDW_PCH_DMIC BIT(4) -#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 5) -#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 5) & GENMASK(5, 0)) -#define SOF_RT715_DAI_ID_FIX BIT(11) -#define SOF_SDW_NO_AGGREGATION BIT(12) +#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) +#define SOF_SDW_FOUR_SPK BIT(4) +#define SOF_SDW_TGL_HDMI BIT(5) +#define SOF_SDW_PCH_DMIC BIT(6) +#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7) +#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) +#define SOF_RT715_DAI_ID_FIX BIT(13) +#define SOF_SDW_NO_AGGREGATION BIT(14) /* BT audio offload: reserve 3 bits for future */ -#define SOF_BT_OFFLOAD_SSP_SHIFT 13 -#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(15, 13)) +#define SOF_BT_OFFLOAD_SSP_SHIFT 15 +#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(17, 15)) #define SOF_BT_OFFLOAD_SSP(quirk) \ (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) -#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(16) +#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18) struct sof_sdw_codec_info { const int part_id; @@ -67,12 +62,13 @@ struct sof_sdw_codec_info { const char *dai_name; const struct snd_soc_ops *ops; - int (*init)(const struct snd_soc_acpi_link_adr *link, + int (*init)(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); - int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link); + int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; @@ -81,6 +77,7 @@ struct mc_private { struct list_head hdmi_pcm_list; bool idisp_codec; struct snd_soc_jack sdw_headset; + struct device *headset_codec_dev; /* only one headset per card */ }; extern unsigned long sof_sdw_quirk; @@ -100,21 +97,24 @@ int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card); int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); /* RT711 support */ -int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt711_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link); +int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); /* RT711-SDCA support */ -int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt711_sdca_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); -int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link); +int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); /* RT700 support */ -int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt700_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -122,31 +122,36 @@ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, /* RT1308 support */ extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; -int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt1308_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* RT1316 support */ -int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt1316_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* RT715 support */ -int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt715_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* RT715-SDCA support */ -int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt715_sdca_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* MAX98373 support */ -int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_mx8373_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -154,7 +159,8 @@ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, int sof_sdw_mx8373_late_probe(struct snd_soc_card *card); /* RT5682 support */ -int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt5682_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 25daef910aee..77a3f32db11e 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -90,7 +90,7 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl static int mx8373_sdw_prepare(struct snd_pcm_substream *substream) { - int ret = 0; + int ret; /* according to soc_pcm_prepare dai link prepare is called first */ ret = sdw_prepare(substream); @@ -102,7 +102,7 @@ static int mx8373_sdw_prepare(struct snd_pcm_substream *substream) static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream) { - int ret = 0; + int ret; /* according to soc_pcm_hw_free dai link free is called first */ ret = sdw_hw_free(substream); @@ -120,7 +120,8 @@ static const struct snd_soc_ops max_98373_sdw_ops = { .shutdown = sdw_shutdown, }; -int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_mx8373_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 0d476f6f6313..f078fb1aad02 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -127,7 +127,8 @@ struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { .hw_params = rt1308_i2s_hw_params, }; -int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt1308_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c index d6e1ebf18d57..58194b380232 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1316.c +++ b/sound/soc/intel/boards/sof_sdw_rt1316.c @@ -89,7 +89,8 @@ static int all_spk_init(struct snd_soc_pcm_runtime *rtd) return second_spk_init(rtd); } -int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt1316_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 5fa1a59615b6..ea55479609a8 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -111,7 +111,8 @@ static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt5682_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 21e7e4a81779..bb9584c8f866 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -110,7 +110,8 @@ static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt700_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 04074c09dded..c38b70c9fac3 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -21,23 +21,23 @@ * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int rt711_add_codec_device_props(const char *sdw_dev_name) +static int rt711_add_codec_device_props(struct device *sdw_dev) { struct property_entry props[MAX_NO_PROPS] = {}; - struct device *sdw_dev; + struct fwnode_handle *fwnode; int ret; - sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name); - if (!sdw_dev) - return -EPROBE_DEFER; + if (!SOF_RT711_JDSRC(sof_sdw_quirk)) + return 0; + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk)); - if (SOF_RT711_JDSRC(sof_sdw_quirk)) { - props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", - SOF_RT711_JDSRC(sof_sdw_quirk)); - } + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); - ret = device_add_properties(sdw_dev, props); - put_device(sdw_dev); + fwnode_handle_put(fwnode); return ret; } @@ -135,26 +135,24 @@ static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link) +int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct device *sdw_dev; - - sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, - dai_link->codecs[0].name); - if (!sdw_dev) - return -EINVAL; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); - device_remove_properties(sdw_dev); - put_device(sdw_dev); + device_remove_software_node(ctx->headset_codec_dev); + put_device(ctx->headset_codec_dev); return 0; } -int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt711_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) { + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct device *sdw_dev; int ret; /* @@ -164,9 +162,16 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, if (!playback) return 0; - ret = rt711_add_codec_device_props(dai_links->codecs[0].name); - if (ret < 0) + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); + if (!sdw_dev) + return -EPROBE_DEFER; + + ret = rt711_add_codec_device_props(sdw_dev); + if (ret < 0) { + put_device(sdw_dev); return ret; + } + ctx->headset_codec_dev = sdw_dev; dai_links->init = rt711_rtd_init; diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c index 19496f0f9110..4215ddc36419 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c @@ -21,23 +21,24 @@ * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name) +static int rt711_sdca_add_codec_device_props(struct device *sdw_dev) { struct property_entry props[MAX_NO_PROPS] = {}; - struct device *sdw_dev; + struct fwnode_handle *fwnode; int ret; - sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name); - if (!sdw_dev) - return -EPROBE_DEFER; + if (!SOF_RT711_JDSRC(sof_sdw_quirk)) + return 0; - if (SOF_RT711_JDSRC(sof_sdw_quirk)) { - props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", - SOF_RT711_JDSRC(sof_sdw_quirk)); - } + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_RT711_JDSRC(sof_sdw_quirk)); - ret = device_add_properties(sdw_dev, props); - put_device(sdw_dev); + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); return ret; } @@ -135,26 +136,24 @@ static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link) +int sof_sdw_rt711_sdca_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct device *sdw_dev; - - sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, - dai_link->codecs[0].name); - if (!sdw_dev) - return -EINVAL; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); - device_remove_properties(sdw_dev); - put_device(sdw_dev); + device_remove_software_node(ctx->headset_codec_dev); + put_device(ctx->headset_codec_dev); return 0; } -int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt711_sdca_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) { + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct device *sdw_dev; int ret; /* @@ -164,9 +163,16 @@ int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link, if (!playback) return 0; - ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name); - if (ret < 0) + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); + if (!sdw_dev) + return -EPROBE_DEFER; + + ret = rt711_sdca_add_codec_device_props(sdw_dev); + if (ret < 0) { + put_device(sdw_dev); return ret; + } + ctx->headset_codec_dev = sdw_dev; dai_links->init = rt711_sdca_rtd_init; diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c index 9b298f79e784..c8af3780cbc3 100644 --- a/sound/soc/intel/boards/sof_sdw_rt715.c +++ b/sound/soc/intel/boards/sof_sdw_rt715.c @@ -24,7 +24,8 @@ static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } -int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt715_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c index c056e56a139b..85d3d8c355cc 100644 --- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c @@ -24,7 +24,8 @@ static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } -int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, +int sof_sdw_rt715_sdca_init(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 12a205ccdeeb..fef0b2d1de68 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -9,7 +9,8 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m soc-acpi-intel-cml-match.o soc-acpi-intel-icl-match.o \ soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \ soc-acpi-intel-jsl-match.o soc-acpi-intel-adl-match.o \ - soc-acpi-intel-hda-match.o + soc-acpi-intel-hda-match.o \ + soc-acpi-intel-sdw-mockup-match.o obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 39dad32564e6..94b650767e11 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -9,6 +9,7 @@ #include <sound/soc-acpi.h> #include <sound/soc-acpi-intel-match.h> #include "../skylake/skl.h" +#include "soc-acpi-intel-sdw-mockup-match.h" static struct skl_machine_pdata cnl_pdata = { .use_tplg_pcm = true, @@ -60,6 +61,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = { .sof_fw_filename = "sof-cnl.ri", .sof_tplg_filename = "sof-cnl-rt5682-sdw2.tplg" }, + { + .link_mask = GENMASK(3, 0), + .links = sdw_mockup_headset_2amps_mic, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-cnl.ri", + .sof_tplg_filename = "sof-cml-rt711-rt1308-rt715.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(3), + .links = sdw_mockup_headset_1amp_mic, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-cnl.ri", + .sof_tplg_filename = "sof-cml-rt711-rt1308-mono-rt715.tplg", + }, {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 3586ce72c42c..69ff7286d357 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -73,6 +73,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { .quirk_data = &mx98360a_spk, .sof_tplg_filename = "sof-jsl-rt5682-mx98360a.tplg", }, + { + .id = "10134242", + .drv_name = "jsl_cs4242_mx98360a", + .sof_fw_filename = "sof-jsl.ri", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &mx98360a_spk, + .sof_tplg_filename = "sof-jsl-cs42l42-mx98360a.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c new file mode 100644 index 000000000000..a3d33997736a --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// soc-acpi-intel-sdw-mockup-match.c - tables and support for SoundWire +// mockup device ACPI enumeration. +// +// Copyright (c) 2021, Intel Corporation. +// + +#include <sound/soc-acpi.h> +#include <sound/soc-acpi-intel-match.h> +#include "soc-acpi-intel-sdw-mockup-match.h" + +static const struct snd_soc_acpi_endpoint sdw_mockup_single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, +}; + +static const struct snd_soc_acpi_endpoint sdw_mockup_l_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 0, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint sdw_mockup_r_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1, +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_headset_0_adr[] = { + { + .adr = 0x0000000105AA5500ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_headset0" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_headset_1_adr[] = { + { + .adr = 0x0001000105AA5500ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_headset1" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_adr[] = { + { + .adr = 0x000100010555AA00ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_amp1" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_adr[] = { + { + .adr = 0x000200010555AA00ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_amp2" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_mic_0_adr[] = { + { + .adr = 0x0000000105555500ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_mic0" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_mic_3_adr[] = { + { + .adr = 0x0003000105555500ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_single_endpoint, + .name_prefix = "sdw_mockup_mic3" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_amp_1_group1_adr[] = { + { + .adr = 0x000100010555AA00ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_l_endpoint, + .name_prefix = "sdw_mockup_amp1_l" + } +}; + +static const struct snd_soc_acpi_adr_device sdw_mockup_amp_2_group1_adr[] = { + { + .adr = 0x000200010555AA00ull, + .num_endpoints = 1, + .endpoints = &sdw_mockup_r_endpoint, + .name_prefix = "sdw_mockup_amp2_r" + } +}; + +const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr), + .adr_d = sdw_mockup_headset_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_adr), + .adr_d = sdw_mockup_amp_1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr), + .adr_d = sdw_mockup_mic_3_adr, + }, + {} +}; + +const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(sdw_mockup_headset_0_adr), + .adr_d = sdw_mockup_headset_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(sdw_mockup_amp_1_group1_adr), + .adr_d = sdw_mockup_amp_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_group1_adr), + .adr_d = sdw_mockup_amp_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(sdw_mockup_mic_3_adr), + .adr_d = sdw_mockup_mic_3_adr, + }, + {} +}; + +const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(sdw_mockup_headset_1_adr), + .adr_d = sdw_mockup_headset_1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(sdw_mockup_amp_2_adr), + .adr_d = sdw_mockup_amp_2_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(sdw_mockup_mic_0_adr), + .adr_d = sdw_mockup_mic_0_adr, + }, + {} +}; diff --git a/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h new file mode 100644 index 000000000000..c99eecd19e03 --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-sdw-mockup-match.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * soc-acpi-intel-sdw-mockup-match.h - tables and support for SoundWire + * mockup device ACPI enumeration. + * + * Copyright (c) 2021, Intel Corporation. + * + */ + +#ifndef _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH +#define _SND_SOC_ACPI_INTEL_SDW_MOCKUP_MATCH + +extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_1amp_mic[]; +extern const struct snd_soc_acpi_link_adr sdw_mockup_headset_2amps_mic[]; +extern const struct snd_soc_acpi_link_adr sdw_mockup_mic_headset_1amp[]; + +#endif diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 66595e3ab13f..785d5f5f8a9c 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -8,6 +8,7 @@ #include <sound/soc-acpi.h> #include <sound/soc-acpi-intel-match.h> +#include "soc-acpi-intel-sdw-mockup-match.h" static const struct snd_soc_acpi_codecs tgl_codecs = { .num_codecs = 1, @@ -196,6 +197,15 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = { {} }; +static const struct snd_soc_acpi_link_adr tgl_rvp_headset_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_0_adr), + .adr_d = rt711_0_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr tgl_hp[] = { { .mask = BIT(0), @@ -351,6 +361,28 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines); /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { + /* mockup tests need to be first */ + { + .link_mask = GENMASK(3, 0), + .links = sdw_mockup_headset_2amps_mic, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(3), + .links = sdw_mockup_headset_1amp_mic, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(2), + .links = sdw_mockup_mic_headset_1amp, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt715-rt711-rt1308-mono.tplg", + }, { .link_mask = 0x7, .links = tgl_sdw_rt711_link1_rt1308_link2_rt715_link0, @@ -398,6 +430,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg", }, + { + .link_mask = 0x1, /* rt711 on link 0 */ + .links = tgl_rvp_headset_only, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-tgl-rt711.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines); diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index 476ef1897961..eaad180af42e 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -472,6 +472,75 @@ static void skl_set_base_module_format(struct skl_dev *skl, base_cfg->is_pages = res->is_pages; } +static void fill_pin_params(struct skl_audio_data_format *pin_fmt, + struct skl_module_fmt *format) +{ + pin_fmt->number_of_channels = format->channels; + pin_fmt->s_freq = format->s_freq; + pin_fmt->bit_depth = format->bit_depth; + pin_fmt->valid_bit_depth = format->valid_bit_depth; + pin_fmt->ch_cfg = format->ch_cfg; + pin_fmt->sample_type = format->sample_type; + pin_fmt->channel_map = format->ch_map; + pin_fmt->interleaving = format->interleaving_style; +} + +/* + * Any module configuration begins with a base module configuration but + * can be followed by a generic extension containing audio format for all + * module's pins that are in use. + */ +static void skl_set_base_ext_module_format(struct skl_dev *skl, + struct skl_module_cfg *mconfig, + struct skl_base_cfg_ext *base_cfg_ext) +{ + struct skl_module *module = mconfig->module; + struct skl_module_pin_resources *pin_res; + struct skl_module_iface *fmt = &module->formats[mconfig->fmt_idx]; + struct skl_module_res *res = &module->resources[mconfig->res_idx]; + struct skl_module_fmt *format; + struct skl_pin_format *pin_fmt; + char *params; + int i; + + base_cfg_ext->nr_input_pins = res->nr_input_pins; + base_cfg_ext->nr_output_pins = res->nr_output_pins; + base_cfg_ext->priv_param_length = + mconfig->formats_config[SKL_PARAM_INIT].caps_size; + + for (i = 0; i < res->nr_input_pins; i++) { + pin_res = &res->input[i]; + pin_fmt = &base_cfg_ext->pins_fmt[i]; + + pin_fmt->pin_idx = pin_res->pin_index; + pin_fmt->buf_size = pin_res->buf_size; + + format = &fmt->inputs[pin_res->pin_index].fmt; + fill_pin_params(&pin_fmt->audio_fmt, format); + } + + for (i = 0; i < res->nr_output_pins; i++) { + pin_res = &res->output[i]; + pin_fmt = &base_cfg_ext->pins_fmt[res->nr_input_pins + i]; + + pin_fmt->pin_idx = pin_res->pin_index; + pin_fmt->buf_size = pin_res->buf_size; + + format = &fmt->outputs[pin_res->pin_index].fmt; + fill_pin_params(&pin_fmt->audio_fmt, format); + } + + if (!base_cfg_ext->priv_param_length) + return; + + params = (char *)base_cfg_ext + sizeof(struct skl_base_cfg_ext); + params += (base_cfg_ext->nr_input_pins + base_cfg_ext->nr_output_pins) * + sizeof(struct skl_pin_format); + + memcpy(params, mconfig->formats_config[SKL_PARAM_INIT].caps, + mconfig->formats_config[SKL_PARAM_INIT].caps_size); +} + /* * Copies copier capabilities into copier module and updates copier module * config size. @@ -479,15 +548,15 @@ static void skl_set_base_module_format(struct skl_dev *skl, static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, struct skl_cpr_cfg *cpr_mconfig) { - if (mconfig->formats_config.caps_size == 0) + if (mconfig->formats_config[SKL_PARAM_INIT].caps_size == 0) return; memcpy(cpr_mconfig->gtw_cfg.config_data, - mconfig->formats_config.caps, - mconfig->formats_config.caps_size); + mconfig->formats_config[SKL_PARAM_INIT].caps, + mconfig->formats_config[SKL_PARAM_INIT].caps_size); cpr_mconfig->gtw_cfg.config_length = - (mconfig->formats_config.caps_size) / 4; + (mconfig->formats_config[SKL_PARAM_INIT].caps_size) / 4; } #define SKL_NON_GATEWAY_CPR_NODE_ID 0xFFFFFFFF @@ -738,28 +807,6 @@ static void skl_set_copier_format(struct skl_dev *skl, } /* - * Algo module are DSP pre processing modules. Algo module take base module - * configuration and params - */ - -static void skl_set_algo_format(struct skl_dev *skl, - struct skl_module_cfg *mconfig, - struct skl_algo_cfg *algo_mcfg) -{ - struct skl_base_cfg *base_cfg = (struct skl_base_cfg *)algo_mcfg; - - skl_set_base_module_format(skl, mconfig, base_cfg); - - if (mconfig->formats_config.caps_size == 0) - return; - - memcpy(algo_mcfg->params, - mconfig->formats_config.caps, - mconfig->formats_config.caps_size); - -} - -/* * Mic select module allows selecting one or many input channels, thus * acting as a demux. * @@ -781,12 +828,14 @@ static void skl_set_base_outfmt_format(struct skl_dev *skl, static u16 skl_get_module_param_size(struct skl_dev *skl, struct skl_module_cfg *mconfig) { + struct skl_module_res *res; + struct skl_module *module = mconfig->module; u16 param_size; switch (mconfig->m_type) { case SKL_MODULE_TYPE_COPIER: param_size = sizeof(struct skl_cpr_cfg); - param_size += mconfig->formats_config.caps_size; + param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size; return param_size; case SKL_MODULE_TYPE_SRCINT: @@ -795,22 +844,24 @@ static u16 skl_get_module_param_size(struct skl_dev *skl, case SKL_MODULE_TYPE_UPDWMIX: return sizeof(struct skl_up_down_mixer_cfg); - case SKL_MODULE_TYPE_ALGO: - param_size = sizeof(struct skl_base_cfg); - param_size += mconfig->formats_config.caps_size; - return param_size; - case SKL_MODULE_TYPE_BASE_OUTFMT: case SKL_MODULE_TYPE_MIC_SELECT: - case SKL_MODULE_TYPE_KPB: return sizeof(struct skl_base_outfmt_cfg); - default: - /* - * return only base cfg when no specific module type is - * specified - */ + case SKL_MODULE_TYPE_MIXER: + case SKL_MODULE_TYPE_KPB: return sizeof(struct skl_base_cfg); + + case SKL_MODULE_TYPE_ALGO: + default: + res = &module->resources[mconfig->res_idx]; + + param_size = sizeof(struct skl_base_cfg) + sizeof(struct skl_base_cfg_ext); + param_size += (res->nr_input_pins + res->nr_output_pins) * + sizeof(struct skl_pin_format); + param_size += mconfig->formats_config[SKL_PARAM_INIT].caps_size; + + return param_size; } return 0; @@ -851,20 +902,23 @@ static int skl_set_module_format(struct skl_dev *skl, skl_set_updown_mixer_format(skl, module_config, *param_data); break; - case SKL_MODULE_TYPE_ALGO: - skl_set_algo_format(skl, module_config, *param_data); - break; - case SKL_MODULE_TYPE_BASE_OUTFMT: case SKL_MODULE_TYPE_MIC_SELECT: - case SKL_MODULE_TYPE_KPB: skl_set_base_outfmt_format(skl, module_config, *param_data); break; - default: + case SKL_MODULE_TYPE_MIXER: + case SKL_MODULE_TYPE_KPB: skl_set_base_module_format(skl, module_config, *param_data); break; + case SKL_MODULE_TYPE_ALGO: + default: + skl_set_base_module_format(skl, module_config, *param_data); + skl_set_base_ext_module_format(skl, module_config, + *param_data + + sizeof(struct skl_base_cfg)); + break; } dev_dbg(skl->dev, "Module type=%d id=%d config size: %d bytes\n", @@ -1085,19 +1139,6 @@ int skl_unbind_modules(struct skl_dev *skl, return ret; } -static void fill_pin_params(struct skl_audio_data_format *pin_fmt, - struct skl_module_fmt *format) -{ - pin_fmt->number_of_channels = format->channels; - pin_fmt->s_freq = format->s_freq; - pin_fmt->bit_depth = format->bit_depth; - pin_fmt->valid_bit_depth = format->valid_bit_depth; - pin_fmt->ch_cfg = format->ch_cfg; - pin_fmt->sample_type = format->sample_type; - pin_fmt->channel_map = format->ch_map; - pin_fmt->interleaving = format->interleaving_style; -} - #define CPR_SINK_FMT_PARAM_ID 2 /* diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index b1ca64d2f7ea..9ecaf6a1e847 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -1214,13 +1214,6 @@ static snd_pcm_uframes_t skl_platform_soc_pointer( return bytes_to_frames(substream->runtime, pos); } -static int skl_platform_soc_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *area) -{ - return snd_pcm_lib_default_mmap(substream, area); -} - static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream, u64 nsec) { @@ -1317,21 +1310,6 @@ static int skl_get_module_info(struct skl_dev *skl, return -EIO; } - list_for_each_entry(module, &skl->uuid_list, list) { - if (guid_equal(uuid_mod, &module->uuid)) { - mconfig->id.module_id = module->id; - if (mconfig->module) - mconfig->module->loadable = module->is_loadable; - ret = 0; - break; - } - } - - if (ret) - return ret; - - uuid_mod = &module->uuid; - ret = -EIO; for (i = 0; i < skl->nr_modules; i++) { skl_module = skl->modules[i]; uuid_tplg = &skl_module->uuid; @@ -1341,10 +1319,18 @@ static int skl_get_module_info(struct skl_dev *skl, break; } } + if (skl->nr_modules && ret) return ret; + ret = -EIO; list_for_each_entry(module, &skl->uuid_list, list) { + if (guid_equal(uuid_mod, &module->uuid)) { + mconfig->id.module_id = module->id; + mconfig->module->loadable = module->is_loadable; + ret = 0; + } + for (i = 0; i < MAX_IN_QUEUE; i++) { pin_id = &mconfig->m_in_pin[i].id; if (guid_equal(&pin_id->mod_uuid, &module->uuid)) @@ -1358,7 +1344,7 @@ static int skl_get_module_info(struct skl_dev *skl, } } - return 0; + return ret; } static int skl_populate_modules(struct skl_dev *skl) @@ -1460,7 +1446,6 @@ static const struct snd_soc_component_driver skl_component = { .trigger = skl_platform_soc_trigger, .pointer = skl_platform_soc_pointer, .get_time_info = skl_platform_soc_get_time_info, - .mmap = skl_platform_soc_mmap, .pcm_construct = skl_platform_soc_new, .module_get_upon_open = 1, /* increment refcount when a pcm is opened */ }; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index c0fdab39e7c2..b036852d6889 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -113,7 +113,7 @@ static int is_skl_dsp_widget_type(struct snd_soc_dapm_widget *w, static void skl_dump_mconfig(struct skl_dev *skl, struct skl_module_cfg *mcfg) { - struct skl_module_iface *iface = &mcfg->module->formats[0]; + struct skl_module_iface *iface = &mcfg->module->formats[mcfg->fmt_idx]; dev_dbg(skl->dev, "Dumping config\n"); dev_dbg(skl->dev, "Input Format:\n"); @@ -195,8 +195,8 @@ static void skl_tplg_update_params_fixup(struct skl_module_cfg *m_cfg, struct skl_module_fmt *in_fmt, *out_fmt; /* Fixups will be applied to pin 0 only */ - in_fmt = &m_cfg->module->formats[0].inputs[0].fmt; - out_fmt = &m_cfg->module->formats[0].outputs[0].fmt; + in_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].inputs[0].fmt; + out_fmt = &m_cfg->module->formats[m_cfg->fmt_idx].outputs[0].fmt; if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (is_fe) { @@ -239,9 +239,9 @@ static void skl_tplg_update_buffer_size(struct skl_dev *skl, /* Since fixups is applied to pin 0 only, ibs, obs needs * change for pin 0 only */ - res = &mcfg->module->resources[0]; - in_fmt = &mcfg->module->formats[0].inputs[0].fmt; - out_fmt = &mcfg->module->formats[0].outputs[0].fmt; + res = &mcfg->module->resources[mcfg->res_idx]; + in_fmt = &mcfg->module->formats[mcfg->fmt_idx].inputs[0].fmt; + out_fmt = &mcfg->module->formats[mcfg->fmt_idx].outputs[0].fmt; if (mcfg->m_type == SKL_MODULE_TYPE_SRCINT) multiplier = 5; @@ -292,7 +292,7 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, struct skl_module_iface *m_iface = &m_cfg->module->formats[fmt_idx]; /* check if we already have blob */ - if (m_cfg->formats_config.caps_size > 0) + if (m_cfg->formats_config[SKL_PARAM_INIT].caps_size > 0) return 0; dev_dbg(skl->dev, "Applying default cfg blob\n"); @@ -328,8 +328,8 @@ static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w, cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type, s_fmt, ch, s_freq, dir, dev_type); if (cfg) { - m_cfg->formats_config.caps_size = cfg->size; - m_cfg->formats_config.caps = (u32 *) &cfg->caps; + m_cfg->formats_config[SKL_PARAM_INIT].caps_size = cfg->size; + m_cfg->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps; } else { dev_err(skl->dev, "Blob NULL for id %x type %d dirn %d\n", m_cfg->vbus_id, link_type, dir); @@ -386,9 +386,9 @@ static int skl_tplg_set_module_params(struct snd_soc_dapm_widget *w, struct skl_algo_data *bc; struct skl_specific_cfg *sp_cfg; - if (mconfig->formats_config.caps_size > 0 && - mconfig->formats_config.set_params == SKL_PARAM_SET) { - sp_cfg = &mconfig->formats_config; + if (mconfig->formats_config[SKL_PARAM_SET].caps_size > 0 && + mconfig->formats_config[SKL_PARAM_SET].set_params == SKL_PARAM_SET) { + sp_cfg = &mconfig->formats_config[SKL_PARAM_SET]; ret = skl_set_module_params(skl, sp_cfg->caps, sp_cfg->caps_size, sp_cfg->param_id, mconfig); @@ -438,8 +438,10 @@ static int skl_tplg_set_module_init_data(struct snd_soc_dapm_widget *w) if (bc->set_params != SKL_PARAM_INIT) continue; - mconfig->formats_config.caps = (u32 *)bc->params; - mconfig->formats_config.caps_size = bc->size; + mconfig->formats_config[SKL_PARAM_INIT].caps = + (u32 *)bc->params; + mconfig->formats_config[SKL_PARAM_INIT].caps_size = + bc->size; break; } @@ -498,8 +500,6 @@ skl_tplg_init_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) mconfig->id.module_id, mconfig->guid); if (ret < 0) return ret; - - mconfig->m_state = SKL_MODULE_LOADED; } /* prepare the DMA if the module is gateway cpr */ @@ -558,8 +558,7 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, mconfig = w_module->w->priv; uuid_mod = (guid_t *)mconfig->guid; - if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod && - mconfig->m_state > SKL_MODULE_UNINIT) { + if (mconfig->module->loadable && skl->dsp->fw_ops.unload_mod) { ret = skl->dsp->fw_ops.unload_mod(skl->dsp, mconfig->id.module_id); if (ret < 0) @@ -641,8 +640,9 @@ skl_tplg_get_pipe_config(struct skl_dev *skl, struct skl_module_cfg *mconfig) return 0; } - if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE) { - dev_dbg(skl->dev, "No conn_type detected, take 0th config\n"); + if (pipe->conn_type == SKL_PIPE_CONN_TYPE_NONE || pipe->nr_cfgs == 1) { + dev_dbg(skl->dev, "No conn_type or just 1 pathcfg, taking 0th for %d\n", + pipe->ppl_id); pipe->cur_config_idx = 0; pipe->memory_pages = pconfig->mem_pages; @@ -801,9 +801,10 @@ static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w, return 0; } - if (mconfig->formats_config.caps_size > 0 && - mconfig->formats_config.set_params == SKL_PARAM_BIND) { - sp_cfg = &mconfig->formats_config; + if (mconfig->formats_config[SKL_PARAM_BIND].caps_size > 0 && + mconfig->formats_config[SKL_PARAM_BIND].set_params == + SKL_PARAM_BIND) { + sp_cfg = &mconfig->formats_config[SKL_PARAM_BIND]; ret = skl_set_module_params(skl, sp_cfg->caps, sp_cfg->caps_size, sp_cfg->param_id, mconfig); @@ -1463,12 +1464,6 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol, struct skl_dev *skl = get_skl_ctx(w->dapm->dev); if (ac->params) { - /* - * Widget data is expected to be stripped of T and L - */ - size -= 2 * sizeof(unsigned int); - data += 2; - if (size > ac->max) return -EINVAL; ac->size = size; @@ -1505,7 +1500,8 @@ static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol, static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig, struct skl_mic_sel_config *mic_cfg, struct device *dev) { - struct skl_specific_cfg *sp_cfg = &mconfig->formats_config; + struct skl_specific_cfg *sp_cfg = + &mconfig->formats_config[SKL_PARAM_INIT]; sp_cfg->caps_size = sizeof(struct skl_mic_sel_config); sp_cfg->set_params = SKL_PARAM_SET; @@ -1637,11 +1633,12 @@ int skl_tplg_update_pipe_params(struct device *dev, struct skl_module_cfg *mconfig, struct skl_pipe_params *params) { - struct skl_module_res *res = &mconfig->module->resources[0]; + struct skl_module_res *res; struct skl_dev *skl = get_skl_ctx(dev); struct skl_module_fmt *format = NULL; u8 cfg_idx = mconfig->pipe->cur_config_idx; + res = &mconfig->module->resources[mconfig->res_idx]; skl_tplg_fill_dma_id(mconfig, params); mconfig->fmt_idx = mconfig->mod_cfg[cfg_idx].fmt_idx; mconfig->res_idx = mconfig->mod_cfg[cfg_idx].res_idx; @@ -1650,9 +1647,9 @@ int skl_tplg_update_pipe_params(struct device *dev, return 0; if (params->stream == SNDRV_PCM_STREAM_PLAYBACK) - format = &mconfig->module->formats[0].inputs[0].fmt; + format = &mconfig->module->formats[mconfig->fmt_idx].inputs[0].fmt; else - format = &mconfig->module->formats[0].outputs[0].fmt; + format = &mconfig->module->formats[mconfig->fmt_idx].outputs[0].fmt; /* set the hw_params */ format->s_freq = params->s_freq; @@ -1827,7 +1824,7 @@ static u8 skl_tplg_be_link_type(int dev_type) * Fill the BE gateway parameters * The BE gateway expects a blob of parameters which are kept in the ACPI * NHLT blob, so query the blob for interface type (i2s/pdm) and instance. - * The port can have multiple settings so pick based on the PCM + * The port can have multiple settings so pick based on the pipeline * parameters */ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, @@ -1835,6 +1832,8 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, struct skl_pipe_params *params) { struct nhlt_specific_cfg *cfg; + struct skl_pipe *pipe = mconfig->pipe; + struct skl_pipe_fmt *pipe_fmt; struct skl_dev *skl = get_skl_ctx(dai->dev); int link_type = skl_tplg_be_link_type(mconfig->dev_type); u8 dev_type = skl_tplg_be_dev_type(mconfig->dev_type); @@ -1844,20 +1843,23 @@ static int skl_tplg_be_fill_pipe_params(struct snd_soc_dai *dai, if (link_type == NHLT_LINK_HDA) return 0; + if (pipe->direction == SNDRV_PCM_STREAM_PLAYBACK) + pipe_fmt = &pipe->configs[pipe->pipe_config_idx].out_fmt; + else + pipe_fmt = &pipe->configs[pipe->pipe_config_idx].in_fmt; + /* update the blob based on virtual bus_id*/ cfg = skl_get_ep_blob(skl, mconfig->vbus_id, link_type, - params->s_fmt, params->ch, - params->s_freq, params->stream, + pipe_fmt->bps, pipe_fmt->channels, + pipe_fmt->freq, pipe->direction, dev_type); if (cfg) { - mconfig->formats_config.caps_size = cfg->size; - mconfig->formats_config.caps = (u32 *) &cfg->caps; + mconfig->formats_config[SKL_PARAM_INIT].caps_size = cfg->size; + mconfig->formats_config[SKL_PARAM_INIT].caps = (u32 *)&cfg->caps; } else { - dev_err(dai->dev, "Blob NULL for id %x type %d dirn %d\n", - mconfig->vbus_id, link_type, - params->stream); - dev_err(dai->dev, "PCM: ch %d, freq %d, fmt %d\n", - params->ch, params->s_freq, params->s_fmt); + dev_err(dai->dev, "Blob NULL for id:%d type:%d dirn:%d ch:%d, freq:%d, fmt:%d\n", + mconfig->vbus_id, link_type, params->stream, + params->ch, params->s_freq, params->s_fmt); return -EINVAL; } @@ -2570,19 +2572,26 @@ static int skl_tplg_get_token(struct device *dev, break; + case SKL_TKN_U32_FMT_CFG_IDX: + if (tkn_elem->value > SKL_MAX_PARAMS_TYPES) + return -EINVAL; + + mconfig->fmt_cfg_idx = tkn_elem->value; + break; + case SKL_TKN_U32_CAPS_SIZE: - mconfig->formats_config.caps_size = + mconfig->formats_config[mconfig->fmt_cfg_idx].caps_size = tkn_elem->value; break; case SKL_TKN_U32_CAPS_SET_PARAMS: - mconfig->formats_config.set_params = + mconfig->formats_config[mconfig->fmt_cfg_idx].set_params = tkn_elem->value; break; case SKL_TKN_U32_CAPS_PARAMS_ID: - mconfig->formats_config.param_id = + mconfig->formats_config[mconfig->fmt_cfg_idx].param_id = tkn_elem->value; break; @@ -2796,6 +2805,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, struct skl_dfw_v4_module *dfw = (struct skl_dfw_v4_module *)tplg_w->priv.data; int ret; + int idx = mconfig->fmt_cfg_idx; dev_dbg(dev, "Parsing Skylake v4 widget topology data\n"); @@ -2829,7 +2839,7 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, mconfig->dev_type = dfw->dev_type; mconfig->hw_conn_type = dfw->hw_conn_type; mconfig->time_slot = dfw->time_slot; - mconfig->formats_config.caps_size = dfw->caps.caps_size; + mconfig->formats_config[idx].caps_size = dfw->caps.caps_size; mconfig->m_in_pin = devm_kcalloc(dev, MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin), @@ -2850,21 +2860,39 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, dfw->is_dynamic_out_pin, mconfig->module->max_output_pins); - if (mconfig->formats_config.caps_size) { - mconfig->formats_config.set_params = dfw->caps.set_params; - mconfig->formats_config.param_id = dfw->caps.param_id; - mconfig->formats_config.caps = - devm_kzalloc(dev, mconfig->formats_config.caps_size, + if (mconfig->formats_config[idx].caps_size) { + mconfig->formats_config[idx].set_params = dfw->caps.set_params; + mconfig->formats_config[idx].param_id = dfw->caps.param_id; + mconfig->formats_config[idx].caps = + devm_kzalloc(dev, mconfig->formats_config[idx].caps_size, GFP_KERNEL); - if (!mconfig->formats_config.caps) + if (!mconfig->formats_config[idx].caps) return -ENOMEM; - memcpy(mconfig->formats_config.caps, dfw->caps.caps, + memcpy(mconfig->formats_config[idx].caps, dfw->caps.caps, dfw->caps.caps_size); } return 0; } +static int skl_tplg_get_caps_data(struct device *dev, char *data, + struct skl_module_cfg *mconfig) +{ + int idx = mconfig->fmt_cfg_idx; + + if (mconfig->formats_config[idx].caps_size > 0) { + mconfig->formats_config[idx].caps = + devm_kzalloc(dev, mconfig->formats_config[idx].caps_size, + GFP_KERNEL); + if (!mconfig->formats_config[idx].caps) + return -ENOMEM; + memcpy(mconfig->formats_config[idx].caps, data, + mconfig->formats_config[idx].caps_size); + } + + return mconfig->formats_config[idx].caps_size; +} + /* * Parse the private data for the token and corresponding value. * The private data can have multiple data blocks. So, a data block @@ -2925,18 +2953,14 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, if (block_type == SKL_TYPE_TUPLE) { ret = skl_tplg_get_tokens(dev, data, skl, mconfig, block_size); - - if (ret < 0) - return ret; - - --num_blocks; } else { - if (mconfig->formats_config.caps_size > 0) - memcpy(mconfig->formats_config.caps, data, - mconfig->formats_config.caps_size); - --num_blocks; - ret = mconfig->formats_config.caps_size; + ret = skl_tplg_get_caps_data(dev, data, mconfig); } + + if (ret < 0) + return ret; + + --num_blocks; off += ret; } @@ -3027,6 +3051,9 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, int index, */ mconfig->id.module_id = -1; + /* To provide backward compatibility, set default as SKL_PARAM_INIT */ + mconfig->fmt_cfg_idx = SKL_PARAM_INIT; + /* Parse private data for tuples */ ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); if (ret < 0) diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index fb011862fb24..f0695b2ac5dd 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -81,6 +81,8 @@ enum skl_s_freq { SKL_FS_INVALID }; +#define SKL_MAX_PARAMS_TYPES 4 + enum skl_widget_type { SKL_WIDGET_VMIXER = 1, SKL_WIDGET_MIXER = 2, @@ -150,6 +152,21 @@ struct skl_up_down_mixer_cfg { u32 ch_map; } __packed; +struct skl_pin_format { + u32 pin_idx; + u32 buf_size; + struct skl_audio_data_format audio_fmt; +} __packed; + +struct skl_base_cfg_ext { + u16 nr_input_pins; + u16 nr_output_pins; + u8 reserved[8]; + u32 priv_param_length; + /* Input pin formats followed by output ones. */ + struct skl_pin_format pins_fmt[0]; +} __packed; + struct skl_algo_cfg { struct skl_base_cfg base_cfg; char params[]; @@ -311,10 +328,8 @@ struct skl_pipe { enum skl_module_state { SKL_MODULE_UNINIT = 0, - SKL_MODULE_LOADED = 1, - SKL_MODULE_INIT_DONE = 2, - SKL_MODULE_BIND_DONE = 3, - SKL_MODULE_UNLOADED = 4, + SKL_MODULE_INIT_DONE = 1, + SKL_MODULE_BIND_DONE = 2, }; enum d0i3_capability { @@ -373,6 +388,7 @@ struct skl_module_cfg { struct skl_module *module; int res_idx; int fmt_idx; + int fmt_cfg_idx; u8 domain; bool homogenous_inputs; bool homogenous_outputs; @@ -403,7 +419,7 @@ struct skl_module_cfg { enum skl_hw_conn_type hw_conn_type; enum skl_module_state m_state; struct skl_pipe *pipe; - struct skl_specific_cfg formats_config; + struct skl_specific_cfg formats_config[SKL_MAX_PARAMS_TYPES]; struct skl_pipe_mcfg mod_cfg[SKL_MAX_MODULES_IN_PIPE]; }; diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 74dae4332d17..cf567a89f421 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -184,3 +184,27 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682 with the MT6359 RT1015 RT5682 audio codec. Select Y if you have such device. If unsure select "N". + +config SND_SOC_MT8195 + tristate "ASoC support for Mediatek MT8195 chip" + select SND_SOC_MEDIATEK + help + This adds ASoC platform driver support for Mediatek MT8195 chip + that can be used with other codecs. + Select Y if you have such device. + If unsure select "N". + +config SND_SOC_MT8195_MT6359_RT1019_RT5682 + tristate "ASoC Audio driver for MT8195 with MT6359 RT1019 RT5682 codec" + depends on I2C + depends on SND_SOC_MT8195 + select SND_SOC_MT6359 + select SND_SOC_RT1015P + select SND_SOC_RT5682_I2C + select SND_SOC_DMIC + select SND_SOC_HDMI_CODEC + help + This adds ASoC driver for Mediatek MT8195 boards + with the MT6359 RT1019 RT5682 audio codec. + Select Y if you have such device. + If unsure select "N". diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile index f6cb6b8508e3..34778ca12106 100644 --- a/sound/soc/mediatek/Makefile +++ b/sound/soc/mediatek/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/ obj-$(CONFIG_SND_SOC_MT8173) += mt8173/ obj-$(CONFIG_SND_SOC_MT8183) += mt8183/ obj-$(CONFIG_SND_SOC_MT8192) += mt8192/ +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/ diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 3cb2adf420bb..baaa5881b1d4 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -139,7 +139,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, substream->runtime->dma_area, substream->runtime->dma_bytes); - memset_io(substream->runtime->dma_area, 0, + memset_io((void __force __iomem *)substream->runtime->dma_area, 0, substream->runtime->dma_bytes); /* set addr */ @@ -433,11 +433,20 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, phys_buf_addr_upper_32); } - /* set MSB to 33-bit */ - if (memif->data->msb_reg >= 0) + /* + * set MSB to 33-bit, for memif address + * only for memif base address, if msb_end_reg exists + */ + if (memif->data->msb_reg) mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg, 1, msb_at_bit33, memif->data->msb_shift); + /* set MSB to 33-bit, for memif end address */ + if (memif->data->msb_end_reg) + mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg, + 1, msb_at_bit33, + memif->data->msb_end_shift); + return 0; } EXPORT_SYMBOL_GPL(mtk_memif_set_addr); @@ -464,6 +473,13 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe, else mono = (channel == 1) ? 1 : 0; + /* for specific configuration of memif mono mode */ + if (memif->data->int_odd_flag_reg) + mtk_regmap_update_bits(afe->regmap, + memif->data->int_odd_flag_reg, + 1, mono, + memif->data->int_odd_flag_shift); + return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg, 1, mono, memif->data->mono_shift); } diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h index a6f68c68581c..ef83e78c22a8 100644 --- a/sound/soc/mediatek/common/mtk-base-afe.h +++ b/sound/soc/mediatek/common/mtk-base-afe.h @@ -29,6 +29,8 @@ struct mtk_base_memif_data { int quad_ch_reg; int quad_ch_mask; int quad_ch_shift; + int int_odd_flag_reg; + int int_odd_flag_shift; int enable_reg; int enable_shift; int hd_reg; @@ -37,10 +39,13 @@ struct mtk_base_memif_data { int hd_align_mshift; int msb_reg; int msb_shift; - int msb2_reg; - int msb2_shift; + int msb_end_reg; + int msb_end_shift; int agent_disable_reg; int agent_disable_shift; + int ch_num_reg; + int ch_num_shift; + int ch_num_maskbit; /* playback memif only */ int pbuf_reg; int pbuf_mask; @@ -62,6 +67,7 @@ struct mtk_base_irq_data { int irq_en_shift; int irq_clr_reg; int irq_clr_shift; + int irq_status_shift; }; struct device; diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index c4a598cbbdaa..14e77df06b01 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1119,25 +1119,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) afe->regmap = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(afe->regmap)) { dev_err(dev, "could not get regmap from parent\n"); - return PTR_ERR(afe->regmap); + ret = PTR_ERR(afe->regmap); + goto err_pm_disable; } ret = regmap_attach_dev(dev, afe->regmap, &mt8183_afe_regmap_config); if (ret) { dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret); - return ret; + goto err_pm_disable; } rstc = devm_reset_control_get(dev, "audiosys"); if (IS_ERR(rstc)) { ret = PTR_ERR(rstc); dev_err(dev, "could not get audiosys reset:%d\n", ret); - return ret; + goto err_pm_disable; } ret = reset_control_reset(rstc); if (ret) { dev_err(dev, "failed to trigger audio reset:%d\n", ret); - return ret; + goto err_pm_disable; } /* enable clock for regcache get default value from hw */ @@ -1147,7 +1148,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config); if (ret) { dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret); - return ret; + goto err_pm_disable; } pm_runtime_put_sync(&pdev->dev); @@ -1160,8 +1161,10 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) afe->memif_size = MT8183_MEMIF_NUM; afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), GFP_KERNEL); - if (!afe->memif) - return -ENOMEM; + if (!afe->memif) { + ret = -ENOMEM; + goto err_pm_disable; + } for (i = 0; i < afe->memif_size; i++) { afe->memif[i].data = &memif_data[i]; @@ -1178,22 +1181,26 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) afe->irqs_size = MT8183_IRQ_NUM; afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), GFP_KERNEL); - if (!afe->irqs) - return -ENOMEM; + if (!afe->irqs) { + ret = -ENOMEM; + goto err_pm_disable; + } for (i = 0; i < afe->irqs_size; i++) afe->irqs[i].irq_data = &irq_data[i]; /* request irq */ irq_id = platform_get_irq(pdev, 0); - if (irq_id < 0) - return irq_id; + if (irq_id < 0) { + ret = irq_id; + goto err_pm_disable; + } ret = devm_request_irq(dev, irq_id, mt8183_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); if (ret) { dev_err(dev, "could not request_irq for asys-isr\n"); - return ret; + goto err_pm_disable; } /* init sub_dais */ @@ -1204,7 +1211,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_warn(afe->dev, "dai register i %d fail, ret %d\n", i, ret); - return ret; + goto err_pm_disable; } } @@ -1213,7 +1220,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n", ret); - return ret; + goto err_pm_disable; } afe->mtk_afe_hardware = &mt8183_afe_hardware; @@ -1229,7 +1236,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) NULL, 0); if (ret) { dev_warn(dev, "err_platform\n"); - return ret; + goto err_pm_disable; } ret = devm_snd_soc_register_component(afe->dev, @@ -1238,10 +1245,14 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) afe->num_dai_drivers); if (ret) { dev_warn(dev, "err_dai_component\n"); - return ret; + goto err_pm_disable; } return ret; + +err_pm_disable: + pm_runtime_disable(&pdev->dev); + return ret; } static int mt8183_afe_pcm_dev_remove(struct platform_device *pdev) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 7a1724f5ff4c..31c280339c50 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2229,12 +2229,13 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->regmap = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(afe->regmap)) { dev_err(dev, "could not get regmap from parent\n"); - return PTR_ERR(afe->regmap); + ret = PTR_ERR(afe->regmap); + goto err_pm_disable; } ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config); if (ret) { dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret); - return ret; + goto err_pm_disable; } /* enable clock for regcache get default value from hw */ @@ -2244,7 +2245,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config); if (ret) { dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret); - return ret; + goto err_pm_disable; } pm_runtime_put_sync(&pdev->dev); @@ -2257,8 +2258,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->memif_size = MT8192_MEMIF_NUM; afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), GFP_KERNEL); - if (!afe->memif) - return -ENOMEM; + if (!afe->memif) { + ret = -ENOMEM; + goto err_pm_disable; + } for (i = 0; i < afe->memif_size; i++) { afe->memif[i].data = &memif_data[i]; @@ -2272,22 +2275,26 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->irqs_size = MT8192_IRQ_NUM; afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), GFP_KERNEL); - if (!afe->irqs) - return -ENOMEM; + if (!afe->irqs) { + ret = -ENOMEM; + goto err_pm_disable; + } for (i = 0; i < afe->irqs_size; i++) afe->irqs[i].irq_data = &irq_data[i]; /* request irq */ irq_id = platform_get_irq(pdev, 0); - if (irq_id < 0) - return irq_id; + if (irq_id < 0) { + ret = irq_id; + goto err_pm_disable; + } ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); if (ret) { dev_err(dev, "could not request_irq for Afe_ISR_Handle\n"); - return ret; + goto err_pm_disable; } /* init sub_dais */ diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile new file mode 100644 index 000000000000..44775f400b40 --- /dev/null +++ b/sound/soc/mediatek/mt8195/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +# platform driver +snd-soc-mt8195-afe-objs := \ + mt8195-audsys-clk.o \ + mt8195-afe-clk.o \ + mt8195-afe-pcm.o \ + mt8195-dai-adda.o \ + mt8195-dai-etdm.o \ + mt8195-dai-pcm.o + +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o + +# machine driver +obj-$(CONFIG_SND_SOC_MT8195_MT6359_RT1019_RT5682) += mt8195-mt6359-rt1019-rt5682.o diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c new file mode 100644 index 000000000000..8420b2c71332 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mt8195-afe-clk.c -- Mediatek 8195 afe clock ctrl + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/clk.h> + +#include "mt8195-afe-common.h" +#include "mt8195-afe-clk.h" +#include "mt8195-reg.h" +#include "mt8195-audsys-clk.h" + +static const char *aud_clks[MT8195_CLK_NUM] = { + /* xtal */ + [MT8195_CLK_XTAL_26M] = "clk26m", + /* divider */ + [MT8195_CLK_TOP_APLL1] = "apll1_ck", + [MT8195_CLK_TOP_APLL2] = "apll2_ck", + [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0", + [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1", + [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2", + [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3", + [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9", + /* mux */ + [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel", + [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel", + [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel", + [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] = "audio_local_bus_sel", + [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel", + [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel", + [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel", + [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel", + [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel", + /* clock gate */ + [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b", + [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp", + /* afe clock gate */ + [MT8195_CLK_AUD_AFE] = "aud_afe", + [MT8195_CLK_AUD_APLL] = "aud_apll", + [MT8195_CLK_AUD_APLL2] = "aud_apll2", + [MT8195_CLK_AUD_DAC] = "aud_dac", + [MT8195_CLK_AUD_ADC] = "aud_adc", + [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires", + [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp", + [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires", + [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc", + [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires", + [MT8195_CLK_AUD_I2SIN] = "aud_i2sin", + [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in", + [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out", + [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out", + [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out", + [MT8195_CLK_AUD_ASRC11] = "aud_asrc11", + [MT8195_CLK_AUD_ASRC12] = "aud_asrc12", + [MT8195_CLK_AUD_A1SYS] = "aud_a1sys", + [MT8195_CLK_AUD_A2SYS] = "aud_a2sys", + [MT8195_CLK_AUD_PCMIF] = "aud_pcmif", + [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1", + [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2", + [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3", + [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4", + [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5", + [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6", + [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8", + [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9", + [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10", + [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2", + [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3", + [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6", + [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7", + [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8", + [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10", + [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11", +}; + +int mt8195_afe_get_mclk_source_clk_id(int sel) +{ + switch (sel) { + case MT8195_MCK_SEL_26M: + return MT8195_CLK_XTAL_26M; + case MT8195_MCK_SEL_APLL1: + return MT8195_CLK_TOP_APLL1; + case MT8195_MCK_SEL_APLL2: + return MT8195_CLK_TOP_APLL2; + default: + return -EINVAL; + } +} + +int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int clk_id = mt8195_afe_get_mclk_source_clk_id(apll); + + if (clk_id < 0) { + dev_dbg(afe->dev, "invalid clk id\n"); + return 0; + } + + return clk_get_rate(afe_priv->clk[clk_id]); +} + +int mt8195_afe_get_default_mclk_source_by_rate(int rate) +{ + return ((rate % 8000) == 0) ? + MT8195_MCK_SEL_APLL1 : MT8195_MCK_SEL_APLL2; +} + +int mt8195_afe_init_clock(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int i; + + mt8195_audsys_clk_register(afe); + + afe_priv->clk = + devm_kcalloc(afe->dev, MT8195_CLK_NUM, sizeof(*afe_priv->clk), + GFP_KERNEL); + if (!afe_priv->clk) + return -ENOMEM; + + for (i = 0; i < MT8195_CLK_NUM; i++) { + afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]); + if (IS_ERR(afe_priv->clk[i])) { + dev_dbg(afe->dev, "%s(), devm_clk_get %s fail, ret %ld\n", + __func__, aud_clks[i], + PTR_ERR(afe_priv->clk[i])); + return PTR_ERR(afe_priv->clk[i]); + } + } + + return 0; +} + +void mt8195_afe_deinit_clock(struct mtk_base_afe *afe) +{ + mt8195_audsys_clk_unregister(afe); +} + +int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + int ret; + + if (clk) { + ret = clk_prepare_enable(clk); + if (ret) { + dev_dbg(afe->dev, "%s(), failed to enable clk\n", + __func__); + return ret; + } + } else { + dev_dbg(afe->dev, "NULL clk\n"); + } + return 0; +} +EXPORT_SYMBOL_GPL(mt8195_afe_enable_clk); + +void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + if (clk) + clk_disable_unprepare(clk); + else + dev_dbg(afe->dev, "NULL clk\n"); +} +EXPORT_SYMBOL_GPL(mt8195_afe_disable_clk); + +int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + int ret; + + if (clk) { + ret = clk_prepare(clk); + if (ret) { + dev_dbg(afe->dev, "%s(), failed to prepare clk\n", + __func__); + return ret; + } + } else { + dev_dbg(afe->dev, "NULL clk\n"); + } + return 0; +} + +void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + if (clk) + clk_unprepare(clk); + else + dev_dbg(afe->dev, "NULL clk\n"); +} + +int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk) +{ + int ret; + + if (clk) { + ret = clk_enable(clk); + if (ret) { + dev_dbg(afe->dev, "%s(), failed to clk enable\n", + __func__); + return ret; + } + } else { + dev_dbg(afe->dev, "NULL clk\n"); + } + return 0; +} + +void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk) +{ + if (clk) + clk_disable(clk); + else + dev_dbg(afe->dev, "NULL clk\n"); +} + +int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, + unsigned int rate) +{ + int ret; + + if (clk) { + ret = clk_set_rate(clk, rate); + if (ret) { + dev_dbg(afe->dev, "%s(), failed to set clk rate\n", + __func__); + return ret; + } + } + + return 0; +} + +int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, + struct clk *parent) +{ + int ret; + + if (clk && parent) { + ret = clk_set_parent(clk, parent); + if (ret) { + dev_dbg(afe->dev, "%s(), failed to set clk parent\n", + __func__); + return ret; + } + } + + return 0; +} + +static unsigned int get_top_cg_reg(unsigned int cg_type) +{ + switch (cg_type) { + case MT8195_TOP_CG_A1SYS_TIMING: + case MT8195_TOP_CG_A2SYS_TIMING: + case MT8195_TOP_CG_26M_TIMING: + return ASYS_TOP_CON; + default: + return 0; + } +} + +static unsigned int get_top_cg_mask(unsigned int cg_type) +{ + switch (cg_type) { + case MT8195_TOP_CG_A1SYS_TIMING: + return ASYS_TOP_CON_A1SYS_TIMING_ON; + case MT8195_TOP_CG_A2SYS_TIMING: + return ASYS_TOP_CON_A2SYS_TIMING_ON; + case MT8195_TOP_CG_26M_TIMING: + return ASYS_TOP_CON_26M_TIMING_ON; + default: + return 0; + } +} + +static unsigned int get_top_cg_on_val(unsigned int cg_type) +{ + switch (cg_type) { + case MT8195_TOP_CG_A1SYS_TIMING: + case MT8195_TOP_CG_A2SYS_TIMING: + case MT8195_TOP_CG_26M_TIMING: + return get_top_cg_mask(cg_type); + default: + return 0; + } +} + +static unsigned int get_top_cg_off_val(unsigned int cg_type) +{ + switch (cg_type) { + case MT8195_TOP_CG_A1SYS_TIMING: + case MT8195_TOP_CG_A2SYS_TIMING: + case MT8195_TOP_CG_26M_TIMING: + return 0; + default: + return get_top_cg_mask(cg_type); + } +} + +static int mt8195_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_on_val(cg_type); + + regmap_update_bits(afe->regmap, reg, mask, val); + return 0; +} + +static int mt8195_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_off_val(cg_type); + + regmap_update_bits(afe->regmap, reg, mask, val); + return 0; +} + +int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int i; + unsigned int clk_array[] = { + MT8195_CLK_SCP_ADSP_AUDIODSP, /* bus clock for infra */ + MT8195_CLK_TOP_AUDIO_H_SEL, /* clock for ADSP bus */ + MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL, /* bus clock for DRAM access */ + MT8195_CLK_TOP_AUD_INTBUS_SEL, /* bus clock for AFE SRAM access */ + MT8195_CLK_INFRA_AO_AUDIO_26M_B, /* audio 26M clock */ + MT8195_CLK_AUD_AFE, /* AFE HW master switch */ + MT8195_CLK_AUD_A1SYS_HP, /* AFE HW clock*/ + MT8195_CLK_AUD_A1SYS, /* AFE HW clock */ + }; + + for (i = 0; i < ARRAY_SIZE(clk_array); i++) + mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]); + + return 0; +} + +int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int i; + unsigned int clk_array[] = { + MT8195_CLK_AUD_A1SYS, + MT8195_CLK_AUD_A1SYS_HP, + MT8195_CLK_AUD_AFE, + MT8195_CLK_INFRA_AO_AUDIO_26M_B, + MT8195_CLK_TOP_AUD_INTBUS_SEL, + MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL, + MT8195_CLK_TOP_AUDIO_H_SEL, + MT8195_CLK_SCP_ADSP_AUDIODSP, + }; + + for (i = 0; i < ARRAY_SIZE(clk_array); i++) + mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]); + + return 0; +} + +static int mt8195_afe_enable_afe_on(struct mtk_base_afe *afe) +{ + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1); + return 0; +} + +static int mt8195_afe_disable_afe_on(struct mtk_base_afe *afe) +{ + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0); + return 0; +} + +static int mt8195_afe_enable_timing_sys(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int i; + unsigned int clk_array[] = { + MT8195_CLK_AUD_A1SYS, + MT8195_CLK_AUD_A2SYS, + }; + unsigned int cg_array[] = { + MT8195_TOP_CG_A1SYS_TIMING, + MT8195_TOP_CG_A2SYS_TIMING, + MT8195_TOP_CG_26M_TIMING, + }; + + for (i = 0; i < ARRAY_SIZE(clk_array); i++) + mt8195_afe_enable_clk(afe, afe_priv->clk[clk_array[i]]); + + for (i = 0; i < ARRAY_SIZE(cg_array); i++) + mt8195_afe_enable_top_cg(afe, cg_array[i]); + + return 0; +} + +static int mt8195_afe_disable_timing_sys(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int i; + unsigned int clk_array[] = { + MT8195_CLK_AUD_A2SYS, + MT8195_CLK_AUD_A1SYS, + }; + unsigned int cg_array[] = { + MT8195_TOP_CG_26M_TIMING, + MT8195_TOP_CG_A2SYS_TIMING, + MT8195_TOP_CG_A1SYS_TIMING, + }; + + for (i = 0; i < ARRAY_SIZE(cg_array); i++) + mt8195_afe_disable_top_cg(afe, cg_array[i]); + + for (i = 0; i < ARRAY_SIZE(clk_array); i++) + mt8195_afe_disable_clk(afe, afe_priv->clk[clk_array[i]]); + + return 0; +} + +int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe) +{ + mt8195_afe_enable_timing_sys(afe); + + mt8195_afe_enable_afe_on(afe); + + return 0; +} + +int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe) +{ + mt8195_afe_disable_afe_on(afe); + + mt8195_afe_disable_timing_sys(afe); + + return 0; +} diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.h b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h new file mode 100644 index 000000000000..f8e6eeb29a89 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8195-afe-clk.h -- Mediatek 8195 afe clock ctrl definition + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT8195_AFE_CLK_H_ +#define _MT8195_AFE_CLK_H_ + +enum { + /* xtal */ + MT8195_CLK_XTAL_26M, + /* divider */ + MT8195_CLK_TOP_APLL1, + MT8195_CLK_TOP_APLL2, + MT8195_CLK_TOP_APLL12_DIV0, + MT8195_CLK_TOP_APLL12_DIV1, + MT8195_CLK_TOP_APLL12_DIV2, + MT8195_CLK_TOP_APLL12_DIV3, + MT8195_CLK_TOP_APLL12_DIV9, + /* mux */ + MT8195_CLK_TOP_A1SYS_HP_SEL, + MT8195_CLK_TOP_AUD_INTBUS_SEL, + MT8195_CLK_TOP_AUDIO_H_SEL, + MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL, + MT8195_CLK_TOP_DPTX_M_SEL, + MT8195_CLK_TOP_I2SO1_M_SEL, + MT8195_CLK_TOP_I2SO2_M_SEL, + MT8195_CLK_TOP_I2SI1_M_SEL, + MT8195_CLK_TOP_I2SI2_M_SEL, + /* clock gate */ + MT8195_CLK_INFRA_AO_AUDIO_26M_B, + MT8195_CLK_SCP_ADSP_AUDIODSP, + MT8195_CLK_AUD_AFE, + MT8195_CLK_AUD_APLL, + MT8195_CLK_AUD_APLL2, + MT8195_CLK_AUD_DAC, + MT8195_CLK_AUD_ADC, + MT8195_CLK_AUD_DAC_HIRES, + MT8195_CLK_AUD_A1SYS_HP, + MT8195_CLK_AUD_ADC_HIRES, + MT8195_CLK_AUD_ADDA6_ADC, + MT8195_CLK_AUD_ADDA6_ADC_HIRES, + MT8195_CLK_AUD_I2SIN, + MT8195_CLK_AUD_TDM_IN, + MT8195_CLK_AUD_I2S_OUT, + MT8195_CLK_AUD_TDM_OUT, + MT8195_CLK_AUD_HDMI_OUT, + MT8195_CLK_AUD_ASRC11, + MT8195_CLK_AUD_ASRC12, + MT8195_CLK_AUD_A1SYS, + MT8195_CLK_AUD_A2SYS, + MT8195_CLK_AUD_PCMIF, + MT8195_CLK_AUD_MEMIF_UL1, + MT8195_CLK_AUD_MEMIF_UL2, + MT8195_CLK_AUD_MEMIF_UL3, + MT8195_CLK_AUD_MEMIF_UL4, + MT8195_CLK_AUD_MEMIF_UL5, + MT8195_CLK_AUD_MEMIF_UL6, + MT8195_CLK_AUD_MEMIF_UL8, + MT8195_CLK_AUD_MEMIF_UL9, + MT8195_CLK_AUD_MEMIF_UL10, + MT8195_CLK_AUD_MEMIF_DL2, + MT8195_CLK_AUD_MEMIF_DL3, + MT8195_CLK_AUD_MEMIF_DL6, + MT8195_CLK_AUD_MEMIF_DL7, + MT8195_CLK_AUD_MEMIF_DL8, + MT8195_CLK_AUD_MEMIF_DL10, + MT8195_CLK_AUD_MEMIF_DL11, + MT8195_CLK_NUM, +}; + +enum { + MT8195_MCK_SEL_26M, + MT8195_MCK_SEL_APLL1, + MT8195_MCK_SEL_APLL2, + MT8195_MCK_SEL_APLL3, + MT8195_MCK_SEL_APLL4, + MT8195_MCK_SEL_APLL5, + MT8195_MCK_SEL_HDMIRX_APLL, + MT8195_MCK_SEL_NUM, +}; + +struct mtk_base_afe; + +int mt8195_afe_get_mclk_source_clk_id(int sel); +int mt8195_afe_get_mclk_source_rate(struct mtk_base_afe *afe, int apll); +int mt8195_afe_get_default_mclk_source_by_rate(int rate); +int mt8195_afe_init_clock(struct mtk_base_afe *afe); +void mt8195_afe_deinit_clock(struct mtk_base_afe *afe); +int mt8195_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk); +void mt8195_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk); +int mt8195_afe_prepare_clk(struct mtk_base_afe *afe, struct clk *clk); +void mt8195_afe_unprepare_clk(struct mtk_base_afe *afe, struct clk *clk); +int mt8195_afe_enable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk); +void mt8195_afe_disable_clk_atomic(struct mtk_base_afe *afe, struct clk *clk); +int mt8195_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, + unsigned int rate); +int mt8195_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, + struct clk *parent); +int mt8195_afe_enable_main_clock(struct mtk_base_afe *afe); +int mt8195_afe_disable_main_clock(struct mtk_base_afe *afe); +int mt8195_afe_enable_reg_rw_clk(struct mtk_base_afe *afe); +int mt8195_afe_disable_reg_rw_clk(struct mtk_base_afe *afe); + +#endif diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-common.h b/sound/soc/mediatek/mt8195/mt8195-afe-common.h new file mode 100644 index 000000000000..f93f439e2bd9 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-afe-common.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8195-afe-common.h -- Mediatek 8195 audio driver definitions + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT_8195_AFE_COMMON_H_ +#define _MT_8195_AFE_COMMON_H_ + +#include <sound/soc.h> +#include <linux/list.h> +#include <linux/regmap.h> +#include "../common/mtk-base-afe.h" + +enum { + MT8195_DAI_START, + MT8195_AFE_MEMIF_START = MT8195_DAI_START, + MT8195_AFE_MEMIF_DL2 = MT8195_AFE_MEMIF_START, + MT8195_AFE_MEMIF_DL3, + MT8195_AFE_MEMIF_DL6, + MT8195_AFE_MEMIF_DL7, + MT8195_AFE_MEMIF_DL8, + MT8195_AFE_MEMIF_DL10, + MT8195_AFE_MEMIF_DL11, + MT8195_AFE_MEMIF_UL_START, + MT8195_AFE_MEMIF_UL1 = MT8195_AFE_MEMIF_UL_START, + MT8195_AFE_MEMIF_UL2, + MT8195_AFE_MEMIF_UL3, + MT8195_AFE_MEMIF_UL4, + MT8195_AFE_MEMIF_UL5, + MT8195_AFE_MEMIF_UL6, + MT8195_AFE_MEMIF_UL8, + MT8195_AFE_MEMIF_UL9, + MT8195_AFE_MEMIF_UL10, + MT8195_AFE_MEMIF_END, + MT8195_AFE_MEMIF_NUM = (MT8195_AFE_MEMIF_END - MT8195_AFE_MEMIF_START), + MT8195_AFE_IO_START = MT8195_AFE_MEMIF_END, + MT8195_AFE_IO_DL_SRC = MT8195_AFE_IO_START, + MT8195_AFE_IO_DPTX, + MT8195_AFE_IO_ETDM_START, + MT8195_AFE_IO_ETDM1_IN = MT8195_AFE_IO_ETDM_START, + MT8195_AFE_IO_ETDM2_IN, + MT8195_AFE_IO_ETDM1_OUT, + MT8195_AFE_IO_ETDM2_OUT, + MT8195_AFE_IO_ETDM3_OUT, + MT8195_AFE_IO_ETDM_END, + MT8195_AFE_IO_ETDM_NUM = + (MT8195_AFE_IO_ETDM_END - MT8195_AFE_IO_ETDM_START), + MT8195_AFE_IO_PCM = MT8195_AFE_IO_ETDM_END, + MT8195_AFE_IO_UL_SRC1, + MT8195_AFE_IO_UL_SRC2, + MT8195_AFE_IO_END, + MT8195_AFE_IO_NUM = (MT8195_AFE_IO_END - MT8195_AFE_IO_START), + MT8195_DAI_END = MT8195_AFE_IO_END, + MT8195_DAI_NUM = (MT8195_DAI_END - MT8195_DAI_START), +}; + +enum { + MT8195_TOP_CG_A1SYS_TIMING, + MT8195_TOP_CG_A2SYS_TIMING, + MT8195_TOP_CG_26M_TIMING, + MT8195_TOP_CG_NUM, +}; + +enum { + MT8195_AFE_IRQ_1, + MT8195_AFE_IRQ_2, + MT8195_AFE_IRQ_3, + MT8195_AFE_IRQ_8, + MT8195_AFE_IRQ_9, + MT8195_AFE_IRQ_10, + MT8195_AFE_IRQ_13, + MT8195_AFE_IRQ_14, + MT8195_AFE_IRQ_15, + MT8195_AFE_IRQ_16, + MT8195_AFE_IRQ_17, + MT8195_AFE_IRQ_18, + MT8195_AFE_IRQ_19, + MT8195_AFE_IRQ_20, + MT8195_AFE_IRQ_21, + MT8195_AFE_IRQ_22, + MT8195_AFE_IRQ_23, + MT8195_AFE_IRQ_24, + MT8195_AFE_IRQ_25, + MT8195_AFE_IRQ_26, + MT8195_AFE_IRQ_27, + MT8195_AFE_IRQ_28, + MT8195_AFE_IRQ_NUM, +}; + +enum { + MT8195_ETDM_OUT1_1X_EN = 9, + MT8195_ETDM_OUT2_1X_EN = 10, + MT8195_ETDM_OUT3_1X_EN = 11, + MT8195_ETDM_IN1_1X_EN = 12, + MT8195_ETDM_IN2_1X_EN = 13, + MT8195_ETDM_IN1_NX_EN = 25, + MT8195_ETDM_IN2_NX_EN = 26, +}; + +enum { + MT8195_MTKAIF_MISO_0, + MT8195_MTKAIF_MISO_1, + MT8195_MTKAIF_MISO_2, + MT8195_MTKAIF_MISO_NUM, +}; + +struct mtk_dai_memif_irq_priv { + unsigned int asys_timing_sel; +}; + +struct mtkaif_param { + bool mtkaif_calibration_ok; + int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM]; + int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM]; + int mtkaif_dmic_on; + int mtkaif_adda6_only; +}; + +struct clk; + +struct mt8195_afe_private { + struct clk **clk; + struct clk_lookup **lookup; + struct regmap *topckgen; + int pm_runtime_bypass_reg_ctl; +#ifdef CONFIG_DEBUG_FS + struct dentry **debugfs_dentry; +#endif + int afe_on_ref_cnt; + int top_cg_ref_cnt[MT8195_TOP_CG_NUM]; + spinlock_t afe_ctrl_lock; /* Lock for afe control */ + struct mtk_dai_memif_irq_priv irq_priv[MT8195_AFE_IRQ_NUM]; + struct mtkaif_param mtkaif_params; + + /* dai */ + void *dai_priv[MT8195_DAI_NUM]; +}; + +int mt8195_afe_fs_timing(unsigned int rate); +/* dai register */ +int mt8195_dai_adda_register(struct mtk_base_afe *afe); +int mt8195_dai_etdm_register(struct mtk_base_afe *afe); +int mt8195_dai_pcm_register(struct mtk_base_afe *afe); + +#define MT8195_SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put, id) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_info_enum_double, \ + .get = xhandler_get, .put = xhandler_put, \ + .device = id, \ + .private_value = (unsigned long)&xenum, \ +} + +#endif diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c new file mode 100644 index 000000000000..6635c3f72ecc --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -0,0 +1,3281 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek ALSA SoC AFE platform driver for 8195 + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/pm_runtime.h> +#include "mt8195-afe-common.h" +#include "mt8195-afe-clk.h" +#include "mt8195-reg.h" +#include "../common/mtk-afe-platform-driver.h" +#include "../common/mtk-afe-fe-dai.h" + +#define MT8195_MEMIF_BUFFER_BYTES_ALIGN (0x40) +#define MT8195_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff) + +struct mtk_dai_memif_priv { + unsigned int asys_timing_sel; +}; + +static const struct snd_pcm_hardware mt8195_afe_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = 64, + .period_bytes_max = 256 * 1024, + .periods_min = 2, + .periods_max = 256, + .buffer_bytes_max = 256 * 2 * 1024, +}; + +struct mt8195_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +static const struct mt8195_afe_rate mt8195_afe_rates[] = { + { .rate = 8000, .reg_value = 0, }, + { .rate = 12000, .reg_value = 1, }, + { .rate = 16000, .reg_value = 2, }, + { .rate = 24000, .reg_value = 3, }, + { .rate = 32000, .reg_value = 4, }, + { .rate = 48000, .reg_value = 5, }, + { .rate = 96000, .reg_value = 6, }, + { .rate = 192000, .reg_value = 7, }, + { .rate = 384000, .reg_value = 8, }, + { .rate = 7350, .reg_value = 16, }, + { .rate = 11025, .reg_value = 17, }, + { .rate = 14700, .reg_value = 18, }, + { .rate = 22050, .reg_value = 19, }, + { .rate = 29400, .reg_value = 20, }, + { .rate = 44100, .reg_value = 21, }, + { .rate = 88200, .reg_value = 22, }, + { .rate = 176400, .reg_value = 23, }, + { .rate = 352800, .reg_value = 24, }, +}; + +int mt8195_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8195_afe_rates); i++) + if (mt8195_afe_rates[i].rate == rate) + return mt8195_afe_rates[i].reg_value; + + return -EINVAL; +} + +static int mt8195_memif_fs(struct snd_pcm_substream *substream, + unsigned int rate) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + int id = asoc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[id]; + int fs = mt8195_afe_fs_timing(rate); + + switch (memif->data->id) { + case MT8195_AFE_MEMIF_DL10: + fs = MT8195_ETDM_OUT3_1X_EN; + break; + case MT8195_AFE_MEMIF_UL8: + fs = MT8195_ETDM_IN1_NX_EN; + break; + case MT8195_AFE_MEMIF_UL3: + fs = MT8195_ETDM_IN2_NX_EN; + break; + default: + break; + } + + return fs; +} + +static int mt8195_irq_fs(struct snd_pcm_substream *substream, + unsigned int rate) +{ + int fs = mt8195_memif_fs(substream, rate); + + switch (fs) { + case MT8195_ETDM_IN1_NX_EN: + fs = MT8195_ETDM_IN1_1X_EN; + break; + case MT8195_ETDM_IN2_NX_EN: + fs = MT8195_ETDM_IN2_1X_EN; + break; + default: + break; + } + + return fs; +} + +enum { + MT8195_AFE_CM0, + MT8195_AFE_CM1, + MT8195_AFE_CM2, + MT8195_AFE_CM_NUM, +}; + +struct mt8195_afe_channel_merge { + int id; + int reg; + unsigned int sel_shift; + unsigned int sel_maskbit; + unsigned int sel_default; + unsigned int ch_num_shift; + unsigned int ch_num_maskbit; + unsigned int en_shift; + unsigned int en_maskbit; + unsigned int update_cnt_shift; + unsigned int update_cnt_maskbit; + unsigned int update_cnt_default; +}; + +static const struct mt8195_afe_channel_merge + mt8195_afe_cm[MT8195_AFE_CM_NUM] = { + [MT8195_AFE_CM0] = { + .id = MT8195_AFE_CM0, + .reg = AFE_CM0_CON, + .sel_shift = 30, + .sel_maskbit = 0x1, + .sel_default = 1, + .ch_num_shift = 2, + .ch_num_maskbit = 0x3f, + .en_shift = 0, + .en_maskbit = 0x1, + .update_cnt_shift = 16, + .update_cnt_maskbit = 0x1fff, + .update_cnt_default = 0x3, + }, + [MT8195_AFE_CM1] = { + .id = MT8195_AFE_CM1, + .reg = AFE_CM1_CON, + .sel_shift = 30, + .sel_maskbit = 0x1, + .sel_default = 1, + .ch_num_shift = 2, + .ch_num_maskbit = 0x1f, + .en_shift = 0, + .en_maskbit = 0x1, + .update_cnt_shift = 16, + .update_cnt_maskbit = 0x1fff, + .update_cnt_default = 0x3, + }, + [MT8195_AFE_CM2] = { + .id = MT8195_AFE_CM2, + .reg = AFE_CM2_CON, + .sel_shift = 30, + .sel_maskbit = 0x1, + .sel_default = 1, + .ch_num_shift = 2, + .ch_num_maskbit = 0x1f, + .en_shift = 0, + .en_maskbit = 0x1, + .update_cnt_shift = 16, + .update_cnt_maskbit = 0x1fff, + .update_cnt_default = 0x3, + }, +}; + +static int mt8195_afe_memif_is_ul(int id) +{ + if (id >= MT8195_AFE_MEMIF_UL_START && id < MT8195_AFE_MEMIF_END) + return 1; + else + return 0; +} + +static const struct mt8195_afe_channel_merge* +mt8195_afe_found_cm(struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int id = -EINVAL; + + if (mt8195_afe_memif_is_ul(dai->id) == 0) + return NULL; + + switch (dai->id) { + case MT8195_AFE_MEMIF_UL9: + id = MT8195_AFE_CM0; + break; + case MT8195_AFE_MEMIF_UL2: + id = MT8195_AFE_CM1; + break; + case MT8195_AFE_MEMIF_UL10: + id = MT8195_AFE_CM2; + break; + default: + break; + } + + if (id < 0) { + dev_dbg(afe->dev, "%s, memif %d cannot find CM!\n", + __func__, dai->id); + return NULL; + } + + return &mt8195_afe_cm[id]; +} + +static int mt8195_afe_config_cm(struct mtk_base_afe *afe, + const struct mt8195_afe_channel_merge *cm, + unsigned int channels) +{ + if (!cm) + return -EINVAL; + + regmap_update_bits(afe->regmap, + cm->reg, + cm->sel_maskbit << cm->sel_shift, + cm->sel_default << cm->sel_shift); + + regmap_update_bits(afe->regmap, + cm->reg, + cm->ch_num_maskbit << cm->ch_num_shift, + (channels - 1) << cm->ch_num_shift); + + regmap_update_bits(afe->regmap, + cm->reg, + cm->update_cnt_maskbit << cm->update_cnt_shift, + cm->update_cnt_default << cm->update_cnt_shift); + + return 0; +} + +static int mt8195_afe_enable_cm(struct mtk_base_afe *afe, + const struct mt8195_afe_channel_merge *cm, + bool enable) +{ + if (!cm) + return -EINVAL; + + regmap_update_bits(afe->regmap, + cm->reg, + cm->en_maskbit << cm->en_shift, + enable << cm->en_shift); + + return 0; +} + +static int +mt8195_afe_paired_memif_clk_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, + int enable) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int id = asoc_rtd_to_cpu(rtd, 0)->id; + int clk_id; + + if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10) + return 0; + + if (enable) { + clk_id = MT8195_CLK_AUD_MEMIF_DL10; + mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]); + clk_id = MT8195_CLK_AUD_MEMIF_DL8; + mt8195_afe_prepare_clk(afe, afe_priv->clk[clk_id]); + } else { + clk_id = MT8195_CLK_AUD_MEMIF_DL8; + mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]); + clk_id = MT8195_CLK_AUD_MEMIF_DL10; + mt8195_afe_unprepare_clk(afe, afe_priv->clk[clk_id]); + } + + return 0; +} + +static int +mt8195_afe_paired_memif_clk_enable(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai, + int enable) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int id = asoc_rtd_to_cpu(rtd, 0)->id; + int clk_id; + + if (id != MT8195_AFE_MEMIF_DL8 && id != MT8195_AFE_MEMIF_DL10) + return 0; + + if (enable) { + /* DL8_DL10_MEM */ + clk_id = MT8195_CLK_AUD_MEMIF_DL10; + mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]); + udelay(1); + /* DL8_DL10_AGENT */ + clk_id = MT8195_CLK_AUD_MEMIF_DL8; + mt8195_afe_enable_clk_atomic(afe, afe_priv->clk[clk_id]); + } else { + /* DL8_DL10_AGENT */ + clk_id = MT8195_CLK_AUD_MEMIF_DL8; + mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]); + /* DL8_DL10_MEM */ + clk_id = MT8195_CLK_AUD_MEMIF_DL10; + mt8195_afe_disable_clk_atomic(afe, afe_priv->clk[clk_id]); + } + + return 0; +} + +static int mt8195_afe_fe_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int id = asoc_rtd_to_cpu(rtd, 0)->id; + int ret = 0; + + mt8195_afe_paired_memif_clk_prepare(substream, dai, 1); + + ret = mtk_afe_fe_startup(substream, dai); + + snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, + MT8195_MEMIF_BUFFER_BYTES_ALIGN); + + if (id != MT8195_AFE_MEMIF_DL7) + goto out; + + ret = snd_pcm_hw_constraint_minmax(runtime, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 1, + MT8195_MEMIF_DL7_MAX_PERIOD_SIZE); + if (ret < 0) + dev_dbg(afe->dev, "hw_constraint_minmax failed\n"); +out: + return ret; +} + +static void mt8195_afe_fe_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + mtk_afe_fe_shutdown(substream, dai); + mt8195_afe_paired_memif_clk_prepare(substream, dai, 0); +} + +static int mt8195_afe_fe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int id = asoc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[id]; + const struct mtk_base_memif_data *data = memif->data; + const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai); + unsigned int ch_num = params_channels(params); + + mt8195_afe_config_cm(afe, cm, params_channels(params)); + + if (data->ch_num_reg >= 0) { + regmap_update_bits(afe->regmap, data->ch_num_reg, + data->ch_num_maskbit << data->ch_num_shift, + ch_num << data->ch_num_shift); + } + + return mtk_afe_fe_hw_params(substream, params, dai); +} + +static int mt8195_afe_fe_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return mtk_afe_fe_hw_free(substream, dai); +} + +static int mt8195_afe_fe_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + return mtk_afe_fe_prepare(substream, dai); +} + +static int mt8195_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int ret = 0; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + const struct mt8195_afe_channel_merge *cm = mt8195_afe_found_cm(dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + mt8195_afe_enable_cm(afe, cm, true); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + mt8195_afe_enable_cm(afe, cm, false); + break; + default: + break; + } + + ret = mtk_afe_fe_trigger(substream, cmd, dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + mt8195_afe_paired_memif_clk_enable(substream, dai, 1); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + mt8195_afe_paired_memif_clk_enable(substream, dai, 0); + break; + default: + break; + } + + return ret; +} + +static int mt8195_afe_fe_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + return 0; +} + +static const struct snd_soc_dai_ops mt8195_afe_fe_dai_ops = { + .startup = mt8195_afe_fe_startup, + .shutdown = mt8195_afe_fe_shutdown, + .hw_params = mt8195_afe_fe_hw_params, + .hw_free = mt8195_afe_fe_hw_free, + .prepare = mt8195_afe_fe_prepare, + .trigger = mt8195_afe_fe_trigger, + .set_fmt = mt8195_afe_fe_set_fmt, +}; + +#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000 |\ + SNDRV_PCM_RATE_352800 |\ + SNDRV_PCM_RATE_384000) + +#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mt8195_memif_dai_driver[] = { + /* FE DAIs: memory intefaces to CPU */ + { + .name = "DL2", + .id = MT8195_AFE_MEMIF_DL2, + .playback = { + .stream_name = "DL2", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL3", + .id = MT8195_AFE_MEMIF_DL3, + .playback = { + .stream_name = "DL3", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL6", + .id = MT8195_AFE_MEMIF_DL6, + .playback = { + .stream_name = "DL6", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL7", + .id = MT8195_AFE_MEMIF_DL7, + .playback = { + .stream_name = "DL7", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL8", + .id = MT8195_AFE_MEMIF_DL8, + .playback = { + .stream_name = "DL8", + .channels_min = 1, + .channels_max = 24, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL10", + .id = MT8195_AFE_MEMIF_DL10, + .playback = { + .stream_name = "DL10", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "DL11", + .id = MT8195_AFE_MEMIF_DL11, + .playback = { + .stream_name = "DL11", + .channels_min = 1, + .channels_max = 48, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL1", + .id = MT8195_AFE_MEMIF_UL1, + .capture = { + .stream_name = "UL1", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL2", + .id = MT8195_AFE_MEMIF_UL2, + .capture = { + .stream_name = "UL2", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL3", + .id = MT8195_AFE_MEMIF_UL3, + .capture = { + .stream_name = "UL3", + .channels_min = 1, + .channels_max = 16, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL4", + .id = MT8195_AFE_MEMIF_UL4, + .capture = { + .stream_name = "UL4", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL5", + .id = MT8195_AFE_MEMIF_UL5, + .capture = { + .stream_name = "UL5", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL6", + .id = MT8195_AFE_MEMIF_UL6, + .capture = { + .stream_name = "UL6", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL8", + .id = MT8195_AFE_MEMIF_UL8, + .capture = { + .stream_name = "UL8", + .channels_min = 1, + .channels_max = 24, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL9", + .id = MT8195_AFE_MEMIF_UL9, + .capture = { + .stream_name = "UL9", + .channels_min = 1, + .channels_max = 32, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, + { + .name = "UL10", + .id = MT8195_AFE_MEMIF_UL10, + .capture = { + .stream_name = "UL10", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mt8195_afe_fe_dai_ops, + }, +}; + +static const struct snd_kcontrol_new o002_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN2, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN2, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN2, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN2, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN2_2, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN2_2, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN2_5, 8, 1, 0), +}; + +static const struct snd_kcontrol_new o003_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN3, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN3, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN3, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN3, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN3_2, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN3_2, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN3_5, 9, 1, 0), +}; + +static const struct snd_kcontrol_new o004_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN4, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN4, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN4, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN4_2, 10, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN4_5, 10, 1, 0), +}; + +static const struct snd_kcontrol_new o005_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN5, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN5, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN5, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN5_2, 11, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN5_5, 11, 1, 0), +}; + +static const struct snd_kcontrol_new o006_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN6, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN6, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN6, 26, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN6_2, 12, 1, 0), +}; + +static const struct snd_kcontrol_new o007_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN7, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN7, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN7, 27, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN7_2, 13, 1, 0), +}; + +static const struct snd_kcontrol_new o008_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN8, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN8, 28, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN8_2, 14, 1, 0), +}; + +static const struct snd_kcontrol_new o009_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN9, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN9, 29, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN9_2, 15, 1, 0), +}; + +static const struct snd_kcontrol_new o010_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN10, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN10, 30, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN10_1, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN10_2, 8, 1, 0), +}; + +static const struct snd_kcontrol_new o011_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN11, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN11, 31, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN11_1, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN11_2, 9, 1, 0), +}; + +static const struct snd_kcontrol_new o012_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN12, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN12_1, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN12_1, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I074 Switch", AFE_CONN12_2, 10, 1, 0), +}; + +static const struct snd_kcontrol_new o013_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN13, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN13_1, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN13_1, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I075 Switch", AFE_CONN13_2, 11, 1, 0), +}; + +static const struct snd_kcontrol_new o014_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN14, 26, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN14_1, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN14_1, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I076 Switch", AFE_CONN14_2, 12, 1, 0), +}; + +static const struct snd_kcontrol_new o015_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN15, 27, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN15_1, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN15_1, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I077 Switch", AFE_CONN15_2, 13, 1, 0), +}; + +static const struct snd_kcontrol_new o016_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN16, 28, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN16_1, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN16_1, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I078 Switch", AFE_CONN16_2, 14, 1, 0), +}; + +static const struct snd_kcontrol_new o017_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN17, 29, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN17_1, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN17_1, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I079 Switch", AFE_CONN17_2, 15, 1, 0), +}; + +static const struct snd_kcontrol_new o018_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN18_1, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I080 Switch", AFE_CONN18_2, 16, 1, 0), +}; + +static const struct snd_kcontrol_new o019_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN19_1, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I081 Switch", AFE_CONN19_2, 17, 1, 0), +}; + +static const struct snd_kcontrol_new o020_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN20_1, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I082 Switch", AFE_CONN20_2, 18, 1, 0), +}; + +static const struct snd_kcontrol_new o021_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN21_1, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I083 Switch", AFE_CONN21_2, 19, 1, 0), +}; + +static const struct snd_kcontrol_new o022_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN22_1, 10, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I084 Switch", AFE_CONN22_2, 20, 1, 0), +}; + +static const struct snd_kcontrol_new o023_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN23_1, 11, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I085 Switch", AFE_CONN23_2, 21, 1, 0), +}; + +static const struct snd_kcontrol_new o024_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN24_1, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I086 Switch", AFE_CONN24_2, 22, 1, 0), +}; + +static const struct snd_kcontrol_new o025_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN25_1, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I087 Switch", AFE_CONN25_2, 23, 1, 0), +}; + +static const struct snd_kcontrol_new o026_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN26_1, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I088 Switch", AFE_CONN26_2, 24, 1, 0), +}; + +static const struct snd_kcontrol_new o027_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN27_1, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I089 Switch", AFE_CONN27_2, 25, 1, 0), +}; + +static const struct snd_kcontrol_new o028_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN28_1, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I090 Switch", AFE_CONN28_2, 26, 1, 0), +}; + +static const struct snd_kcontrol_new o029_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN29_1, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I091 Switch", AFE_CONN29_2, 27, 1, 0), +}; + +static const struct snd_kcontrol_new o030_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN30_1, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I092 Switch", AFE_CONN30_2, 28, 1, 0), +}; + +static const struct snd_kcontrol_new o031_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN31_1, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I093 Switch", AFE_CONN31_2, 29, 1, 0), +}; + +static const struct snd_kcontrol_new o032_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN32_1, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I094 Switch", AFE_CONN32_2, 30, 1, 0), +}; + +static const struct snd_kcontrol_new o033_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN33_1, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I095 Switch", AFE_CONN33_2, 31, 1, 0), +}; + +static const struct snd_kcontrol_new o034_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN34, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN34, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN34, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN34, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN34_2, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I072 Switch", AFE_CONN34_2, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN34_5, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN34_5, 10, 1, 0), +}; + +static const struct snd_kcontrol_new o035_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN35, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN35, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN35, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN35, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN35_2, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I073 Switch", AFE_CONN35_2, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I137 Switch", AFE_CONN35_4, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I139 Switch", AFE_CONN35_4, 11, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN35_5, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN35_5, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN35_5, 10, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN35_5, 11, 1, 0), +}; + +static const struct snd_kcontrol_new o036_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN36, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN36, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN36, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN36_2, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN36_5, 8, 1, 0), +}; + +static const struct snd_kcontrol_new o037_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN37, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN37, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN37, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN37_2, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN37_5, 9, 1, 0), +}; + +static const struct snd_kcontrol_new o038_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN38, 22, 1, 0), +}; + +static const struct snd_kcontrol_new o039_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN39, 23, 1, 0), +}; + +static const struct snd_kcontrol_new o040_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN40, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I012 Switch", AFE_CONN40, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN40, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I168 Switch", AFE_CONN40_5, 8, 1, 0), +}; + +static const struct snd_kcontrol_new o041_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN41, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I013 Switch", AFE_CONN41, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN41, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I169 Switch", AFE_CONN41_5, 9, 1, 0), +}; + +static const struct snd_kcontrol_new o042_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I014 Switch", AFE_CONN42, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN42, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I170 Switch", AFE_CONN42_5, 10, 1, 0), +}; + +static const struct snd_kcontrol_new o043_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I015 Switch", AFE_CONN43, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN43, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I171 Switch", AFE_CONN43_5, 11, 1, 0), +}; + +static const struct snd_kcontrol_new o044_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I016 Switch", AFE_CONN44, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN44, 26, 1, 0), +}; + +static const struct snd_kcontrol_new o045_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I017 Switch", AFE_CONN45, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN45, 27, 1, 0), +}; + +static const struct snd_kcontrol_new o046_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I018 Switch", AFE_CONN46, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN46, 28, 1, 0), +}; + +static const struct snd_kcontrol_new o047_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I019 Switch", AFE_CONN47, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN47, 29, 1, 0), +}; + +static const struct snd_kcontrol_new o182_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN182, 24, 1, 0), +}; + +static const struct snd_kcontrol_new o183_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN183, 25, 1, 0), +}; + +static const char * const dl8_dl11_data_sel_mux_text[] = { + "dl8", "dl11", +}; + +static SOC_ENUM_SINGLE_DECL(dl8_dl11_data_sel_mux_enum, + AFE_DAC_CON2, 0, dl8_dl11_data_sel_mux_text); + +static const struct snd_kcontrol_new dl8_dl11_data_sel_mux = + SOC_DAPM_ENUM("DL8_DL11 Sink", dl8_dl11_data_sel_mux_enum); + +static const struct snd_soc_dapm_widget mt8195_memif_widgets[] = { + /* DL6 */ + SND_SOC_DAPM_MIXER("I000", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I001", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DL3 */ + SND_SOC_DAPM_MIXER("I020", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I021", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DL11 */ + SND_SOC_DAPM_MIXER("I022", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I023", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I024", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I025", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I026", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I027", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I028", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I029", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I030", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I031", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I034", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I035", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I036", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I037", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I038", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I039", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I040", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I041", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I042", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I043", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I044", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I045", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DL11/DL8 */ + SND_SOC_DAPM_MIXER("I046", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I047", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I048", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I049", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I050", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I051", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I052", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I053", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I054", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I055", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I056", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I057", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I058", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I059", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I060", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I061", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I062", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I063", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I064", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I065", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I066", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I067", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I068", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I069", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* DL2 */ + SND_SOC_DAPM_MIXER("I070", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I071", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("DL8_DL11 Mux", + SND_SOC_NOPM, 0, 0, &dl8_dl11_data_sel_mux), + + /* UL9 */ + SND_SOC_DAPM_MIXER("O002", SND_SOC_NOPM, 0, 0, + o002_mix, ARRAY_SIZE(o002_mix)), + SND_SOC_DAPM_MIXER("O003", SND_SOC_NOPM, 0, 0, + o003_mix, ARRAY_SIZE(o003_mix)), + SND_SOC_DAPM_MIXER("O004", SND_SOC_NOPM, 0, 0, + o004_mix, ARRAY_SIZE(o004_mix)), + SND_SOC_DAPM_MIXER("O005", SND_SOC_NOPM, 0, 0, + o005_mix, ARRAY_SIZE(o005_mix)), + SND_SOC_DAPM_MIXER("O006", SND_SOC_NOPM, 0, 0, + o006_mix, ARRAY_SIZE(o006_mix)), + SND_SOC_DAPM_MIXER("O007", SND_SOC_NOPM, 0, 0, + o007_mix, ARRAY_SIZE(o007_mix)), + SND_SOC_DAPM_MIXER("O008", SND_SOC_NOPM, 0, 0, + o008_mix, ARRAY_SIZE(o008_mix)), + SND_SOC_DAPM_MIXER("O009", SND_SOC_NOPM, 0, 0, + o009_mix, ARRAY_SIZE(o009_mix)), + SND_SOC_DAPM_MIXER("O010", SND_SOC_NOPM, 0, 0, + o010_mix, ARRAY_SIZE(o010_mix)), + SND_SOC_DAPM_MIXER("O011", SND_SOC_NOPM, 0, 0, + o011_mix, ARRAY_SIZE(o011_mix)), + SND_SOC_DAPM_MIXER("O012", SND_SOC_NOPM, 0, 0, + o012_mix, ARRAY_SIZE(o012_mix)), + SND_SOC_DAPM_MIXER("O013", SND_SOC_NOPM, 0, 0, + o013_mix, ARRAY_SIZE(o013_mix)), + SND_SOC_DAPM_MIXER("O014", SND_SOC_NOPM, 0, 0, + o014_mix, ARRAY_SIZE(o014_mix)), + SND_SOC_DAPM_MIXER("O015", SND_SOC_NOPM, 0, 0, + o015_mix, ARRAY_SIZE(o015_mix)), + SND_SOC_DAPM_MIXER("O016", SND_SOC_NOPM, 0, 0, + o016_mix, ARRAY_SIZE(o016_mix)), + SND_SOC_DAPM_MIXER("O017", SND_SOC_NOPM, 0, 0, + o017_mix, ARRAY_SIZE(o017_mix)), + SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0, + o018_mix, ARRAY_SIZE(o018_mix)), + SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0, + o019_mix, ARRAY_SIZE(o019_mix)), + SND_SOC_DAPM_MIXER("O020", SND_SOC_NOPM, 0, 0, + o020_mix, ARRAY_SIZE(o020_mix)), + SND_SOC_DAPM_MIXER("O021", SND_SOC_NOPM, 0, 0, + o021_mix, ARRAY_SIZE(o021_mix)), + SND_SOC_DAPM_MIXER("O022", SND_SOC_NOPM, 0, 0, + o022_mix, ARRAY_SIZE(o022_mix)), + SND_SOC_DAPM_MIXER("O023", SND_SOC_NOPM, 0, 0, + o023_mix, ARRAY_SIZE(o023_mix)), + SND_SOC_DAPM_MIXER("O024", SND_SOC_NOPM, 0, 0, + o024_mix, ARRAY_SIZE(o024_mix)), + SND_SOC_DAPM_MIXER("O025", SND_SOC_NOPM, 0, 0, + o025_mix, ARRAY_SIZE(o025_mix)), + SND_SOC_DAPM_MIXER("O026", SND_SOC_NOPM, 0, 0, + o026_mix, ARRAY_SIZE(o026_mix)), + SND_SOC_DAPM_MIXER("O027", SND_SOC_NOPM, 0, 0, + o027_mix, ARRAY_SIZE(o027_mix)), + SND_SOC_DAPM_MIXER("O028", SND_SOC_NOPM, 0, 0, + o028_mix, ARRAY_SIZE(o028_mix)), + SND_SOC_DAPM_MIXER("O029", SND_SOC_NOPM, 0, 0, + o029_mix, ARRAY_SIZE(o029_mix)), + SND_SOC_DAPM_MIXER("O030", SND_SOC_NOPM, 0, 0, + o030_mix, ARRAY_SIZE(o030_mix)), + SND_SOC_DAPM_MIXER("O031", SND_SOC_NOPM, 0, 0, + o031_mix, ARRAY_SIZE(o031_mix)), + SND_SOC_DAPM_MIXER("O032", SND_SOC_NOPM, 0, 0, + o032_mix, ARRAY_SIZE(o032_mix)), + SND_SOC_DAPM_MIXER("O033", SND_SOC_NOPM, 0, 0, + o033_mix, ARRAY_SIZE(o033_mix)), + + /* UL4 */ + SND_SOC_DAPM_MIXER("O034", SND_SOC_NOPM, 0, 0, + o034_mix, ARRAY_SIZE(o034_mix)), + SND_SOC_DAPM_MIXER("O035", SND_SOC_NOPM, 0, 0, + o035_mix, ARRAY_SIZE(o035_mix)), + + /* UL5 */ + SND_SOC_DAPM_MIXER("O036", SND_SOC_NOPM, 0, 0, + o036_mix, ARRAY_SIZE(o036_mix)), + SND_SOC_DAPM_MIXER("O037", SND_SOC_NOPM, 0, 0, + o037_mix, ARRAY_SIZE(o037_mix)), + + /* UL10 */ + SND_SOC_DAPM_MIXER("O038", SND_SOC_NOPM, 0, 0, + o038_mix, ARRAY_SIZE(o038_mix)), + SND_SOC_DAPM_MIXER("O039", SND_SOC_NOPM, 0, 0, + o039_mix, ARRAY_SIZE(o039_mix)), + SND_SOC_DAPM_MIXER("O182", SND_SOC_NOPM, 0, 0, + o182_mix, ARRAY_SIZE(o182_mix)), + SND_SOC_DAPM_MIXER("O183", SND_SOC_NOPM, 0, 0, + o183_mix, ARRAY_SIZE(o183_mix)), + + /* UL2 */ + SND_SOC_DAPM_MIXER("O040", SND_SOC_NOPM, 0, 0, + o040_mix, ARRAY_SIZE(o040_mix)), + SND_SOC_DAPM_MIXER("O041", SND_SOC_NOPM, 0, 0, + o041_mix, ARRAY_SIZE(o041_mix)), + SND_SOC_DAPM_MIXER("O042", SND_SOC_NOPM, 0, 0, + o042_mix, ARRAY_SIZE(o042_mix)), + SND_SOC_DAPM_MIXER("O043", SND_SOC_NOPM, 0, 0, + o043_mix, ARRAY_SIZE(o043_mix)), + SND_SOC_DAPM_MIXER("O044", SND_SOC_NOPM, 0, 0, + o044_mix, ARRAY_SIZE(o044_mix)), + SND_SOC_DAPM_MIXER("O045", SND_SOC_NOPM, 0, 0, + o045_mix, ARRAY_SIZE(o045_mix)), + SND_SOC_DAPM_MIXER("O046", SND_SOC_NOPM, 0, 0, + o046_mix, ARRAY_SIZE(o046_mix)), + SND_SOC_DAPM_MIXER("O047", SND_SOC_NOPM, 0, 0, + o047_mix, ARRAY_SIZE(o047_mix)), +}; + +static const struct snd_soc_dapm_route mt8195_memif_routes[] = { + {"I000", NULL, "DL6"}, + {"I001", NULL, "DL6"}, + + {"I020", NULL, "DL3"}, + {"I021", NULL, "DL3"}, + + {"I022", NULL, "DL11"}, + {"I023", NULL, "DL11"}, + {"I024", NULL, "DL11"}, + {"I025", NULL, "DL11"}, + {"I026", NULL, "DL11"}, + {"I027", NULL, "DL11"}, + {"I028", NULL, "DL11"}, + {"I029", NULL, "DL11"}, + {"I030", NULL, "DL11"}, + {"I031", NULL, "DL11"}, + {"I032", NULL, "DL11"}, + {"I033", NULL, "DL11"}, + {"I034", NULL, "DL11"}, + {"I035", NULL, "DL11"}, + {"I036", NULL, "DL11"}, + {"I037", NULL, "DL11"}, + {"I038", NULL, "DL11"}, + {"I039", NULL, "DL11"}, + {"I040", NULL, "DL11"}, + {"I041", NULL, "DL11"}, + {"I042", NULL, "DL11"}, + {"I043", NULL, "DL11"}, + {"I044", NULL, "DL11"}, + {"I045", NULL, "DL11"}, + + {"DL8_DL11 Mux", "dl8", "DL8"}, + {"DL8_DL11 Mux", "dl11", "DL11"}, + + {"I046", NULL, "DL8_DL11 Mux"}, + {"I047", NULL, "DL8_DL11 Mux"}, + {"I048", NULL, "DL8_DL11 Mux"}, + {"I049", NULL, "DL8_DL11 Mux"}, + {"I050", NULL, "DL8_DL11 Mux"}, + {"I051", NULL, "DL8_DL11 Mux"}, + {"I052", NULL, "DL8_DL11 Mux"}, + {"I053", NULL, "DL8_DL11 Mux"}, + {"I054", NULL, "DL8_DL11 Mux"}, + {"I055", NULL, "DL8_DL11 Mux"}, + {"I056", NULL, "DL8_DL11 Mux"}, + {"I057", NULL, "DL8_DL11 Mux"}, + {"I058", NULL, "DL8_DL11 Mux"}, + {"I059", NULL, "DL8_DL11 Mux"}, + {"I060", NULL, "DL8_DL11 Mux"}, + {"I061", NULL, "DL8_DL11 Mux"}, + {"I062", NULL, "DL8_DL11 Mux"}, + {"I063", NULL, "DL8_DL11 Mux"}, + {"I064", NULL, "DL8_DL11 Mux"}, + {"I065", NULL, "DL8_DL11 Mux"}, + {"I066", NULL, "DL8_DL11 Mux"}, + {"I067", NULL, "DL8_DL11 Mux"}, + {"I068", NULL, "DL8_DL11 Mux"}, + {"I069", NULL, "DL8_DL11 Mux"}, + + {"I070", NULL, "DL2"}, + {"I071", NULL, "DL2"}, + + {"UL9", NULL, "O002"}, + {"UL9", NULL, "O003"}, + {"UL9", NULL, "O004"}, + {"UL9", NULL, "O005"}, + {"UL9", NULL, "O006"}, + {"UL9", NULL, "O007"}, + {"UL9", NULL, "O008"}, + {"UL9", NULL, "O009"}, + {"UL9", NULL, "O010"}, + {"UL9", NULL, "O011"}, + {"UL9", NULL, "O012"}, + {"UL9", NULL, "O013"}, + {"UL9", NULL, "O014"}, + {"UL9", NULL, "O015"}, + {"UL9", NULL, "O016"}, + {"UL9", NULL, "O017"}, + {"UL9", NULL, "O018"}, + {"UL9", NULL, "O019"}, + {"UL9", NULL, "O020"}, + {"UL9", NULL, "O021"}, + {"UL9", NULL, "O022"}, + {"UL9", NULL, "O023"}, + {"UL9", NULL, "O024"}, + {"UL9", NULL, "O025"}, + {"UL9", NULL, "O026"}, + {"UL9", NULL, "O027"}, + {"UL9", NULL, "O028"}, + {"UL9", NULL, "O029"}, + {"UL9", NULL, "O030"}, + {"UL9", NULL, "O031"}, + {"UL9", NULL, "O032"}, + {"UL9", NULL, "O033"}, + + {"UL4", NULL, "O034"}, + {"UL4", NULL, "O035"}, + + {"UL5", NULL, "O036"}, + {"UL5", NULL, "O037"}, + + {"UL10", NULL, "O038"}, + {"UL10", NULL, "O039"}, + {"UL10", NULL, "O182"}, + {"UL10", NULL, "O183"}, + + {"UL2", NULL, "O040"}, + {"UL2", NULL, "O041"}, + {"UL2", NULL, "O042"}, + {"UL2", NULL, "O043"}, + {"UL2", NULL, "O044"}, + {"UL2", NULL, "O045"}, + {"UL2", NULL, "O046"}, + {"UL2", NULL, "O047"}, + + {"O004", "I000 Switch", "I000"}, + {"O005", "I001 Switch", "I001"}, + + {"O006", "I000 Switch", "I000"}, + {"O007", "I001 Switch", "I001"}, + + {"O010", "I022 Switch", "I022"}, + {"O011", "I023 Switch", "I023"}, + {"O012", "I024 Switch", "I024"}, + {"O013", "I025 Switch", "I025"}, + {"O014", "I026 Switch", "I026"}, + {"O015", "I027 Switch", "I027"}, + {"O016", "I028 Switch", "I028"}, + {"O017", "I029 Switch", "I029"}, + + {"O010", "I046 Switch", "I046"}, + {"O011", "I047 Switch", "I047"}, + {"O012", "I048 Switch", "I048"}, + {"O013", "I049 Switch", "I049"}, + {"O014", "I050 Switch", "I050"}, + {"O015", "I051 Switch", "I051"}, + {"O016", "I052 Switch", "I052"}, + {"O017", "I053 Switch", "I053"}, + {"O002", "I022 Switch", "I022"}, + {"O003", "I023 Switch", "I023"}, + {"O004", "I024 Switch", "I024"}, + {"O005", "I025 Switch", "I025"}, + {"O006", "I026 Switch", "I026"}, + {"O007", "I027 Switch", "I027"}, + {"O008", "I028 Switch", "I028"}, + {"O009", "I029 Switch", "I029"}, + {"O010", "I030 Switch", "I030"}, + {"O011", "I031 Switch", "I031"}, + {"O012", "I032 Switch", "I032"}, + {"O013", "I033 Switch", "I033"}, + {"O014", "I034 Switch", "I034"}, + {"O015", "I035 Switch", "I035"}, + {"O016", "I036 Switch", "I036"}, + {"O017", "I037 Switch", "I037"}, + {"O018", "I038 Switch", "I038"}, + {"O019", "I039 Switch", "I039"}, + {"O020", "I040 Switch", "I040"}, + {"O021", "I041 Switch", "I041"}, + {"O022", "I042 Switch", "I042"}, + {"O023", "I043 Switch", "I043"}, + {"O024", "I044 Switch", "I044"}, + {"O025", "I045 Switch", "I045"}, + {"O026", "I046 Switch", "I046"}, + {"O027", "I047 Switch", "I047"}, + {"O028", "I048 Switch", "I048"}, + {"O029", "I049 Switch", "I049"}, + {"O030", "I050 Switch", "I050"}, + {"O031", "I051 Switch", "I051"}, + {"O032", "I052 Switch", "I052"}, + {"O033", "I053 Switch", "I053"}, + + {"O002", "I000 Switch", "I000"}, + {"O003", "I001 Switch", "I001"}, + {"O002", "I020 Switch", "I020"}, + {"O003", "I021 Switch", "I021"}, + {"O002", "I070 Switch", "I070"}, + {"O003", "I071 Switch", "I071"}, + + {"O034", "I000 Switch", "I000"}, + {"O035", "I001 Switch", "I001"}, + {"O034", "I002 Switch", "I002"}, + {"O035", "I003 Switch", "I003"}, + {"O034", "I012 Switch", "I012"}, + {"O035", "I013 Switch", "I013"}, + {"O034", "I020 Switch", "I020"}, + {"O035", "I021 Switch", "I021"}, + {"O034", "I070 Switch", "I070"}, + {"O035", "I071 Switch", "I071"}, + {"O034", "I072 Switch", "I072"}, + {"O035", "I073 Switch", "I073"}, + + {"O036", "I000 Switch", "I000"}, + {"O037", "I001 Switch", "I001"}, + {"O036", "I012 Switch", "I012"}, + {"O037", "I013 Switch", "I013"}, + {"O036", "I020 Switch", "I020"}, + {"O037", "I021 Switch", "I021"}, + {"O036", "I070 Switch", "I070"}, + {"O037", "I071 Switch", "I071"}, + {"O036", "I168 Switch", "I168"}, + {"O037", "I169 Switch", "I169"}, + + {"O038", "I022 Switch", "I022"}, + {"O039", "I023 Switch", "I023"}, + {"O182", "I024 Switch", "I024"}, + {"O183", "I025 Switch", "I025"}, + + {"O040", "I022 Switch", "I022"}, + {"O041", "I023 Switch", "I023"}, + {"O042", "I024 Switch", "I024"}, + {"O043", "I025 Switch", "I025"}, + {"O044", "I026 Switch", "I026"}, + {"O045", "I027 Switch", "I027"}, + {"O046", "I028 Switch", "I028"}, + {"O047", "I029 Switch", "I029"}, + + {"O040", "I002 Switch", "I002"}, + {"O041", "I003 Switch", "I003"}, + {"O002", "I012 Switch", "I012"}, + {"O003", "I013 Switch", "I013"}, + {"O004", "I014 Switch", "I014"}, + {"O005", "I015 Switch", "I015"}, + {"O006", "I016 Switch", "I016"}, + {"O007", "I017 Switch", "I017"}, + {"O008", "I018 Switch", "I018"}, + {"O009", "I019 Switch", "I019"}, + + {"O040", "I012 Switch", "I012"}, + {"O041", "I013 Switch", "I013"}, + {"O042", "I014 Switch", "I014"}, + {"O043", "I015 Switch", "I015"}, + {"O044", "I016 Switch", "I016"}, + {"O045", "I017 Switch", "I017"}, + {"O046", "I018 Switch", "I018"}, + {"O047", "I019 Switch", "I019"}, + + {"O002", "I072 Switch", "I072"}, + {"O003", "I073 Switch", "I073"}, + {"O004", "I074 Switch", "I074"}, + {"O005", "I075 Switch", "I075"}, + {"O006", "I076 Switch", "I076"}, + {"O007", "I077 Switch", "I077"}, + {"O008", "I078 Switch", "I078"}, + {"O009", "I079 Switch", "I079"}, + + {"O010", "I072 Switch", "I072"}, + {"O011", "I073 Switch", "I073"}, + {"O012", "I074 Switch", "I074"}, + {"O013", "I075 Switch", "I075"}, + {"O014", "I076 Switch", "I076"}, + {"O015", "I077 Switch", "I077"}, + {"O016", "I078 Switch", "I078"}, + {"O017", "I079 Switch", "I079"}, + {"O018", "I080 Switch", "I080"}, + {"O019", "I081 Switch", "I081"}, + {"O020", "I082 Switch", "I082"}, + {"O021", "I083 Switch", "I083"}, + {"O022", "I084 Switch", "I084"}, + {"O023", "I085 Switch", "I085"}, + {"O024", "I086 Switch", "I086"}, + {"O025", "I087 Switch", "I087"}, + {"O026", "I088 Switch", "I088"}, + {"O027", "I089 Switch", "I089"}, + {"O028", "I090 Switch", "I090"}, + {"O029", "I091 Switch", "I091"}, + {"O030", "I092 Switch", "I092"}, + {"O031", "I093 Switch", "I093"}, + {"O032", "I094 Switch", "I094"}, + {"O033", "I095 Switch", "I095"}, + + {"O002", "I168 Switch", "I168"}, + {"O003", "I169 Switch", "I169"}, + {"O004", "I170 Switch", "I170"}, + {"O005", "I171 Switch", "I171"}, + + {"O034", "I168 Switch", "I168"}, + {"O035", "I168 Switch", "I168"}, + {"O035", "I169 Switch", "I169"}, + + {"O034", "I170 Switch", "I170"}, + {"O035", "I170 Switch", "I170"}, + {"O035", "I171 Switch", "I171"}, + + {"O040", "I168 Switch", "I168"}, + {"O041", "I169 Switch", "I169"}, + {"O042", "I170 Switch", "I170"}, + {"O043", "I171 Switch", "I171"}, +}; + +static const char * const mt8195_afe_1x_en_sel_text[] = { + "a1sys_a2sys", "a3sys", "a4sys", +}; + +static const unsigned int mt8195_afe_1x_en_sel_values[] = { + 0, 1, 2, +}; + +static int mt8195_memif_1x_en_sel_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_memif_priv *memif_priv; + unsigned int dai_id = kcontrol->id.device; + long val = ucontrol->value.integer.value[0]; + int ret = 0; + + memif_priv = afe_priv->dai_priv[dai_id]; + + if (val == memif_priv->asys_timing_sel) + return 0; + + ret = snd_soc_put_enum_double(kcontrol, ucontrol); + + memif_priv->asys_timing_sel = val; + + return ret; +} + +static int mt8195_asys_irq_1x_en_sel_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + unsigned int id = kcontrol->id.device; + long val = ucontrol->value.integer.value[0]; + int ret = 0; + + if (val == afe_priv->irq_priv[id].asys_timing_sel) + return 0; + + ret = snd_soc_put_enum_double(kcontrol, ucontrol); + + afe_priv->irq_priv[id].asys_timing_sel = val; + + return ret; +} + +static SOC_VALUE_ENUM_SINGLE_DECL(dl2_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 18, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl3_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 20, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl6_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 22, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl7_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 24, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl8_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 26, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl10_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 28, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(dl11_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 30, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul1_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 0, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul2_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 2, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul3_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 4, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul4_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 6, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul5_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 8, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul6_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 10, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul8_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 12, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul9_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 14, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(ul10_1x_en_sel_enum, + A3_A4_TIMING_SEL1, 16, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); + +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq1_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 0, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq2_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 2, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq3_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 4, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq4_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 6, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq5_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 8, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq6_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 10, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq7_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 12, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq8_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 14, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq9_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 16, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq10_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 18, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq11_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 20, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq12_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 22, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq13_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 24, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq14_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 26, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq15_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 28, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); +static SOC_VALUE_ENUM_SINGLE_DECL(asys_irq16_1x_en_sel_enum, + A3_A4_TIMING_SEL6, 30, 0x3, + mt8195_afe_1x_en_sel_text, + mt8195_afe_1x_en_sel_values); + +static const struct snd_kcontrol_new mt8195_memif_controls[] = { + MT8195_SOC_ENUM_EXT("dl2_1x_en_sel", + dl2_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL2), + MT8195_SOC_ENUM_EXT("dl3_1x_en_sel", + dl3_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL3), + MT8195_SOC_ENUM_EXT("dl6_1x_en_sel", + dl6_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL6), + MT8195_SOC_ENUM_EXT("dl7_1x_en_sel", + dl7_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL7), + MT8195_SOC_ENUM_EXT("dl8_1x_en_sel", + dl8_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL8), + MT8195_SOC_ENUM_EXT("dl10_1x_en_sel", + dl10_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL10), + MT8195_SOC_ENUM_EXT("dl11_1x_en_sel", + dl11_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_DL11), + MT8195_SOC_ENUM_EXT("ul1_1x_en_sel", + ul1_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL1), + MT8195_SOC_ENUM_EXT("ul2_1x_en_sel", + ul2_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL2), + MT8195_SOC_ENUM_EXT("ul3_1x_en_sel", + ul3_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL3), + MT8195_SOC_ENUM_EXT("ul4_1x_en_sel", + ul4_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL4), + MT8195_SOC_ENUM_EXT("ul5_1x_en_sel", + ul5_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL5), + MT8195_SOC_ENUM_EXT("ul6_1x_en_sel", + ul6_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL6), + MT8195_SOC_ENUM_EXT("ul8_1x_en_sel", + ul8_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL8), + MT8195_SOC_ENUM_EXT("ul9_1x_en_sel", + ul9_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL9), + MT8195_SOC_ENUM_EXT("ul10_1x_en_sel", + ul10_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_memif_1x_en_sel_put, + MT8195_AFE_MEMIF_UL10), + MT8195_SOC_ENUM_EXT("asys_irq1_1x_en_sel", + asys_irq1_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_13), + MT8195_SOC_ENUM_EXT("asys_irq2_1x_en_sel", + asys_irq2_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_14), + MT8195_SOC_ENUM_EXT("asys_irq3_1x_en_sel", + asys_irq3_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_15), + MT8195_SOC_ENUM_EXT("asys_irq4_1x_en_sel", + asys_irq4_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_16), + MT8195_SOC_ENUM_EXT("asys_irq5_1x_en_sel", + asys_irq5_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_17), + MT8195_SOC_ENUM_EXT("asys_irq6_1x_en_sel", + asys_irq6_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_18), + MT8195_SOC_ENUM_EXT("asys_irq7_1x_en_sel", + asys_irq7_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_19), + MT8195_SOC_ENUM_EXT("asys_irq8_1x_en_sel", + asys_irq8_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_20), + MT8195_SOC_ENUM_EXT("asys_irq9_1x_en_sel", + asys_irq9_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_21), + MT8195_SOC_ENUM_EXT("asys_irq10_1x_en_sel", + asys_irq10_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_22), + MT8195_SOC_ENUM_EXT("asys_irq11_1x_en_sel", + asys_irq11_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_23), + MT8195_SOC_ENUM_EXT("asys_irq12_1x_en_sel", + asys_irq12_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_24), + MT8195_SOC_ENUM_EXT("asys_irq13_1x_en_sel", + asys_irq13_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_25), + MT8195_SOC_ENUM_EXT("asys_irq14_1x_en_sel", + asys_irq14_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_26), + MT8195_SOC_ENUM_EXT("asys_irq15_1x_en_sel", + asys_irq15_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_27), + MT8195_SOC_ENUM_EXT("asys_irq16_1x_en_sel", + asys_irq16_1x_en_sel_enum, + snd_soc_get_enum_double, + mt8195_asys_irq_1x_en_sel_put, + MT8195_AFE_IRQ_28), +}; + +static const struct snd_soc_component_driver mt8195_afe_pcm_dai_component = { + .name = "mt8195-afe-pcm-dai", +}; + +static const struct mtk_base_memif_data memif_data[MT8195_AFE_MEMIF_NUM] = { + [MT8195_AFE_MEMIF_DL2] = { + .name = "DL2", + .id = MT8195_AFE_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .reg_ofs_end = AFE_DL2_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 18, + .hd_reg = AFE_DL2_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 18, + .ch_num_reg = AFE_DL2_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 18, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 18, + }, + [MT8195_AFE_MEMIF_DL3] = { + .name = "DL3", + .id = MT8195_AFE_MEMIF_DL3, + .reg_ofs_base = AFE_DL3_BASE, + .reg_ofs_cur = AFE_DL3_CUR, + .reg_ofs_end = AFE_DL3_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 19, + .hd_reg = AFE_DL3_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 19, + .ch_num_reg = AFE_DL3_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 19, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 19, + }, + [MT8195_AFE_MEMIF_DL6] = { + .name = "DL6", + .id = MT8195_AFE_MEMIF_DL6, + .reg_ofs_base = AFE_DL6_BASE, + .reg_ofs_cur = AFE_DL6_CUR, + .reg_ofs_end = AFE_DL6_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON1, + .fs_shift = 0, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 22, + .hd_reg = AFE_DL6_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 22, + .ch_num_reg = AFE_DL6_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 22, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 22, + }, + [MT8195_AFE_MEMIF_DL7] = { + .name = "DL7", + .id = MT8195_AFE_MEMIF_DL7, + .reg_ofs_base = AFE_DL7_BASE, + .reg_ofs_cur = AFE_DL7_CUR, + .reg_ofs_end = AFE_DL7_END, + .fs_reg = -1, + .fs_shift = 0, + .fs_maskbit = 0, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 23, + .hd_reg = AFE_DL7_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 23, + .ch_num_reg = AFE_DL7_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 23, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 23, + }, + [MT8195_AFE_MEMIF_DL8] = { + .name = "DL8", + .id = MT8195_AFE_MEMIF_DL8, + .reg_ofs_base = AFE_DL8_BASE, + .reg_ofs_cur = AFE_DL8_CUR, + .reg_ofs_end = AFE_DL8_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON1, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 24, + .hd_reg = AFE_DL8_CON0, + .hd_shift = 6, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = AFE_DL8_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x3f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 24, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 24, + }, + [MT8195_AFE_MEMIF_DL10] = { + .name = "DL10", + .id = MT8195_AFE_MEMIF_DL10, + .reg_ofs_base = AFE_DL10_BASE, + .reg_ofs_cur = AFE_DL10_CUR, + .reg_ofs_end = AFE_DL10_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON1, + .fs_shift = 20, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 26, + .hd_reg = AFE_DL10_CON0, + .hd_shift = 5, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = AFE_DL10_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 26, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 26, + }, + [MT8195_AFE_MEMIF_DL11] = { + .name = "DL11", + .id = MT8195_AFE_MEMIF_DL11, + .reg_ofs_base = AFE_DL11_BASE, + .reg_ofs_cur = AFE_DL11_CUR, + .reg_ofs_end = AFE_DL11_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON1, + .fs_shift = 25, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 27, + .hd_reg = AFE_DL11_CON0, + .hd_shift = 7, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 27, + .ch_num_reg = AFE_DL11_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x7f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 27, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 27, + }, + [MT8195_AFE_MEMIF_UL1] = { + .name = "UL1", + .id = MT8195_AFE_MEMIF_UL1, + .reg_ofs_base = AFE_UL1_BASE, + .reg_ofs_cur = AFE_UL1_CUR, + .reg_ofs_end = AFE_UL1_END, + .fs_reg = -1, + .fs_shift = 0, + .fs_maskbit = 0, + .mono_reg = AFE_UL1_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL1_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 1, + .hd_reg = AFE_UL1_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 0, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 0, + }, + [MT8195_AFE_MEMIF_UL2] = { + .name = "UL2", + .id = MT8195_AFE_MEMIF_UL2, + .reg_ofs_base = AFE_UL2_BASE, + .reg_ofs_cur = AFE_UL2_CUR, + .reg_ofs_end = AFE_UL2_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 5, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL2_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL2_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 2, + .hd_reg = AFE_UL2_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 1, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 1, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 1, + }, + [MT8195_AFE_MEMIF_UL3] = { + .name = "UL3", + .id = MT8195_AFE_MEMIF_UL3, + .reg_ofs_base = AFE_UL3_BASE, + .reg_ofs_cur = AFE_UL3_CUR, + .reg_ofs_end = AFE_UL3_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL3_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL3_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 3, + .hd_reg = AFE_UL3_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 2, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 2, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 2, + }, + [MT8195_AFE_MEMIF_UL4] = { + .name = "UL4", + .id = MT8195_AFE_MEMIF_UL4, + .reg_ofs_base = AFE_UL4_BASE, + .reg_ofs_cur = AFE_UL4_CUR, + .reg_ofs_end = AFE_UL4_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL4_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL4_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 4, + .hd_reg = AFE_UL4_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 3, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 3, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 3, + }, + [MT8195_AFE_MEMIF_UL5] = { + .name = "UL5", + .id = MT8195_AFE_MEMIF_UL5, + .reg_ofs_base = AFE_UL5_BASE, + .reg_ofs_cur = AFE_UL5_CUR, + .reg_ofs_end = AFE_UL5_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 20, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL5_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL5_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 5, + .hd_reg = AFE_UL5_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 4, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 4, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 4, + }, + [MT8195_AFE_MEMIF_UL6] = { + .name = "UL6", + .id = MT8195_AFE_MEMIF_UL6, + .reg_ofs_base = AFE_UL6_BASE, + .reg_ofs_cur = AFE_UL6_CUR, + .reg_ofs_end = AFE_UL6_END, + .fs_reg = -1, + .fs_shift = 0, + .fs_maskbit = 0, + .mono_reg = AFE_UL6_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL6_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 6, + .hd_reg = AFE_UL6_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 5, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 5, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 5, + }, + [MT8195_AFE_MEMIF_UL8] = { + .name = "UL8", + .id = MT8195_AFE_MEMIF_UL8, + .reg_ofs_base = AFE_UL8_BASE, + .reg_ofs_cur = AFE_UL8_CUR, + .reg_ofs_end = AFE_UL8_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON3, + .fs_shift = 5, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL8_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL8_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 8, + .hd_reg = AFE_UL8_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 7, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 7, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 7, + }, + [MT8195_AFE_MEMIF_UL9] = { + .name = "UL9", + .id = MT8195_AFE_MEMIF_UL9, + .reg_ofs_base = AFE_UL9_BASE, + .reg_ofs_cur = AFE_UL9_CUR, + .reg_ofs_end = AFE_UL9_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON3, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL9_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL9_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 9, + .hd_reg = AFE_UL9_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 8, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 8, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 8, + }, + [MT8195_AFE_MEMIF_UL10] = { + .name = "UL10", + .id = MT8195_AFE_MEMIF_UL10, + .reg_ofs_base = AFE_UL10_BASE, + .reg_ofs_cur = AFE_UL10_CUR, + .reg_ofs_end = AFE_UL10_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON3, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL10_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL10_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 10, + .hd_reg = AFE_UL10_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 9, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 9, + .msb_end_reg = AFE_NORMAL_END_ADR_MSB, + .msb_end_shift = 9, + }, +}; + +static const struct mtk_base_irq_data irq_data[MT8195_AFE_IRQ_NUM] = { + [MT8195_AFE_IRQ_1] = { + .id = MT8195_AFE_IRQ_1, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ1_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 0, + .irq_status_shift = 16, + }, + [MT8195_AFE_IRQ_2] = { + .id = MT8195_AFE_IRQ_2, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ2_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 1, + .irq_status_shift = 17, + }, + [MT8195_AFE_IRQ_3] = { + .id = MT8195_AFE_IRQ_3, + .irq_cnt_reg = AFE_IRQ3_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ3_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 2, + .irq_status_shift = 18, + }, + [MT8195_AFE_IRQ_8] = { + .id = MT8195_AFE_IRQ_8, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ8_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 7, + .irq_status_shift = 23, + }, + [MT8195_AFE_IRQ_9] = { + .id = MT8195_AFE_IRQ_9, + .irq_cnt_reg = AFE_IRQ9_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ9_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 8, + .irq_status_shift = 24, + }, + [MT8195_AFE_IRQ_10] = { + .id = MT8195_AFE_IRQ_10, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0, + .irq_en_reg = AFE_IRQ10_CON, + .irq_en_shift = 31, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 9, + .irq_status_shift = 25, + }, + [MT8195_AFE_IRQ_13] = { + .id = MT8195_AFE_IRQ_13, + .irq_cnt_reg = ASYS_IRQ1_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ1_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ1_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 0, + .irq_status_shift = 0, + }, + [MT8195_AFE_IRQ_14] = { + .id = MT8195_AFE_IRQ_14, + .irq_cnt_reg = ASYS_IRQ2_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ2_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ2_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 1, + .irq_status_shift = 1, + }, + [MT8195_AFE_IRQ_15] = { + .id = MT8195_AFE_IRQ_15, + .irq_cnt_reg = ASYS_IRQ3_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ3_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ3_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 2, + .irq_status_shift = 2, + }, + [MT8195_AFE_IRQ_16] = { + .id = MT8195_AFE_IRQ_16, + .irq_cnt_reg = ASYS_IRQ4_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ4_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ4_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 3, + .irq_status_shift = 3, + }, + [MT8195_AFE_IRQ_17] = { + .id = MT8195_AFE_IRQ_17, + .irq_cnt_reg = ASYS_IRQ5_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ5_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ5_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 4, + .irq_status_shift = 4, + }, + [MT8195_AFE_IRQ_18] = { + .id = MT8195_AFE_IRQ_18, + .irq_cnt_reg = ASYS_IRQ6_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ6_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ6_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 5, + .irq_status_shift = 5, + }, + [MT8195_AFE_IRQ_19] = { + .id = MT8195_AFE_IRQ_19, + .irq_cnt_reg = ASYS_IRQ7_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ7_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ7_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 6, + .irq_status_shift = 6, + }, + [MT8195_AFE_IRQ_20] = { + .id = MT8195_AFE_IRQ_20, + .irq_cnt_reg = ASYS_IRQ8_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ8_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ8_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 7, + .irq_status_shift = 7, + }, + [MT8195_AFE_IRQ_21] = { + .id = MT8195_AFE_IRQ_21, + .irq_cnt_reg = ASYS_IRQ9_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ9_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ9_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 8, + .irq_status_shift = 8, + }, + [MT8195_AFE_IRQ_22] = { + .id = MT8195_AFE_IRQ_22, + .irq_cnt_reg = ASYS_IRQ10_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ10_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ10_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 9, + .irq_status_shift = 9, + }, + [MT8195_AFE_IRQ_23] = { + .id = MT8195_AFE_IRQ_23, + .irq_cnt_reg = ASYS_IRQ11_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ11_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ11_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 10, + .irq_status_shift = 10, + }, + [MT8195_AFE_IRQ_24] = { + .id = MT8195_AFE_IRQ_24, + .irq_cnt_reg = ASYS_IRQ12_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ12_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ12_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 11, + .irq_status_shift = 11, + }, + [MT8195_AFE_IRQ_25] = { + .id = MT8195_AFE_IRQ_25, + .irq_cnt_reg = ASYS_IRQ13_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ13_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ13_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 12, + .irq_status_shift = 12, + }, + [MT8195_AFE_IRQ_26] = { + .id = MT8195_AFE_IRQ_26, + .irq_cnt_reg = ASYS_IRQ14_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ14_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ14_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 13, + .irq_status_shift = 13, + }, + [MT8195_AFE_IRQ_27] = { + .id = MT8195_AFE_IRQ_27, + .irq_cnt_reg = ASYS_IRQ15_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ15_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ15_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 14, + .irq_status_shift = 14, + }, + [MT8195_AFE_IRQ_28] = { + .id = MT8195_AFE_IRQ_28, + .irq_cnt_reg = ASYS_IRQ16_CON, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0xffffff, + .irq_fs_reg = ASYS_IRQ16_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0x1ffff, + .irq_en_reg = ASYS_IRQ16_CON, + .irq_en_shift = 31, + .irq_clr_reg = ASYS_IRQ_CLR, + .irq_clr_shift = 15, + .irq_status_shift = 15, + }, +}; + +static const int mt8195_afe_memif_const_irqs[MT8195_AFE_MEMIF_NUM] = { + [MT8195_AFE_MEMIF_DL2] = MT8195_AFE_IRQ_13, + [MT8195_AFE_MEMIF_DL3] = MT8195_AFE_IRQ_14, + [MT8195_AFE_MEMIF_DL6] = MT8195_AFE_IRQ_15, + [MT8195_AFE_MEMIF_DL7] = MT8195_AFE_IRQ_1, + [MT8195_AFE_MEMIF_DL8] = MT8195_AFE_IRQ_16, + [MT8195_AFE_MEMIF_DL10] = MT8195_AFE_IRQ_17, + [MT8195_AFE_MEMIF_DL11] = MT8195_AFE_IRQ_18, + [MT8195_AFE_MEMIF_UL1] = MT8195_AFE_IRQ_3, + [MT8195_AFE_MEMIF_UL2] = MT8195_AFE_IRQ_19, + [MT8195_AFE_MEMIF_UL3] = MT8195_AFE_IRQ_20, + [MT8195_AFE_MEMIF_UL4] = MT8195_AFE_IRQ_21, + [MT8195_AFE_MEMIF_UL5] = MT8195_AFE_IRQ_22, + [MT8195_AFE_MEMIF_UL6] = MT8195_AFE_IRQ_9, + [MT8195_AFE_MEMIF_UL8] = MT8195_AFE_IRQ_23, + [MT8195_AFE_MEMIF_UL9] = MT8195_AFE_IRQ_24, + [MT8195_AFE_MEMIF_UL10] = MT8195_AFE_IRQ_25, +}; + +static bool mt8195_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* these auto-gen reg has read-only bit, so put it as volatile */ + /* volatile reg cannot be cached, so cannot be set when power off */ + switch (reg) { + case AUDIO_TOP_CON0: + case AUDIO_TOP_CON1: + case AUDIO_TOP_CON3: + case AUDIO_TOP_CON4: + case AUDIO_TOP_CON5: + case AUDIO_TOP_CON6: + case ASYS_IRQ_CLR: + case ASYS_IRQ_STATUS: + case ASYS_IRQ_MON1: + case ASYS_IRQ_MON2: + case AFE_IRQ_MCU_CLR: + case AFE_IRQ_STATUS: + case AFE_IRQ3_CON_MON: + case AFE_IRQ_MCU_MON2: + case ADSP_IRQ_STATUS: + case AFE_APLL_TUNER_CFG: + case AFE_APLL_TUNER_CFG1: + case AUDIO_TOP_STA0: + case AUDIO_TOP_STA1: + case AFE_GAIN1_CUR: + case AFE_GAIN2_CUR: + case AFE_IEC_BURST_INFO: + case AFE_IEC_CHL_STAT0: + case AFE_IEC_CHL_STAT1: + case AFE_IEC_CHR_STAT0: + case AFE_IEC_CHR_STAT1: + case AFE_SPDIFIN_CHSTS1: + case AFE_SPDIFIN_CHSTS2: + case AFE_SPDIFIN_CHSTS3: + case AFE_SPDIFIN_CHSTS4: + case AFE_SPDIFIN_CHSTS5: + case AFE_SPDIFIN_CHSTS6: + case AFE_SPDIFIN_DEBUG1: + case AFE_SPDIFIN_DEBUG2: + case AFE_SPDIFIN_DEBUG3: + case AFE_SPDIFIN_DEBUG4: + case AFE_SPDIFIN_EC: + case AFE_SPDIFIN_CKLOCK_CFG: + case AFE_SPDIFIN_BR_DBG1: + case AFE_SPDIFIN_CKFBDIV: + case AFE_SPDIFIN_INT_EXT: + case AFE_SPDIFIN_INT_EXT2: + case SPDIFIN_FREQ_STATUS: + case SPDIFIN_USERCODE1: + case SPDIFIN_USERCODE2: + case SPDIFIN_USERCODE3: + case SPDIFIN_USERCODE4: + case SPDIFIN_USERCODE5: + case SPDIFIN_USERCODE6: + case SPDIFIN_USERCODE7: + case SPDIFIN_USERCODE8: + case SPDIFIN_USERCODE9: + case SPDIFIN_USERCODE10: + case SPDIFIN_USERCODE11: + case SPDIFIN_USERCODE12: + case AFE_SPDIFIN_APLL_TUNER_CFG: + case AFE_LINEIN_APLL_TUNER_MON: + case AFE_EARC_APLL_TUNER_MON: + case AFE_CM0_MON: + case AFE_CM1_MON: + case AFE_CM2_MON: + case AFE_MPHONE_MULTI_DET_MON0: + case AFE_MPHONE_MULTI_DET_MON1: + case AFE_MPHONE_MULTI_DET_MON2: + case AFE_MPHONE_MULTI2_DET_MON0: + case AFE_MPHONE_MULTI2_DET_MON1: + case AFE_MPHONE_MULTI2_DET_MON2: + case AFE_ADDA_MTKAIF_MON0: + case AFE_ADDA_MTKAIF_MON1: + case AFE_AUD_PAD_TOP: + case AFE_ADDA6_MTKAIF_MON0: + case AFE_ADDA6_MTKAIF_MON1: + case AFE_ADDA6_SRC_DEBUG_MON0: + case AFE_ADDA6_UL_SRC_MON0: + case AFE_ADDA6_UL_SRC_MON1: + case AFE_ASRC11_NEW_CON8: + case AFE_ASRC11_NEW_CON9: + case AFE_ASRC12_NEW_CON8: + case AFE_ASRC12_NEW_CON9: + case AFE_LRCK_CNT: + case AFE_DAC_MON0: + case AFE_DL2_CUR: + case AFE_DL3_CUR: + case AFE_DL6_CUR: + case AFE_DL7_CUR: + case AFE_DL8_CUR: + case AFE_DL10_CUR: + case AFE_DL11_CUR: + case AFE_UL1_CUR: + case AFE_UL2_CUR: + case AFE_UL3_CUR: + case AFE_UL4_CUR: + case AFE_UL5_CUR: + case AFE_UL6_CUR: + case AFE_UL8_CUR: + case AFE_UL9_CUR: + case AFE_UL10_CUR: + case AFE_DL8_CHK_SUM1: + case AFE_DL8_CHK_SUM2: + case AFE_DL8_CHK_SUM3: + case AFE_DL8_CHK_SUM4: + case AFE_DL8_CHK_SUM5: + case AFE_DL8_CHK_SUM6: + case AFE_DL10_CHK_SUM1: + case AFE_DL10_CHK_SUM2: + case AFE_DL10_CHK_SUM3: + case AFE_DL10_CHK_SUM4: + case AFE_DL10_CHK_SUM5: + case AFE_DL10_CHK_SUM6: + case AFE_DL11_CHK_SUM1: + case AFE_DL11_CHK_SUM2: + case AFE_DL11_CHK_SUM3: + case AFE_DL11_CHK_SUM4: + case AFE_DL11_CHK_SUM5: + case AFE_DL11_CHK_SUM6: + case AFE_UL1_CHK_SUM1: + case AFE_UL1_CHK_SUM2: + case AFE_UL2_CHK_SUM1: + case AFE_UL2_CHK_SUM2: + case AFE_UL3_CHK_SUM1: + case AFE_UL3_CHK_SUM2: + case AFE_UL4_CHK_SUM1: + case AFE_UL4_CHK_SUM2: + case AFE_UL5_CHK_SUM1: + case AFE_UL5_CHK_SUM2: + case AFE_UL6_CHK_SUM1: + case AFE_UL6_CHK_SUM2: + case AFE_UL8_CHK_SUM1: + case AFE_UL8_CHK_SUM2: + case AFE_DL2_CHK_SUM1: + case AFE_DL2_CHK_SUM2: + case AFE_DL3_CHK_SUM1: + case AFE_DL3_CHK_SUM2: + case AFE_DL6_CHK_SUM1: + case AFE_DL6_CHK_SUM2: + case AFE_DL7_CHK_SUM1: + case AFE_DL7_CHK_SUM2: + case AFE_UL9_CHK_SUM1: + case AFE_UL9_CHK_SUM2: + case AFE_BUS_MON1: + case UL1_MOD2AGT_CNT_LAT: + case UL2_MOD2AGT_CNT_LAT: + case UL3_MOD2AGT_CNT_LAT: + case UL4_MOD2AGT_CNT_LAT: + case UL5_MOD2AGT_CNT_LAT: + case UL6_MOD2AGT_CNT_LAT: + case UL8_MOD2AGT_CNT_LAT: + case UL9_MOD2AGT_CNT_LAT: + case UL10_MOD2AGT_CNT_LAT: + case AFE_MEMIF_BUF_FULL_MON: + case AFE_MEMIF_BUF_MON1: + case AFE_MEMIF_BUF_MON3: + case AFE_MEMIF_BUF_MON4: + case AFE_MEMIF_BUF_MON5: + case AFE_MEMIF_BUF_MON6: + case AFE_MEMIF_BUF_MON7: + case AFE_MEMIF_BUF_MON8: + case AFE_MEMIF_BUF_MON9: + case AFE_MEMIF_BUF_MON10: + case DL2_AGENT2MODULE_CNT: + case DL3_AGENT2MODULE_CNT: + case DL6_AGENT2MODULE_CNT: + case DL7_AGENT2MODULE_CNT: + case DL8_AGENT2MODULE_CNT: + case DL10_AGENT2MODULE_CNT: + case DL11_AGENT2MODULE_CNT: + case UL1_MODULE2AGENT_CNT: + case UL2_MODULE2AGENT_CNT: + case UL3_MODULE2AGENT_CNT: + case UL4_MODULE2AGENT_CNT: + case UL5_MODULE2AGENT_CNT: + case UL6_MODULE2AGENT_CNT: + case UL8_MODULE2AGENT_CNT: + case UL9_MODULE2AGENT_CNT: + case UL10_MODULE2AGENT_CNT: + case AFE_DMIC0_SRC_DEBUG_MON0: + case AFE_DMIC0_UL_SRC_MON0: + case AFE_DMIC0_UL_SRC_MON1: + case AFE_DMIC1_SRC_DEBUG_MON0: + case AFE_DMIC1_UL_SRC_MON0: + case AFE_DMIC1_UL_SRC_MON1: + case AFE_DMIC2_SRC_DEBUG_MON0: + case AFE_DMIC2_UL_SRC_MON0: + case AFE_DMIC2_UL_SRC_MON1: + case AFE_DMIC3_SRC_DEBUG_MON0: + case AFE_DMIC3_UL_SRC_MON0: + case AFE_DMIC3_UL_SRC_MON1: + case DMIC_GAIN1_CUR: + case DMIC_GAIN2_CUR: + case DMIC_GAIN3_CUR: + case DMIC_GAIN4_CUR: + case ETDM_IN1_MONITOR: + case ETDM_IN2_MONITOR: + case ETDM_OUT1_MONITOR: + case ETDM_OUT2_MONITOR: + case ETDM_OUT3_MONITOR: + case AFE_ADDA_SRC_DEBUG_MON0: + case AFE_ADDA_SRC_DEBUG_MON1: + case AFE_ADDA_DL_SDM_FIFO_MON: + case AFE_ADDA_DL_SRC_LCH_MON: + case AFE_ADDA_DL_SRC_RCH_MON: + case AFE_ADDA_DL_SDM_OUT_MON: + case AFE_GASRC0_NEW_CON8: + case AFE_GASRC0_NEW_CON9: + case AFE_GASRC0_NEW_CON12: + case AFE_GASRC1_NEW_CON8: + case AFE_GASRC1_NEW_CON9: + case AFE_GASRC1_NEW_CON12: + case AFE_GASRC2_NEW_CON8: + case AFE_GASRC2_NEW_CON9: + case AFE_GASRC2_NEW_CON12: + case AFE_GASRC3_NEW_CON8: + case AFE_GASRC3_NEW_CON9: + case AFE_GASRC3_NEW_CON12: + case AFE_GASRC4_NEW_CON8: + case AFE_GASRC4_NEW_CON9: + case AFE_GASRC4_NEW_CON12: + case AFE_GASRC5_NEW_CON8: + case AFE_GASRC5_NEW_CON9: + case AFE_GASRC5_NEW_CON12: + case AFE_GASRC6_NEW_CON8: + case AFE_GASRC6_NEW_CON9: + case AFE_GASRC6_NEW_CON12: + case AFE_GASRC7_NEW_CON8: + case AFE_GASRC7_NEW_CON9: + case AFE_GASRC7_NEW_CON12: + case AFE_GASRC8_NEW_CON8: + case AFE_GASRC8_NEW_CON9: + case AFE_GASRC8_NEW_CON12: + case AFE_GASRC9_NEW_CON8: + case AFE_GASRC9_NEW_CON9: + case AFE_GASRC9_NEW_CON12: + case AFE_GASRC10_NEW_CON8: + case AFE_GASRC10_NEW_CON9: + case AFE_GASRC10_NEW_CON12: + case AFE_GASRC11_NEW_CON8: + case AFE_GASRC11_NEW_CON9: + case AFE_GASRC11_NEW_CON12: + case AFE_GASRC12_NEW_CON8: + case AFE_GASRC12_NEW_CON9: + case AFE_GASRC12_NEW_CON12: + case AFE_GASRC13_NEW_CON8: + case AFE_GASRC13_NEW_CON9: + case AFE_GASRC13_NEW_CON12: + case AFE_GASRC14_NEW_CON8: + case AFE_GASRC14_NEW_CON9: + case AFE_GASRC14_NEW_CON12: + case AFE_GASRC15_NEW_CON8: + case AFE_GASRC15_NEW_CON9: + case AFE_GASRC15_NEW_CON12: + case AFE_GASRC16_NEW_CON8: + case AFE_GASRC16_NEW_CON9: + case AFE_GASRC16_NEW_CON12: + case AFE_GASRC17_NEW_CON8: + case AFE_GASRC17_NEW_CON9: + case AFE_GASRC17_NEW_CON12: + case AFE_GASRC18_NEW_CON8: + case AFE_GASRC18_NEW_CON9: + case AFE_GASRC18_NEW_CON12: + case AFE_GASRC19_NEW_CON8: + case AFE_GASRC19_NEW_CON9: + case AFE_GASRC19_NEW_CON12: + return true; + default: + return false; + }; +} + +static const struct regmap_config mt8195_afe_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .volatile_reg = mt8195_is_volatile_reg, + .max_register = AFE_MAX_REGISTER, + .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1), + .cache_type = REGCACHE_FLAT, +}; + +#define AFE_IRQ_CLR_BITS (0x387) +#define ASYS_IRQ_CLR_BITS (0xffff) + +static irqreturn_t mt8195_afe_irq_handler(int irq_id, void *dev_id) +{ + struct mtk_base_afe *afe = dev_id; + unsigned int val = 0; + unsigned int asys_irq_clr_bits = 0; + unsigned int afe_irq_clr_bits = 0; + unsigned int irq_status_bits = 0; + unsigned int irq_clr_bits = 0; + unsigned int mcu_irq_mask = 0; + int i = 0; + int ret = 0; + + ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &val); + if (ret) { + dev_info(afe->dev, "%s irq status err\n", __func__); + afe_irq_clr_bits = AFE_IRQ_CLR_BITS; + asys_irq_clr_bits = ASYS_IRQ_CLR_BITS; + goto err_irq; + } + + ret = regmap_read(afe->regmap, AFE_IRQ_MASK, &mcu_irq_mask); + if (ret) { + dev_info(afe->dev, "%s read irq mask err\n", __func__); + afe_irq_clr_bits = AFE_IRQ_CLR_BITS; + asys_irq_clr_bits = ASYS_IRQ_CLR_BITS; + goto err_irq; + } + + /* only clr cpu irq */ + val &= mcu_irq_mask; + + for (i = 0; i < MT8195_AFE_MEMIF_NUM; i++) { + struct mtk_base_afe_memif *memif = &afe->memif[i]; + struct mtk_base_irq_data const *irq_data; + + if (memif->irq_usage < 0) + continue; + + irq_data = afe->irqs[memif->irq_usage].irq_data; + + irq_status_bits = BIT(irq_data->irq_status_shift); + irq_clr_bits = BIT(irq_data->irq_clr_shift); + + if (!(val & irq_status_bits)) + continue; + + if (irq_data->irq_clr_reg == ASYS_IRQ_CLR) + asys_irq_clr_bits |= irq_clr_bits; + else + afe_irq_clr_bits |= irq_clr_bits; + + snd_pcm_period_elapsed(memif->substream); + } + +err_irq: + /* clear irq */ + if (asys_irq_clr_bits) + regmap_write(afe->regmap, ASYS_IRQ_CLR, asys_irq_clr_bits); + if (afe_irq_clr_bits) + regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, afe_irq_clr_bits); + + return IRQ_HANDLED; +} + +static int mt8195_afe_runtime_suspend(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + + if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) + goto skip_regmap; + + mt8195_afe_disable_main_clock(afe); + + regcache_cache_only(afe->regmap, true); + regcache_mark_dirty(afe->regmap); + +skip_regmap: + mt8195_afe_disable_reg_rw_clk(afe); + + return 0; +} + +static int mt8195_afe_runtime_resume(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + + mt8195_afe_enable_reg_rw_clk(afe); + + if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) + goto skip_regmap; + + regcache_cache_only(afe->regmap, false); + regcache_sync(afe->regmap); + + mt8195_afe_enable_main_clock(afe); +skip_regmap: + return 0; +} + +static int mt8195_afe_component_probe(struct snd_soc_component *component) +{ + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + int ret = 0; + + snd_soc_component_init_regmap(component, afe->regmap); + + ret = mtk_afe_add_sub_dai_control(component); + + return ret; +} + +static const struct snd_soc_component_driver mt8195_afe_component = { + .name = AFE_PCM_NAME, + .pointer = mtk_afe_pcm_pointer, + .pcm_construct = mtk_afe_pcm_new, + .probe = mt8195_afe_component_probe, +}; + +static int init_memif_priv_data(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_memif_priv *memif_priv; + int i; + + for (i = MT8195_AFE_MEMIF_START; i < MT8195_AFE_MEMIF_END; i++) { + memif_priv = devm_kzalloc(afe->dev, + sizeof(struct mtk_dai_memif_priv), + GFP_KERNEL); + if (!memif_priv) + return -ENOMEM; + + afe_priv->dai_priv[i] = memif_priv; + } + + return 0; +} + +static int mt8195_dai_memif_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mt8195_memif_dai_driver; + dai->num_dai_drivers = ARRAY_SIZE(mt8195_memif_dai_driver); + + dai->dapm_widgets = mt8195_memif_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mt8195_memif_widgets); + dai->dapm_routes = mt8195_memif_routes; + dai->num_dapm_routes = ARRAY_SIZE(mt8195_memif_routes); + dai->controls = mt8195_memif_controls; + dai->num_controls = ARRAY_SIZE(mt8195_memif_controls); + + return init_memif_priv_data(afe); +} + +typedef int (*dai_register_cb)(struct mtk_base_afe *); +static const dai_register_cb dai_register_cbs[] = { + mt8195_dai_adda_register, + mt8195_dai_etdm_register, + mt8195_dai_pcm_register, + mt8195_dai_memif_register, +}; + +static const struct reg_sequence mt8195_afe_reg_defaults[] = { + { AFE_IRQ_MASK, 0x387ffff }, + { AFE_IRQ3_CON, BIT(30) }, + { AFE_IRQ9_CON, BIT(30) }, + { ETDM_IN1_CON4, 0x12000100 }, + { ETDM_IN2_CON4, 0x12000100 }, +}; + +static const struct reg_sequence mt8195_cg_patch[] = { + { AUDIO_TOP_CON0, 0xfffffffb }, + { AUDIO_TOP_CON1, 0xfffffffa }, +}; + +static int mt8195_afe_init_registers(struct mtk_base_afe *afe) +{ + return regmap_multi_reg_write(afe->regmap, + mt8195_afe_reg_defaults, + ARRAY_SIZE(mt8195_afe_reg_defaults)); +} + +static void mt8195_afe_parse_of(struct mtk_base_afe *afe, + struct device_node *np) +{ +#if IS_ENABLED(CONFIG_SND_SOC_MT6359) + struct mt8195_afe_private *afe_priv = afe->platform_priv; + + afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->of_node, + "mediatek,topckgen"); + if (IS_ERR(afe_priv->topckgen)) { + dev_info(afe->dev, "%s() Cannot find topckgen controller: %ld\n", + __func__, PTR_ERR(afe_priv->topckgen)); + } +#endif +} + +static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev) +{ + struct mtk_base_afe *afe; + struct mt8195_afe_private *afe_priv; + struct resource *res; + struct device *dev = &pdev->dev; + int i, irq_id, ret; + struct snd_soc_component *component; + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33)); + if (ret) + return ret; + + afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + + afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv), + GFP_KERNEL); + if (!afe->platform_priv) + return -ENOMEM; + + afe_priv = afe->platform_priv; + afe->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + afe->base_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(afe->base_addr)) + return PTR_ERR(afe->base_addr); + + /* initial audio related clock */ + ret = mt8195_afe_init_clock(afe); + if (ret) { + dev_err(dev, "init clock error\n"); + return ret; + } + + spin_lock_init(&afe_priv->afe_ctrl_lock); + + mutex_init(&afe->irq_alloc_lock); + + /* irq initialize */ + afe->irqs_size = MT8195_AFE_IRQ_NUM; + afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), + GFP_KERNEL); + if (!afe->irqs) + return -ENOMEM; + + for (i = 0; i < afe->irqs_size; i++) + afe->irqs[i].irq_data = &irq_data[i]; + + /* init memif */ + afe->memif_size = MT8195_AFE_MEMIF_NUM; + afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), + GFP_KERNEL); + if (!afe->memif) + return -ENOMEM; + + for (i = 0; i < afe->memif_size; i++) { + afe->memif[i].data = &memif_data[i]; + afe->memif[i].irq_usage = mt8195_afe_memif_const_irqs[i]; + afe->memif[i].const_irq = 1; + afe->irqs[afe->memif[i].irq_usage].irq_occupyed = true; + } + + /* request irq */ + irq_id = platform_get_irq(pdev, 0); + if (irq_id < 0) { + dev_err(dev, "%s no irq found\n", dev->of_node->name); + return -ENXIO; + } + + ret = devm_request_irq(dev, irq_id, mt8195_afe_irq_handler, + IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); + if (ret) { + dev_err(dev, "could not request_irq for asys-isr\n"); + return ret; + } + + /* init sub_dais */ + INIT_LIST_HEAD(&afe->sub_dais); + + for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { + ret = dai_register_cbs[i](afe); + if (ret) { + dev_warn(dev, "dai register i %d fail, ret %d\n", + i, ret); + return ret; + } + } + + /* init dai_driver and component_driver */ + ret = mtk_afe_combine_sub_dai(afe); + if (ret) { + dev_warn(dev, "mtk_afe_combine_sub_dai fail, ret %d\n", + ret); + return ret; + } + + afe->mtk_afe_hardware = &mt8195_afe_hardware; + afe->memif_fs = mt8195_memif_fs; + afe->irq_fs = mt8195_irq_fs; + + afe->runtime_resume = mt8195_afe_runtime_resume; + afe->runtime_suspend = mt8195_afe_runtime_suspend; + + platform_set_drvdata(pdev, afe); + + mt8195_afe_parse_of(afe, pdev->dev.of_node); + + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = mt8195_afe_runtime_resume(dev); + if (ret) + return ret; + } + + /* enable clock for regcache get default value from hw */ + afe_priv->pm_runtime_bypass_reg_ctl = true; + pm_runtime_get_sync(dev); + + afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, + &mt8195_afe_regmap_config); + if (IS_ERR(afe->regmap)) { + ret = PTR_ERR(afe->regmap); + goto err_pm_put; + } + + ret = regmap_register_patch(afe->regmap, mt8195_cg_patch, + ARRAY_SIZE(mt8195_cg_patch)); + if (ret < 0) { + dev_err(dev, "Failed to apply cg patch\n"); + goto err_pm_put; + } + + /* register component */ + ret = devm_snd_soc_register_component(dev, &mt8195_afe_component, + NULL, 0); + if (ret) { + dev_warn(dev, "err_platform\n"); + goto err_pm_put; + } + + component = devm_kzalloc(dev, sizeof(*component), GFP_KERNEL); + if (!component) { + ret = -ENOMEM; + goto err_pm_put; + } + + ret = snd_soc_component_initialize(component, + &mt8195_afe_pcm_dai_component, + dev); + if (ret) + goto err_pm_put; + +#ifdef CONFIG_DEBUG_FS + component->debugfs_prefix = "pcm"; +#endif + + ret = snd_soc_add_component(component, + afe->dai_drivers, + afe->num_dai_drivers); + if (ret) { + dev_warn(dev, "err_dai_component\n"); + goto err_pm_put; + } + + mt8195_afe_init_registers(afe); + + pm_runtime_put_sync(dev); + afe_priv->pm_runtime_bypass_reg_ctl = false; + + regcache_cache_only(afe->regmap, true); + regcache_mark_dirty(afe->regmap); + + return 0; + +err_pm_put: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + + return ret; +} + +static int mt8195_afe_pcm_dev_remove(struct platform_device *pdev) +{ + struct mtk_base_afe *afe = platform_get_drvdata(pdev); + + snd_soc_unregister_component(&pdev->dev); + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + mt8195_afe_runtime_suspend(&pdev->dev); + + mt8195_afe_deinit_clock(afe); + return 0; +} + +static const struct of_device_id mt8195_afe_pcm_dt_match[] = { + {.compatible = "mediatek,mt8195-audio", }, + {}, +}; +MODULE_DEVICE_TABLE(of, mt8195_afe_pcm_dt_match); + +static const struct dev_pm_ops mt8195_afe_pm_ops = { + SET_RUNTIME_PM_OPS(mt8195_afe_runtime_suspend, + mt8195_afe_runtime_resume, NULL) +}; + +static struct platform_driver mt8195_afe_pcm_driver = { + .driver = { + .name = "mt8195-audio", + .of_match_table = mt8195_afe_pcm_dt_match, +#ifdef CONFIG_PM + .pm = &mt8195_afe_pm_ops, +#endif + }, + .probe = mt8195_afe_pcm_dev_probe, + .remove = mt8195_afe_pcm_dev_remove, +}; + +module_platform_driver(mt8195_afe_pcm_driver); + +MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8195"); +MODULE_AUTHOR("Bicycle Tsai <bicycle.tsai@mediatek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c new file mode 100644 index 000000000000..740aa6ddda0e --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mt8195-audsys-clk.h -- Mediatek 8195 audsys clock control + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include "mt8195-afe-common.h" +#include "mt8195-audsys-clk.h" +#include "mt8195-audsys-clkid.h" +#include "mt8195-reg.h" + +struct afe_gate { + int id; + const char *name; + const char *parent_name; + int reg; + u8 bit; + const struct clk_ops *ops; + unsigned long flags; + u8 cg_flags; +}; + +#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .reg = _reg, \ + .bit = _bit, \ + .flags = _flags, \ + .cg_flags = _cgflags, \ + } + +#define GATE_AFE(_id, _name, _parent, _reg, _bit) \ + GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, \ + CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE) + +#define GATE_AUD0(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit) + +#define GATE_AUD1(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit) + +#define GATE_AUD3(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON3, _bit) + +#define GATE_AUD4(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON4, _bit) + +#define GATE_AUD5(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON5, _bit) + +#define GATE_AUD6(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON6, _bit) + +static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = { + /* AUD0 */ + GATE_AUD0(CLK_AUD_AFE, "aud_afe", "a1sys_hp_sel", 2), + GATE_AUD0(CLK_AUD_LRCK_CNT, "aud_lrck_cnt", "a1sys_hp_sel", 4), + GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_APLL, "aud_spdifin_tuner_apll", "apll4_sel", 10), + GATE_AUD0(CLK_AUD_SPDIFIN_TUNER_DBG, "aud_spdifin_tuner_dbg", "apll4_sel", 11), + GATE_AUD0(CLK_AUD_UL_TML, "aud_ul_tml", "a1sys_hp_sel", 18), + GATE_AUD0(CLK_AUD_APLL1_TUNER, "aud_apll1_tuner", "apll1_sel", 19), + GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "apll2_sel", 20), + GATE_AUD0(CLK_AUD_TOP0_SPDF, "aud_top0_spdf", "aud_iec_sel", 21), + GATE_AUD0(CLK_AUD_APLL, "aud_apll", "apll1_sel", 23), + GATE_AUD0(CLK_AUD_APLL2, "aud_apll2", "apll2_sel", 24), + GATE_AUD0(CLK_AUD_DAC, "aud_dac", "a1sys_hp_sel", 25), + GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "a1sys_hp_sel", 26), + GATE_AUD0(CLK_AUD_TML, "aud_tml", "a1sys_hp_sel", 27), + GATE_AUD0(CLK_AUD_ADC, "aud_adc", "a1sys_hp_sel", 28), + GATE_AUD0(CLK_AUD_DAC_HIRES, "aud_dac_hires", "audio_h_sel", 31), + + /* AUD1 */ + GATE_AUD1(CLK_AUD_A1SYS_HP, "aud_a1sys_hp", "a1sys_hp_sel", 2), + GATE_AUD1(CLK_AUD_AFE_DMIC1, "aud_afe_dmic1", "a1sys_hp_sel", 10), + GATE_AUD1(CLK_AUD_AFE_DMIC2, "aud_afe_dmic2", "a1sys_hp_sel", 11), + GATE_AUD1(CLK_AUD_AFE_DMIC3, "aud_afe_dmic3", "a1sys_hp_sel", 12), + GATE_AUD1(CLK_AUD_AFE_DMIC4, "aud_afe_dmic4", "a1sys_hp_sel", 13), + GATE_AUD1(CLK_AUD_AFE_26M_DMIC_TM, "aud_afe_26m_dmic_tm", "a1sys_hp_sel", 14), + GATE_AUD1(CLK_AUD_UL_TML_HIRES, "aud_ul_tml_hires", "audio_h_sel", 16), + GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "audio_h_sel", 17), + GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "a1sys_hp_sel", 18), + GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "audio_h_sel", 19), + + /* AUD3 */ + GATE_AUD3(CLK_AUD_LINEIN_TUNER, "aud_linein_tuner", "apll5_sel", 5), + GATE_AUD3(CLK_AUD_EARC_TUNER, "aud_earc_tuner", "apll3_sel", 7), + + /* AUD4 */ + GATE_AUD4(CLK_AUD_I2SIN, "aud_i2sin", "a1sys_hp_sel", 0), + GATE_AUD4(CLK_AUD_TDM_IN, "aud_tdm_in", "a1sys_hp_sel", 1), + GATE_AUD4(CLK_AUD_I2S_OUT, "aud_i2s_out", "a1sys_hp_sel", 6), + GATE_AUD4(CLK_AUD_TDM_OUT, "aud_tdm_out", "a1sys_hp_sel", 7), + GATE_AUD4(CLK_AUD_HDMI_OUT, "aud_hdmi_out", "a1sys_hp_sel", 8), + GATE_AUD4(CLK_AUD_ASRC11, "aud_asrc11", "a1sys_hp_sel", 16), + GATE_AUD4(CLK_AUD_ASRC12, "aud_asrc12", "a1sys_hp_sel", 17), + GATE_AUD4(CLK_AUD_MULTI_IN, "aud_multi_in", "mphone_slave_b", 19), + GATE_AUD4(CLK_AUD_INTDIR, "aud_intdir", "intdir_sel", 20), + GATE_AUD4(CLK_AUD_A1SYS, "aud_a1sys", "a1sys_hp_sel", 21), + GATE_AUD4(CLK_AUD_A2SYS, "aud_a2sys", "a2sys_sel", 22), + GATE_AUD4(CLK_AUD_PCMIF, "aud_pcmif", "a1sys_hp_sel", 24), + GATE_AUD4(CLK_AUD_A3SYS, "aud_a3sys", "a3sys_sel", 30), + GATE_AUD4(CLK_AUD_A4SYS, "aud_a4sys", "a4sys_sel", 31), + + /* AUD5 */ + GATE_AUD5(CLK_AUD_MEMIF_UL1, "aud_memif_ul1", "a1sys_hp_sel", 0), + GATE_AUD5(CLK_AUD_MEMIF_UL2, "aud_memif_ul2", "a1sys_hp_sel", 1), + GATE_AUD5(CLK_AUD_MEMIF_UL3, "aud_memif_ul3", "a1sys_hp_sel", 2), + GATE_AUD5(CLK_AUD_MEMIF_UL4, "aud_memif_ul4", "a1sys_hp_sel", 3), + GATE_AUD5(CLK_AUD_MEMIF_UL5, "aud_memif_ul5", "a1sys_hp_sel", 4), + GATE_AUD5(CLK_AUD_MEMIF_UL6, "aud_memif_ul6", "a1sys_hp_sel", 5), + GATE_AUD5(CLK_AUD_MEMIF_UL8, "aud_memif_ul8", "a1sys_hp_sel", 7), + GATE_AUD5(CLK_AUD_MEMIF_UL9, "aud_memif_ul9", "a1sys_hp_sel", 8), + GATE_AUD5(CLK_AUD_MEMIF_UL10, "aud_memif_ul10", "a1sys_hp_sel", 9), + GATE_AUD5(CLK_AUD_MEMIF_DL2, "aud_memif_dl2", "a1sys_hp_sel", 18), + GATE_AUD5(CLK_AUD_MEMIF_DL3, "aud_memif_dl3", "a1sys_hp_sel", 19), + GATE_AUD5(CLK_AUD_MEMIF_DL6, "aud_memif_dl6", "a1sys_hp_sel", 22), + GATE_AUD5(CLK_AUD_MEMIF_DL7, "aud_memif_dl7", "a1sys_hp_sel", 23), + GATE_AUD5(CLK_AUD_MEMIF_DL8, "aud_memif_dl8", "a1sys_hp_sel", 24), + GATE_AUD5(CLK_AUD_MEMIF_DL10, "aud_memif_dl10", "a1sys_hp_sel", 26), + GATE_AUD5(CLK_AUD_MEMIF_DL11, "aud_memif_dl11", "a1sys_hp_sel", 27), + + /* AUD6 */ + GATE_AUD6(CLK_AUD_GASRC0, "aud_gasrc0", "asm_h_sel", 0), + GATE_AUD6(CLK_AUD_GASRC1, "aud_gasrc1", "asm_h_sel", 1), + GATE_AUD6(CLK_AUD_GASRC2, "aud_gasrc2", "asm_h_sel", 2), + GATE_AUD6(CLK_AUD_GASRC3, "aud_gasrc3", "asm_h_sel", 3), + GATE_AUD6(CLK_AUD_GASRC4, "aud_gasrc4", "asm_h_sel", 4), + GATE_AUD6(CLK_AUD_GASRC5, "aud_gasrc5", "asm_h_sel", 5), + GATE_AUD6(CLK_AUD_GASRC6, "aud_gasrc6", "asm_h_sel", 6), + GATE_AUD6(CLK_AUD_GASRC7, "aud_gasrc7", "asm_h_sel", 7), + GATE_AUD6(CLK_AUD_GASRC8, "aud_gasrc8", "asm_h_sel", 8), + GATE_AUD6(CLK_AUD_GASRC9, "aud_gasrc9", "asm_h_sel", 9), + GATE_AUD6(CLK_AUD_GASRC10, "aud_gasrc10", "asm_h_sel", 10), + GATE_AUD6(CLK_AUD_GASRC11, "aud_gasrc11", "asm_h_sel", 11), + GATE_AUD6(CLK_AUD_GASRC12, "aud_gasrc12", "asm_h_sel", 12), + GATE_AUD6(CLK_AUD_GASRC13, "aud_gasrc13", "asm_h_sel", 13), + GATE_AUD6(CLK_AUD_GASRC14, "aud_gasrc14", "asm_h_sel", 14), + GATE_AUD6(CLK_AUD_GASRC15, "aud_gasrc15", "asm_h_sel", 15), + GATE_AUD6(CLK_AUD_GASRC16, "aud_gasrc16", "asm_h_sel", 16), + GATE_AUD6(CLK_AUD_GASRC17, "aud_gasrc17", "asm_h_sel", 17), + GATE_AUD6(CLK_AUD_GASRC18, "aud_gasrc18", "asm_h_sel", 18), + GATE_AUD6(CLK_AUD_GASRC19, "aud_gasrc19", "asm_h_sel", 19), +}; + +int mt8195_audsys_clk_register(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK, + sizeof(*afe_priv->lookup), + GFP_KERNEL); + + if (!afe_priv->lookup) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + const struct afe_gate *gate = &aud_clks[i]; + + clk = clk_register_gate(afe->dev, gate->name, gate->parent_name, + gate->flags, afe->base_addr + gate->reg, + gate->bit, gate->cg_flags, NULL); + + if (IS_ERR(clk)) { + dev_err(afe->dev, "Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */ + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return -ENOMEM; + + cl->clk = clk; + cl->con_id = gate->name; + cl->dev_id = dev_name(afe->dev); + clkdev_add(cl); + + afe_priv->lookup[i] = cl; + } + + return 0; +} + +void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + if (!afe_priv) + return; + + for (i = 0; i < CLK_AUD_NR_CLK; i++) { + cl = afe_priv->lookup[i]; + if (!cl) + continue; + + clk = cl->clk; + clk_unregister_gate(clk); + + clkdev_drop(cl); + } +} diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h new file mode 100644 index 000000000000..239d31016ba7 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clk.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8195-audsys-clk.h -- Mediatek 8195 audsys clock definition + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT8195_AUDSYS_CLK_H_ +#define _MT8195_AUDSYS_CLK_H_ + +int mt8195_audsys_clk_register(struct mtk_base_afe *afe); +void mt8195_audsys_clk_unregister(struct mtk_base_afe *afe); + +#endif diff --git a/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h new file mode 100644 index 000000000000..4dd0a5c8b8fa --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-audsys-clkid.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8195-audsys-clkid.h -- Mediatek 8195 audsys clock id definition + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT8195_AUDSYS_CLKID_H_ +#define _MT8195_AUDSYS_CLKID_H_ + +enum{ + CLK_AUD_AFE, + CLK_AUD_LRCK_CNT, + CLK_AUD_SPDIFIN_TUNER_APLL, + CLK_AUD_SPDIFIN_TUNER_DBG, + CLK_AUD_UL_TML, + CLK_AUD_APLL1_TUNER, + CLK_AUD_APLL2_TUNER, + CLK_AUD_TOP0_SPDF, + CLK_AUD_APLL, + CLK_AUD_APLL2, + CLK_AUD_DAC, + CLK_AUD_DAC_PREDIS, + CLK_AUD_TML, + CLK_AUD_ADC, + CLK_AUD_DAC_HIRES, + CLK_AUD_A1SYS_HP, + CLK_AUD_AFE_DMIC1, + CLK_AUD_AFE_DMIC2, + CLK_AUD_AFE_DMIC3, + CLK_AUD_AFE_DMIC4, + CLK_AUD_AFE_26M_DMIC_TM, + CLK_AUD_UL_TML_HIRES, + CLK_AUD_ADC_HIRES, + CLK_AUD_ADDA6_ADC, + CLK_AUD_ADDA6_ADC_HIRES, + CLK_AUD_LINEIN_TUNER, + CLK_AUD_EARC_TUNER, + CLK_AUD_I2SIN, + CLK_AUD_TDM_IN, + CLK_AUD_I2S_OUT, + CLK_AUD_TDM_OUT, + CLK_AUD_HDMI_OUT, + CLK_AUD_ASRC11, + CLK_AUD_ASRC12, + CLK_AUD_MULTI_IN, + CLK_AUD_INTDIR, + CLK_AUD_A1SYS, + CLK_AUD_A2SYS, + CLK_AUD_PCMIF, + CLK_AUD_A3SYS, + CLK_AUD_A4SYS, + CLK_AUD_MEMIF_UL1, + CLK_AUD_MEMIF_UL2, + CLK_AUD_MEMIF_UL3, + CLK_AUD_MEMIF_UL4, + CLK_AUD_MEMIF_UL5, + CLK_AUD_MEMIF_UL6, + CLK_AUD_MEMIF_UL8, + CLK_AUD_MEMIF_UL9, + CLK_AUD_MEMIF_UL10, + CLK_AUD_MEMIF_DL2, + CLK_AUD_MEMIF_DL3, + CLK_AUD_MEMIF_DL6, + CLK_AUD_MEMIF_DL7, + CLK_AUD_MEMIF_DL8, + CLK_AUD_MEMIF_DL10, + CLK_AUD_MEMIF_DL11, + CLK_AUD_GASRC0, + CLK_AUD_GASRC1, + CLK_AUD_GASRC2, + CLK_AUD_GASRC3, + CLK_AUD_GASRC4, + CLK_AUD_GASRC5, + CLK_AUD_GASRC6, + CLK_AUD_GASRC7, + CLK_AUD_GASRC8, + CLK_AUD_GASRC9, + CLK_AUD_GASRC10, + CLK_AUD_GASRC11, + CLK_AUD_GASRC12, + CLK_AUD_GASRC13, + CLK_AUD_GASRC14, + CLK_AUD_GASRC15, + CLK_AUD_GASRC16, + CLK_AUD_GASRC17, + CLK_AUD_GASRC18, + CLK_AUD_GASRC19, + CLK_AUD_NR_CLK, +}; + +#endif diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c new file mode 100644 index 000000000000..878dec0b69ed --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c @@ -0,0 +1,830 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI ADDA Control + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/delay.h> +#include <linux/regmap.h> +#include "mt8195-afe-clk.h" +#include "mt8195-afe-common.h" +#include "mt8195-reg.h" + +#define ADDA_DL_GAIN_LOOPBACK 0x1800 +#define ADDA_HIRES_THRES 48000 + +enum { + SUPPLY_SEQ_CLOCK_SEL, + SUPPLY_SEQ_CLOCK_ON, + SUPPLY_SEQ_ADDA_DL_ON, + SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SUPPLY_SEQ_ADDA_UL_ON, + SUPPLY_SEQ_ADDA_AFE_ON, +}; + +enum { + MTK_AFE_ADDA_DL_RATE_8K = 0, + MTK_AFE_ADDA_DL_RATE_11K = 1, + MTK_AFE_ADDA_DL_RATE_12K = 2, + MTK_AFE_ADDA_DL_RATE_16K = 3, + MTK_AFE_ADDA_DL_RATE_22K = 4, + MTK_AFE_ADDA_DL_RATE_24K = 5, + MTK_AFE_ADDA_DL_RATE_32K = 6, + MTK_AFE_ADDA_DL_RATE_44K = 7, + MTK_AFE_ADDA_DL_RATE_48K = 8, + MTK_AFE_ADDA_DL_RATE_96K = 9, + MTK_AFE_ADDA_DL_RATE_192K = 10, +}; + +enum { + MTK_AFE_ADDA_UL_RATE_8K = 0, + MTK_AFE_ADDA_UL_RATE_16K = 1, + MTK_AFE_ADDA_UL_RATE_32K = 2, + MTK_AFE_ADDA_UL_RATE_48K = 3, + MTK_AFE_ADDA_UL_RATE_96K = 4, + MTK_AFE_ADDA_UL_RATE_192K = 5, +}; + +enum { + DELAY_DATA_MISO1 = 0, + DELAY_DATA_MISO0 = 1, + DELAY_DATA_MISO2 = 1, +}; + +enum { + MTK_AFE_ADDA, + MTK_AFE_ADDA6, +}; + +struct mtk_dai_adda_priv { + bool hires_required; +}; + +static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_DL_RATE_8K; + case 11025: + return MTK_AFE_ADDA_DL_RATE_11K; + case 12000: + return MTK_AFE_ADDA_DL_RATE_12K; + case 16000: + return MTK_AFE_ADDA_DL_RATE_16K; + case 22050: + return MTK_AFE_ADDA_DL_RATE_22K; + case 24000: + return MTK_AFE_ADDA_DL_RATE_24K; + case 32000: + return MTK_AFE_ADDA_DL_RATE_32K; + case 44100: + return MTK_AFE_ADDA_DL_RATE_44K; + case 48000: + return MTK_AFE_ADDA_DL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_DL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_DL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + return MTK_AFE_ADDA_DL_RATE_48K; + } +} + +static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_UL_RATE_8K; + case 16000: + return MTK_AFE_ADDA_UL_RATE_16K; + case 32000: + return MTK_AFE_ADDA_UL_RATE_32K; + case 48000: + return MTK_AFE_ADDA_UL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_UL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_UL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + return MTK_AFE_ADDA_UL_RATE_48K; + } +} + +static int mt8195_adda_mtkaif_init(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + int delay_data; + int delay_cycle; + unsigned int mask = 0; + unsigned int val = 0; + + /* set rx protocol 2 & mtkaif_rxif_clkinv_adc inverse */ + mask = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2); + val = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2); + + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, mask, val); + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_CFG0, mask, val); + + mask = RG_RX_PROTOCOL2; + val = RG_RX_PROTOCOL2; + regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, mask, val); + + if (!param->mtkaif_calibration_ok) { + dev_info(afe->dev, "%s(), calibration fail\n", __func__); + return 0; + } + + /* set delay for ch1, ch2 */ + if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] >= + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) { + delay_data = DELAY_DATA_MISO1; + delay_cycle = + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] - + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]; + } else { + delay_data = DELAY_DATA_MISO0; + delay_cycle = + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] - + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0]; + } + + val = 0; + mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK); + val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) & + MTKAIF_RXIF_DELAY_CYCLE_MASK; + val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT; + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG2, mask, val); + + /* set delay between ch3 and ch2 */ + if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] >= + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) { + delay_data = DELAY_DATA_MISO1; + delay_cycle = + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] - + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]; + } else { + delay_data = DELAY_DATA_MISO2; + delay_cycle = + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] - + param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2]; + } + + val = 0; + mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK); + val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) & + MTKAIF_RXIF_DELAY_CYCLE_MASK; + val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT; + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_RX_CFG2, mask, val); + + return 0; +} + +static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8195_adda_mtkaif_init(afe); + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + break; + default: + break; + } + + return 0; +} + +static void mtk_adda_ul_mictype(struct mtk_base_afe *afe, int adda, bool dmic) +{ + unsigned int reg = 0; + unsigned int mask = 0; + unsigned int val = 0; + + switch (adda) { + case MTK_AFE_ADDA: + reg = AFE_ADDA_UL_SRC_CON0; + break; + case MTK_AFE_ADDA6: + reg = AFE_ADDA6_UL_SRC_CON0; + break; + default: + dev_info(afe->dev, "%s(), wrong parameter\n", __func__); + return; + } + + mask = (UL_SDM3_LEVEL_CTL | UL_MODE_3P25M_CH1_CTL | + UL_MODE_3P25M_CH2_CTL); + + /* turn on dmic, ch1, ch2 */ + if (dmic) + val = mask; + + regmap_update_bits(afe->regmap, reg, mask, val); +} + +static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mtk_adda_ul_mictype(afe, MTK_AFE_ADDA, param->mtkaif_dmic_on); + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + break; + default: + break; + } + + return 0; +} + +static int mtk_adda6_ul_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + unsigned int val; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mtk_adda_ul_mictype(afe, MTK_AFE_ADDA6, param->mtkaif_dmic_on); + + val = (param->mtkaif_adda6_only ? + ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE : 0); + + regmap_update_bits(afe->regmap, + AFE_ADDA_MTKAIF_SYNCWORD_CFG, + ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE, + val); + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + break; + default: + break; + } + + return 0; +} + +static int mtk_audio_hires_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct clk *clk = afe_priv->clk[MT8195_CLK_TOP_AUDIO_H_SEL]; + struct clk *clk_parent; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + clk_parent = afe_priv->clk[MT8195_CLK_TOP_APLL1]; + break; + case SND_SOC_DAPM_POST_PMD: + clk_parent = afe_priv->clk[MT8195_CLK_XTAL_26M]; + break; + default: + return 0; + } + mt8195_afe_set_clk_parent(afe, clk, clk_parent); + + return 0; +} + +static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int dai_id; + + if (strstr(name, "aud_adc_hires")) + dai_id = MT8195_AFE_IO_UL_SRC1; + else if (strstr(name, "aud_adda6_adc_hires")) + dai_id = MT8195_AFE_IO_UL_SRC2; + else if (strstr(name, "aud_dac_hires")) + dai_id = MT8195_AFE_IO_DL_SRC; + else + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_dai_adda_priv *adda_priv; + + adda_priv = get_adda_priv_by_name(afe, w->name); + + if (!adda_priv) { + dev_info(afe->dev, "adda_priv == NULL"); + return 0; + } + + return (adda_priv->hires_required) ? 1 : 0; +} + +static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN176, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN176, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN176, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN176, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN176_2, 6, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_adda_o177_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN177, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN177, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN177, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN177, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN177_2, 7, 1, 0), +}; + +static const char * const adda_dlgain_mux_map[] = { + "Bypass", "Connect", +}; + +static SOC_ENUM_SINGLE_DECL(adda_dlgain_mux_map_enum, + SND_SOC_NOPM, 0, + adda_dlgain_mux_map); + +static const struct snd_kcontrol_new adda_dlgain_mux_control = + SOC_DAPM_ENUM("DL_GAIN_MUX", adda_dlgain_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = { + SND_SOC_DAPM_MIXER("I168", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I169", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I170", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I171", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("O176", SND_SOC_NOPM, 0, 0, + mtk_dai_adda_o176_mix, + ARRAY_SIZE(mtk_dai_adda_o176_mix)), + SND_SOC_DAPM_MIXER("O177", SND_SOC_NOPM, 0, 0, + mtk_dai_adda_o177_mix, + ARRAY_SIZE(mtk_dai_adda_o177_mix)), + + SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON, + AFE_ADDA_UL_DL_CON0, + ADDA_AFE_ON_SHIFT, 0, + NULL, + 0), + + SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON, + AFE_ADDA_DL_SRC2_CON0, + DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT, 0, + mtk_adda_dl_event, + SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA_UL_SRC_CON0, + UL_SRC_ON_TMP_CTL_SHIFT, 0, + mtk_adda_ul_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("ADDA6 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA6_UL_SRC_CON0, + UL_SRC_ON_TMP_CTL_SHIFT, 0, + mtk_adda6_ul_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("AUDIO_HIRES", SUPPLY_SEQ_CLOCK_SEL, + SND_SOC_NOPM, + 0, 0, + mtk_audio_hires_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SND_SOC_NOPM, + 0, 0, + mtk_adda_mtkaif_cfg_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_MUX("DL_GAIN_MUX", SND_SOC_NOPM, 0, 0, + &adda_dlgain_mux_control), + + SND_SOC_DAPM_PGA("DL_GAIN", AFE_ADDA_DL_SRC2_CON0, + DL_2_GAIN_ON_CTL_PRE_SHIFT, 0, NULL, 0), + + SND_SOC_DAPM_INPUT("ADDA_INPUT"), + SND_SOC_DAPM_OUTPUT("ADDA_OUTPUT"), + + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adda6_adc_hires"), +}; + +static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = { + {"ADDA Capture", NULL, "ADDA Enable"}, + {"ADDA Capture", NULL, "ADDA Capture Enable"}, + {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"}, + {"ADDA Capture", NULL, "aud_adc"}, + {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect}, + {"aud_adc_hires", NULL, "AUDIO_HIRES"}, + + {"ADDA6 Capture", NULL, "ADDA Enable"}, + {"ADDA6 Capture", NULL, "ADDA6 Capture Enable"}, + {"ADDA6 Capture", NULL, "ADDA_MTKAIF_CFG"}, + {"ADDA6 Capture", NULL, "aud_adda6_adc"}, + {"ADDA6 Capture", NULL, "aud_adda6_adc_hires", + mtk_afe_adda_hires_connect}, + {"aud_adda6_adc_hires", NULL, "AUDIO_HIRES"}, + + {"I168", NULL, "ADDA Capture"}, + {"I169", NULL, "ADDA Capture"}, + {"I170", NULL, "ADDA6 Capture"}, + {"I171", NULL, "ADDA6 Capture"}, + + {"ADDA Playback", NULL, "ADDA Enable"}, + {"ADDA Playback", NULL, "ADDA Playback Enable"}, + {"ADDA Playback", NULL, "aud_dac"}, + {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect}, + {"aud_dac_hires", NULL, "AUDIO_HIRES"}, + + {"DL_GAIN", NULL, "O176"}, + {"DL_GAIN", NULL, "O177"}, + + {"DL_GAIN_MUX", "Bypass", "O176"}, + {"DL_GAIN_MUX", "Bypass", "O177"}, + {"DL_GAIN_MUX", "Connect", "DL_GAIN"}, + + {"ADDA Playback", NULL, "DL_GAIN_MUX"}, + + {"O176", "I000 Switch", "I000"}, + {"O177", "I001 Switch", "I001"}, + + {"O176", "I002 Switch", "I002"}, + {"O177", "I003 Switch", "I003"}, + + {"O176", "I020 Switch", "I020"}, + {"O177", "I021 Switch", "I021"}, + + {"O176", "I022 Switch", "I022"}, + {"O177", "I023 Switch", "I023"}, + + {"O176", "I070 Switch", "I070"}, + {"O177", "I071 Switch", "I071"}, + + {"ADDA Capture", NULL, "ADDA_INPUT"}, + {"ADDA6 Capture", NULL, "ADDA_INPUT"}, + {"ADDA_OUTPUT", NULL, "ADDA Playback"}, +}; + +static int mt8195_adda_dl_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + unsigned int reg = AFE_ADDA_DL_SRC2_CON1; + unsigned int mask = DL_2_GAIN_CTL_PRE_MASK; + unsigned int value = (unsigned int)(ucontrol->value.integer.value[0]); + + regmap_update_bits(afe->regmap, reg, mask, DL_2_GAIN_CTL_PRE(value)); + return 0; +} + +static int mt8195_adda_dl_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + unsigned int reg = AFE_ADDA_DL_SRC2_CON1; + unsigned int mask = DL_2_GAIN_CTL_PRE_MASK; + unsigned int value = 0; + + regmap_read(afe->regmap, reg, &value); + + ucontrol->value.integer.value[0] = ((value & mask) >> + DL_2_GAIN_CTL_PRE_SHIFT); + return 0; +} + +static int mt8195_adda6_only_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + + ucontrol->value.integer.value[0] = param->mtkaif_adda6_only; + return 0; +} + +static int mt8195_adda6_only_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + int mtkaif_adda6_only; + + mtkaif_adda6_only = ucontrol->value.integer.value[0]; + + dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n", + __func__, kcontrol->id.name, mtkaif_adda6_only); + + param->mtkaif_adda6_only = mtkaif_adda6_only; + + return 0; +} + +static int mt8195_adda_dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + + ucontrol->value.integer.value[0] = param->mtkaif_dmic_on; + return 0; +} + +static int mt8195_adda_dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + int dmic_on; + + dmic_on = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n", + __func__, kcontrol->id.name, dmic_on); + + param->mtkaif_dmic_on = dmic_on; + return 0; +} + +static const struct snd_kcontrol_new mtk_dai_adda_controls[] = { + SOC_SINGLE_EXT("ADDA_DL_Gain", SND_SOC_NOPM, 0, 65535, 0, + mt8195_adda_dl_gain_get, mt8195_adda_dl_gain_put), + SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC", 0, + mt8195_adda_dmic_get, mt8195_adda_dmic_set), + SOC_SINGLE_BOOL_EXT("MTKAIF_ADDA6_ONLY", 0, + mt8195_adda6_only_get, + mt8195_adda6_only_set), +}; + +static int mtk_dai_da_configure(struct mtk_base_afe *afe, + unsigned int rate, int id) +{ + unsigned int val = 0; + unsigned int mask = 0; + + /* set sampling rate */ + mask |= DL_2_INPUT_MODE_CTL_MASK; + val |= DL_2_INPUT_MODE_CTL(afe_adda_dl_rate_transform(afe, rate)); + + /* turn off saturation */ + mask |= DL_2_CH1_SATURATION_EN_CTL; + mask |= DL_2_CH2_SATURATION_EN_CTL; + + /* turn off mute function */ + mask |= DL_2_MUTE_CH1_OFF_CTL_PRE; + mask |= DL_2_MUTE_CH2_OFF_CTL_PRE; + val |= DL_2_MUTE_CH1_OFF_CTL_PRE; + val |= DL_2_MUTE_CH2_OFF_CTL_PRE; + + /* set voice input data if input sample rate is 8k or 16k */ + mask |= DL_2_VOICE_MODE_CTL_PRE; + if (rate == 8000 || rate == 16000) + val |= DL_2_VOICE_MODE_CTL_PRE; + + regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, mask, val); + + mask = 0; + val = 0; + + /* new 2nd sdm */ + mask |= DL_USE_NEW_2ND_SDM; + val |= DL_USE_NEW_2ND_SDM; + regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON, mask, val); + + return 0; +} + +static int mtk_dai_ad_configure(struct mtk_base_afe *afe, + unsigned int rate, int id) +{ + unsigned int val = 0; + unsigned int mask = 0; + + mask |= UL_VOICE_MODE_CTL_MASK; + val |= UL_VOICE_MODE_CTL(afe_adda_ul_rate_transform(afe, rate)); + + switch (id) { + case MT8195_AFE_IO_UL_SRC1: + regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, + mask, val); + break; + case MT8195_AFE_IO_UL_SRC2: + regmap_update_bits(afe->regmap, AFE_ADDA6_UL_SRC_CON0, + mask, val); + break; + default: + break; + } + return 0; +} + +static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id]; + unsigned int rate = params_rate(params); + int id = dai->id; + int ret = 0; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, id, substream->stream, rate); + + if (rate > ADDA_HIRES_THRES) + adda_priv->hires_required = 1; + else + adda_priv->hires_required = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + ret = mtk_dai_da_configure(afe, rate, id); + else + ret = mtk_dai_ad_configure(afe, rate, id); + + return ret; +} + +static const struct snd_soc_dai_ops mtk_dai_adda_ops = { + .hw_params = mtk_dai_adda_hw_params, +}; + +/* dai driver */ +#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_adda_driver[] = { + { + .name = "DL_SRC", + .id = MT8195_AFE_IO_DL_SRC, + .playback = { + .stream_name = "ADDA Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_PLAYBACK_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "UL_SRC1", + .id = MT8195_AFE_IO_UL_SRC1, + .capture = { + .stream_name = "ADDA Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "UL_SRC2", + .id = MT8195_AFE_IO_UL_SRC2, + .capture = { + .stream_name = "ADDA6 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, +}; + +static int init_adda_priv_data(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_adda_priv *adda_priv; + int adda_dai_list[] = { MT8195_AFE_IO_DL_SRC, + MT8195_AFE_IO_UL_SRC1, + MT8195_AFE_IO_UL_SRC2}; + int i; + + for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) { + adda_priv = devm_kzalloc(afe->dev, + sizeof(struct mtk_dai_adda_priv), + GFP_KERNEL); + if (!adda_priv) + return -ENOMEM; + + afe_priv->dai_priv[adda_dai_list[i]] = adda_priv; + } + + return 0; +} + +int mt8195_dai_adda_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_adda_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver); + + dai->dapm_widgets = mtk_dai_adda_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets); + dai->dapm_routes = mtk_dai_adda_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes); + dai->controls = mtk_dai_adda_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_adda_controls); + + return init_adda_priv_data(afe); +} diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c new file mode 100644 index 000000000000..bd9876cf02c8 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -0,0 +1,2639 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI eTDM Control + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/delay.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <sound/pcm_params.h> +#include "mt8195-afe-clk.h" +#include "mt8195-afe-common.h" +#include "mt8195-reg.h" + +#define MT8195_ETDM_MAX_CHANNELS 24 +#define MT8195_ETDM_NORMAL_MAX_BCK_RATE 24576000 +#define ETDM_TO_DAI_ID(x) ((x) + MT8195_AFE_IO_ETDM_START) +#define ENUM_TO_STR(x) #x + +enum { + MTK_DAI_ETDM_FORMAT_I2S = 0, + MTK_DAI_ETDM_FORMAT_LJ, + MTK_DAI_ETDM_FORMAT_RJ, + MTK_DAI_ETDM_FORMAT_EIAJ, + MTK_DAI_ETDM_FORMAT_DSPA, + MTK_DAI_ETDM_FORMAT_DSPB, +}; + +enum { + MTK_DAI_ETDM_DATA_ONE_PIN = 0, + MTK_DAI_ETDM_DATA_MULTI_PIN, +}; + +enum { + ETDM_IN, + ETDM_OUT, +}; + +enum { + ETDM_IN_FROM_PAD, + ETDM_IN_FROM_ETDM_OUT1, + ETDM_IN_FROM_ETDM_OUT2, +}; + +enum { + ETDM_IN_SLAVE_FROM_PAD, + ETDM_IN_SLAVE_FROM_ETDM_OUT1, + ETDM_IN_SLAVE_FROM_ETDM_OUT2, +}; + +enum { + ETDM_OUT_SLAVE_FROM_PAD, + ETDM_OUT_SLAVE_FROM_ETDM_IN1, + ETDM_OUT_SLAVE_FROM_ETDM_IN2, +}; + +enum { + COWORK_ETDM_NONE = 0, + COWORK_ETDM_IN1_M = 2, + COWORK_ETDM_IN1_S = 3, + COWORK_ETDM_IN2_M = 4, + COWORK_ETDM_IN2_S = 5, + COWORK_ETDM_OUT1_M = 10, + COWORK_ETDM_OUT1_S = 11, + COWORK_ETDM_OUT2_M = 12, + COWORK_ETDM_OUT2_S = 13, + COWORK_ETDM_OUT3_M = 14, + COWORK_ETDM_OUT3_S = 15, +}; + +enum { + ETDM_RELATCH_TIMING_A1A2SYS, + ETDM_RELATCH_TIMING_A3SYS, + ETDM_RELATCH_TIMING_A4SYS, +}; + +enum { + ETDM_SYNC_NONE, + ETDM_SYNC_FROM_IN1, + ETDM_SYNC_FROM_IN2, + ETDM_SYNC_FROM_OUT1, + ETDM_SYNC_FROM_OUT2, + ETDM_SYNC_FROM_OUT3, +}; + +struct etdm_con_reg { + unsigned int con0; + unsigned int con1; + unsigned int con2; + unsigned int con3; + unsigned int con4; + unsigned int con5; +}; + +struct mtk_dai_etdm_rate { + unsigned int rate; + unsigned int reg_value; +}; + +struct mtk_dai_etdm_priv { + unsigned int clock_mode; + unsigned int data_mode; + bool slave_mode; + bool lrck_inv; + bool bck_inv; + unsigned int format; + unsigned int slots; + unsigned int lrck_width; + unsigned int mclk_freq; + unsigned int mclk_apll; + unsigned int mclk_dir; + int cowork_source_id; //dai id + unsigned int cowork_slv_count; + int cowork_slv_id[MT8195_AFE_IO_ETDM_NUM - 1]; //dai_id + bool in_disable_ch[MT8195_ETDM_MAX_CHANNELS]; + unsigned int en_ref_cnt; +}; + +static const struct mtk_dai_etdm_rate mt8195_etdm_rates[] = { + { .rate = 8000, .reg_value = 0, }, + { .rate = 12000, .reg_value = 1, }, + { .rate = 16000, .reg_value = 2, }, + { .rate = 24000, .reg_value = 3, }, + { .rate = 32000, .reg_value = 4, }, + { .rate = 48000, .reg_value = 5, }, + { .rate = 96000, .reg_value = 7, }, + { .rate = 192000, .reg_value = 9, }, + { .rate = 384000, .reg_value = 11, }, + { .rate = 11025, .reg_value = 16, }, + { .rate = 22050, .reg_value = 17, }, + { .rate = 44100, .reg_value = 18, }, + { .rate = 88200, .reg_value = 19, }, + { .rate = 176400, .reg_value = 20, }, + { .rate = 352800, .reg_value = 21, }, +}; + +static int get_etdm_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8195_etdm_rates); i++) + if (mt8195_etdm_rates[i].rate == rate) + return mt8195_etdm_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int get_etdm_ch_fixup(unsigned int channels) +{ + if (channels > 16) + return 24; + else if (channels > 8) + return 16; + else if (channels > 4) + return 8; + else if (channels > 2) + return 4; + else + return 2; +} + +static int get_etdm_reg(unsigned int dai_id, struct etdm_con_reg *etdm_reg) +{ + switch (dai_id) { + case MT8195_AFE_IO_ETDM1_IN: + etdm_reg->con0 = ETDM_IN1_CON0; + etdm_reg->con1 = ETDM_IN1_CON1; + etdm_reg->con2 = ETDM_IN1_CON2; + etdm_reg->con3 = ETDM_IN1_CON3; + etdm_reg->con4 = ETDM_IN1_CON4; + etdm_reg->con5 = ETDM_IN1_CON5; + break; + case MT8195_AFE_IO_ETDM2_IN: + etdm_reg->con0 = ETDM_IN2_CON0; + etdm_reg->con1 = ETDM_IN2_CON1; + etdm_reg->con2 = ETDM_IN2_CON2; + etdm_reg->con3 = ETDM_IN2_CON3; + etdm_reg->con4 = ETDM_IN2_CON4; + etdm_reg->con5 = ETDM_IN2_CON5; + break; + case MT8195_AFE_IO_ETDM1_OUT: + etdm_reg->con0 = ETDM_OUT1_CON0; + etdm_reg->con1 = ETDM_OUT1_CON1; + etdm_reg->con2 = ETDM_OUT1_CON2; + etdm_reg->con3 = ETDM_OUT1_CON3; + etdm_reg->con4 = ETDM_OUT1_CON4; + etdm_reg->con5 = ETDM_OUT1_CON5; + break; + case MT8195_AFE_IO_ETDM2_OUT: + etdm_reg->con0 = ETDM_OUT2_CON0; + etdm_reg->con1 = ETDM_OUT2_CON1; + etdm_reg->con2 = ETDM_OUT2_CON2; + etdm_reg->con3 = ETDM_OUT2_CON3; + etdm_reg->con4 = ETDM_OUT2_CON4; + etdm_reg->con5 = ETDM_OUT2_CON5; + break; + case MT8195_AFE_IO_ETDM3_OUT: + case MT8195_AFE_IO_DPTX: + etdm_reg->con0 = ETDM_OUT3_CON0; + etdm_reg->con1 = ETDM_OUT3_CON1; + etdm_reg->con2 = ETDM_OUT3_CON2; + etdm_reg->con3 = ETDM_OUT3_CON3; + etdm_reg->con4 = ETDM_OUT3_CON4; + etdm_reg->con5 = ETDM_OUT3_CON5; + break; + default: + return -EINVAL; + } + return 0; +} + +static int get_etdm_dir(unsigned int dai_id) +{ + switch (dai_id) { + case MT8195_AFE_IO_ETDM1_IN: + case MT8195_AFE_IO_ETDM2_IN: + return ETDM_IN; + case MT8195_AFE_IO_ETDM1_OUT: + case MT8195_AFE_IO_ETDM2_OUT: + case MT8195_AFE_IO_ETDM3_OUT: + return ETDM_OUT; + default: + return -EINVAL; + } +} + +static int get_etdm_wlen(unsigned int bitwidth) +{ + return bitwidth <= 16 ? 16 : 32; +} + +static int is_cowork_mode(struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + + return (etdm_data->cowork_slv_count > 0 || + etdm_data->cowork_source_id != COWORK_ETDM_NONE); +} + +static int sync_to_dai_id(int source_sel) +{ + switch (source_sel) { + case ETDM_SYNC_FROM_IN1: + return MT8195_AFE_IO_ETDM1_IN; + case ETDM_SYNC_FROM_IN2: + return MT8195_AFE_IO_ETDM2_IN; + case ETDM_SYNC_FROM_OUT1: + return MT8195_AFE_IO_ETDM1_OUT; + case ETDM_SYNC_FROM_OUT2: + return MT8195_AFE_IO_ETDM2_OUT; + case ETDM_SYNC_FROM_OUT3: + return MT8195_AFE_IO_ETDM3_OUT; + default: + return 0; + } +} + +static int get_etdm_cowork_master_id(struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + int dai_id = etdm_data->cowork_source_id; + + if (dai_id == COWORK_ETDM_NONE) + dai_id = dai->id; + + return dai_id; +} + +static const struct snd_kcontrol_new mtk_dai_etdm_o048_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN48, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN48, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN48_1, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN48_2, 6, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o049_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN49, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN49, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN49_1, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN49_2, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o050_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN50, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN50_1, 16, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o051_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN51, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN51_1, 17, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o052_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN52, 26, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN52_1, 18, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o053_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN53, 27, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN53_1, 19, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o054_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN54, 28, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN54_1, 20, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o055_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN55, 29, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN55_1, 21, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o056_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN56, 30, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN56_1, 22, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o057_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN57, 31, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN57_1, 23, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o058_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN58_1, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN58_1, 24, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o059_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN59_1, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN59_1, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o060_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN60_1, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN60_1, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o061_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN61_1, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN61_1, 27, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o062_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN62_1, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN62_1, 28, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o063_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN63_1, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN63_1, 29, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o064_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN64_1, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN64_1, 30, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o065_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN65_1, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN65_1, 31, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o066_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN66_1, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN66_2, 0, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o067_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN67_1, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN67_2, 1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o068_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN68_1, 10, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN68_2, 2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o069_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN69_1, 11, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN69_2, 3, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o070_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN70_1, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN70_2, 4, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o071_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN71_1, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN71_2, 5, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o072_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN72, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN72, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I046 Switch", AFE_CONN72_1, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN72_2, 6, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o073_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN73, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN73, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I047 Switch", AFE_CONN73_1, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN73_2, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o074_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I024 Switch", AFE_CONN74, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I048 Switch", AFE_CONN74_1, 16, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o075_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I025 Switch", AFE_CONN75, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I049 Switch", AFE_CONN75_1, 17, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o076_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I026 Switch", AFE_CONN76, 26, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I050 Switch", AFE_CONN76_1, 18, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o077_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I027 Switch", AFE_CONN77, 27, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I051 Switch", AFE_CONN77_1, 19, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o078_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I028 Switch", AFE_CONN78, 28, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I052 Switch", AFE_CONN78_1, 20, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o079_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I029 Switch", AFE_CONN79, 29, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I053 Switch", AFE_CONN79_1, 21, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o080_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I030 Switch", AFE_CONN80, 30, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I054 Switch", AFE_CONN80_1, 22, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o081_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I031 Switch", AFE_CONN81, 31, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I055 Switch", AFE_CONN81_1, 23, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o082_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I032 Switch", AFE_CONN82_1, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I056 Switch", AFE_CONN82_1, 24, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o083_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I033 Switch", AFE_CONN83_1, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I057 Switch", AFE_CONN83_1, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o084_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I034 Switch", AFE_CONN84_1, 2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I058 Switch", AFE_CONN84_1, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o085_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I035 Switch", AFE_CONN85_1, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I059 Switch", AFE_CONN85_1, 27, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o086_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I036 Switch", AFE_CONN86_1, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I060 Switch", AFE_CONN86_1, 28, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o087_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I037 Switch", AFE_CONN87_1, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I061 Switch", AFE_CONN87_1, 29, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o088_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I038 Switch", AFE_CONN88_1, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I062 Switch", AFE_CONN88_1, 30, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o089_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I039 Switch", AFE_CONN89_1, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I063 Switch", AFE_CONN89_1, 31, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o090_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I040 Switch", AFE_CONN90_1, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I064 Switch", AFE_CONN90_2, 0, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o091_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I041 Switch", AFE_CONN91_1, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I065 Switch", AFE_CONN91_2, 1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o092_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I042 Switch", AFE_CONN92_1, 10, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I066 Switch", AFE_CONN92_2, 2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o093_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I043 Switch", AFE_CONN93_1, 11, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I067 Switch", AFE_CONN93_2, 3, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o094_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I044 Switch", AFE_CONN94_1, 12, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I068 Switch", AFE_CONN94_2, 4, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_etdm_o095_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I045 Switch", AFE_CONN95_1, 13, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I069 Switch", AFE_CONN95_2, 5, 1, 0), +}; + +static const char * const mt8195_etdm_clk_src_sel_text[] = { + "26m", + "a1sys_a2sys", + "a3sys", + "a4sys", +}; + +static SOC_ENUM_SINGLE_EXT_DECL(etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_text); + +static const char * const hdmitx_dptx_mux_map[] = { + "Disconnect", "Connect", +}; + +static int hdmitx_dptx_mux_map_value[] = { + 0, 1, +}; + +/* HDMI_OUT_MUX */ +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(hdmi_out_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + hdmitx_dptx_mux_map, + hdmitx_dptx_mux_map_value); + +static const struct snd_kcontrol_new hdmi_out_mux_control = + SOC_DAPM_ENUM("HDMI_OUT_MUX", hdmi_out_mux_map_enum); + +/* DPTX_OUT_MUX */ +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(dptx_out_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + hdmitx_dptx_mux_map, + hdmitx_dptx_mux_map_value); + +static const struct snd_kcontrol_new dptx_out_mux_control = + SOC_DAPM_ENUM("DPTX_OUT_MUX", dptx_out_mux_map_enum); + +/* HDMI_CH0_MUX ~ HDMI_CH7_MUX */ +static const char *const afe_conn_hdmi_mux_map[] = { + "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", +}; + +static int afe_conn_hdmi_mux_map_value[] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum, + AFE_TDMOUT_CONN0, + 0, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch0_mux_control = + SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum, + AFE_TDMOUT_CONN0, + 4, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch1_mux_control = + SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum, + AFE_TDMOUT_CONN0, + 8, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch2_mux_control = + SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum, + AFE_TDMOUT_CONN0, + 12, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch3_mux_control = + SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum, + AFE_TDMOUT_CONN0, + 16, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch4_mux_control = + SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum, + AFE_TDMOUT_CONN0, + 20, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch5_mux_control = + SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum, + AFE_TDMOUT_CONN0, + 24, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch6_mux_control = + SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum, + AFE_TDMOUT_CONN0, + 28, + 0xf, + afe_conn_hdmi_mux_map, + afe_conn_hdmi_mux_map_value); + +static const struct snd_kcontrol_new hdmi_ch7_mux_control = + SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum); + +static int mt8195_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + unsigned int source = ucontrol->value.enumerated.item[0]; + unsigned int val; + unsigned int mask; + unsigned int reg; + + if (source >= e->items) + return -EINVAL; + + reg = 0; + if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) { + reg = ETDM_OUT1_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + val = ETDM_OUT_CON4_CLOCK(source); + } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) { + reg = ETDM_OUT2_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + val = ETDM_OUT_CON4_CLOCK(source); + } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) { + reg = ETDM_OUT3_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + val = ETDM_OUT_CON4_CLOCK(source); + } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) { + reg = ETDM_IN1_CON2; + mask = ETDM_IN_CON2_CLOCK_MASK; + val = ETDM_IN_CON2_CLOCK(source); + } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) { + reg = ETDM_IN2_CON2; + mask = ETDM_IN_CON2_CLOCK_MASK; + val = ETDM_IN_CON2_CLOCK(source); + } + + if (reg) + regmap_update_bits(afe->regmap, reg, mask, val); + + return 0; +} + +static int mt8195_etdm_clk_src_sel_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + unsigned int value = 0; + unsigned int reg = 0; + unsigned int mask = 0; + unsigned int shift = 0; + + if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) { + reg = ETDM_OUT1_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + shift = ETDM_OUT_CON4_CLOCK_SHIFT; + } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) { + reg = ETDM_OUT2_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + shift = ETDM_OUT_CON4_CLOCK_SHIFT; + } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) { + reg = ETDM_OUT3_CON4; + mask = ETDM_OUT_CON4_CLOCK_MASK; + shift = ETDM_OUT_CON4_CLOCK_SHIFT; + } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) { + reg = ETDM_IN1_CON2; + mask = ETDM_IN_CON2_CLOCK_MASK; + shift = ETDM_IN_CON2_CLOCK_SHIFT; + } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) { + reg = ETDM_IN2_CON2; + mask = ETDM_IN_CON2_CLOCK_MASK; + shift = ETDM_IN_CON2_CLOCK_SHIFT; + } + + if (reg) + regmap_read(afe->regmap, reg, &value); + + value &= mask; + value >>= shift; + ucontrol->value.enumerated.item[0] = value; + return 0; +} + +static const struct snd_kcontrol_new mtk_dai_etdm_controls[] = { + SOC_ENUM_EXT("ETDM_OUT1_Clock_Source", + etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_get, + mt8195_etdm_clk_src_sel_put), + SOC_ENUM_EXT("ETDM_OUT2_Clock_Source", + etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_get, + mt8195_etdm_clk_src_sel_put), + SOC_ENUM_EXT("ETDM_OUT3_Clock_Source", + etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_get, + mt8195_etdm_clk_src_sel_put), + SOC_ENUM_EXT("ETDM_IN1_Clock_Source", + etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_get, + mt8195_etdm_clk_src_sel_put), + SOC_ENUM_EXT("ETDM_IN2_Clock_Source", + etdmout_clk_src_enum, + mt8195_etdm_clk_src_sel_get, + mt8195_etdm_clk_src_sel_put), +}; + +static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = { + /* eTDM_IN2 */ + SND_SOC_DAPM_MIXER("I012", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I013", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I014", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I015", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I016", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I017", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I018", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I019", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* eTDM_IN1 */ + SND_SOC_DAPM_MIXER("I072", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I073", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I074", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I075", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I076", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I077", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I078", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I079", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I080", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I081", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I082", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I083", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I084", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I085", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I086", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I087", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I088", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I089", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I090", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I091", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I092", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I093", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I094", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I095", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* eTDM_OUT2 */ + SND_SOC_DAPM_MIXER("O048", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o048_mix, + ARRAY_SIZE(mtk_dai_etdm_o048_mix)), + SND_SOC_DAPM_MIXER("O049", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o049_mix, + ARRAY_SIZE(mtk_dai_etdm_o049_mix)), + SND_SOC_DAPM_MIXER("O050", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o050_mix, + ARRAY_SIZE(mtk_dai_etdm_o050_mix)), + SND_SOC_DAPM_MIXER("O051", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o051_mix, + ARRAY_SIZE(mtk_dai_etdm_o051_mix)), + SND_SOC_DAPM_MIXER("O052", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o052_mix, + ARRAY_SIZE(mtk_dai_etdm_o052_mix)), + SND_SOC_DAPM_MIXER("O053", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o053_mix, + ARRAY_SIZE(mtk_dai_etdm_o053_mix)), + SND_SOC_DAPM_MIXER("O054", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o054_mix, + ARRAY_SIZE(mtk_dai_etdm_o054_mix)), + SND_SOC_DAPM_MIXER("O055", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o055_mix, + ARRAY_SIZE(mtk_dai_etdm_o055_mix)), + SND_SOC_DAPM_MIXER("O056", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o056_mix, + ARRAY_SIZE(mtk_dai_etdm_o056_mix)), + SND_SOC_DAPM_MIXER("O057", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o057_mix, + ARRAY_SIZE(mtk_dai_etdm_o057_mix)), + SND_SOC_DAPM_MIXER("O058", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o058_mix, + ARRAY_SIZE(mtk_dai_etdm_o058_mix)), + SND_SOC_DAPM_MIXER("O059", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o059_mix, + ARRAY_SIZE(mtk_dai_etdm_o059_mix)), + SND_SOC_DAPM_MIXER("O060", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o060_mix, + ARRAY_SIZE(mtk_dai_etdm_o060_mix)), + SND_SOC_DAPM_MIXER("O061", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o061_mix, + ARRAY_SIZE(mtk_dai_etdm_o061_mix)), + SND_SOC_DAPM_MIXER("O062", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o062_mix, + ARRAY_SIZE(mtk_dai_etdm_o062_mix)), + SND_SOC_DAPM_MIXER("O063", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o063_mix, + ARRAY_SIZE(mtk_dai_etdm_o063_mix)), + SND_SOC_DAPM_MIXER("O064", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o064_mix, + ARRAY_SIZE(mtk_dai_etdm_o064_mix)), + SND_SOC_DAPM_MIXER("O065", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o065_mix, + ARRAY_SIZE(mtk_dai_etdm_o065_mix)), + SND_SOC_DAPM_MIXER("O066", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o066_mix, + ARRAY_SIZE(mtk_dai_etdm_o066_mix)), + SND_SOC_DAPM_MIXER("O067", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o067_mix, + ARRAY_SIZE(mtk_dai_etdm_o067_mix)), + SND_SOC_DAPM_MIXER("O068", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o068_mix, + ARRAY_SIZE(mtk_dai_etdm_o068_mix)), + SND_SOC_DAPM_MIXER("O069", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o069_mix, + ARRAY_SIZE(mtk_dai_etdm_o069_mix)), + SND_SOC_DAPM_MIXER("O070", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o070_mix, + ARRAY_SIZE(mtk_dai_etdm_o070_mix)), + SND_SOC_DAPM_MIXER("O071", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o071_mix, + ARRAY_SIZE(mtk_dai_etdm_o071_mix)), + + /* eTDM_OUT1 */ + SND_SOC_DAPM_MIXER("O072", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o072_mix, + ARRAY_SIZE(mtk_dai_etdm_o072_mix)), + SND_SOC_DAPM_MIXER("O073", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o073_mix, + ARRAY_SIZE(mtk_dai_etdm_o073_mix)), + SND_SOC_DAPM_MIXER("O074", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o074_mix, + ARRAY_SIZE(mtk_dai_etdm_o074_mix)), + SND_SOC_DAPM_MIXER("O075", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o075_mix, + ARRAY_SIZE(mtk_dai_etdm_o075_mix)), + SND_SOC_DAPM_MIXER("O076", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o076_mix, + ARRAY_SIZE(mtk_dai_etdm_o076_mix)), + SND_SOC_DAPM_MIXER("O077", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o077_mix, + ARRAY_SIZE(mtk_dai_etdm_o077_mix)), + SND_SOC_DAPM_MIXER("O078", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o078_mix, + ARRAY_SIZE(mtk_dai_etdm_o078_mix)), + SND_SOC_DAPM_MIXER("O079", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o079_mix, + ARRAY_SIZE(mtk_dai_etdm_o079_mix)), + SND_SOC_DAPM_MIXER("O080", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o080_mix, + ARRAY_SIZE(mtk_dai_etdm_o080_mix)), + SND_SOC_DAPM_MIXER("O081", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o081_mix, + ARRAY_SIZE(mtk_dai_etdm_o081_mix)), + SND_SOC_DAPM_MIXER("O082", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o082_mix, + ARRAY_SIZE(mtk_dai_etdm_o082_mix)), + SND_SOC_DAPM_MIXER("O083", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o083_mix, + ARRAY_SIZE(mtk_dai_etdm_o083_mix)), + SND_SOC_DAPM_MIXER("O084", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o084_mix, + ARRAY_SIZE(mtk_dai_etdm_o084_mix)), + SND_SOC_DAPM_MIXER("O085", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o085_mix, + ARRAY_SIZE(mtk_dai_etdm_o085_mix)), + SND_SOC_DAPM_MIXER("O086", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o086_mix, + ARRAY_SIZE(mtk_dai_etdm_o086_mix)), + SND_SOC_DAPM_MIXER("O087", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o087_mix, + ARRAY_SIZE(mtk_dai_etdm_o087_mix)), + SND_SOC_DAPM_MIXER("O088", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o088_mix, + ARRAY_SIZE(mtk_dai_etdm_o088_mix)), + SND_SOC_DAPM_MIXER("O089", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o089_mix, + ARRAY_SIZE(mtk_dai_etdm_o089_mix)), + SND_SOC_DAPM_MIXER("O090", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o090_mix, + ARRAY_SIZE(mtk_dai_etdm_o090_mix)), + SND_SOC_DAPM_MIXER("O091", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o091_mix, + ARRAY_SIZE(mtk_dai_etdm_o091_mix)), + SND_SOC_DAPM_MIXER("O092", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o092_mix, + ARRAY_SIZE(mtk_dai_etdm_o092_mix)), + SND_SOC_DAPM_MIXER("O093", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o093_mix, + ARRAY_SIZE(mtk_dai_etdm_o093_mix)), + SND_SOC_DAPM_MIXER("O094", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o094_mix, + ARRAY_SIZE(mtk_dai_etdm_o094_mix)), + SND_SOC_DAPM_MIXER("O095", SND_SOC_NOPM, 0, 0, + mtk_dai_etdm_o095_mix, + ARRAY_SIZE(mtk_dai_etdm_o095_mix)), + + /* eTDM_OUT3 */ + SND_SOC_DAPM_MUX("HDMI_OUT_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_out_mux_control), + SND_SOC_DAPM_MUX("DPTX_OUT_MUX", SND_SOC_NOPM, 0, 0, + &dptx_out_mux_control), + + SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch0_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch1_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch2_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch3_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch4_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch5_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch6_mux_control), + SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0, + &hdmi_ch7_mux_control), + + SND_SOC_DAPM_INPUT("ETDM_INPUT"), + SND_SOC_DAPM_OUTPUT("ETDM_OUTPUT"), +}; + +static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = { + {"I012", NULL, "ETDM2 Capture"}, + {"I013", NULL, "ETDM2 Capture"}, + {"I014", NULL, "ETDM2 Capture"}, + {"I015", NULL, "ETDM2 Capture"}, + {"I016", NULL, "ETDM2 Capture"}, + {"I017", NULL, "ETDM2 Capture"}, + {"I018", NULL, "ETDM2 Capture"}, + {"I019", NULL, "ETDM2 Capture"}, + + {"I072", NULL, "ETDM1 Capture"}, + {"I073", NULL, "ETDM1 Capture"}, + {"I074", NULL, "ETDM1 Capture"}, + {"I075", NULL, "ETDM1 Capture"}, + {"I076", NULL, "ETDM1 Capture"}, + {"I077", NULL, "ETDM1 Capture"}, + {"I078", NULL, "ETDM1 Capture"}, + {"I079", NULL, "ETDM1 Capture"}, + {"I080", NULL, "ETDM1 Capture"}, + {"I081", NULL, "ETDM1 Capture"}, + {"I082", NULL, "ETDM1 Capture"}, + {"I083", NULL, "ETDM1 Capture"}, + {"I084", NULL, "ETDM1 Capture"}, + {"I085", NULL, "ETDM1 Capture"}, + {"I086", NULL, "ETDM1 Capture"}, + {"I087", NULL, "ETDM1 Capture"}, + {"I088", NULL, "ETDM1 Capture"}, + {"I089", NULL, "ETDM1 Capture"}, + {"I090", NULL, "ETDM1 Capture"}, + {"I091", NULL, "ETDM1 Capture"}, + {"I092", NULL, "ETDM1 Capture"}, + {"I093", NULL, "ETDM1 Capture"}, + {"I094", NULL, "ETDM1 Capture"}, + {"I095", NULL, "ETDM1 Capture"}, + + {"UL8", NULL, "ETDM1 Capture"}, + {"UL3", NULL, "ETDM2 Capture"}, + + {"ETDM2 Playback", NULL, "O048"}, + {"ETDM2 Playback", NULL, "O049"}, + {"ETDM2 Playback", NULL, "O050"}, + {"ETDM2 Playback", NULL, "O051"}, + {"ETDM2 Playback", NULL, "O052"}, + {"ETDM2 Playback", NULL, "O053"}, + {"ETDM2 Playback", NULL, "O054"}, + {"ETDM2 Playback", NULL, "O055"}, + {"ETDM2 Playback", NULL, "O056"}, + {"ETDM2 Playback", NULL, "O057"}, + {"ETDM2 Playback", NULL, "O058"}, + {"ETDM2 Playback", NULL, "O059"}, + {"ETDM2 Playback", NULL, "O060"}, + {"ETDM2 Playback", NULL, "O061"}, + {"ETDM2 Playback", NULL, "O062"}, + {"ETDM2 Playback", NULL, "O063"}, + {"ETDM2 Playback", NULL, "O064"}, + {"ETDM2 Playback", NULL, "O065"}, + {"ETDM2 Playback", NULL, "O066"}, + {"ETDM2 Playback", NULL, "O067"}, + {"ETDM2 Playback", NULL, "O068"}, + {"ETDM2 Playback", NULL, "O069"}, + {"ETDM2 Playback", NULL, "O070"}, + {"ETDM2 Playback", NULL, "O071"}, + + {"ETDM1 Playback", NULL, "O072"}, + {"ETDM1 Playback", NULL, "O073"}, + {"ETDM1 Playback", NULL, "O074"}, + {"ETDM1 Playback", NULL, "O075"}, + {"ETDM1 Playback", NULL, "O076"}, + {"ETDM1 Playback", NULL, "O077"}, + {"ETDM1 Playback", NULL, "O078"}, + {"ETDM1 Playback", NULL, "O079"}, + {"ETDM1 Playback", NULL, "O080"}, + {"ETDM1 Playback", NULL, "O081"}, + {"ETDM1 Playback", NULL, "O082"}, + {"ETDM1 Playback", NULL, "O083"}, + {"ETDM1 Playback", NULL, "O084"}, + {"ETDM1 Playback", NULL, "O085"}, + {"ETDM1 Playback", NULL, "O086"}, + {"ETDM1 Playback", NULL, "O087"}, + {"ETDM1 Playback", NULL, "O088"}, + {"ETDM1 Playback", NULL, "O089"}, + {"ETDM1 Playback", NULL, "O090"}, + {"ETDM1 Playback", NULL, "O091"}, + {"ETDM1 Playback", NULL, "O092"}, + {"ETDM1 Playback", NULL, "O093"}, + {"ETDM1 Playback", NULL, "O094"}, + {"ETDM1 Playback", NULL, "O095"}, + + {"O048", "I020 Switch", "I020"}, + {"O049", "I021 Switch", "I021"}, + + {"O048", "I022 Switch", "I022"}, + {"O049", "I023 Switch", "I023"}, + {"O050", "I024 Switch", "I024"}, + {"O051", "I025 Switch", "I025"}, + {"O052", "I026 Switch", "I026"}, + {"O053", "I027 Switch", "I027"}, + {"O054", "I028 Switch", "I028"}, + {"O055", "I029 Switch", "I029"}, + {"O056", "I030 Switch", "I030"}, + {"O057", "I031 Switch", "I031"}, + {"O058", "I032 Switch", "I032"}, + {"O059", "I033 Switch", "I033"}, + {"O060", "I034 Switch", "I034"}, + {"O061", "I035 Switch", "I035"}, + {"O062", "I036 Switch", "I036"}, + {"O063", "I037 Switch", "I037"}, + {"O064", "I038 Switch", "I038"}, + {"O065", "I039 Switch", "I039"}, + {"O066", "I040 Switch", "I040"}, + {"O067", "I041 Switch", "I041"}, + {"O068", "I042 Switch", "I042"}, + {"O069", "I043 Switch", "I043"}, + {"O070", "I044 Switch", "I044"}, + {"O071", "I045 Switch", "I045"}, + + {"O048", "I046 Switch", "I046"}, + {"O049", "I047 Switch", "I047"}, + {"O050", "I048 Switch", "I048"}, + {"O051", "I049 Switch", "I049"}, + {"O052", "I050 Switch", "I050"}, + {"O053", "I051 Switch", "I051"}, + {"O054", "I052 Switch", "I052"}, + {"O055", "I053 Switch", "I053"}, + {"O056", "I054 Switch", "I054"}, + {"O057", "I055 Switch", "I055"}, + {"O058", "I056 Switch", "I056"}, + {"O059", "I057 Switch", "I057"}, + {"O060", "I058 Switch", "I058"}, + {"O061", "I059 Switch", "I059"}, + {"O062", "I060 Switch", "I060"}, + {"O063", "I061 Switch", "I061"}, + {"O064", "I062 Switch", "I062"}, + {"O065", "I063 Switch", "I063"}, + {"O066", "I064 Switch", "I064"}, + {"O067", "I065 Switch", "I065"}, + {"O068", "I066 Switch", "I066"}, + {"O069", "I067 Switch", "I067"}, + {"O070", "I068 Switch", "I068"}, + {"O071", "I069 Switch", "I069"}, + + {"O048", "I070 Switch", "I070"}, + {"O049", "I071 Switch", "I071"}, + + {"O072", "I020 Switch", "I020"}, + {"O073", "I021 Switch", "I021"}, + + {"O072", "I022 Switch", "I022"}, + {"O073", "I023 Switch", "I023"}, + {"O074", "I024 Switch", "I024"}, + {"O075", "I025 Switch", "I025"}, + {"O076", "I026 Switch", "I026"}, + {"O077", "I027 Switch", "I027"}, + {"O078", "I028 Switch", "I028"}, + {"O079", "I029 Switch", "I029"}, + {"O080", "I030 Switch", "I030"}, + {"O081", "I031 Switch", "I031"}, + {"O082", "I032 Switch", "I032"}, + {"O083", "I033 Switch", "I033"}, + {"O084", "I034 Switch", "I034"}, + {"O085", "I035 Switch", "I035"}, + {"O086", "I036 Switch", "I036"}, + {"O087", "I037 Switch", "I037"}, + {"O088", "I038 Switch", "I038"}, + {"O089", "I039 Switch", "I039"}, + {"O090", "I040 Switch", "I040"}, + {"O091", "I041 Switch", "I041"}, + {"O092", "I042 Switch", "I042"}, + {"O093", "I043 Switch", "I043"}, + {"O094", "I044 Switch", "I044"}, + {"O095", "I045 Switch", "I045"}, + + {"O072", "I046 Switch", "I046"}, + {"O073", "I047 Switch", "I047"}, + {"O074", "I048 Switch", "I048"}, + {"O075", "I049 Switch", "I049"}, + {"O076", "I050 Switch", "I050"}, + {"O077", "I051 Switch", "I051"}, + {"O078", "I052 Switch", "I052"}, + {"O079", "I053 Switch", "I053"}, + {"O080", "I054 Switch", "I054"}, + {"O081", "I055 Switch", "I055"}, + {"O082", "I056 Switch", "I056"}, + {"O083", "I057 Switch", "I057"}, + {"O084", "I058 Switch", "I058"}, + {"O085", "I059 Switch", "I059"}, + {"O086", "I060 Switch", "I060"}, + {"O087", "I061 Switch", "I061"}, + {"O088", "I062 Switch", "I062"}, + {"O089", "I063 Switch", "I063"}, + {"O090", "I064 Switch", "I064"}, + {"O091", "I065 Switch", "I065"}, + {"O092", "I066 Switch", "I066"}, + {"O093", "I067 Switch", "I067"}, + {"O094", "I068 Switch", "I068"}, + {"O095", "I069 Switch", "I069"}, + + {"O072", "I070 Switch", "I070"}, + {"O073", "I071 Switch", "I071"}, + + {"HDMI_CH0_MUX", "CH0", "DL10"}, + {"HDMI_CH0_MUX", "CH1", "DL10"}, + {"HDMI_CH0_MUX", "CH2", "DL10"}, + {"HDMI_CH0_MUX", "CH3", "DL10"}, + {"HDMI_CH0_MUX", "CH4", "DL10"}, + {"HDMI_CH0_MUX", "CH5", "DL10"}, + {"HDMI_CH0_MUX", "CH6", "DL10"}, + {"HDMI_CH0_MUX", "CH7", "DL10"}, + + {"HDMI_CH1_MUX", "CH0", "DL10"}, + {"HDMI_CH1_MUX", "CH1", "DL10"}, + {"HDMI_CH1_MUX", "CH2", "DL10"}, + {"HDMI_CH1_MUX", "CH3", "DL10"}, + {"HDMI_CH1_MUX", "CH4", "DL10"}, + {"HDMI_CH1_MUX", "CH5", "DL10"}, + {"HDMI_CH1_MUX", "CH6", "DL10"}, + {"HDMI_CH1_MUX", "CH7", "DL10"}, + + {"HDMI_CH2_MUX", "CH0", "DL10"}, + {"HDMI_CH2_MUX", "CH1", "DL10"}, + {"HDMI_CH2_MUX", "CH2", "DL10"}, + {"HDMI_CH2_MUX", "CH3", "DL10"}, + {"HDMI_CH2_MUX", "CH4", "DL10"}, + {"HDMI_CH2_MUX", "CH5", "DL10"}, + {"HDMI_CH2_MUX", "CH6", "DL10"}, + {"HDMI_CH2_MUX", "CH7", "DL10"}, + + {"HDMI_CH3_MUX", "CH0", "DL10"}, + {"HDMI_CH3_MUX", "CH1", "DL10"}, + {"HDMI_CH3_MUX", "CH2", "DL10"}, + {"HDMI_CH3_MUX", "CH3", "DL10"}, + {"HDMI_CH3_MUX", "CH4", "DL10"}, + {"HDMI_CH3_MUX", "CH5", "DL10"}, + {"HDMI_CH3_MUX", "CH6", "DL10"}, + {"HDMI_CH3_MUX", "CH7", "DL10"}, + + {"HDMI_CH4_MUX", "CH0", "DL10"}, + {"HDMI_CH4_MUX", "CH1", "DL10"}, + {"HDMI_CH4_MUX", "CH2", "DL10"}, + {"HDMI_CH4_MUX", "CH3", "DL10"}, + {"HDMI_CH4_MUX", "CH4", "DL10"}, + {"HDMI_CH4_MUX", "CH5", "DL10"}, + {"HDMI_CH4_MUX", "CH6", "DL10"}, + {"HDMI_CH4_MUX", "CH7", "DL10"}, + + {"HDMI_CH5_MUX", "CH0", "DL10"}, + {"HDMI_CH5_MUX", "CH1", "DL10"}, + {"HDMI_CH5_MUX", "CH2", "DL10"}, + {"HDMI_CH5_MUX", "CH3", "DL10"}, + {"HDMI_CH5_MUX", "CH4", "DL10"}, + {"HDMI_CH5_MUX", "CH5", "DL10"}, + {"HDMI_CH5_MUX", "CH6", "DL10"}, + {"HDMI_CH5_MUX", "CH7", "DL10"}, + + {"HDMI_CH6_MUX", "CH0", "DL10"}, + {"HDMI_CH6_MUX", "CH1", "DL10"}, + {"HDMI_CH6_MUX", "CH2", "DL10"}, + {"HDMI_CH6_MUX", "CH3", "DL10"}, + {"HDMI_CH6_MUX", "CH4", "DL10"}, + {"HDMI_CH6_MUX", "CH5", "DL10"}, + {"HDMI_CH6_MUX", "CH6", "DL10"}, + {"HDMI_CH6_MUX", "CH7", "DL10"}, + + {"HDMI_CH7_MUX", "CH0", "DL10"}, + {"HDMI_CH7_MUX", "CH1", "DL10"}, + {"HDMI_CH7_MUX", "CH2", "DL10"}, + {"HDMI_CH7_MUX", "CH3", "DL10"}, + {"HDMI_CH7_MUX", "CH4", "DL10"}, + {"HDMI_CH7_MUX", "CH5", "DL10"}, + {"HDMI_CH7_MUX", "CH6", "DL10"}, + {"HDMI_CH7_MUX", "CH7", "DL10"}, + + {"HDMI_OUT_MUX", "Connect", "HDMI_CH0_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH1_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH2_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH3_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH4_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH5_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH6_MUX"}, + {"HDMI_OUT_MUX", "Connect", "HDMI_CH7_MUX"}, + + {"DPTX_OUT_MUX", "Connect", "HDMI_CH0_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH1_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH2_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH3_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH4_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH5_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH6_MUX"}, + {"DPTX_OUT_MUX", "Connect", "HDMI_CH7_MUX"}, + + {"ETDM3 Playback", NULL, "HDMI_OUT_MUX"}, + {"DPTX Playback", NULL, "DPTX_OUT_MUX"}, + + {"ETDM_OUTPUT", NULL, "DPTX Playback"}, + {"ETDM_OUTPUT", NULL, "ETDM1 Playback"}, + {"ETDM_OUTPUT", NULL, "ETDM2 Playback"}, + {"ETDM_OUTPUT", NULL, "ETDM3 Playback"}, + {"ETDM1 Capture", NULL, "ETDM_INPUT"}, + {"ETDM2 Capture", NULL, "ETDM_INPUT"}, +}; + +static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id) +{ + int ret = 0; + struct etdm_con_reg etdm_reg; + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + etdm_data->en_ref_cnt++; + if (etdm_data->en_ref_cnt == 1) { + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + goto out; + + regmap_update_bits(afe->regmap, etdm_reg.con0, + ETDM_CON0_EN, ETDM_CON0_EN); + } +out: + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + return ret; +} + +static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id) +{ + int ret = 0; + struct etdm_con_reg etdm_reg; + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + if (etdm_data->en_ref_cnt > 0) { + etdm_data->en_ref_cnt--; + if (etdm_data->en_ref_cnt == 0) { + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + goto out; + + regmap_update_bits(afe->regmap, etdm_reg.con0, + ETDM_CON0_EN, 0); + } + } +out: + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + return 0; +} + +static int etdm_cowork_slv_sel(int id, int slave_mode) +{ + if (slave_mode) { + switch (id) { + case MT8195_AFE_IO_ETDM1_IN: + return COWORK_ETDM_IN1_S; + case MT8195_AFE_IO_ETDM2_IN: + return COWORK_ETDM_IN2_S; + case MT8195_AFE_IO_ETDM1_OUT: + return COWORK_ETDM_OUT1_S; + case MT8195_AFE_IO_ETDM2_OUT: + return COWORK_ETDM_OUT2_S; + case MT8195_AFE_IO_ETDM3_OUT: + return COWORK_ETDM_OUT3_S; + default: + return -EINVAL; + } + } else { + switch (id) { + case MT8195_AFE_IO_ETDM1_IN: + return COWORK_ETDM_IN1_M; + case MT8195_AFE_IO_ETDM2_IN: + return COWORK_ETDM_IN2_M; + case MT8195_AFE_IO_ETDM1_OUT: + return COWORK_ETDM_OUT1_M; + case MT8195_AFE_IO_ETDM2_OUT: + return COWORK_ETDM_OUT2_M; + case MT8195_AFE_IO_ETDM3_OUT: + return COWORK_ETDM_OUT3_M; + default: + return -EINVAL; + } + } +} + +static int mt8195_etdm_sync_mode_configure(struct mtk_base_afe *afe, int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + unsigned int reg = 0; + unsigned int mask; + unsigned int val; + int cowork_source_sel; + + if (etdm_data->cowork_source_id == COWORK_ETDM_NONE) + return 0; + + cowork_source_sel = etdm_cowork_slv_sel(etdm_data->cowork_source_id, + etdm_data->slave_mode); + if (cowork_source_sel < 0) + return cowork_source_sel; + + switch (dai_id) { + case MT8195_AFE_IO_ETDM1_IN: + reg = ETDM_COWORK_CON1; + mask = ETDM_IN1_SLAVE_SEL_MASK; + val = ETDM_IN1_SLAVE_SEL(cowork_source_sel); + break; + case MT8195_AFE_IO_ETDM2_IN: + reg = ETDM_COWORK_CON2; + mask = ETDM_IN2_SLAVE_SEL_MASK; + val = ETDM_IN2_SLAVE_SEL(cowork_source_sel); + break; + case MT8195_AFE_IO_ETDM1_OUT: + reg = ETDM_COWORK_CON0; + mask = ETDM_OUT1_SLAVE_SEL_MASK; + val = ETDM_OUT1_SLAVE_SEL(cowork_source_sel); + break; + case MT8195_AFE_IO_ETDM2_OUT: + reg = ETDM_COWORK_CON2; + mask = ETDM_OUT2_SLAVE_SEL_MASK; + val = ETDM_OUT2_SLAVE_SEL(cowork_source_sel); + break; + case MT8195_AFE_IO_ETDM3_OUT: + reg = ETDM_COWORK_CON2; + mask = ETDM_OUT3_SLAVE_SEL_MASK; + val = ETDM_OUT3_SLAVE_SEL(cowork_source_sel); + break; + default: + return 0; + } + + regmap_update_bits(afe->regmap, reg, mask, val); + + return 0; +} + +static int mtk_dai_etdm_get_cg_id_by_dai_id(int dai_id) +{ + int cg_id = -1; + + switch (dai_id) { + case MT8195_AFE_IO_DPTX: + cg_id = MT8195_CLK_AUD_HDMI_OUT; + break; + case MT8195_AFE_IO_ETDM1_IN: + cg_id = MT8195_CLK_AUD_TDM_IN; + break; + case MT8195_AFE_IO_ETDM2_IN: + cg_id = MT8195_CLK_AUD_I2SIN; + break; + case MT8195_AFE_IO_ETDM1_OUT: + cg_id = MT8195_CLK_AUD_TDM_OUT; + break; + case MT8195_AFE_IO_ETDM2_OUT: + cg_id = MT8195_CLK_AUD_I2S_OUT; + break; + case MT8195_AFE_IO_ETDM3_OUT: + cg_id = MT8195_CLK_AUD_HDMI_OUT; + break; + default: + break; + } + + return cg_id; +} + +static int mtk_dai_etdm_get_clk_id_by_dai_id(int dai_id) +{ + int clk_id = -1; + + switch (dai_id) { + case MT8195_AFE_IO_DPTX: + clk_id = MT8195_CLK_TOP_DPTX_M_SEL; + break; + case MT8195_AFE_IO_ETDM1_IN: + clk_id = MT8195_CLK_TOP_I2SI1_M_SEL; + break; + case MT8195_AFE_IO_ETDM2_IN: + clk_id = MT8195_CLK_TOP_I2SI2_M_SEL; + break; + case MT8195_AFE_IO_ETDM1_OUT: + clk_id = MT8195_CLK_TOP_I2SO1_M_SEL; + break; + case MT8195_AFE_IO_ETDM2_OUT: + clk_id = MT8195_CLK_TOP_I2SO2_M_SEL; + break; + case MT8195_AFE_IO_ETDM3_OUT: + default: + break; + } + + return clk_id; +} + +static int mtk_dai_etdm_get_clkdiv_id_by_dai_id(int dai_id) +{ + int clk_id = -1; + + switch (dai_id) { + case MT8195_AFE_IO_DPTX: + clk_id = MT8195_CLK_TOP_APLL12_DIV9; + break; + case MT8195_AFE_IO_ETDM1_IN: + clk_id = MT8195_CLK_TOP_APLL12_DIV0; + break; + case MT8195_AFE_IO_ETDM2_IN: + clk_id = MT8195_CLK_TOP_APLL12_DIV1; + break; + case MT8195_AFE_IO_ETDM1_OUT: + clk_id = MT8195_CLK_TOP_APLL12_DIV2; + break; + case MT8195_AFE_IO_ETDM2_OUT: + clk_id = MT8195_CLK_TOP_APLL12_DIV3; + break; + case MT8195_AFE_IO_ETDM3_OUT: + default: + break; + } + + return clk_id; +} + +static int mtk_dai_etdm_enable_mclk(struct mtk_base_afe *afe, int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id); + + if (clkdiv_id < 0) + return -EINVAL; + + mt8195_afe_enable_clk(afe, afe_priv->clk[clkdiv_id]); + + return 0; +} + +static int mtk_dai_etdm_disable_mclk(struct mtk_base_afe *afe, int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id); + + if (clkdiv_id < 0) + return -EINVAL; + + mt8195_afe_disable_clk(afe, afe_priv->clk[clkdiv_id]); + + return 0; +} + +/* dai ops */ +static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *mst_etdm_data; + int cg_id; + int mst_dai_id; + int slv_dai_id; + int i; + + if (is_cowork_mode(dai)) { + mst_dai_id = get_etdm_cowork_master_id(dai); + mtk_dai_etdm_enable_mclk(afe, mst_dai_id); + + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); + if (cg_id >= 0) + mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]); + + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; + + for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { + slv_dai_id = mst_etdm_data->cowork_slv_id[i]; + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id); + if (cg_id >= 0) + mt8195_afe_enable_clk(afe, + afe_priv->clk[cg_id]); + } + } else { + mtk_dai_etdm_enable_mclk(afe, dai->id); + + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id); + if (cg_id >= 0) + mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]); + } + + return 0; +} + +static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *mst_etdm_data; + int cg_id; + int mst_dai_id; + int slv_dai_id; + int i; + + if (is_cowork_mode(dai)) { + mst_dai_id = get_etdm_cowork_master_id(dai); + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(mst_dai_id); + if (cg_id >= 0) + mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]); + + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; + for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { + slv_dai_id = mst_etdm_data->cowork_slv_id[i]; + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(slv_dai_id); + if (cg_id >= 0) + mt8195_afe_disable_clk(afe, + afe_priv->clk[cg_id]); + } + mtk_dai_etdm_disable_mclk(afe, mst_dai_id); + } else { + cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id); + if (cg_id >= 0) + mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]); + + mtk_dai_etdm_disable_mclk(afe, dai->id); + } +} + +static int mtk_dai_etdm_fifo_mode(struct mtk_base_afe *afe, + int dai_id, unsigned int rate) +{ + unsigned int mode = 0; + unsigned int reg = 0; + unsigned int val = 0; + unsigned int mask = (ETDM_IN_AFIFO_MODE_MASK | ETDM_IN_USE_AFIFO); + + if (rate != 0) + mode = mt8195_afe_fs_timing(rate); + + switch (dai_id) { + case MT8195_AFE_IO_ETDM1_IN: + reg = ETDM_IN1_AFIFO_CON; + if (rate == 0) + mode = MT8195_ETDM_IN1_1X_EN; + break; + case MT8195_AFE_IO_ETDM2_IN: + reg = ETDM_IN2_AFIFO_CON; + if (rate == 0) + mode = MT8195_ETDM_IN2_1X_EN; + break; + default: + return -EINVAL; + } + + val = (mode | ETDM_IN_USE_AFIFO); + + regmap_update_bits(afe->regmap, reg, mask, val); + return 0; +} + +static int mtk_dai_etdm_in_configure(struct mtk_base_afe *afe, + unsigned int rate, + unsigned int channels, + int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct etdm_con_reg etdm_reg; + bool slave_mode = etdm_data->slave_mode; + unsigned int data_mode = etdm_data->data_mode; + unsigned int lrck_width = etdm_data->lrck_width; + unsigned int val = 0; + unsigned int mask = 0; + int i; + int ret; + + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", + __func__, rate, channels, dai_id); + + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + return ret; + + if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) + slave_mode = true; + + /* afifo */ + if (slave_mode) + mtk_dai_etdm_fifo_mode(afe, dai_id, 0); + else + mtk_dai_etdm_fifo_mode(afe, dai_id, rate); + + /* con1 */ + if (lrck_width > 0) { + mask |= (ETDM_IN_CON1_LRCK_AUTO_MODE | + ETDM_IN_CON1_LRCK_WIDTH_MASK); + val |= ETDM_IN_CON1_LRCK_WIDTH(lrck_width); + } + regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val); + + mask = 0; + val = 0; + + /* con2 */ + if (!slave_mode) { + mask |= ETDM_IN_CON2_UPDATE_GAP_MASK; + if (rate == 352800 || rate == 384000) + val |= ETDM_IN_CON2_UPDATE_GAP(4); + else + val |= ETDM_IN_CON2_UPDATE_GAP(3); + } + mask |= (ETDM_IN_CON2_MULTI_IP_2CH_MODE | + ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK); + if (data_mode == MTK_DAI_ETDM_DATA_MULTI_PIN) { + val |= ETDM_IN_CON2_MULTI_IP_2CH_MODE | + ETDM_IN_CON2_MULTI_IP_TOTAL_CH(channels); + } + regmap_update_bits(afe->regmap, etdm_reg.con2, mask, val); + + mask = 0; + val = 0; + + /* con3 */ + mask |= ETDM_IN_CON3_DISABLE_OUT_MASK; + for (i = 0; i < channels; i += 2) { + if (etdm_data->in_disable_ch[i] && + etdm_data->in_disable_ch[i + 1]) + val |= ETDM_IN_CON3_DISABLE_OUT(i >> 1); + } + if (!slave_mode) { + mask |= ETDM_IN_CON3_FS_MASK; + val |= ETDM_IN_CON3_FS(get_etdm_fs_timing(rate)); + } + regmap_update_bits(afe->regmap, etdm_reg.con3, mask, val); + + mask = 0; + val = 0; + + /* con4 */ + mask |= (ETDM_IN_CON4_MASTER_LRCK_INV | ETDM_IN_CON4_MASTER_BCK_INV | + ETDM_IN_CON4_SLAVE_LRCK_INV | ETDM_IN_CON4_SLAVE_BCK_INV); + if (slave_mode) { + if (etdm_data->lrck_inv) + val |= ETDM_IN_CON4_SLAVE_LRCK_INV; + if (etdm_data->bck_inv) + val |= ETDM_IN_CON4_SLAVE_BCK_INV; + } else { + if (etdm_data->lrck_inv) + val |= ETDM_IN_CON4_MASTER_LRCK_INV; + if (etdm_data->bck_inv) + val |= ETDM_IN_CON4_MASTER_BCK_INV; + } + regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val); + + mask = 0; + val = 0; + + /* con5 */ + mask |= ETDM_IN_CON5_LR_SWAP_MASK; + mask |= ETDM_IN_CON5_ENABLE_ODD_MASK; + for (i = 0; i < channels; i += 2) { + if (etdm_data->in_disable_ch[i] && + !etdm_data->in_disable_ch[i + 1]) { + if (i == (channels - 2)) + val |= ETDM_IN_CON5_LR_SWAP(15); + else + val |= ETDM_IN_CON5_LR_SWAP(i >> 1); + val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1); + } else if (!etdm_data->in_disable_ch[i] && + etdm_data->in_disable_ch[i + 1]) { + val |= ETDM_IN_CON5_ENABLE_ODD(i >> 1); + } + } + regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val); + return 0; +} + +static int mtk_dai_etdm_out_configure(struct mtk_base_afe *afe, + unsigned int rate, + unsigned int channels, + int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct etdm_con_reg etdm_reg; + bool slave_mode = etdm_data->slave_mode; + unsigned int lrck_width = etdm_data->lrck_width; + unsigned int val = 0; + unsigned int mask = 0; + int ret; + int fs = 0; + + dev_dbg(afe->dev, "%s rate %u channels %u, id %d\n", + __func__, rate, channels, dai_id); + + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + return ret; + + if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) + slave_mode = true; + + /* con0 */ + mask = ETDM_OUT_CON0_RELATCH_DOMAIN_MASK; + val = ETDM_OUT_CON0_RELATCH_DOMAIN(ETDM_RELATCH_TIMING_A1A2SYS); + regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val); + + mask = 0; + val = 0; + + /* con1 */ + if (lrck_width > 0) { + mask |= (ETDM_OUT_CON1_LRCK_AUTO_MODE | + ETDM_OUT_CON1_LRCK_WIDTH_MASK); + val |= ETDM_OUT_CON1_LRCK_WIDTH(lrck_width); + } + regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val); + + mask = 0; + val = 0; + + if (slave_mode) { + /* con2 */ + mask = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV | + ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN); + val = (ETDM_OUT_CON2_LRCK_DELAY_BCK_INV | + ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN); + regmap_update_bits(afe->regmap, etdm_reg.con2, + mask, val); + mask = 0; + val = 0; + } else { + /* con4 */ + mask |= ETDM_OUT_CON4_FS_MASK; + val |= ETDM_OUT_CON4_FS(get_etdm_fs_timing(rate)); + } + + mask |= ETDM_OUT_CON4_RELATCH_EN_MASK; + if (dai_id == MT8195_AFE_IO_ETDM1_OUT) + fs = MT8195_ETDM_OUT1_1X_EN; + else if (dai_id == MT8195_AFE_IO_ETDM2_OUT) + fs = MT8195_ETDM_OUT2_1X_EN; + + val |= ETDM_OUT_CON4_RELATCH_EN(fs); + + regmap_update_bits(afe->regmap, etdm_reg.con4, mask, val); + + mask = 0; + val = 0; + + /* con5 */ + mask |= (ETDM_OUT_CON5_MASTER_LRCK_INV | ETDM_OUT_CON5_MASTER_BCK_INV | + ETDM_OUT_CON5_SLAVE_LRCK_INV | ETDM_OUT_CON5_SLAVE_BCK_INV); + if (slave_mode) { + if (etdm_data->lrck_inv) + val |= ETDM_OUT_CON5_SLAVE_LRCK_INV; + if (etdm_data->bck_inv) + val |= ETDM_OUT_CON5_SLAVE_BCK_INV; + } else { + if (etdm_data->lrck_inv) + val |= ETDM_OUT_CON5_MASTER_LRCK_INV; + if (etdm_data->bck_inv) + val |= ETDM_OUT_CON5_MASTER_BCK_INV; + } + regmap_update_bits(afe->regmap, etdm_reg.con5, mask, val); + + return 0; +} + +static int mtk_dai_etdm_mclk_configure(struct mtk_base_afe *afe, int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + int clk_id = mtk_dai_etdm_get_clk_id_by_dai_id(dai_id); + int clkdiv_id = mtk_dai_etdm_get_clkdiv_id_by_dai_id(dai_id); + int apll; + int apll_clk_id; + struct etdm_con_reg etdm_reg; + unsigned int val = 0; + unsigned int mask = 0; + int ret = 0; + + if (clk_id < 0 || clkdiv_id < 0) + return 0; + + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + return ret; + + mask |= ETDM_CON1_MCLK_OUTPUT; + if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT) + val |= ETDM_CON1_MCLK_OUTPUT; + regmap_update_bits(afe->regmap, etdm_reg.con1, mask, val); + + if (etdm_data->mclk_freq) { + apll = etdm_data->mclk_apll; + apll_clk_id = mt8195_afe_get_mclk_source_clk_id(apll); + if (apll_clk_id < 0) + return apll_clk_id; + + /* select apll */ + ret = mt8195_afe_set_clk_parent(afe, afe_priv->clk[clk_id], + afe_priv->clk[apll_clk_id]); + if (ret) + return ret; + + /* set rate */ + ret = mt8195_afe_set_clk_rate(afe, afe_priv->clk[clkdiv_id], + etdm_data->mclk_freq); + } else { + if (etdm_data->mclk_dir == SND_SOC_CLOCK_OUT) + dev_dbg(afe->dev, "%s mclk freq = 0\n", __func__); + } + return ret; +} + +static int mtk_dai_etdm_configure(struct mtk_base_afe *afe, + unsigned int rate, + unsigned int channels, + unsigned int bit_width, + int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + struct etdm_con_reg etdm_reg; + bool slave_mode = etdm_data->slave_mode; + unsigned int etdm_channels; + unsigned int val = 0; + unsigned int mask = 0; + unsigned int bck; + unsigned int wlen = get_etdm_wlen(bit_width); + int ret; + + ret = get_etdm_reg(dai_id, &etdm_reg); + if (ret < 0) + return ret; + + if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) + slave_mode = true; + + dev_dbg(afe->dev, "%s fmt %u data %u lrck %d-%u bck %d, clock %u slv %u\n", + __func__, etdm_data->format, etdm_data->data_mode, + etdm_data->lrck_inv, etdm_data->lrck_width, etdm_data->bck_inv, + etdm_data->clock_mode, etdm_data->slave_mode); + dev_dbg(afe->dev, "%s rate %u channels %u bitwiedh %u, id %d\n", + __func__, rate, channels, bit_width, dai_id); + + etdm_channels = (etdm_data->data_mode == MTK_DAI_ETDM_DATA_ONE_PIN) ? + get_etdm_ch_fixup(channels) : 2; + + bck = rate * etdm_channels * wlen; + if (bck > MT8195_ETDM_NORMAL_MAX_BCK_RATE) { + dev_info(afe->dev, "%s bck rate %u not support\n", + __func__, bck); + return -EINVAL; + } + + /* con0 */ + mask |= ETDM_CON0_BIT_LEN_MASK; + val |= ETDM_CON0_BIT_LEN(bit_width); + mask |= ETDM_CON0_WORD_LEN_MASK; + val |= ETDM_CON0_WORD_LEN(wlen); + mask |= ETDM_CON0_FORMAT_MASK; + val |= ETDM_CON0_FORMAT(etdm_data->format); + mask |= ETDM_CON0_CH_NUM_MASK; + val |= ETDM_CON0_CH_NUM(etdm_channels); + + mask |= ETDM_CON0_SLAVE_MODE; + if (slave_mode) { + if (dai_id == MT8195_AFE_IO_ETDM1_OUT && + etdm_data->cowork_source_id == COWORK_ETDM_NONE) { + dev_info(afe->dev, "%s id %d only support master mode\n", + __func__, dai_id); + return -EINVAL; + } + val |= ETDM_CON0_SLAVE_MODE; + } + regmap_update_bits(afe->regmap, etdm_reg.con0, mask, val); + + if (get_etdm_dir(dai_id) == ETDM_IN) + mtk_dai_etdm_in_configure(afe, rate, channels, dai_id); + else + mtk_dai_etdm_out_configure(afe, rate, channels, dai_id); + + return 0; +} + +static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int ret = 0; + unsigned int rate = params_rate(params); + unsigned int bit_width = params_width(params); + unsigned int channels = params_channels(params); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *mst_etdm_data; + int mst_dai_id; + int slv_dai_id; + int i; + + dev_dbg(afe->dev, "%s '%s' period %u-%u\n", + __func__, snd_pcm_stream_str(substream), + params_period_size(params), params_periods(params)); + + if (is_cowork_mode(dai)) { + mst_dai_id = get_etdm_cowork_master_id(dai); + + ret = mtk_dai_etdm_mclk_configure(afe, mst_dai_id); + if (ret) + return ret; + + ret = mtk_dai_etdm_configure(afe, rate, channels, + bit_width, mst_dai_id); + if (ret) + return ret; + + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; + for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { + slv_dai_id = mst_etdm_data->cowork_slv_id[i]; + ret = mtk_dai_etdm_configure(afe, rate, channels, + bit_width, slv_dai_id); + if (ret) + return ret; + + ret = mt8195_etdm_sync_mode_configure(afe, slv_dai_id); + if (ret) + return ret; + } + } else { + ret = mtk_dai_etdm_mclk_configure(afe, dai->id); + if (ret) + return ret; + + ret = mtk_dai_etdm_configure(afe, rate, channels, + bit_width, dai->id); + } + + return ret; +} + +static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int ret = 0; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *mst_etdm_data; + int mst_dai_id; + int slv_dai_id; + int i; + + dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + if (is_cowork_mode(dai)) { + mst_dai_id = get_etdm_cowork_master_id(dai); + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; + + //open master first + ret |= mt8195_afe_enable_etdm(afe, mst_dai_id); + for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { + slv_dai_id = mst_etdm_data->cowork_slv_id[i]; + ret |= mt8195_afe_enable_etdm(afe, slv_dai_id); + } + } else { + ret = mt8195_afe_enable_etdm(afe, dai->id); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + if (is_cowork_mode(dai)) { + mst_dai_id = get_etdm_cowork_master_id(dai); + mst_etdm_data = afe_priv->dai_priv[mst_dai_id]; + + for (i = 0; i < mst_etdm_data->cowork_slv_count; i++) { + slv_dai_id = mst_etdm_data->cowork_slv_id[i]; + ret |= mt8195_afe_disable_etdm(afe, slv_dai_id); + } + // close master at last + ret |= mt8195_afe_disable_etdm(afe, mst_dai_id); + } else { + ret = mt8195_afe_disable_etdm(afe, dai->id); + } + break; + default: + break; + } + return ret; +} + +static int mtk_dai_etdm_cal_mclk(struct mtk_base_afe *afe, int freq, int dai_id) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai_id]; + int apll; + int apll_rate; + + if (freq == 0) { + etdm_data->mclk_freq = freq; + return 0; + } + + apll = mt8195_afe_get_default_mclk_source_by_rate(freq); + apll_rate = mt8195_afe_get_mclk_source_rate(afe, apll); + + if (freq > apll_rate) { + dev_info(afe->dev, "freq %d > apll rate %d\n", freq, apll_rate); + return -EINVAL; + } + + if (apll_rate % freq != 0) { + dev_info(afe->dev, "APLL%d cannot generate freq Hz\n", apll); + return -EINVAL; + } + + etdm_data->mclk_apll = apll; + etdm_data->mclk_freq = freq; + + return 0; +} + +static int mtk_dai_etdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + int dai_id; + + dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n", + __func__, dai->id, freq, dir); + if (is_cowork_mode(dai)) + dai_id = get_etdm_cowork_master_id(dai); + else + dai_id = dai->id; + + etdm_data = afe_priv->dai_priv[dai_id]; + etdm_data->mclk_dir = dir; + return mtk_dai_etdm_cal_mclk(afe, freq, dai_id); +} + +static int mtk_dai_etdm_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, + int slots, int slot_width) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s id %d slot_width %d\n", + __func__, dai->id, slot_width); + + etdm_data->slots = slots; + etdm_data->lrck_width = slot_width; + return 0; +} + +static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + etdm_data->format = MTK_DAI_ETDM_FORMAT_LJ; + break; + case SND_SOC_DAIFMT_RIGHT_J: + etdm_data->format = MTK_DAI_ETDM_FORMAT_RJ; + break; + case SND_SOC_DAIFMT_DSP_A: + etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA; + break; + case SND_SOC_DAIFMT_DSP_B: + etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + etdm_data->bck_inv = false; + etdm_data->lrck_inv = false; + break; + case SND_SOC_DAIFMT_NB_IF: + etdm_data->bck_inv = false; + etdm_data->lrck_inv = true; + break; + case SND_SOC_DAIFMT_IB_NF: + etdm_data->bck_inv = true; + etdm_data->lrck_inv = false; + break; + case SND_SOC_DAIFMT_IB_IF: + etdm_data->bck_inv = true; + etdm_data->lrck_inv = true; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + etdm_data->slave_mode = true; + break; + case SND_SOC_DAIFMT_CBS_CFS: + etdm_data->slave_mode = false; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_hdmitx_dptx_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id); + + if (cg_id >= 0) + mt8195_afe_enable_clk(afe, afe_priv->clk[cg_id]); + + mtk_dai_etdm_enable_mclk(afe, dai->id); + + return 0; +} + +static void mtk_dai_hdmitx_dptx_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + int cg_id = mtk_dai_etdm_get_cg_id_by_dai_id(dai->id); + + mtk_dai_etdm_disable_mclk(afe, dai->id); + + if (cg_id >= 0) + mt8195_afe_disable_clk(afe, afe_priv->clk[cg_id]); +} + +static unsigned int mtk_dai_get_dptx_ch_en(unsigned int channel) +{ + switch (channel) { + case 1 ... 2: + return AFE_DPTX_CON_CH_EN_2CH; + case 3 ... 4: + return AFE_DPTX_CON_CH_EN_4CH; + case 5 ... 6: + return AFE_DPTX_CON_CH_EN_6CH; + case 7 ... 8: + return AFE_DPTX_CON_CH_EN_8CH; + default: + return AFE_DPTX_CON_CH_EN_2CH; + } +} + +static unsigned int mtk_dai_get_dptx_ch(unsigned int ch) +{ + return (ch > 2) ? + AFE_DPTX_CON_CH_NUM_8CH : AFE_DPTX_CON_CH_NUM_2CH; +} + +static unsigned int mtk_dai_get_dptx_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + AFE_DPTX_CON_16BIT : AFE_DPTX_CON_24BIT; +} + +static int mtk_dai_hdmitx_dptx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + snd_pcm_format_t format = params_format(params); + int width = snd_pcm_format_physical_width(format); + int ret = 0; + + /* dptx configure */ + if (dai->id == MT8195_AFE_IO_DPTX) { + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + AFE_DPTX_CON_CH_EN_MASK, + mtk_dai_get_dptx_ch_en(channels)); + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + AFE_DPTX_CON_CH_NUM_MASK, + mtk_dai_get_dptx_ch(channels)); + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + AFE_DPTX_CON_16BIT_MASK, + mtk_dai_get_dptx_wlen(format)); + + if (mtk_dai_get_dptx_ch(channels) == AFE_DPTX_CON_CH_NUM_8CH) { + etdm_data->data_mode = MTK_DAI_ETDM_DATA_ONE_PIN; + channels = 8; + } else { + channels = 2; + } + } else { + etdm_data->data_mode = MTK_DAI_ETDM_DATA_MULTI_PIN; + } + + ret = mtk_dai_etdm_mclk_configure(afe, dai->id); + if (ret) + return ret; + + ret = mtk_dai_etdm_configure(afe, rate, channels, width, dai->id); + + return ret; +} + +static int mtk_dai_hdmitx_dptx_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int ret = 0; + + dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* enable dptx interface */ + if (dai->id == MT8195_AFE_IO_DPTX) + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + AFE_DPTX_CON_ON_MASK, + AFE_DPTX_CON_ON); + + /* enable etdm_out3 */ + ret = mt8195_afe_enable_etdm(afe, dai->id); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + /* disable etdm_out3 */ + ret = mt8195_afe_disable_etdm(afe, dai->id); + + /* disable dptx interface */ + if (dai->id == MT8195_AFE_IO_DPTX) + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + AFE_DPTX_CON_ON_MASK, 0); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int mtk_dai_hdmitx_dptx_set_sysclk(struct snd_soc_dai *dai, + int clk_id, + unsigned int freq, + int dir) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s id %d freq %u, dir %d\n", + __func__, dai->id, freq, dir); + + etdm_data->mclk_dir = dir; + return mtk_dai_etdm_cal_mclk(afe, freq, dai->id); +} + +static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { + .startup = mtk_dai_etdm_startup, + .shutdown = mtk_dai_etdm_shutdown, + .hw_params = mtk_dai_etdm_hw_params, + .trigger = mtk_dai_etdm_trigger, + .set_sysclk = mtk_dai_etdm_set_sysclk, + .set_fmt = mtk_dai_etdm_set_fmt, + .set_tdm_slot = mtk_dai_etdm_set_tdm_slot, +}; + +static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = { + .startup = mtk_dai_hdmitx_dptx_startup, + .shutdown = mtk_dai_hdmitx_dptx_shutdown, + .hw_params = mtk_dai_hdmitx_dptx_hw_params, + .trigger = mtk_dai_hdmitx_dptx_trigger, + .set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk, + .set_fmt = mtk_dai_etdm_set_fmt, +}; + +/* dai driver */ +#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_384000) + +#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static int mtk_dai_etdm_probe(struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id); + + if (etdm_data->mclk_freq) { + dev_dbg(afe->dev, "MCLK always on, rate %d\n", + etdm_data->mclk_freq); + pm_runtime_get_sync(afe->dev); + mtk_dai_etdm_mclk_configure(afe, dai->id); + mtk_dai_etdm_enable_mclk(afe, dai->id); + pm_runtime_put_sync(afe->dev); + } + return 0; +} + +static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = { + { + .name = "DPTX", + .id = MT8195_AFE_IO_DPTX, + .playback = { + .stream_name = "DPTX Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_hdmitx_dptx_ops, + }, + { + .name = "ETDM1_IN", + .id = MT8195_AFE_IO_ETDM1_IN, + .capture = { + .stream_name = "ETDM1 Capture", + .channels_min = 1, + .channels_max = 24, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_etdm_ops, + .probe = mtk_dai_etdm_probe, + }, + { + .name = "ETDM2_IN", + .id = MT8195_AFE_IO_ETDM2_IN, + .capture = { + .stream_name = "ETDM2 Capture", + .channels_min = 1, + .channels_max = 16, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_etdm_ops, + .probe = mtk_dai_etdm_probe, + }, + { + .name = "ETDM1_OUT", + .id = MT8195_AFE_IO_ETDM1_OUT, + .playback = { + .stream_name = "ETDM1 Playback", + .channels_min = 1, + .channels_max = 24, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_etdm_ops, + .probe = mtk_dai_etdm_probe, + }, + { + .name = "ETDM2_OUT", + .id = MT8195_AFE_IO_ETDM2_OUT, + .playback = { + .stream_name = "ETDM2 Playback", + .channels_min = 1, + .channels_max = 24, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_etdm_ops, + .probe = mtk_dai_etdm_probe, + }, + { + .name = "ETDM3_OUT", + .id = MT8195_AFE_IO_ETDM3_OUT, + .playback = { + .stream_name = "ETDM3 Playback", + .channels_min = 1, + .channels_max = 8, + .rates = MTK_ETDM_RATES, + .formats = MTK_ETDM_FORMATS, + }, + .ops = &mtk_dai_hdmitx_dptx_ops, + .probe = mtk_dai_etdm_probe, + }, +}; + +static void mt8195_etdm_update_sync_info(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data; + struct mtk_dai_etdm_priv *mst_data; + int i; + int mst_dai_id; + + for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) { + etdm_data = afe_priv->dai_priv[i]; + if (etdm_data->cowork_source_id != COWORK_ETDM_NONE) { + mst_dai_id = etdm_data->cowork_source_id; + mst_data = afe_priv->dai_priv[mst_dai_id]; + if (mst_data->cowork_source_id != COWORK_ETDM_NONE) + dev_info(afe->dev, "%s [%d] wrong sync source\n" + , __func__, i); + mst_data->cowork_slv_id[mst_data->cowork_slv_count] = i; + mst_data->cowork_slv_count++; + } + } +} + +static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe) +{ + const struct device_node *of_node = afe->dev->of_node; + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_data; + int i, j; + char prop[48]; + u8 disable_chn[MT8195_ETDM_MAX_CHANNELS]; + int max_chn = MT8195_ETDM_MAX_CHANNELS; + u32 sel; + int ret; + int dai_id; + unsigned int sync_id; + struct { + const char *name; + const unsigned int sync_id; + } of_afe_etdms[MT8195_AFE_IO_ETDM_NUM] = { + {"etdm-in1", ETDM_SYNC_FROM_IN1}, + {"etdm-in2", ETDM_SYNC_FROM_IN2}, + {"etdm-out1", ETDM_SYNC_FROM_OUT1}, + {"etdm-out2", ETDM_SYNC_FROM_OUT2}, + {"etdm-out3", ETDM_SYNC_FROM_OUT3}, + }; + + for (i = 0; i < MT8195_AFE_IO_ETDM_NUM; i++) { + dai_id = ETDM_TO_DAI_ID(i); + etdm_data = afe_priv->dai_priv[dai_id]; + + ret = snprintf(prop, sizeof(prop), + "mediatek,%s-mclk-always-on-rate", + of_afe_etdms[i].name); + if (ret < 0) { + dev_info(afe->dev, "%s snprintf err=%d\n", + __func__, ret); + return; + } + ret = of_property_read_u32(of_node, prop, &sel); + if (ret == 0) { + etdm_data->mclk_dir = SND_SOC_CLOCK_OUT; + if (mtk_dai_etdm_cal_mclk(afe, sel, dai_id)) + dev_info(afe->dev, "%s unsupported mclk %uHz\n", + __func__, sel); + } + + ret = snprintf(prop, sizeof(prop), + "mediatek,%s-multi-pin-mode", + of_afe_etdms[i].name); + if (ret < 0) { + dev_info(afe->dev, "%s snprintf err=%d\n", + __func__, ret); + return; + } + etdm_data->data_mode = of_property_read_bool(of_node, prop); + + ret = snprintf(prop, sizeof(prop), + "mediatek,%s-cowork-source", + of_afe_etdms[i].name); + if (ret < 0) { + dev_info(afe->dev, "%s snprintf err=%d\n", + __func__, ret); + return; + } + ret = of_property_read_u32(of_node, prop, &sel); + if (ret == 0) { + if (sel >= MT8195_AFE_IO_ETDM_NUM) { + dev_info(afe->dev, "%s invalid id=%d\n", + __func__, sel); + etdm_data->cowork_source_id = COWORK_ETDM_NONE; + } else { + sync_id = of_afe_etdms[sel].sync_id; + etdm_data->cowork_source_id = + sync_to_dai_id(sync_id); + } + } else { + etdm_data->cowork_source_id = COWORK_ETDM_NONE; + } + } + + /* etdm in only */ + for (i = 0; i < 2; i++) { + ret = snprintf(prop, sizeof(prop), + "mediatek,%s-chn-disabled", + of_afe_etdms[i].name); + if (ret < 0) { + dev_info(afe->dev, "%s snprintf err=%d\n", + __func__, ret); + return; + } + ret = of_property_read_variable_u8_array(of_node, prop, + disable_chn, + 1, max_chn); + if (ret < 0) + continue; + + for (j = 0; j < ret; j++) { + if (disable_chn[j] >= MT8195_ETDM_MAX_CHANNELS) + dev_info(afe->dev, "%s [%d] invalid chn %u\n", + __func__, j, disable_chn[j]); + else + etdm_data->in_disable_ch[disable_chn[j]] = true; + } + } + mt8195_etdm_update_sync_info(afe); +} + +static int init_etdm_priv_data(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_etdm_priv *etdm_priv; + int i; + + for (i = MT8195_AFE_IO_ETDM_START; i < MT8195_AFE_IO_ETDM_END; i++) { + etdm_priv = devm_kzalloc(afe->dev, + sizeof(struct mtk_dai_etdm_priv), + GFP_KERNEL); + if (!etdm_priv) + return -ENOMEM; + + afe_priv->dai_priv[i] = etdm_priv; + } + + afe_priv->dai_priv[MT8195_AFE_IO_DPTX] = + afe_priv->dai_priv[MT8195_AFE_IO_ETDM3_OUT]; + + mt8195_dai_etdm_parse_of(afe); + return 0; +} + +int mt8195_dai_etdm_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_etdm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver); + + dai->dapm_widgets = mtk_dai_etdm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets); + dai->dapm_routes = mtk_dai_etdm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes); + dai->controls = mtk_dai_etdm_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_etdm_controls); + + return init_etdm_priv_data(afe); +} diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c new file mode 100644 index 000000000000..5d10d2c4c991 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI PCM I/F Control + * + * Copyright (c) 2020 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <linux/regmap.h> +#include <sound/pcm_params.h> +#include "mt8195-afe-clk.h" +#include "mt8195-afe-common.h" +#include "mt8195-reg.h" + +enum { + MTK_DAI_PCM_FMT_I2S, + MTK_DAI_PCM_FMT_EIAJ, + MTK_DAI_PCM_FMT_MODEA, + MTK_DAI_PCM_FMT_MODEB, +}; + +enum { + MTK_DAI_PCM_CLK_A1SYS, + MTK_DAI_PCM_CLK_A2SYS, + MTK_DAI_PCM_CLK_26M_48K, + MTK_DAI_PCM_CLK_26M_441K, +}; + +struct mtk_dai_pcm_rate { + unsigned int rate; + unsigned int reg_value; +}; + +struct mtk_dai_pcmif_priv { + unsigned int slave_mode; + unsigned int lrck_inv; + unsigned int bck_inv; + unsigned int format; +}; + +static const struct mtk_dai_pcm_rate mtk_dai_pcm_rates[] = { + { .rate = 8000, .reg_value = 0, }, + { .rate = 16000, .reg_value = 1, }, + { .rate = 32000, .reg_value = 2, }, + { .rate = 48000, .reg_value = 3, }, + { .rate = 11025, .reg_value = 1, }, + { .rate = 22050, .reg_value = 2, }, + { .rate = 44100, .reg_value = 3, }, +}; + +static int mtk_dai_pcm_mode(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mtk_dai_pcm_rates); i++) + if (mtk_dai_pcm_rates[i].rate == rate) + return mtk_dai_pcm_rates[i].reg_value; + + return -EINVAL; +} + +static const struct snd_kcontrol_new mtk_dai_pcm_o000_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN0, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN0_2, 6, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_dai_pcm_o001_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN1, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN1_2, 7, 1, 0), +}; + +static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { + SND_SOC_DAPM_MIXER("I002", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I003", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("O000", SND_SOC_NOPM, 0, 0, + mtk_dai_pcm_o000_mix, + ARRAY_SIZE(mtk_dai_pcm_o000_mix)), + SND_SOC_DAPM_MIXER("O001", SND_SOC_NOPM, 0, 0, + mtk_dai_pcm_o001_mix, + ARRAY_SIZE(mtk_dai_pcm_o001_mix)), + + SND_SOC_DAPM_INPUT("PCM1_INPUT"), + SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"), +}; + +static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { + {"I002", NULL, "PCM1 Capture"}, + {"I003", NULL, "PCM1 Capture"}, + + {"O000", "I000 Switch", "I000"}, + {"O001", "I001 Switch", "I001"}, + + {"O000", "I070 Switch", "I070"}, + {"O001", "I071 Switch", "I071"}, + + {"PCM1 Playback", NULL, "O000"}, + {"PCM1 Playback", NULL, "O001"}, + + {"PCM1_OUTPUT", NULL, "PCM1 Playback"}, + {"PCM1 Capture", NULL, "PCM1_INPUT"}, +}; + +static void mtk_dai_pcm_enable(struct mtk_base_afe *afe) +{ + regmap_update_bits(afe->regmap, PCM_INTF_CON1, + PCM_INTF_CON1_PCM_EN, PCM_INTF_CON1_PCM_EN); +} + +static void mtk_dai_pcm_disable(struct mtk_base_afe *afe) +{ + regmap_update_bits(afe->regmap, PCM_INTF_CON1, + PCM_INTF_CON1_PCM_EN, 0x0); +} + +static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime * const runtime = substream->runtime; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; + unsigned int slave_mode = pcmif_priv->slave_mode; + unsigned int lrck_inv = pcmif_priv->lrck_inv; + unsigned int bck_inv = pcmif_priv->bck_inv; + unsigned int fmt = pcmif_priv->format; + unsigned int bit_width = dai->sample_bits; + unsigned int val = 0; + unsigned int mask = 0; + int fs = 0; + int mode = 0; + + /* sync freq mode */ + fs = mt8195_afe_fs_timing(runtime->rate); + if (fs < 0) + return -EINVAL; + val |= PCM_INTF_CON2_SYNC_FREQ_MODE(fs); + mask |= PCM_INTF_CON2_SYNC_FREQ_MODE_MASK; + + /* clk domain sel */ + if (runtime->rate % 8000) + val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_441K); + else + val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_48K); + mask |= PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK; + + regmap_update_bits(afe->regmap, PCM_INTF_CON2, mask, val); + + val = 0; + mask = 0; + + /* pcm mode */ + mode = mtk_dai_pcm_mode(runtime->rate); + if (mode < 0) + return -EINVAL; + val |= PCM_INTF_CON1_PCM_MODE(mode); + mask |= PCM_INTF_CON1_PCM_MODE_MASK; + + /* pcm format */ + val |= PCM_INTF_CON1_PCM_FMT(fmt); + mask |= PCM_INTF_CON1_PCM_FMT_MASK; + + /* pcm sync length */ + if (fmt == MTK_DAI_PCM_FMT_MODEA || + fmt == MTK_DAI_PCM_FMT_MODEB) + val |= PCM_INTF_CON1_SYNC_LENGTH(1); + else + val |= PCM_INTF_CON1_SYNC_LENGTH(bit_width); + mask |= PCM_INTF_CON1_SYNC_LENGTH_MASK; + + /* pcm bits, word length */ + if (bit_width > 16) { + val |= PCM_INTF_CON1_PCM_24BIT; + val |= PCM_INTF_CON1_PCM_WLEN_64BCK; + } else { + val |= PCM_INTF_CON1_PCM_16BIT; + val |= PCM_INTF_CON1_PCM_WLEN_32BCK; + } + mask |= PCM_INTF_CON1_PCM_BIT_MASK; + mask |= PCM_INTF_CON1_PCM_WLEN_MASK; + + /* master/slave */ + if (!slave_mode) { + val |= PCM_INTF_CON1_PCM_MASTER; + + if (lrck_inv) + val |= PCM_INTF_CON1_SYNC_OUT_INV; + if (bck_inv) + val |= PCM_INTF_CON1_BCLK_OUT_INV; + mask |= PCM_INTF_CON1_CLK_OUT_INV_MASK; + } else { + val |= PCM_INTF_CON1_PCM_SLAVE; + + if (lrck_inv) + val |= PCM_INTF_CON1_SYNC_IN_INV; + if (bck_inv) + val |= PCM_INTF_CON1_BCLK_IN_INV; + mask |= PCM_INTF_CON1_CLK_IN_INV_MASK; + + /* TODO: add asrc setting for slave mode */ + } + mask |= PCM_INTF_CON1_PCM_M_S_MASK; + + regmap_update_bits(afe->regmap, PCM_INTF_CON1, mask, val); + + return 0; +} + +/* dai ops */ +static int mtk_dai_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + + if (dai->component->active) + return 0; + + mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]); + mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]); + mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]); + + return 0; +} + +static void mtk_dai_pcm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + + if (dai->component->active) + return; + + mtk_dai_pcm_disable(afe); + + mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]); + mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]); + mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]); +} + +static int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int ret = 0; + + if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) && + snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) + return 0; + + ret = mtk_dai_pcm_configure(substream, dai); + if (ret) + return ret; + + mtk_dai_pcm_enable(afe); + + return 0; +} + +static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + pcmif_priv->format = MTK_DAI_PCM_FMT_I2S; + break; + case SND_SOC_DAIFMT_DSP_A: + pcmif_priv->format = MTK_DAI_PCM_FMT_MODEA; + break; + case SND_SOC_DAIFMT_DSP_B: + pcmif_priv->format = MTK_DAI_PCM_FMT_MODEB; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + pcmif_priv->bck_inv = 0; + pcmif_priv->lrck_inv = 0; + break; + case SND_SOC_DAIFMT_NB_IF: + pcmif_priv->bck_inv = 0; + pcmif_priv->lrck_inv = 1; + break; + case SND_SOC_DAIFMT_IB_NF: + pcmif_priv->bck_inv = 1; + pcmif_priv->lrck_inv = 0; + break; + case SND_SOC_DAIFMT_IB_IF: + pcmif_priv->bck_inv = 1; + pcmif_priv->lrck_inv = 1; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + pcmif_priv->slave_mode = 1; + break; + case SND_SOC_DAIFMT_CBS_CFS: + pcmif_priv->slave_mode = 0; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { + .startup = mtk_dai_pcm_startup, + .shutdown = mtk_dai_pcm_shutdown, + .prepare = mtk_dai_pcm_prepare, + .set_fmt = mtk_dai_pcm_set_fmt, +}; + +/* dai driver */ +#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000) + +#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { + { + .name = "PCM1", + .id = MT8195_AFE_IO_PCM, + .playback = { + .stream_name = "PCM1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .capture = { + .stream_name = "PCM1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mtk_dai_pcm_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + }, +}; + +static int init_pcmif_priv_data(struct mtk_base_afe *afe) +{ + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtk_dai_pcmif_priv *pcmif_priv; + + pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_pcmif_priv), + GFP_KERNEL); + if (!pcmif_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8195_AFE_IO_PCM] = pcmif_priv; + return 0; +} + +int mt8195_dai_pcm_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_pcm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); + + dai->dapm_widgets = mtk_dai_pcm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); + dai->dapm_routes = mtk_dai_pcm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); + + return init_pcmif_priv_data(afe); +} diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c new file mode 100644 index 000000000000..5dc217f59bd6 --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c @@ -0,0 +1,1087 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8195-mt6359-rt1019-rt5682.c -- +// MT8195-MT6359-RT1019-RT6358 ALSA SoC machine driver +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Trevor Wu <trevor.wu@mediatek.com> +// + +#include <linux/input.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <sound/jack.h> +#include <sound/pcm_params.h> +#include <sound/rt5682.h> +#include <sound/soc.h> +#include "../../codecs/mt6359.h" +#include "../../codecs/rt5682.h" +#include "../common/mtk-afe-platform-driver.h" +#include "mt8195-afe-common.h" + +#define RT1019_CODEC_DAI "HiFi" +#define RT1019_DEV0_NAME "rt1019p" + +#define RT5682_CODEC_DAI "rt5682-aif1" +#define RT5682_DEV0_NAME "rt5682.2-001a" + +struct mt8195_mt6359_rt1019_rt5682_priv { + struct snd_soc_jack headset_jack; + struct snd_soc_jack dp_jack; + struct snd_soc_jack hdmi_jack; +}; + +static const struct snd_soc_dapm_widget + mt8195_mt6359_rt1019_rt5682_widgets[] = { + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route mt8195_mt6359_rt1019_rt5682_routes[] = { + /* speaker */ + { "Speakers", NULL, "Speaker" }, + /* headset */ + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + { "IN1P", NULL, "Headset Mic" }, +}; + +static const struct snd_kcontrol_new mt8195_mt6359_rt1019_rt5682_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + int bitwidth; + int ret; + + bitwidth = snd_pcm_format_width(params_format(params)); + if (bitwidth < 0) { + dev_err(card->dev, "invalid bit width: %d\n", bitwidth); + return bitwidth; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); + if (ret) { + dev_err(card->dev, "failed to set tdm slot\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, + RT5682_PLL1_S_BCLK1, + params_rate(params) * 64, + params_rate(params) * 512); + if (ret) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT5682_SCLK_S_PLL1, + params_rate(params) * 512, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8195_rt5682_etdm_ops = { + .hw_params = mt8195_rt5682_etdm_hw_params, +}; + +#define CKSYS_AUD_TOP_CFG 0x032c +#define CKSYS_AUD_TOP_MON 0x0330 + +static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_afe = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); + struct mt8195_afe_private *afe_priv = afe->platform_priv; + struct mtkaif_param *param = &afe_priv->mtkaif_params; + int phase; + unsigned int monitor; + int mtkaif_calibration_num_phase; + int test_done_1, test_done_2, test_done_3; + int cycle_1, cycle_2, cycle_3; + int prev_cycle_1, prev_cycle_2, prev_cycle_3; + int chosen_phase_1, chosen_phase_2, chosen_phase_3; + int counter; + bool mtkaif_calibration_ok; + int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM]; + int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM]; + int i; + + dev_info(afe->dev, "%s(), start\n", __func__); + + param->mtkaif_calibration_ok = false; + for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++) { + param->mtkaif_chosen_phase[i] = -1; + param->mtkaif_phase_cycle[i] = 0; + mtkaif_chosen_phase[i] = -1; + mtkaif_phase_cycle[i] = 0; + } + + if (IS_ERR(afe_priv->topckgen)) { + dev_info(afe->dev, "%s() Cannot find topckgen controller\n", + __func__); + return 0; + } + + pm_runtime_get_sync(afe->dev); + mt6359_mtkaif_calibration_enable(cmpnt_codec); + + /* set test type to synchronizer pulse */ + regmap_update_bits(afe_priv->topckgen, + CKSYS_AUD_TOP_CFG, 0xffff, 0x4); + mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */ + mtkaif_calibration_ok = true; + + for (phase = 0; + phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok; + phase++) { + mt6359_set_mtkaif_calibration_phase(cmpnt_codec, + phase, phase, phase); + + regmap_update_bits(afe_priv->topckgen, + CKSYS_AUD_TOP_CFG, 0x1, 0x1); + + test_done_1 = 0; + test_done_2 = 0; + test_done_3 = 0; + cycle_1 = -1; + cycle_2 = -1; + cycle_3 = -1; + counter = 0; + while (!(test_done_1 & test_done_2 & test_done_3)) { + regmap_read(afe_priv->topckgen, + CKSYS_AUD_TOP_MON, &monitor); + test_done_1 = (monitor >> 28) & 0x1; + test_done_2 = (monitor >> 29) & 0x1; + test_done_3 = (monitor >> 30) & 0x1; + if (test_done_1 == 1) + cycle_1 = monitor & 0xf; + + if (test_done_2 == 1) + cycle_2 = (monitor >> 4) & 0xf; + + if (test_done_3 == 1) + cycle_3 = (monitor >> 8) & 0xf; + + /* handle if never test done */ + if (++counter > 10000) { + dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n", + __func__, + cycle_1, cycle_2, cycle_3, monitor); + mtkaif_calibration_ok = false; + break; + } + } + + if (phase == 0) { + prev_cycle_1 = cycle_1; + prev_cycle_2 = cycle_2; + prev_cycle_3 = cycle_3; + } + + if (cycle_1 != prev_cycle_1 && + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) { + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = phase - 1; + mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] = prev_cycle_1; + } + + if (cycle_2 != prev_cycle_2 && + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) { + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = phase - 1; + mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] = prev_cycle_2; + } + + if (cycle_3 != prev_cycle_3 && + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) { + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = phase - 1; + mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] = prev_cycle_3; + } + + regmap_update_bits(afe_priv->topckgen, + CKSYS_AUD_TOP_CFG, 0x1, 0x0); + + if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] >= 0 && + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] >= 0 && + mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] >= 0) + break; + } + + if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) { + mtkaif_calibration_ok = false; + chosen_phase_1 = 0; + } else { + chosen_phase_1 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0]; + } + + if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) { + mtkaif_calibration_ok = false; + chosen_phase_2 = 0; + } else { + chosen_phase_2 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1]; + } + + if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) { + mtkaif_calibration_ok = false; + chosen_phase_3 = 0; + } else { + chosen_phase_3 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2]; + } + + mt6359_set_mtkaif_calibration_phase(cmpnt_codec, + chosen_phase_1, + chosen_phase_2, + chosen_phase_3); + + mt6359_mtkaif_calibration_disable(cmpnt_codec); + pm_runtime_put(afe->dev); + + param->mtkaif_calibration_ok = mtkaif_calibration_ok; + param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = chosen_phase_1; + param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = chosen_phase_2; + param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = chosen_phase_3; + for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++) + param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i]; + + dev_info(afe->dev, "%s(), end, calibration ok %d\n", + __func__, param->mtkaif_calibration_ok); + + return 0; +} + +static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + + /* set mtkaif protocol */ + mt6359_set_mtkaif_protocol(cmpnt_codec, + MT6359_MTKAIF_PROTOCOL_2_CLK_P2); + + /* mtkaif calibration */ + mt8195_mt6359_mtkaif_calibration(rtd); + + return 0; +} + +static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mt8195_mt6359_rt1019_rt5682_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &priv->headset_jack; + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret); + return ret; + } + + return 0; +}; + +static int mt8195_etdm_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int mt8195_hdmitx_dptx_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 2, 4, 6, 8 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = { + .startup = mt8195_hdmitx_dptx_startup, +}; + +static int mt8195_dptx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 256; + unsigned int mclk_fs = rate * mclk_fs_ratio; + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, + SND_SOC_CLOCK_OUT); +} + +static struct snd_soc_ops mt8195_dptx_ops = { + .hw_params = mt8195_dptx_hw_params, +}; + +static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8195_mt6359_rt1019_rt5682_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + int ret = 0; + + ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, + &priv->dp_jack, NULL, 0); + if (ret) + return ret; + + return snd_soc_component_set_jack(cmpnt_codec, &priv->dp_jack, NULL); +} + +static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8195_mt6359_rt1019_rt5682_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + int ret = 0; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) + return ret; + + return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); +} + +static int mt8195_hdmitx_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) + +{ + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int mt8195_playback_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8195_playback_ops = { + .startup = mt8195_playback_startup, +}; + +static int mt8195_capture_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 1, 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8195_capture_ops = { + .startup = mt8195_capture_startup, +}; + +enum { + DAI_LINK_DL2_FE, + DAI_LINK_DL3_FE, + DAI_LINK_DL6_FE, + DAI_LINK_DL7_FE, + DAI_LINK_DL8_FE, + DAI_LINK_DL10_FE, + DAI_LINK_DL11_FE, + DAI_LINK_UL1_FE, + DAI_LINK_UL2_FE, + DAI_LINK_UL3_FE, + DAI_LINK_UL4_FE, + DAI_LINK_UL5_FE, + DAI_LINK_UL6_FE, + DAI_LINK_UL8_FE, + DAI_LINK_UL9_FE, + DAI_LINK_UL10_FE, + DAI_LINK_DL_SRC_BE, + DAI_LINK_DPTX_BE, + DAI_LINK_ETDM1_IN_BE, + DAI_LINK_ETDM2_IN_BE, + DAI_LINK_ETDM1_OUT_BE, + DAI_LINK_ETDM2_OUT_BE, + DAI_LINK_ETDM3_OUT_BE, + DAI_LINK_PCM1_BE, + DAI_LINK_UL_SRC1_BE, + DAI_LINK_UL_SRC2_BE, +}; + +/* FE */ +SND_SOC_DAILINK_DEFS(DL2_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL3_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL6_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL7_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL8_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL8")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL10_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL10")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DL11_FE, + DAILINK_COMP_ARRAY(COMP_CPU("DL11")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL1_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL2_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL3_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL4_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL5_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL6_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL8_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL8")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL9_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL9")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL10_FE, + DAILINK_COMP_ARRAY(COMP_CPU("UL10")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(DL_SRC_BE, + DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", + "mt6359-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(DPTX_BE, + DAILINK_COMP_ARRAY(COMP_CPU("DPTX")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(ETDM1_IN_BE, + DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(ETDM2_IN_BE, + DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME, + RT5682_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(ETDM1_OUT_BE, + DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME, + RT5682_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(ETDM2_OUT_BE, + DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")), + DAILINK_COMP_ARRAY(COMP_CODEC(RT1019_DEV0_NAME, + RT1019_CODEC_DAI)), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(ETDM3_OUT_BE, + DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(PCM1_BE, + DAILINK_COMP_ARRAY(COMP_CPU("PCM1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL_SRC1_BE, + DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC1")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", + "mt6359-snd-codec-aif1"), + COMP_CODEC("dmic-codec", + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(UL_SRC2_BE, + DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC2")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", + "mt6359-snd-codec-aif2")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = { + /* FE */ + [DAI_LINK_DL2_FE] = { + .name = "DL2_FE", + .stream_name = "DL2 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_playback_ops, + SND_SOC_DAILINK_REG(DL2_FE), + }, + [DAI_LINK_DL3_FE] = { + .name = "DL3_FE", + .stream_name = "DL3 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_playback_ops, + SND_SOC_DAILINK_REG(DL3_FE), + }, + [DAI_LINK_DL6_FE] = { + .name = "DL6_FE", + .stream_name = "DL6 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_playback_ops, + SND_SOC_DAILINK_REG(DL6_FE), + }, + [DAI_LINK_DL7_FE] = { + .name = "DL7_FE", + .stream_name = "DL7 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE, + }, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(DL7_FE), + }, + [DAI_LINK_DL8_FE] = { + .name = "DL8_FE", + .stream_name = "DL8 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_playback_ops, + SND_SOC_DAILINK_REG(DL8_FE), + }, + [DAI_LINK_DL10_FE] = { + .name = "DL10_FE", + .stream_name = "DL10 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_hdmitx_dptx_playback_ops, + SND_SOC_DAILINK_REG(DL10_FE), + }, + [DAI_LINK_DL11_FE] = { + .name = "DL11_FE", + .stream_name = "DL11 Playback", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_playback = 1, + .ops = &mt8195_playback_ops, + SND_SOC_DAILINK_REG(DL11_FE), + }, + [DAI_LINK_UL1_FE] = { + .name = "UL1_FE", + .stream_name = "UL1 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE, + }, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(UL1_FE), + }, + [DAI_LINK_UL2_FE] = { + .name = "UL2_FE", + .stream_name = "UL2 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL2_FE), + }, + [DAI_LINK_UL3_FE] = { + .name = "UL3_FE", + .stream_name = "UL3 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL3_FE), + }, + [DAI_LINK_UL4_FE] = { + .name = "UL4_FE", + .stream_name = "UL4 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL4_FE), + }, + [DAI_LINK_UL5_FE] = { + .name = "UL5_FE", + .stream_name = "UL5 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL5_FE), + }, + [DAI_LINK_UL6_FE] = { + .name = "UL6_FE", + .stream_name = "UL6 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE, + }, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(UL6_FE), + }, + [DAI_LINK_UL8_FE] = { + .name = "UL8_FE", + .stream_name = "UL8 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL8_FE), + }, + [DAI_LINK_UL9_FE] = { + .name = "UL9_FE", + .stream_name = "UL9 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL9_FE), + }, + [DAI_LINK_UL10_FE] = { + .name = "UL10_FE", + .stream_name = "UL10 Capture", + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST, + }, + .dynamic = 1, + .dpcm_capture = 1, + .ops = &mt8195_capture_ops, + SND_SOC_DAILINK_REG(UL10_FE), + }, + /* BE */ + [DAI_LINK_DL_SRC_BE] = { + .name = "DL_SRC_BE", + .init = mt8195_mt6359_init, + .no_pcm = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(DL_SRC_BE), + }, + [DAI_LINK_DPTX_BE] = { + .name = "DPTX_BE", + .no_pcm = 1, + .dpcm_playback = 1, + .ops = &mt8195_dptx_ops, + .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup, + SND_SOC_DAILINK_REG(DPTX_BE), + }, + [DAI_LINK_ETDM1_IN_BE] = { + .name = "ETDM1_IN_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(ETDM1_IN_BE), + }, + [DAI_LINK_ETDM2_IN_BE] = { + .name = "ETDM2_IN_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_capture = 1, + .init = mt8195_rt5682_init, + .ops = &mt8195_rt5682_etdm_ops, + .be_hw_params_fixup = mt8195_etdm_hw_params_fixup, + SND_SOC_DAILINK_REG(ETDM2_IN_BE), + }, + [DAI_LINK_ETDM1_OUT_BE] = { + .name = "ETDM1_OUT_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_playback = 1, + .ops = &mt8195_rt5682_etdm_ops, + .be_hw_params_fixup = mt8195_etdm_hw_params_fixup, + SND_SOC_DAILINK_REG(ETDM1_OUT_BE), + }, + [DAI_LINK_ETDM2_OUT_BE] = { + .name = "ETDM2_OUT_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(ETDM2_OUT_BE), + }, + [DAI_LINK_ETDM3_OUT_BE] = { + .name = "ETDM3_OUT_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_playback = 1, + .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup, + SND_SOC_DAILINK_REG(ETDM3_OUT_BE), + }, + [DAI_LINK_PCM1_BE] = { + .name = "PCM1_BE", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(PCM1_BE), + }, + [DAI_LINK_UL_SRC1_BE] = { + .name = "UL_SRC1_BE", + .no_pcm = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(UL_SRC1_BE), + }, + [DAI_LINK_UL_SRC2_BE] = { + .name = "UL_SRC2_BE", + .no_pcm = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(UL_SRC2_BE), + }, +}; + +static struct snd_soc_card mt8195_mt6359_rt1019_rt5682_soc_card = { + .name = "mt8195_r1019_5682", + .owner = THIS_MODULE, + .dai_link = mt8195_mt6359_rt1019_rt5682_dai_links, + .num_links = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_dai_links), + .controls = mt8195_mt6359_rt1019_rt5682_controls, + .num_controls = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_controls), + .dapm_widgets = mt8195_mt6359_rt1019_rt5682_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_widgets), + .dapm_routes = mt8195_mt6359_rt1019_rt5682_routes, + .num_dapm_routes = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_routes), +}; + +static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &mt8195_mt6359_rt1019_rt5682_soc_card; + struct device_node *platform_node; + struct snd_soc_dai_link *dai_link; + struct mt8195_mt6359_rt1019_rt5682_priv *priv = NULL; + int ret, i; + + card->dev = &pdev->dev; + + platform_node = of_parse_phandle(pdev->dev.of_node, + "mediatek,platform", 0); + if (!platform_node) { + dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n"); + return -EINVAL; + } + + for_each_card_prelinks(card, i, dai_link) { + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; + + if (strcmp(dai_link->name, "DPTX_BE") == 0) { + dai_link->codecs->of_node = + of_parse_phandle(pdev->dev.of_node, + "mediatek,dptx-codec", 0); + if (!dai_link->codecs->of_node) { + dev_err(&pdev->dev, "Property 'dptx-codec' missing or invalid\n"); + return -EINVAL; + } + + dai_link->codecs->name = NULL; + dai_link->codecs->dai_name = "i2s-hifi"; + dai_link->init = mt8195_dptx_codec_init; + } + + if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { + dai_link->codecs->of_node = + of_parse_phandle(pdev->dev.of_node, + "mediatek,hdmi-codec", 0); + if (!dai_link->codecs->of_node) { + dev_err(&pdev->dev, "Property 'hdmi-codec' missing or invalid\n"); + return -EINVAL; + } + + dai_link->codecs->name = NULL; + dai_link->codecs->dai_name = "i2s-hifi"; + dai_link->init = mt8195_hdmi_codec_init; + } + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + snd_soc_card_set_drvdata(card, priv); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); + return ret; +} + +#ifdef CONFIG_OF +static const struct of_device_id mt8195_mt6359_rt1019_rt5682_dt_match[] = { + {.compatible = "mediatek,mt8195_mt6359_rt1019_rt5682",}, + {} +}; +#endif + +static const struct dev_pm_ops mt8195_mt6359_rt1019_rt5682_pm_ops = { + .poweroff = snd_soc_poweroff, + .restore = snd_soc_resume, +}; + +static struct platform_driver mt8195_mt6359_rt1019_rt5682_driver = { + .driver = { + .name = "mt8195_mt6359_rt1019_rt5682", +#ifdef CONFIG_OF + .of_match_table = mt8195_mt6359_rt1019_rt5682_dt_match, +#endif + .pm = &mt8195_mt6359_rt1019_rt5682_pm_ops, + }, + .probe = mt8195_mt6359_rt1019_rt5682_dev_probe, +}; + +module_platform_driver(mt8195_mt6359_rt1019_rt5682_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8195-MT6359-RT1019-RT5682 ALSA SoC machine driver"); +MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("mt8195_mt6359_rt1019_rt5682 soc card"); diff --git a/sound/soc/mediatek/mt8195/mt8195-reg.h b/sound/soc/mediatek/mt8195/mt8195-reg.h new file mode 100644 index 000000000000..d06f9cf85a4e --- /dev/null +++ b/sound/soc/mediatek/mt8195/mt8195-reg.h @@ -0,0 +1,2796 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8195-reg.h -- Mediatek 8195 audio driver reg definition + * + * Copyright (c) 2021 MediaTek Inc. + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT8195_REG_H_ +#define _MT8195_REG_H_ + +#define AFE_SRAM_BASE (0x10880000) +#define AFE_SRAM_SIZE (0x10000) + +#define AUDIO_TOP_CON0 (0x0000) +#define AUDIO_TOP_CON1 (0x0004) +#define AUDIO_TOP_CON2 (0x0008) +#define AUDIO_TOP_CON3 (0x000c) +#define AUDIO_TOP_CON4 (0x0010) +#define AUDIO_TOP_CON5 (0x0014) +#define AUDIO_TOP_CON6 (0x0018) +#define AFE_MAS_HADDR_MSB (0x0020) +#define PWR1_ASM_CON1 (0x0108) +#define ASYS_IRQ_CONFIG (0x0110) +#define ASYS_IRQ1_CON (0x0114) +#define ASYS_IRQ2_CON (0x0118) +#define ASYS_IRQ3_CON (0x011c) +#define ASYS_IRQ4_CON (0x0120) +#define ASYS_IRQ5_CON (0x0124) +#define ASYS_IRQ6_CON (0x0128) +#define ASYS_IRQ7_CON (0x012c) +#define ASYS_IRQ8_CON (0x0130) +#define ASYS_IRQ9_CON (0x0134) +#define ASYS_IRQ10_CON (0x0138) +#define ASYS_IRQ11_CON (0x013c) +#define ASYS_IRQ12_CON (0x0140) +#define ASYS_IRQ13_CON (0x0144) +#define ASYS_IRQ14_CON (0x0148) +#define ASYS_IRQ15_CON (0x014c) +#define ASYS_IRQ16_CON (0x0150) +#define ASYS_IRQ_CLR (0x0154) +#define ASYS_IRQ_STATUS (0x0158) +#define ASYS_IRQ_MON1 (0x015c) +#define ASYS_IRQ_MON2 (0x0160) +#define AFE_IRQ1_CON (0x0164) +#define AFE_IRQ2_CON (0x0168) +#define AFE_IRQ3_CON (0x016c) +#define AFE_IRQ_MCU_CLR (0x0170) +#define AFE_IRQ_STATUS (0x0174) +#define AFE_IRQ_MASK (0x0178) +#define ASYS_IRQ_MASK (0x017c) +#define AFE_IRQ3_CON_MON (0x01b0) +#define AFE_IRQ_MCU_MON2 (0x01b4) +#define AFE_IRQ8_CON (0x01b8) +#define AFE_IRQ9_CON (0x01bc) +#define AFE_IRQ10_CON (0x01c0) +#define AFE_IRQ9_CON_MON (0x01c4) +#define ADSP_IRQ_MASK (0x01c8) +#define ADSP_IRQ_STATUS (0x01cc) +#define AFE_SINEGEN_CON0 (0x01f0) +#define AFE_SINEGEN_CON1 (0x01f4) +#define AFE_SINEGEN_CON2 (0x01f8) +#define AFE_SINEGEN_CON3 (0x01fc) +#define AFE_SPDIF_OUT_CON0 (0x0380) +#define AFE_TDMOUT_CONN0 (0x0390) +#define PWR1_ASM_CON2 (0x03b0) +#define PWR1_ASM_CON3 (0x03b4) +#define PWR1_ASM_CON4 (0x03b8) +#define AFE_APLL_TUNER_CFG (0x03f8) +#define AFE_APLL_TUNER_CFG1 (0x03fc) +#define AUDIO_TOP_STA0 (0x0400) +#define AUDIO_TOP_STA1 (0x0404) +#define AFE_GAIN1_CON0 (0x0410) +#define AFE_GAIN1_CON1 (0x0414) +#define AFE_GAIN1_CON2 (0x0418) +#define AFE_GAIN1_CON3 (0x041c) +#define AFE_GAIN1_CUR (0x0424) +#define AFE_GAIN2_CON0 (0x0428) +#define AFE_GAIN2_CON1 (0x042c) +#define AFE_GAIN2_CON2 (0x0430) +#define AFE_GAIN2_CON3 (0x0434) +#define AFE_GAIN2_CUR (0x043c) +#define AFE_IEC_CFG (0x0480) +#define AFE_IEC_NSNUM (0x0484) +#define AFE_IEC_BURST_INFO (0x0488) +#define AFE_IEC_BURST_LEN (0x048c) +#define AFE_IEC_NSADR (0x0490) +#define AFE_IEC_CHL_STAT0 (0x04a0) +#define AFE_IEC_CHL_STAT1 (0x04a4) +#define AFE_IEC_CHR_STAT0 (0x04a8) +#define AFE_IEC_CHR_STAT1 (0x04ac) +#define AFE_SPDIFIN_CFG0 (0x0500) +#define AFE_SPDIFIN_CFG1 (0x0504) +#define AFE_SPDIFIN_CHSTS1 (0x0508) +#define AFE_SPDIFIN_CHSTS2 (0x050c) +#define AFE_SPDIFIN_CHSTS3 (0x0510) +#define AFE_SPDIFIN_CHSTS4 (0x0514) +#define AFE_SPDIFIN_CHSTS5 (0x0518) +#define AFE_SPDIFIN_CHSTS6 (0x051c) +#define AFE_SPDIFIN_DEBUG1 (0x0520) +#define AFE_SPDIFIN_DEBUG2 (0x0524) +#define AFE_SPDIFIN_DEBUG3 (0x0528) +#define AFE_SPDIFIN_DEBUG4 (0x052c) +#define AFE_SPDIFIN_EC (0x0530) +#define AFE_SPDIFIN_CKLOCK_CFG (0x0534) +#define AFE_SPDIFIN_BR (0x053c) +#define AFE_SPDIFIN_BR_DBG1 (0x0540) +#define AFE_SPDIFIN_CKFBDIV (0x0544) +#define AFE_SPDIFIN_INT_EXT (0x0548) +#define AFE_SPDIFIN_INT_EXT2 (0x054c) +#define SPDIFIN_FREQ_INFO (0x0550) +#define SPDIFIN_FREQ_INFO_2 (0x0554) +#define SPDIFIN_FREQ_INFO_3 (0x0558) +#define SPDIFIN_FREQ_STATUS (0x055c) +#define SPDIFIN_USERCODE1 (0x0560) +#define SPDIFIN_USERCODE2 (0x0564) +#define SPDIFIN_USERCODE3 (0x0568) +#define SPDIFIN_USERCODE4 (0x056c) +#define SPDIFIN_USERCODE5 (0x0570) +#define SPDIFIN_USERCODE6 (0x0574) +#define SPDIFIN_USERCODE7 (0x0578) +#define SPDIFIN_USERCODE8 (0x057c) +#define SPDIFIN_USERCODE9 (0x0580) +#define SPDIFIN_USERCODE10 (0x0584) +#define SPDIFIN_USERCODE11 (0x0588) +#define SPDIFIN_USERCODE12 (0x058c) +#define AFE_SPDIFIN_APLL_TUNER_CFG (0x0594) +#define AFE_SPDIFIN_APLL_TUNER_CFG1 (0x0598) +#define ASYS_TOP_CON (0x0600) +#define AFE_LINEIN_APLL_TUNER_CFG (0x0610) +#define AFE_LINEIN_APLL_TUNER_MON (0x0614) +#define AFE_EARC_APLL_TUNER_CFG (0x0618) +#define AFE_EARC_APLL_TUNER_MON (0x061c) +#define PWR2_TOP_CON0 (0x0634) +#define PWR2_TOP_CON1 (0x0638) +#define PCM_INTF_CON1 (0x063c) +#define PCM_INTF_CON2 (0x0640) +#define AFE_CM0_CON (0x0660) +#define AFE_CM1_CON (0x0664) +#define AFE_CM2_CON (0x0668) +#define AFE_CM0_MON (0x0670) +#define AFE_CM1_MON (0x0674) +#define AFE_CM2_MON (0x0678) +#define AFE_MPHONE_MULTI_CON0 (0x06a4) +#define AFE_MPHONE_MULTI_CON1 (0x06a8) +#define AFE_MPHONE_MULTI_CON2 (0x06ac) +#define AFE_MPHONE_MULTI_MON (0x06b0) +#define AFE_MPHONE_MULTI_DET_REG_CON0 (0x06b4) +#define AFE_MPHONE_MULTI_DET_REG_CON1 (0x06b8) +#define AFE_MPHONE_MULTI_DET_REG_CON2 (0x06bc) +#define AFE_MPHONE_MULTI_DET_REG_CON3 (0x06c0) +#define AFE_MPHONE_MULTI_DET_MON0 (0x06c4) +#define AFE_MPHONE_MULTI_DET_MON1 (0x06c8) +#define AFE_MPHONE_MULTI_DET_MON2 (0x06d0) +#define AFE_MPHONE_MULTI2_CON0 (0x06d4) +#define AFE_MPHONE_MULTI2_CON1 (0x06d8) +#define AFE_MPHONE_MULTI2_CON2 (0x06dc) +#define AFE_MPHONE_MULTI2_MON (0x06e0) +#define AFE_MPHONE_MULTI2_DET_REG_CON0 (0x06e4) +#define AFE_MPHONE_MULTI2_DET_REG_CON1 (0x06e8) +#define AFE_MPHONE_MULTI2_DET_REG_CON2 (0x06ec) +#define AFE_MPHONE_MULTI2_DET_REG_CON3 (0x06f0) +#define AFE_MPHONE_MULTI2_DET_MON0 (0x06f4) +#define AFE_MPHONE_MULTI2_DET_MON1 (0x06f8) +#define AFE_MPHONE_MULTI2_DET_MON2 (0x06fc) +#define AFE_ADDA_IIR_COEF_02_01 (0x0700) +#define AFE_ADDA_IIR_COEF_04_03 (0x0704) +#define AFE_ADDA_IIR_COEF_06_05 (0x0708) +#define AFE_ADDA_IIR_COEF_08_07 (0x070c) +#define AFE_ADDA_IIR_COEF_10_09 (0x0710) +#define AFE_ADDA_ULCF_CFG_02_01 (0x0714) +#define AFE_ADDA_ULCF_CFG_04_03 (0x0718) +#define AFE_ADDA_ULCF_CFG_06_05 (0x071c) +#define AFE_ADDA_ULCF_CFG_08_07 (0x0720) +#define AFE_ADDA_ULCF_CFG_10_09 (0x0724) +#define AFE_ADDA_ULCF_CFG_12_11 (0x0728) +#define AFE_ADDA_ULCF_CFG_14_13 (0x072c) +#define AFE_ADDA_ULCF_CFG_16_15 (0x0730) +#define AFE_ADDA_ULCF_CFG_18_17 (0x0734) +#define AFE_ADDA_ULCF_CFG_20_19 (0x0738) +#define AFE_ADDA_ULCF_CFG_22_21 (0x073c) +#define AFE_ADDA_ULCF_CFG_24_23 (0x0740) +#define AFE_ADDA_ULCF_CFG_26_25 (0x0744) +#define AFE_ADDA_ULCF_CFG_28_27 (0x0748) +#define AFE_ADDA_ULCF_CFG_30_29 (0x074c) +#define AFE_ADDA6_IIR_COEF_02_01 (0x0750) +#define AFE_ADDA6_IIR_COEF_04_03 (0x0754) +#define AFE_ADDA6_IIR_COEF_06_05 (0x0758) +#define AFE_ADDA6_IIR_COEF_08_07 (0x075c) +#define AFE_ADDA6_IIR_COEF_10_09 (0x0760) +#define AFE_ADDA6_ULCF_CFG_02_01 (0x0764) +#define AFE_ADDA6_ULCF_CFG_04_03 (0x0768) +#define AFE_ADDA6_ULCF_CFG_06_05 (0x076c) +#define AFE_ADDA6_ULCF_CFG_08_07 (0x0770) +#define AFE_ADDA6_ULCF_CFG_10_09 (0x0774) +#define AFE_ADDA6_ULCF_CFG_12_11 (0x0778) +#define AFE_ADDA6_ULCF_CFG_14_13 (0x077c) +#define AFE_ADDA6_ULCF_CFG_16_15 (0x0780) +#define AFE_ADDA6_ULCF_CFG_18_17 (0x0784) +#define AFE_ADDA6_ULCF_CFG_20_19 (0x0788) +#define AFE_ADDA6_ULCF_CFG_22_21 (0x078c) +#define AFE_ADDA6_ULCF_CFG_24_23 (0x0790) +#define AFE_ADDA6_ULCF_CFG_26_25 (0x0794) +#define AFE_ADDA6_ULCF_CFG_28_27 (0x0798) +#define AFE_ADDA6_ULCF_CFG_30_29 (0x079c) +#define AFE_ADDA_MTKAIF_CFG0 (0x07a0) +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG (0x07a8) +#define AFE_ADDA_MTKAIF_RX_CFG0 (0x07b4) +#define AFE_ADDA_MTKAIF_RX_CFG1 (0x07b8) +#define AFE_ADDA_MTKAIF_RX_CFG2 (0x07bc) +#define AFE_ADDA_MTKAIF_MON0 (0x07c8) +#define AFE_ADDA_MTKAIF_MON1 (0x07cc) +#define AFE_AUD_PAD_TOP (0x07d4) +#define AFE_ADDA6_MTKAIF_MON0 (0x07d8) +#define AFE_ADDA6_MTKAIF_MON1 (0x07dc) +#define AFE_ADDA6_MTKAIF_CFG0 (0x07e0) +#define AFE_ADDA6_MTKAIF_RX_CFG0 (0x07e4) +#define AFE_ADDA6_MTKAIF_RX_CFG1 (0x07e8) +#define AFE_ADDA6_MTKAIF_RX_CFG2 (0x07ec) +#define AFE_ADDA6_TOP_CON0 (0x07f0) +#define AFE_ADDA6_UL_SRC_CON0 (0x07f4) +#define AFE_ADDA6_UL_SRC_CON1 (0x07f8) +#define AFE_ADDA6_SRC_DEBUG (0x0800) +#define AFE_ADDA6_SRC_DEBUG_MON0 (0x0804) +#define AFE_ADDA6_UL_SRC_MON0 (0x0818) +#define AFE_ADDA6_UL_SRC_MON1 (0x081c) +#define AFE_CONN0_5 (0x0830) +#define AFE_CONN1_5 (0x0834) +#define AFE_CONN2_5 (0x0838) +#define AFE_CONN3_5 (0x083c) +#define AFE_CONN4_5 (0x0840) +#define AFE_CONN5_5 (0x0844) +#define AFE_CONN6_5 (0x0848) +#define AFE_CONN7_5 (0x084c) +#define AFE_CONN8_5 (0x0850) +#define AFE_CONN9_5 (0x0854) +#define AFE_CONN10_5 (0x0858) +#define AFE_CONN11_5 (0x085c) +#define AFE_CONN12_5 (0x0860) +#define AFE_CONN13_5 (0x0864) +#define AFE_CONN14_5 (0x0868) +#define AFE_CONN15_5 (0x086c) +#define AFE_CONN16_5 (0x0870) +#define AFE_CONN17_5 (0x0874) +#define AFE_CONN18_5 (0x0878) +#define AFE_CONN19_5 (0x087c) +#define AFE_CONN20_5 (0x0880) +#define AFE_CONN21_5 (0x0884) +#define AFE_CONN22_5 (0x0888) +#define AFE_CONN23_5 (0x088c) +#define AFE_CONN24_5 (0x0890) +#define AFE_CONN25_5 (0x0894) +#define AFE_CONN26_5 (0x0898) +#define AFE_CONN27_5 (0x089c) +#define AFE_CONN28_5 (0x08a0) +#define AFE_CONN29_5 (0x08a4) +#define AFE_CONN30_5 (0x08a8) +#define AFE_CONN31_5 (0x08ac) +#define AFE_CONN32_5 (0x08b0) +#define AFE_CONN33_5 (0x08b4) +#define AFE_CONN34_5 (0x08b8) +#define AFE_CONN35_5 (0x08bc) +#define AFE_CONN36_5 (0x08c0) +#define AFE_CONN37_5 (0x08c4) +#define AFE_CONN38_5 (0x08c8) +#define AFE_CONN39_5 (0x08cc) +#define AFE_CONN40_5 (0x08d0) +#define AFE_CONN41_5 (0x08d4) +#define AFE_CONN42_5 (0x08d8) +#define AFE_CONN43_5 (0x08dc) +#define AFE_CONN44_5 (0x08e0) +#define AFE_CONN45_5 (0x08e4) +#define AFE_CONN46_5 (0x08e8) +#define AFE_CONN47_5 (0x08ec) +#define AFE_CONN48_5 (0x08f0) +#define AFE_CONN49_5 (0x08f4) +#define AFE_CONN50_5 (0x08f8) +#define AFE_CONN51_5 (0x08fc) +#define AFE_CONN52_5 (0x0900) +#define AFE_CONN53_5 (0x0904) +#define AFE_CONN54_5 (0x0908) +#define AFE_CONN55_5 (0x090c) +#define AFE_CONN56_5 (0x0910) +#define AFE_CONN57_5 (0x0914) +#define AFE_CONN58_5 (0x0918) +#define AFE_CONN59_5 (0x091c) +#define AFE_CONN60_5 (0x0920) +#define AFE_CONN61_5 (0x0924) +#define AFE_CONN62_5 (0x0928) +#define AFE_CONN63_5 (0x092c) +#define AFE_CONN64_5 (0x0930) +#define AFE_CONN65_5 (0x0934) +#define AFE_CONN66_5 (0x0938) +#define AFE_CONN67_5 (0x093c) +#define AFE_CONN68_5 (0x0940) +#define AFE_CONN69_5 (0x0944) +#define AFE_CONN70_5 (0x0948) +#define AFE_CONN71_5 (0x094c) +#define AFE_CONN72_5 (0x0950) +#define AFE_CONN73_5 (0x0954) +#define AFE_CONN74_5 (0x0958) +#define AFE_CONN75_5 (0x095c) +#define AFE_CONN76_5 (0x0960) +#define AFE_CONN77_5 (0x0964) +#define AFE_CONN78_5 (0x0968) +#define AFE_CONN79_5 (0x096c) +#define AFE_CONN80_5 (0x0970) +#define AFE_CONN81_5 (0x0974) +#define AFE_CONN82_5 (0x0978) +#define AFE_CONN83_5 (0x097c) +#define AFE_CONN84_5 (0x0980) +#define AFE_CONN85_5 (0x0984) +#define AFE_CONN86_5 (0x0988) +#define AFE_CONN87_5 (0x098c) +#define AFE_CONN88_5 (0x0990) +#define AFE_CONN89_5 (0x0994) +#define AFE_CONN90_5 (0x0998) +#define AFE_CONN91_5 (0x099c) +#define AFE_CONN92_5 (0x09a0) +#define AFE_CONN93_5 (0x09a4) +#define AFE_CONN94_5 (0x09a8) +#define AFE_CONN95_5 (0x09ac) +#define AFE_CONN96_5 (0x09b0) +#define AFE_CONN97_5 (0x09b4) +#define AFE_CONN98_5 (0x09b8) +#define AFE_CONN99_5 (0x09bc) +#define AFE_CONN100_5 (0x09c0) +#define AFE_CONN101_5 (0x09c4) +#define AFE_CONN102_5 (0x09c8) +#define AFE_CONN103_5 (0x09cc) +#define AFE_CONN104_5 (0x09d0) +#define AFE_CONN105_5 (0x09d4) +#define AFE_CONN106_5 (0x09d8) +#define AFE_CONN107_5 (0x09dc) +#define AFE_CONN108_5 (0x09e0) +#define AFE_CONN109_5 (0x09e4) +#define AFE_CONN110_5 (0x09e8) +#define AFE_CONN111_5 (0x09ec) +#define AFE_CONN112_5 (0x09f0) +#define AFE_CONN113_5 (0x09f4) +#define AFE_CONN114_5 (0x09f8) +#define AFE_CONN115_5 (0x09fc) +#define AFE_CONN116_5 (0x0a00) +#define AFE_CONN117_5 (0x0a04) +#define AFE_CONN118_5 (0x0a08) +#define AFE_CONN119_5 (0x0a0c) +#define AFE_CONN120_5 (0x0a10) +#define AFE_CONN121_5 (0x0a14) +#define AFE_CONN122_5 (0x0a18) +#define AFE_CONN123_5 (0x0a1c) +#define AFE_CONN124_5 (0x0a20) +#define AFE_CONN125_5 (0x0a24) +#define AFE_CONN126_5 (0x0a28) +#define AFE_CONN127_5 (0x0a2c) +#define AFE_CONN128_5 (0x0a30) +#define AFE_CONN129_5 (0x0a34) +#define AFE_CONN130_5 (0x0a38) +#define AFE_CONN131_5 (0x0a3c) +#define AFE_CONN132_5 (0x0a40) +#define AFE_CONN133_5 (0x0a44) +#define AFE_CONN134_5 (0x0a48) +#define AFE_CONN135_5 (0x0a4c) +#define AFE_CONN136_5 (0x0a50) +#define AFE_CONN137_5 (0x0a54) +#define AFE_CONN138_5 (0x0a58) +#define AFE_CONN139_5 (0x0a5c) +#define AFE_CONN_RS_5 (0x0a60) +#define AFE_CONN_DI_5 (0x0a64) +#define AFE_CONN_16BIT_5 (0x0a68) +#define AFE_CONN_24BIT_5 (0x0a6c) +#define AFE_ASRC11_NEW_CON0 (0x0d80) +#define AFE_ASRC11_NEW_CON1 (0x0d84) +#define AFE_ASRC11_NEW_CON2 (0x0d88) +#define AFE_ASRC11_NEW_CON3 (0x0d8c) +#define AFE_ASRC11_NEW_CON4 (0x0d90) +#define AFE_ASRC11_NEW_CON5 (0x0d94) +#define AFE_ASRC11_NEW_CON6 (0x0d98) +#define AFE_ASRC11_NEW_CON7 (0x0d9c) +#define AFE_ASRC11_NEW_CON8 (0x0da0) +#define AFE_ASRC11_NEW_CON9 (0x0da4) +#define AFE_ASRC11_NEW_CON10 (0x0da8) +#define AFE_ASRC11_NEW_CON11 (0x0dac) +#define AFE_ASRC11_NEW_CON13 (0x0db4) +#define AFE_ASRC11_NEW_CON14 (0x0db8) +#define AFE_ASRC12_NEW_CON0 (0x0dc0) +#define AFE_ASRC12_NEW_CON1 (0x0dc4) +#define AFE_ASRC12_NEW_CON2 (0x0dc8) +#define AFE_ASRC12_NEW_CON3 (0x0dcc) +#define AFE_ASRC12_NEW_CON4 (0x0dd0) +#define AFE_ASRC12_NEW_CON5 (0x0dd4) +#define AFE_ASRC12_NEW_CON6 (0x0dd8) +#define AFE_ASRC12_NEW_CON7 (0x0ddc) +#define AFE_ASRC12_NEW_CON8 (0x0de0) +#define AFE_ASRC12_NEW_CON9 (0x0de4) +#define AFE_ASRC12_NEW_CON10 (0x0de8) +#define AFE_ASRC12_NEW_CON11 (0x0dec) +#define AFE_ASRC12_NEW_CON13 (0x0df4) +#define AFE_ASRC12_NEW_CON14 (0x0df8) +#define AFE_LRCK_CNT (0x1018) +#define AFE_DAC_CON0 (0x1200) +#define AFE_DAC_CON1 (0x1204) +#define AFE_DAC_CON2 (0x1208) +#define AFE_DAC_MON0 (0x1218) +#define AFE_DL2_BASE (0x1250) +#define AFE_DL2_CUR (0x1254) +#define AFE_DL2_END (0x1258) +#define AFE_DL2_CON0 (0x125c) +#define AFE_DL3_BASE (0x1260) +#define AFE_DL3_CUR (0x1264) +#define AFE_DL3_END (0x1268) +#define AFE_DL3_CON0 (0x126c) +#define AFE_DL6_BASE (0x1290) +#define AFE_DL6_CUR (0x1294) +#define AFE_DL6_END (0x1298) +#define AFE_DL6_CON0 (0x129c) +#define AFE_DL7_BASE (0x12a0) +#define AFE_DL7_CUR (0x12a4) +#define AFE_DL7_END (0x12a8) +#define AFE_DL7_CON0 (0x12ac) +#define AFE_DL8_BASE (0x12b0) +#define AFE_DL8_CUR (0x12b4) +#define AFE_DL8_END (0x12b8) +#define AFE_DL8_CON0 (0x12bc) +#define AFE_DL10_BASE (0x12d0) +#define AFE_DL10_CUR (0x12d4) +#define AFE_DL10_END (0x12d8) +#define AFE_DL10_CON0 (0x12dc) +#define AFE_DL11_BASE (0x12e0) +#define AFE_DL11_CUR (0x12e4) +#define AFE_DL11_END (0x12e8) +#define AFE_DL11_CON0 (0x12ec) +#define AFE_UL1_BASE (0x1300) +#define AFE_UL1_CUR (0x1304) +#define AFE_UL1_END (0x1308) +#define AFE_UL1_CON0 (0x130c) +#define AFE_UL2_BASE (0x1310) +#define AFE_UL2_CUR (0x1314) +#define AFE_UL2_END (0x1318) +#define AFE_UL2_CON0 (0x131c) +#define AFE_UL3_BASE (0x1320) +#define AFE_UL3_CUR (0x1324) +#define AFE_UL3_END (0x1328) +#define AFE_UL3_CON0 (0x132c) +#define AFE_UL4_BASE (0x1330) +#define AFE_UL4_CUR (0x1334) +#define AFE_UL4_END (0x1338) +#define AFE_UL4_CON0 (0x133c) +#define AFE_UL5_BASE (0x1340) +#define AFE_UL5_CUR (0x1344) +#define AFE_UL5_END (0x1348) +#define AFE_UL5_CON0 (0x134c) +#define AFE_UL6_BASE (0x1350) +#define AFE_UL6_CUR (0x1354) +#define AFE_UL6_END (0x1358) +#define AFE_UL6_CON0 (0x135c) +#define AFE_UL8_BASE (0x1370) +#define AFE_UL8_CUR (0x1374) +#define AFE_UL8_END (0x1378) +#define AFE_UL8_CON0 (0x137c) +#define AFE_UL9_BASE (0x1380) +#define AFE_UL9_CUR (0x1384) +#define AFE_UL9_END (0x1388) +#define AFE_UL9_CON0 (0x138c) +#define AFE_UL10_BASE (0x13d0) +#define AFE_UL10_CUR (0x13d4) +#define AFE_UL10_END (0x13d8) +#define AFE_UL10_CON0 (0x13dc) +#define AFE_DL8_CHK_SUM1 (0x1400) +#define AFE_DL8_CHK_SUM2 (0x1404) +#define AFE_DL8_CHK_SUM3 (0x1408) +#define AFE_DL8_CHK_SUM4 (0x140c) +#define AFE_DL8_CHK_SUM5 (0x1410) +#define AFE_DL8_CHK_SUM6 (0x1414) +#define AFE_DL10_CHK_SUM1 (0x1418) +#define AFE_DL10_CHK_SUM2 (0x141c) +#define AFE_DL10_CHK_SUM3 (0x1420) +#define AFE_DL10_CHK_SUM4 (0x1424) +#define AFE_DL10_CHK_SUM5 (0x1428) +#define AFE_DL10_CHK_SUM6 (0x142c) +#define AFE_DL11_CHK_SUM1 (0x1430) +#define AFE_DL11_CHK_SUM2 (0x1434) +#define AFE_DL11_CHK_SUM3 (0x1438) +#define AFE_DL11_CHK_SUM4 (0x143c) +#define AFE_DL11_CHK_SUM5 (0x1440) +#define AFE_DL11_CHK_SUM6 (0x1444) +#define AFE_UL1_CHK_SUM1 (0x1450) +#define AFE_UL1_CHK_SUM2 (0x1454) +#define AFE_UL2_CHK_SUM1 (0x1458) +#define AFE_UL2_CHK_SUM2 (0x145c) +#define AFE_UL3_CHK_SUM1 (0x1460) +#define AFE_UL3_CHK_SUM2 (0x1464) +#define AFE_UL4_CHK_SUM1 (0x1468) +#define AFE_UL4_CHK_SUM2 (0x146c) +#define AFE_UL5_CHK_SUM1 (0x1470) +#define AFE_UL5_CHK_SUM2 (0x1474) +#define AFE_UL6_CHK_SUM1 (0x1478) +#define AFE_UL6_CHK_SUM2 (0x147c) +#define AFE_UL8_CHK_SUM1 (0x1488) +#define AFE_UL8_CHK_SUM2 (0x148c) +#define AFE_DL2_CHK_SUM1 (0x14a0) +#define AFE_DL2_CHK_SUM2 (0x14a4) +#define AFE_DL3_CHK_SUM1 (0x14b0) +#define AFE_DL3_CHK_SUM2 (0x14b4) +#define AFE_DL6_CHK_SUM1 (0x14e0) +#define AFE_DL6_CHK_SUM2 (0x14e4) +#define AFE_DL7_CHK_SUM1 (0x14f0) +#define AFE_DL7_CHK_SUM2 (0x14f4) +#define AFE_UL9_CHK_SUM1 (0x1528) +#define AFE_UL9_CHK_SUM2 (0x152c) +#define AFE_BUS_MON1 (0x1540) +#define UL1_MOD2AGT_CNT_LAT (0x1568) +#define UL2_MOD2AGT_CNT_LAT (0x156c) +#define UL3_MOD2AGT_CNT_LAT (0x1570) +#define UL4_MOD2AGT_CNT_LAT (0x1574) +#define UL5_MOD2AGT_CNT_LAT (0x1578) +#define UL6_MOD2AGT_CNT_LAT (0x157c) +#define UL8_MOD2AGT_CNT_LAT (0x1588) +#define UL9_MOD2AGT_CNT_LAT (0x158c) +#define UL10_MOD2AGT_CNT_LAT (0x1590) +#define AFE_MEMIF_AGENT_FS_CON0 (0x15a0) +#define AFE_MEMIF_AGENT_FS_CON1 (0x15a4) +#define AFE_MEMIF_AGENT_FS_CON2 (0x15a8) +#define AFE_MEMIF_AGENT_FS_CON3 (0x15ac) +#define AFE_MEMIF_BURST_CFG (0x1600) +#define AFE_MEMIF_BUF_FULL_MON (0x1610) +#define AFE_MEMIF_BUF_MON1 (0x161c) +#define AFE_MEMIF_BUF_MON3 (0x1624) +#define AFE_MEMIF_BUF_MON4 (0x1628) +#define AFE_MEMIF_BUF_MON5 (0x162c) +#define AFE_MEMIF_BUF_MON6 (0x1630) +#define AFE_MEMIF_BUF_MON7 (0x1634) +#define AFE_MEMIF_BUF_MON8 (0x1638) +#define AFE_MEMIF_BUF_MON9 (0x163c) +#define AFE_MEMIF_BUF_MON10 (0x1640) +#define DL2_AGENT2MODULE_CNT (0x1678) +#define DL3_AGENT2MODULE_CNT (0x167c) +#define DL6_AGENT2MODULE_CNT (0x1688) +#define DL7_AGENT2MODULE_CNT (0x168c) +#define DL8_AGENT2MODULE_CNT (0x1690) +#define DL10_AGENT2MODULE_CNT (0x1698) +#define DL11_AGENT2MODULE_CNT (0x169c) +#define UL1_MODULE2AGENT_CNT (0x16a0) +#define UL2_MODULE2AGENT_CNT (0x16a4) +#define UL3_MODULE2AGENT_CNT (0x16a8) +#define UL4_MODULE2AGENT_CNT (0x16ac) +#define UL5_MODULE2AGENT_CNT (0x16b0) +#define UL6_MODULE2AGENT_CNT (0x16b4) +#define UL8_MODULE2AGENT_CNT (0x16bc) +#define UL9_MODULE2AGENT_CNT (0x16c0) +#define UL10_MODULE2AGENT_CNT (0x16c4) +#define AFE_SECURE_CON2 (0x1798) +#define AFE_SECURE_CON1 (0x179c) +#define AFE_SECURE_CON (0x17a0) +#define AFE_SRAM_BOUND (0x17a4) +#define AFE_SE_SECURE_CON (0x17a8) +#define AFE_SECURE_MASK_LOOPBACK (0x17bc) +#define AFE_SECURE_SIDEBAND0 (0x1908) +#define AFE_SECURE_SIDEBAND1 (0x190c) +#define AFE_SECURE_SIDEBAND2 (0x1910) +#define AFE_SECURE_SIDEBAND3 (0x1914) +#define AFE_SECURE_MASK_BASE_ADR_MSB (0x1920) +#define AFE_SECURE_MASK_END_ADR_MSB (0x1924) +#define AFE_NORMAL_BASE_ADR_MSB (0x192c) +#define AFE_NORMAL_END_ADR_MSB (0x1930) +#define AFE_SECURE_MASK_LOOPBACK0 (0x1940) +#define AFE_SECURE_MASK_LOOPBACK1 (0x1944) +#define AFE_SECURE_MASK_LOOPBACK2 (0x1948) +#define AFE_LOOPBACK_CFG0 (0x1950) +#define AFE_LOOPBACK_CFG1 (0x1954) +#define AFE_LOOPBACK_CFG2 (0x1958) +#define AFE_DMIC0_UL_SRC_CON0 (0x1a00) +#define AFE_DMIC0_UL_SRC_CON1 (0x1a04) +#define AFE_DMIC0_SRC_DEBUG (0x1a08) +#define AFE_DMIC0_SRC_DEBUG_MON0 (0x1a0c) +#define AFE_DMIC0_UL_SRC_MON0 (0x1a10) +#define AFE_DMIC0_UL_SRC_MON1 (0x1a14) +#define AFE_DMIC0_IIR_COEF_02_01 (0x1a18) +#define AFE_DMIC0_IIR_COEF_04_03 (0x1a1c) +#define AFE_DMIC0_IIR_COEF_06_05 (0x1a20) +#define AFE_DMIC0_IIR_COEF_08_07 (0x1a24) +#define AFE_DMIC0_IIR_COEF_10_09 (0x1a28) +#define AFE_DMIC1_UL_SRC_CON0 (0x1a68) +#define AFE_DMIC1_UL_SRC_CON1 (0x1a6c) +#define AFE_DMIC1_SRC_DEBUG (0x1a70) +#define AFE_DMIC1_SRC_DEBUG_MON0 (0x1a74) +#define AFE_DMIC1_UL_SRC_MON0 (0x1a78) +#define AFE_DMIC1_UL_SRC_MON1 (0x1a7c) +#define AFE_DMIC1_IIR_COEF_02_01 (0x1a80) +#define AFE_DMIC1_IIR_COEF_04_03 (0x1a84) +#define AFE_DMIC1_IIR_COEF_06_05 (0x1a88) +#define AFE_DMIC1_IIR_COEF_08_07 (0x1a8c) +#define AFE_DMIC1_IIR_COEF_10_09 (0x1a90) +#define AFE_DMIC2_UL_SRC_CON0 (0x1ad0) +#define AFE_DMIC2_UL_SRC_CON1 (0x1ad4) +#define AFE_DMIC2_SRC_DEBUG (0x1ad8) +#define AFE_DMIC2_SRC_DEBUG_MON0 (0x1adc) +#define AFE_DMIC2_UL_SRC_MON0 (0x1ae0) +#define AFE_DMIC2_UL_SRC_MON1 (0x1ae4) +#define AFE_DMIC2_IIR_COEF_02_01 (0x1ae8) +#define AFE_DMIC2_IIR_COEF_04_03 (0x1aec) +#define AFE_DMIC2_IIR_COEF_06_05 (0x1af0) +#define AFE_DMIC2_IIR_COEF_08_07 (0x1af4) +#define AFE_DMIC2_IIR_COEF_10_09 (0x1af8) +#define AFE_DMIC3_UL_SRC_CON0 (0x1b38) +#define AFE_DMIC3_UL_SRC_CON1 (0x1b3c) +#define AFE_DMIC3_SRC_DEBUG (0x1b40) +#define AFE_DMIC3_SRC_DEBUG_MON0 (0x1b44) +#define AFE_DMIC3_UL_SRC_MON0 (0x1b48) +#define AFE_DMIC3_UL_SRC_MON1 (0x1b4c) +#define AFE_DMIC3_IIR_COEF_02_01 (0x1b50) +#define AFE_DMIC3_IIR_COEF_04_03 (0x1b54) +#define AFE_DMIC3_IIR_COEF_06_05 (0x1b58) +#define AFE_DMIC3_IIR_COEF_08_07 (0x1b5c) +#define AFE_DMIC3_IIR_COEF_10_09 (0x1b60) +#define DMIC_BYPASS_HW_GAIN (0x1bf0) +#define DMIC_GAIN1_CON0 (0x1c00) +#define DMIC_GAIN1_CON1 (0x1c04) +#define DMIC_GAIN1_CON2 (0x1c08) +#define DMIC_GAIN1_CON3 (0x1c0c) +#define DMIC_GAIN1_CUR (0x1c10) +#define DMIC_GAIN2_CON0 (0x1c20) +#define DMIC_GAIN2_CON1 (0x1c24) +#define DMIC_GAIN2_CON2 (0x1c28) +#define DMIC_GAIN2_CON3 (0x1c2c) +#define DMIC_GAIN2_CUR (0x1c30) +#define DMIC_GAIN3_CON0 (0x1c40) +#define DMIC_GAIN3_CON1 (0x1c44) +#define DMIC_GAIN3_CON2 (0x1c48) +#define DMIC_GAIN3_CON3 (0x1c4c) +#define DMIC_GAIN3_CUR (0x1c50) +#define DMIC_GAIN4_CON0 (0x1c60) +#define DMIC_GAIN4_CON1 (0x1c64) +#define DMIC_GAIN4_CON2 (0x1c68) +#define DMIC_GAIN4_CON3 (0x1c6c) +#define DMIC_GAIN4_CUR (0x1c70) +#define ETDM_OUT1_DSD_FADE_CON (0x2260) +#define ETDM_OUT1_DSD_FADE_CON1 (0x2264) +#define ETDM_OUT3_DSD_FADE_CON (0x2280) +#define ETDM_OUT3_DSD_FADE_CON1 (0x2284) +#define ETDM_IN1_AFIFO_CON (0x2294) +#define ETDM_IN2_AFIFO_CON (0x2298) +#define ETDM_IN1_MONITOR (0x22c0) +#define ETDM_IN2_MONITOR (0x22c4) +#define ETDM_OUT1_MONITOR (0x22d0) +#define ETDM_OUT2_MONITOR (0x22d4) +#define ETDM_OUT3_MONITOR (0x22d8) +#define ETDM_COWORK_SEC_CON0 (0x22e0) +#define ETDM_COWORK_SEC_CON1 (0x22e4) +#define ETDM_COWORK_SEC_CON2 (0x22e8) +#define ETDM_COWORK_SEC_CON3 (0x22ec) +#define ETDM_COWORK_CON0 (0x22f0) +#define ETDM_COWORK_CON1 (0x22f4) +#define ETDM_COWORK_CON2 (0x22f8) +#define ETDM_COWORK_CON3 (0x22fc) +#define ETDM_IN1_CON0 (0x2300) +#define ETDM_IN1_CON1 (0x2304) +#define ETDM_IN1_CON2 (0x2308) +#define ETDM_IN1_CON3 (0x230c) +#define ETDM_IN1_CON4 (0x2310) +#define ETDM_IN1_CON5 (0x2314) +#define ETDM_IN1_CON6 (0x2318) +#define ETDM_IN1_CON7 (0x231c) +#define ETDM_IN2_CON0 (0x2320) +#define ETDM_IN2_CON1 (0x2324) +#define ETDM_IN2_CON2 (0x2328) +#define ETDM_IN2_CON3 (0x232c) +#define ETDM_IN2_CON4 (0x2330) +#define ETDM_IN2_CON5 (0x2334) +#define ETDM_IN2_CON6 (0x2338) +#define ETDM_IN2_CON7 (0x233c) +#define ETDM_OUT1_CON0 (0x2380) +#define ETDM_OUT1_CON1 (0x2384) +#define ETDM_OUT1_CON2 (0x2388) +#define ETDM_OUT1_CON3 (0x238c) +#define ETDM_OUT1_CON4 (0x2390) +#define ETDM_OUT1_CON5 (0x2394) +#define ETDM_OUT1_CON6 (0x2398) +#define ETDM_OUT1_CON7 (0x239c) +#define ETDM_OUT2_CON0 (0x23a0) +#define ETDM_OUT2_CON1 (0x23a4) +#define ETDM_OUT2_CON2 (0x23a8) +#define ETDM_OUT2_CON3 (0x23ac) +#define ETDM_OUT2_CON4 (0x23b0) +#define ETDM_OUT2_CON5 (0x23b4) +#define ETDM_OUT2_CON6 (0x23b8) +#define ETDM_OUT2_CON7 (0x23bc) +#define ETDM_OUT3_CON0 (0x23c0) +#define ETDM_OUT3_CON1 (0x23c4) +#define ETDM_OUT3_CON2 (0x23c8) +#define ETDM_OUT3_CON3 (0x23cc) +#define ETDM_OUT3_CON4 (0x23d0) +#define ETDM_OUT3_CON5 (0x23d4) +#define ETDM_OUT3_CON6 (0x23d8) +#define ETDM_OUT3_CON7 (0x23dc) +#define ETDM_OUT3_CON8 (0x23e0) +#define ETDM_OUT1_CON8 (0x23e4) +#define ETDM_OUT2_CON8 (0x23e8) +#define GASRC_TIMING_CON0 (0x2414) +#define GASRC_TIMING_CON1 (0x2418) +#define GASRC_TIMING_CON2 (0x241c) +#define GASRC_TIMING_CON3 (0x2420) +#define GASRC_TIMING_CON4 (0x2424) +#define GASRC_TIMING_CON5 (0x2428) +#define GASRC_TIMING_CON6 (0x242c) +#define GASRC_TIMING_CON7 (0x2430) +#define A3_A4_TIMING_SEL0 (0x2440) +#define A3_A4_TIMING_SEL1 (0x2444) +#define A3_A4_TIMING_SEL2 (0x2448) +#define A3_A4_TIMING_SEL3 (0x244c) +#define A3_A4_TIMING_SEL4 (0x2450) +#define A3_A4_TIMING_SEL5 (0x2454) +#define A3_A4_TIMING_SEL6 (0x2458) +#define ASYS_TOP_DEBUG (0x2500) +#define AFE_DPTX_CON (0x2558) +#define AFE_DPTX_MON (0x255c) +#define AFE_ADDA_DL_SRC2_CON0 (0x2d00) +#define AFE_ADDA_DL_SRC2_CON1 (0x2d04) +#define AFE_ADDA_TOP_CON0 (0x2d0c) +#define AFE_ADDA_UL_DL_CON0 (0x2d10) +#define AFE_ADDA_SRC_DEBUG (0x2d14) +#define AFE_ADDA_SRC_DEBUG_MON0 (0x2d18) +#define AFE_ADDA_SRC_DEBUG_MON1 (0x2d20) +#define AFE_ADDA_PREDIS_CON0 (0x2d24) +#define AFE_ADDA_PREDIS_CON1 (0x2d28) +#define AFE_ADDA_PREDIS_CON2 (0x2d2c) +#define AFE_ADDA_PREDIS_CON3 (0x2d30) +#define AFE_ADDA_DL_SDM_DCCOMP_CON (0x2d34) +#define AFE_ADDA_DL_SDM_TEST (0x2d38) +#define AFE_ADDA_DL_DC_COMP_CFG0 (0x2d3c) +#define AFE_ADDA_DL_DC_COMP_CFG1 (0x2d40) +#define AFE_ADDA_DL_SDM_FIFO_MON (0x2d44) +#define AFE_ADDA_DL_SRC_LCH_MON (0x2d50) +#define AFE_ADDA_DL_SRC_RCH_MON (0x2d54) +#define AFE_ADDA_DL_SDM_OUT_MON (0x2d58) +#define AFE_ADDA_DL_SDM_DITHER_CON (0x2d5c) +#define AFE_ADDA_DL_SDM_AUTO_RESET_CON (0x2d60) +#define AFE_ADDA_UL_SRC_CON0 (0x2e3c) +#define AFE_ADDA_UL_SRC_CON1 (0x2e40) +#define AFE_CONN0 (0x3000) +#define AFE_CONN0_1 (0x3004) +#define AFE_CONN0_2 (0x3008) +#define AFE_CONN0_3 (0x300c) +#define AFE_CONN0_4 (0x3010) +#define AFE_CONN1 (0x3014) +#define AFE_CONN1_1 (0x3018) +#define AFE_CONN1_2 (0x301c) +#define AFE_CONN1_3 (0x3020) +#define AFE_CONN1_4 (0x3024) +#define AFE_CONN2 (0x3028) +#define AFE_CONN2_1 (0x302c) +#define AFE_CONN2_2 (0x3030) +#define AFE_CONN2_3 (0x3034) +#define AFE_CONN2_4 (0x3038) +#define AFE_CONN3 (0x303c) +#define AFE_CONN3_1 (0x3040) +#define AFE_CONN3_2 (0x3044) +#define AFE_CONN3_3 (0x3048) +#define AFE_CONN3_4 (0x304c) +#define AFE_CONN4 (0x3050) +#define AFE_CONN4_1 (0x3054) +#define AFE_CONN4_2 (0x3058) +#define AFE_CONN4_3 (0x305c) +#define AFE_CONN4_4 (0x3060) +#define AFE_CONN5 (0x3064) +#define AFE_CONN5_1 (0x3068) +#define AFE_CONN5_2 (0x306c) +#define AFE_CONN5_3 (0x3070) +#define AFE_CONN5_4 (0x3074) +#define AFE_CONN6 (0x3078) +#define AFE_CONN6_1 (0x307c) +#define AFE_CONN6_2 (0x3080) +#define AFE_CONN6_3 (0x3084) +#define AFE_CONN6_4 (0x3088) +#define AFE_CONN7 (0x308c) +#define AFE_CONN7_1 (0x3090) +#define AFE_CONN7_2 (0x3094) +#define AFE_CONN7_3 (0x3098) +#define AFE_CONN7_4 (0x309c) +#define AFE_CONN8 (0x30a0) +#define AFE_CONN8_1 (0x30a4) +#define AFE_CONN8_2 (0x30a8) +#define AFE_CONN8_3 (0x30ac) +#define AFE_CONN8_4 (0x30b0) +#define AFE_CONN9 (0x30b4) +#define AFE_CONN9_1 (0x30b8) +#define AFE_CONN9_2 (0x30bc) +#define AFE_CONN9_3 (0x30c0) +#define AFE_CONN9_4 (0x30c4) +#define AFE_CONN10 (0x30c8) +#define AFE_CONN10_1 (0x30cc) +#define AFE_CONN10_2 (0x30d0) +#define AFE_CONN10_3 (0x30d4) +#define AFE_CONN10_4 (0x30d8) +#define AFE_CONN11 (0x30dc) +#define AFE_CONN11_1 (0x30e0) +#define AFE_CONN11_2 (0x30e4) +#define AFE_CONN11_3 (0x30e8) +#define AFE_CONN11_4 (0x30ec) +#define AFE_CONN12 (0x30f0) +#define AFE_CONN12_1 (0x30f4) +#define AFE_CONN12_2 (0x30f8) +#define AFE_CONN12_3 (0x30fc) +#define AFE_CONN12_4 (0x3100) +#define AFE_CONN13 (0x3104) +#define AFE_CONN13_1 (0x3108) +#define AFE_CONN13_2 (0x310c) +#define AFE_CONN13_3 (0x3110) +#define AFE_CONN13_4 (0x3114) +#define AFE_CONN14 (0x3118) +#define AFE_CONN14_1 (0x311c) +#define AFE_CONN14_2 (0x3120) +#define AFE_CONN14_3 (0x3124) +#define AFE_CONN14_4 (0x3128) +#define AFE_CONN15 (0x312c) +#define AFE_CONN15_1 (0x3130) +#define AFE_CONN15_2 (0x3134) +#define AFE_CONN15_3 (0x3138) +#define AFE_CONN15_4 (0x313c) +#define AFE_CONN16 (0x3140) +#define AFE_CONN16_1 (0x3144) +#define AFE_CONN16_2 (0x3148) +#define AFE_CONN16_3 (0x314c) +#define AFE_CONN16_4 (0x3150) +#define AFE_CONN17 (0x3154) +#define AFE_CONN17_1 (0x3158) +#define AFE_CONN17_2 (0x315c) +#define AFE_CONN17_3 (0x3160) +#define AFE_CONN17_4 (0x3164) +#define AFE_CONN18 (0x3168) +#define AFE_CONN18_1 (0x316c) +#define AFE_CONN18_2 (0x3170) +#define AFE_CONN18_3 (0x3174) +#define AFE_CONN18_4 (0x3178) +#define AFE_CONN19 (0x317c) +#define AFE_CONN19_1 (0x3180) +#define AFE_CONN19_2 (0x3184) +#define AFE_CONN19_3 (0x3188) +#define AFE_CONN19_4 (0x318c) +#define AFE_CONN20 (0x3190) +#define AFE_CONN20_1 (0x3194) +#define AFE_CONN20_2 (0x3198) +#define AFE_CONN20_3 (0x319c) +#define AFE_CONN20_4 (0x31a0) +#define AFE_CONN21 (0x31a4) +#define AFE_CONN21_1 (0x31a8) +#define AFE_CONN21_2 (0x31ac) +#define AFE_CONN21_3 (0x31b0) +#define AFE_CONN21_4 (0x31b4) +#define AFE_CONN22 (0x31b8) +#define AFE_CONN22_1 (0x31bc) +#define AFE_CONN22_2 (0x31c0) +#define AFE_CONN22_3 (0x31c4) +#define AFE_CONN22_4 (0x31c8) +#define AFE_CONN23 (0x31cc) +#define AFE_CONN23_1 (0x31d0) +#define AFE_CONN23_2 (0x31d4) +#define AFE_CONN23_3 (0x31d8) +#define AFE_CONN23_4 (0x31dc) +#define AFE_CONN24 (0x31e0) +#define AFE_CONN24_1 (0x31e4) +#define AFE_CONN24_2 (0x31e8) +#define AFE_CONN24_3 (0x31ec) +#define AFE_CONN24_4 (0x31f0) +#define AFE_CONN25 (0x31f4) +#define AFE_CONN25_1 (0x31f8) +#define AFE_CONN25_2 (0x31fc) +#define AFE_CONN25_3 (0x3200) +#define AFE_CONN25_4 (0x3204) +#define AFE_CONN26 (0x3208) +#define AFE_CONN26_1 (0x320c) +#define AFE_CONN26_2 (0x3210) +#define AFE_CONN26_3 (0x3214) +#define AFE_CONN26_4 (0x3218) +#define AFE_CONN27 (0x321c) +#define AFE_CONN27_1 (0x3220) +#define AFE_CONN27_2 (0x3224) +#define AFE_CONN27_3 (0x3228) +#define AFE_CONN27_4 (0x322c) +#define AFE_CONN28 (0x3230) +#define AFE_CONN28_1 (0x3234) +#define AFE_CONN28_2 (0x3238) +#define AFE_CONN28_3 (0x323c) +#define AFE_CONN28_4 (0x3240) +#define AFE_CONN29 (0x3244) +#define AFE_CONN29_1 (0x3248) +#define AFE_CONN29_2 (0x324c) +#define AFE_CONN29_3 (0x3250) +#define AFE_CONN29_4 (0x3254) +#define AFE_CONN30 (0x3258) +#define AFE_CONN30_1 (0x325c) +#define AFE_CONN30_2 (0x3260) +#define AFE_CONN30_3 (0x3264) +#define AFE_CONN30_4 (0x3268) +#define AFE_CONN31 (0x326c) +#define AFE_CONN31_1 (0x3270) +#define AFE_CONN31_2 (0x3274) +#define AFE_CONN31_3 (0x3278) +#define AFE_CONN31_4 (0x327c) +#define AFE_CONN32 (0x3280) +#define AFE_CONN32_1 (0x3284) +#define AFE_CONN32_2 (0x3288) +#define AFE_CONN32_3 (0x328c) +#define AFE_CONN32_4 (0x3290) +#define AFE_CONN33 (0x3294) +#define AFE_CONN33_1 (0x3298) +#define AFE_CONN33_2 (0x329c) +#define AFE_CONN33_3 (0x32a0) +#define AFE_CONN33_4 (0x32a4) +#define AFE_CONN34 (0x32a8) +#define AFE_CONN34_1 (0x32ac) +#define AFE_CONN34_2 (0x32b0) +#define AFE_CONN34_3 (0x32b4) +#define AFE_CONN34_4 (0x32b8) +#define AFE_CONN35 (0x32bc) +#define AFE_CONN35_1 (0x32c0) +#define AFE_CONN35_2 (0x32c4) +#define AFE_CONN35_3 (0x32c8) +#define AFE_CONN35_4 (0x32cc) +#define AFE_CONN36 (0x32d0) +#define AFE_CONN36_1 (0x32d4) +#define AFE_CONN36_2 (0x32d8) +#define AFE_CONN36_3 (0x32dc) +#define AFE_CONN36_4 (0x32e0) +#define AFE_CONN37 (0x32e4) +#define AFE_CONN37_1 (0x32e8) +#define AFE_CONN37_2 (0x32ec) +#define AFE_CONN37_3 (0x32f0) +#define AFE_CONN37_4 (0x32f4) +#define AFE_CONN38 (0x32f8) +#define AFE_CONN38_1 (0x32fc) +#define AFE_CONN38_2 (0x3300) +#define AFE_CONN38_3 (0x3304) +#define AFE_CONN38_4 (0x3308) +#define AFE_CONN39 (0x330c) +#define AFE_CONN39_1 (0x3310) +#define AFE_CONN39_2 (0x3314) +#define AFE_CONN39_3 (0x3318) +#define AFE_CONN39_4 (0x331c) +#define AFE_CONN40 (0x3320) +#define AFE_CONN40_1 (0x3324) +#define AFE_CONN40_2 (0x3328) +#define AFE_CONN40_3 (0x332c) +#define AFE_CONN40_4 (0x3330) +#define AFE_CONN41 (0x3334) +#define AFE_CONN41_1 (0x3338) +#define AFE_CONN41_2 (0x333c) +#define AFE_CONN41_3 (0x3340) +#define AFE_CONN41_4 (0x3344) +#define AFE_CONN42 (0x3348) +#define AFE_CONN42_1 (0x334c) +#define AFE_CONN42_2 (0x3350) +#define AFE_CONN42_3 (0x3354) +#define AFE_CONN42_4 (0x3358) +#define AFE_CONN43 (0x335c) +#define AFE_CONN43_1 (0x3360) +#define AFE_CONN43_2 (0x3364) +#define AFE_CONN43_3 (0x3368) +#define AFE_CONN43_4 (0x336c) +#define AFE_CONN44 (0x3370) +#define AFE_CONN44_1 (0x3374) +#define AFE_CONN44_2 (0x3378) +#define AFE_CONN44_3 (0x337c) +#define AFE_CONN44_4 (0x3380) +#define AFE_CONN45 (0x3384) +#define AFE_CONN45_1 (0x3388) +#define AFE_CONN45_2 (0x338c) +#define AFE_CONN45_3 (0x3390) +#define AFE_CONN45_4 (0x3394) +#define AFE_CONN46 (0x3398) +#define AFE_CONN46_1 (0x339c) +#define AFE_CONN46_2 (0x33a0) +#define AFE_CONN46_3 (0x33a4) +#define AFE_CONN46_4 (0x33a8) +#define AFE_CONN47 (0x33ac) +#define AFE_CONN47_1 (0x33b0) +#define AFE_CONN47_2 (0x33b4) +#define AFE_CONN47_3 (0x33b8) +#define AFE_CONN47_4 (0x33bc) +#define AFE_CONN48 (0x33c0) +#define AFE_CONN48_1 (0x33c4) +#define AFE_CONN48_2 (0x33c8) +#define AFE_CONN48_3 (0x33cc) +#define AFE_CONN48_4 (0x33d0) +#define AFE_CONN49 (0x33d4) +#define AFE_CONN49_1 (0x33d8) +#define AFE_CONN49_2 (0x33dc) +#define AFE_CONN49_3 (0x33e0) +#define AFE_CONN49_4 (0x33e4) +#define AFE_CONN50 (0x33e8) +#define AFE_CONN50_1 (0x33ec) +#define AFE_CONN50_2 (0x33f0) +#define AFE_CONN50_3 (0x33f4) +#define AFE_CONN50_4 (0x33f8) +#define AFE_CONN51 (0x33fc) +#define AFE_CONN51_1 (0x3400) +#define AFE_CONN51_2 (0x3404) +#define AFE_CONN51_3 (0x3408) +#define AFE_CONN51_4 (0x340c) +#define AFE_CONN52 (0x3410) +#define AFE_CONN52_1 (0x3414) +#define AFE_CONN52_2 (0x3418) +#define AFE_CONN52_3 (0x341c) +#define AFE_CONN52_4 (0x3420) +#define AFE_CONN53 (0x3424) +#define AFE_CONN53_1 (0x3428) +#define AFE_CONN53_2 (0x342c) +#define AFE_CONN53_3 (0x3430) +#define AFE_CONN53_4 (0x3434) +#define AFE_CONN54 (0x3438) +#define AFE_CONN54_1 (0x343c) +#define AFE_CONN54_2 (0x3440) +#define AFE_CONN54_3 (0x3444) +#define AFE_CONN54_4 (0x3448) +#define AFE_CONN55 (0x344c) +#define AFE_CONN55_1 (0x3450) +#define AFE_CONN55_2 (0x3454) +#define AFE_CONN55_3 (0x3458) +#define AFE_CONN55_4 (0x345c) +#define AFE_CONN56 (0x3460) +#define AFE_CONN56_1 (0x3464) +#define AFE_CONN56_2 (0x3468) +#define AFE_CONN56_3 (0x346c) +#define AFE_CONN56_4 (0x3470) +#define AFE_CONN57 (0x3474) +#define AFE_CONN57_1 (0x3478) +#define AFE_CONN57_2 (0x347c) +#define AFE_CONN57_3 (0x3480) +#define AFE_CONN57_4 (0x3484) +#define AFE_CONN58 (0x3488) +#define AFE_CONN58_1 (0x348c) +#define AFE_CONN58_2 (0x3490) +#define AFE_CONN58_3 (0x3494) +#define AFE_CONN58_4 (0x3498) +#define AFE_CONN59 (0x349c) +#define AFE_CONN59_1 (0x34a0) +#define AFE_CONN59_2 (0x34a4) +#define AFE_CONN59_3 (0x34a8) +#define AFE_CONN59_4 (0x34ac) +#define AFE_CONN60 (0x34b0) +#define AFE_CONN60_1 (0x34b4) +#define AFE_CONN60_2 (0x34b8) +#define AFE_CONN60_3 (0x34bc) +#define AFE_CONN60_4 (0x34c0) +#define AFE_CONN61 (0x34c4) +#define AFE_CONN61_1 (0x34c8) +#define AFE_CONN61_2 (0x34cc) +#define AFE_CONN61_3 (0x34d0) +#define AFE_CONN61_4 (0x34d4) +#define AFE_CONN62 (0x34d8) +#define AFE_CONN62_1 (0x34dc) +#define AFE_CONN62_2 (0x34e0) +#define AFE_CONN62_3 (0x34e4) +#define AFE_CONN62_4 (0x34e8) +#define AFE_CONN63 (0x34ec) +#define AFE_CONN63_1 (0x34f0) +#define AFE_CONN63_2 (0x34f4) +#define AFE_CONN63_3 (0x34f8) +#define AFE_CONN63_4 (0x34fc) +#define AFE_CONN64 (0x3500) +#define AFE_CONN64_1 (0x3504) +#define AFE_CONN64_2 (0x3508) +#define AFE_CONN64_3 (0x350c) +#define AFE_CONN64_4 (0x3510) +#define AFE_CONN65 (0x3514) +#define AFE_CONN65_1 (0x3518) +#define AFE_CONN65_2 (0x351c) +#define AFE_CONN65_3 (0x3520) +#define AFE_CONN65_4 (0x3524) +#define AFE_CONN66 (0x3528) +#define AFE_CONN66_1 (0x352c) +#define AFE_CONN66_2 (0x3530) +#define AFE_CONN66_3 (0x3534) +#define AFE_CONN66_4 (0x3538) +#define AFE_CONN67 (0x353c) +#define AFE_CONN67_1 (0x3540) +#define AFE_CONN67_2 (0x3544) +#define AFE_CONN67_3 (0x3548) +#define AFE_CONN67_4 (0x354c) +#define AFE_CONN68 (0x3550) +#define AFE_CONN68_1 (0x3554) +#define AFE_CONN68_2 (0x3558) +#define AFE_CONN68_3 (0x355c) +#define AFE_CONN68_4 (0x3560) +#define AFE_CONN69 (0x3564) +#define AFE_CONN69_1 (0x3568) +#define AFE_CONN69_2 (0x356c) +#define AFE_CONN69_3 (0x3570) +#define AFE_CONN69_4 (0x3574) +#define AFE_CONN70 (0x3578) +#define AFE_CONN70_1 (0x357c) +#define AFE_CONN70_2 (0x3580) +#define AFE_CONN70_3 (0x3584) +#define AFE_CONN70_4 (0x3588) +#define AFE_CONN71 (0x358c) +#define AFE_CONN71_1 (0x3590) +#define AFE_CONN71_2 (0x3594) +#define AFE_CONN71_3 (0x3598) +#define AFE_CONN71_4 (0x359c) +#define AFE_CONN72 (0x35a0) +#define AFE_CONN72_1 (0x35a4) +#define AFE_CONN72_2 (0x35a8) +#define AFE_CONN72_3 (0x35ac) +#define AFE_CONN72_4 (0x35b0) +#define AFE_CONN73 (0x35b4) +#define AFE_CONN73_1 (0x35b8) +#define AFE_CONN73_2 (0x35bc) +#define AFE_CONN73_3 (0x35c0) +#define AFE_CONN73_4 (0x35c4) +#define AFE_CONN74 (0x35c8) +#define AFE_CONN74_1 (0x35cc) +#define AFE_CONN74_2 (0x35d0) +#define AFE_CONN74_3 (0x35d4) +#define AFE_CONN74_4 (0x35d8) +#define AFE_CONN75 (0x35dc) +#define AFE_CONN75_1 (0x35e0) +#define AFE_CONN75_2 (0x35e4) +#define AFE_CONN75_3 (0x35e8) +#define AFE_CONN75_4 (0x35ec) +#define AFE_CONN76 (0x35f0) +#define AFE_CONN76_1 (0x35f4) +#define AFE_CONN76_2 (0x35f8) +#define AFE_CONN76_3 (0x35fc) +#define AFE_CONN76_4 (0x3600) +#define AFE_CONN77 (0x3604) +#define AFE_CONN77_1 (0x3608) +#define AFE_CONN77_2 (0x360c) +#define AFE_CONN77_3 (0x3610) +#define AFE_CONN77_4 (0x3614) +#define AFE_CONN78 (0x3618) +#define AFE_CONN78_1 (0x361c) +#define AFE_CONN78_2 (0x3620) +#define AFE_CONN78_3 (0x3624) +#define AFE_CONN78_4 (0x3628) +#define AFE_CONN79 (0x362c) +#define AFE_CONN79_1 (0x3630) +#define AFE_CONN79_2 (0x3634) +#define AFE_CONN79_3 (0x3638) +#define AFE_CONN79_4 (0x363c) +#define AFE_CONN80 (0x3640) +#define AFE_CONN80_1 (0x3644) +#define AFE_CONN80_2 (0x3648) +#define AFE_CONN80_3 (0x364c) +#define AFE_CONN80_4 (0x3650) +#define AFE_CONN81 (0x3654) +#define AFE_CONN81_1 (0x3658) +#define AFE_CONN81_2 (0x365c) +#define AFE_CONN81_3 (0x3660) +#define AFE_CONN81_4 (0x3664) +#define AFE_CONN82 (0x3668) +#define AFE_CONN82_1 (0x366c) +#define AFE_CONN82_2 (0x3670) +#define AFE_CONN82_3 (0x3674) +#define AFE_CONN82_4 (0x3678) +#define AFE_CONN83 (0x367c) +#define AFE_CONN83_1 (0x3680) +#define AFE_CONN83_2 (0x3684) +#define AFE_CONN83_3 (0x3688) +#define AFE_CONN83_4 (0x368c) +#define AFE_CONN84 (0x3690) +#define AFE_CONN84_1 (0x3694) +#define AFE_CONN84_2 (0x3698) +#define AFE_CONN84_3 (0x369c) +#define AFE_CONN84_4 (0x36a0) +#define AFE_CONN85 (0x36a4) +#define AFE_CONN85_1 (0x36a8) +#define AFE_CONN85_2 (0x36ac) +#define AFE_CONN85_3 (0x36b0) +#define AFE_CONN85_4 (0x36b4) +#define AFE_CONN86 (0x36b8) +#define AFE_CONN86_1 (0x36bc) +#define AFE_CONN86_2 (0x36c0) +#define AFE_CONN86_3 (0x36c4) +#define AFE_CONN86_4 (0x36c8) +#define AFE_CONN87 (0x36cc) +#define AFE_CONN87_1 (0x36d0) +#define AFE_CONN87_2 (0x36d4) +#define AFE_CONN87_3 (0x36d8) +#define AFE_CONN87_4 (0x36dc) +#define AFE_CONN88 (0x36e0) +#define AFE_CONN88_1 (0x36e4) +#define AFE_CONN88_2 (0x36e8) +#define AFE_CONN88_3 (0x36ec) +#define AFE_CONN88_4 (0x36f0) +#define AFE_CONN89 (0x36f4) +#define AFE_CONN89_1 (0x36f8) +#define AFE_CONN89_2 (0x36fc) +#define AFE_CONN89_3 (0x3700) +#define AFE_CONN89_4 (0x3704) +#define AFE_CONN90 (0x3708) +#define AFE_CONN90_1 (0x370c) +#define AFE_CONN90_2 (0x3710) +#define AFE_CONN90_3 (0x3714) +#define AFE_CONN90_4 (0x3718) +#define AFE_CONN91 (0x371c) +#define AFE_CONN91_1 (0x3720) +#define AFE_CONN91_2 (0x3724) +#define AFE_CONN91_3 (0x3728) +#define AFE_CONN91_4 (0x372c) +#define AFE_CONN92 (0x3730) +#define AFE_CONN92_1 (0x3734) +#define AFE_CONN92_2 (0x3738) +#define AFE_CONN92_3 (0x373c) +#define AFE_CONN92_4 (0x3740) +#define AFE_CONN93 (0x3744) +#define AFE_CONN93_1 (0x3748) +#define AFE_CONN93_2 (0x374c) +#define AFE_CONN93_3 (0x3750) +#define AFE_CONN93_4 (0x3754) +#define AFE_CONN94 (0x3758) +#define AFE_CONN94_1 (0x375c) +#define AFE_CONN94_2 (0x3760) +#define AFE_CONN94_3 (0x3764) +#define AFE_CONN94_4 (0x3768) +#define AFE_CONN95 (0x376c) +#define AFE_CONN95_1 (0x3770) +#define AFE_CONN95_2 (0x3774) +#define AFE_CONN95_3 (0x3778) +#define AFE_CONN95_4 (0x377c) +#define AFE_CONN96 (0x3780) +#define AFE_CONN96_1 (0x3784) +#define AFE_CONN96_2 (0x3788) +#define AFE_CONN96_3 (0x378c) +#define AFE_CONN96_4 (0x3790) +#define AFE_CONN97 (0x3794) +#define AFE_CONN97_1 (0x3798) +#define AFE_CONN97_2 (0x379c) +#define AFE_CONN97_3 (0x37a0) +#define AFE_CONN97_4 (0x37a4) +#define AFE_CONN98 (0x37a8) +#define AFE_CONN98_1 (0x37ac) +#define AFE_CONN98_2 (0x37b0) +#define AFE_CONN98_3 (0x37b4) +#define AFE_CONN98_4 (0x37b8) +#define AFE_CONN99 (0x37bc) +#define AFE_CONN99_1 (0x37c0) +#define AFE_CONN99_2 (0x37c4) +#define AFE_CONN99_3 (0x37c8) +#define AFE_CONN99_4 (0x37cc) +#define AFE_CONN100 (0x37d0) +#define AFE_CONN100_1 (0x37d4) +#define AFE_CONN100_2 (0x37d8) +#define AFE_CONN100_3 (0x37dc) +#define AFE_CONN100_4 (0x37e0) +#define AFE_CONN101 (0x37e4) +#define AFE_CONN101_1 (0x37e8) +#define AFE_CONN101_2 (0x37ec) +#define AFE_CONN101_3 (0x37f0) +#define AFE_CONN101_4 (0x37f4) +#define AFE_CONN102 (0x37f8) +#define AFE_CONN102_1 (0x37fc) +#define AFE_CONN102_2 (0x3800) +#define AFE_CONN102_3 (0x3804) +#define AFE_CONN102_4 (0x3808) +#define AFE_CONN103 (0x380c) +#define AFE_CONN103_1 (0x3810) +#define AFE_CONN103_2 (0x3814) +#define AFE_CONN103_3 (0x3818) +#define AFE_CONN103_4 (0x381c) +#define AFE_CONN104 (0x3820) +#define AFE_CONN104_1 (0x3824) +#define AFE_CONN104_2 (0x3828) +#define AFE_CONN104_3 (0x382c) +#define AFE_CONN104_4 (0x3830) +#define AFE_CONN105 (0x3834) +#define AFE_CONN105_1 (0x3838) +#define AFE_CONN105_2 (0x383c) +#define AFE_CONN105_3 (0x3840) +#define AFE_CONN105_4 (0x3844) +#define AFE_CONN106 (0x3848) +#define AFE_CONN106_1 (0x384c) +#define AFE_CONN106_2 (0x3850) +#define AFE_CONN106_3 (0x3854) +#define AFE_CONN106_4 (0x3858) +#define AFE_CONN107 (0x385c) +#define AFE_CONN107_1 (0x3860) +#define AFE_CONN107_2 (0x3864) +#define AFE_CONN107_3 (0x3868) +#define AFE_CONN107_4 (0x386c) +#define AFE_CONN108 (0x3870) +#define AFE_CONN108_1 (0x3874) +#define AFE_CONN108_2 (0x3878) +#define AFE_CONN108_3 (0x387c) +#define AFE_CONN108_4 (0x3880) +#define AFE_CONN109 (0x3884) +#define AFE_CONN109_1 (0x3888) +#define AFE_CONN109_2 (0x388c) +#define AFE_CONN109_3 (0x3890) +#define AFE_CONN109_4 (0x3894) +#define AFE_CONN110 (0x3898) +#define AFE_CONN110_1 (0x389c) +#define AFE_CONN110_2 (0x38a0) +#define AFE_CONN110_3 (0x38a4) +#define AFE_CONN110_4 (0x38a8) +#define AFE_CONN111 (0x38ac) +#define AFE_CONN111_1 (0x38b0) +#define AFE_CONN111_2 (0x38b4) +#define AFE_CONN111_3 (0x38b8) +#define AFE_CONN111_4 (0x38bc) +#define AFE_CONN112 (0x38c0) +#define AFE_CONN112_1 (0x38c4) +#define AFE_CONN112_2 (0x38c8) +#define AFE_CONN112_3 (0x38cc) +#define AFE_CONN112_4 (0x38d0) +#define AFE_CONN113 (0x38d4) +#define AFE_CONN113_1 (0x38d8) +#define AFE_CONN113_2 (0x38dc) +#define AFE_CONN113_3 (0x38e0) +#define AFE_CONN113_4 (0x38e4) +#define AFE_CONN114 (0x38e8) +#define AFE_CONN114_1 (0x38ec) +#define AFE_CONN114_2 (0x38f0) +#define AFE_CONN114_3 (0x38f4) +#define AFE_CONN114_4 (0x38f8) +#define AFE_CONN115 (0x38fc) +#define AFE_CONN115_1 (0x3900) +#define AFE_CONN115_2 (0x3904) +#define AFE_CONN115_3 (0x3908) +#define AFE_CONN115_4 (0x390c) +#define AFE_CONN116 (0x3910) +#define AFE_CONN116_1 (0x3914) +#define AFE_CONN116_2 (0x3918) +#define AFE_CONN116_3 (0x391c) +#define AFE_CONN116_4 (0x3920) +#define AFE_CONN117 (0x3924) +#define AFE_CONN117_1 (0x3928) +#define AFE_CONN117_2 (0x392c) +#define AFE_CONN117_3 (0x3930) +#define AFE_CONN117_4 (0x3934) +#define AFE_CONN118 (0x3938) +#define AFE_CONN118_1 (0x393c) +#define AFE_CONN118_2 (0x3940) +#define AFE_CONN118_3 (0x3944) +#define AFE_CONN118_4 (0x3948) +#define AFE_CONN119 (0x394c) +#define AFE_CONN119_1 (0x3950) +#define AFE_CONN119_2 (0x3954) +#define AFE_CONN119_3 (0x3958) +#define AFE_CONN119_4 (0x395c) +#define AFE_CONN120 (0x3960) +#define AFE_CONN120_1 (0x3964) +#define AFE_CONN120_2 (0x3968) +#define AFE_CONN120_3 (0x396c) +#define AFE_CONN120_4 (0x3970) +#define AFE_CONN121 (0x3974) +#define AFE_CONN121_1 (0x3978) +#define AFE_CONN121_2 (0x397c) +#define AFE_CONN121_3 (0x3980) +#define AFE_CONN121_4 (0x3984) +#define AFE_CONN122 (0x3988) +#define AFE_CONN122_1 (0x398c) +#define AFE_CONN122_2 (0x3990) +#define AFE_CONN122_3 (0x3994) +#define AFE_CONN122_4 (0x3998) +#define AFE_CONN123 (0x399c) +#define AFE_CONN123_1 (0x39a0) +#define AFE_CONN123_2 (0x39a4) +#define AFE_CONN123_3 (0x39a8) +#define AFE_CONN123_4 (0x39ac) +#define AFE_CONN124 (0x39b0) +#define AFE_CONN124_1 (0x39b4) +#define AFE_CONN124_2 (0x39b8) +#define AFE_CONN124_3 (0x39bc) +#define AFE_CONN124_4 (0x39c0) +#define AFE_CONN125 (0x39c4) +#define AFE_CONN125_1 (0x39c8) +#define AFE_CONN125_2 (0x39cc) +#define AFE_CONN125_3 (0x39d0) +#define AFE_CONN125_4 (0x39d4) +#define AFE_CONN126 (0x39d8) +#define AFE_CONN126_1 (0x39dc) +#define AFE_CONN126_2 (0x39e0) +#define AFE_CONN126_3 (0x39e4) +#define AFE_CONN126_4 (0x39e8) +#define AFE_CONN127 (0x39ec) +#define AFE_CONN127_1 (0x39f0) +#define AFE_CONN127_2 (0x39f4) +#define AFE_CONN127_3 (0x39f8) +#define AFE_CONN127_4 (0x39fc) +#define AFE_CONN128 (0x3a00) +#define AFE_CONN128_1 (0x3a04) +#define AFE_CONN128_2 (0x3a08) +#define AFE_CONN128_3 (0x3a0c) +#define AFE_CONN128_4 (0x3a10) +#define AFE_CONN129 (0x3a14) +#define AFE_CONN129_1 (0x3a18) +#define AFE_CONN129_2 (0x3a1c) +#define AFE_CONN129_3 (0x3a20) +#define AFE_CONN129_4 (0x3a24) +#define AFE_CONN130 (0x3a28) +#define AFE_CONN130_1 (0x3a2c) +#define AFE_CONN130_2 (0x3a30) +#define AFE_CONN130_3 (0x3a34) +#define AFE_CONN130_4 (0x3a38) +#define AFE_CONN131 (0x3a3c) +#define AFE_CONN131_1 (0x3a40) +#define AFE_CONN131_2 (0x3a44) +#define AFE_CONN131_3 (0x3a48) +#define AFE_CONN131_4 (0x3a4c) +#define AFE_CONN132 (0x3a50) +#define AFE_CONN132_1 (0x3a54) +#define AFE_CONN132_2 (0x3a58) +#define AFE_CONN132_3 (0x3a5c) +#define AFE_CONN132_4 (0x3a60) +#define AFE_CONN133 (0x3a64) +#define AFE_CONN133_1 (0x3a68) +#define AFE_CONN133_2 (0x3a6c) +#define AFE_CONN133_3 (0x3a70) +#define AFE_CONN133_4 (0x3a74) +#define AFE_CONN134 (0x3a78) +#define AFE_CONN134_1 (0x3a7c) +#define AFE_CONN134_2 (0x3a80) +#define AFE_CONN134_3 (0x3a84) +#define AFE_CONN134_4 (0x3a88) +#define AFE_CONN135 (0x3a8c) +#define AFE_CONN135_1 (0x3a90) +#define AFE_CONN135_2 (0x3a94) +#define AFE_CONN135_3 (0x3a98) +#define AFE_CONN135_4 (0x3a9c) +#define AFE_CONN136 (0x3aa0) +#define AFE_CONN136_1 (0x3aa4) +#define AFE_CONN136_2 (0x3aa8) +#define AFE_CONN136_3 (0x3aac) +#define AFE_CONN136_4 (0x3ab0) +#define AFE_CONN137 (0x3ab4) +#define AFE_CONN137_1 (0x3ab8) +#define AFE_CONN137_2 (0x3abc) +#define AFE_CONN137_3 (0x3ac0) +#define AFE_CONN137_4 (0x3ac4) +#define AFE_CONN138 (0x3ac8) +#define AFE_CONN138_1 (0x3acc) +#define AFE_CONN138_2 (0x3ad0) +#define AFE_CONN138_3 (0x3ad4) +#define AFE_CONN138_4 (0x3ad8) +#define AFE_CONN139 (0x3adc) +#define AFE_CONN139_1 (0x3ae0) +#define AFE_CONN139_2 (0x3ae4) +#define AFE_CONN139_3 (0x3ae8) +#define AFE_CONN139_4 (0x3aec) +#define AFE_CONN_RS (0x3af0) +#define AFE_CONN_RS_1 (0x3af4) +#define AFE_CONN_RS_2 (0x3af8) +#define AFE_CONN_RS_3 (0x3afc) +#define AFE_CONN_RS_4 (0x3b00) +#define AFE_CONN_16BIT (0x3b04) +#define AFE_CONN_16BIT_1 (0x3b08) +#define AFE_CONN_16BIT_2 (0x3b0c) +#define AFE_CONN_16BIT_3 (0x3b10) +#define AFE_CONN_16BIT_4 (0x3b14) +#define AFE_CONN_24BIT (0x3b18) +#define AFE_CONN_24BIT_1 (0x3b1c) +#define AFE_CONN_24BIT_2 (0x3b20) +#define AFE_CONN_24BIT_3 (0x3b24) +#define AFE_CONN_24BIT_4 (0x3b28) +#define AFE_CONN_DI (0x3b2c) +#define AFE_CONN_DI_1 (0x3b30) +#define AFE_CONN_DI_2 (0x3b34) +#define AFE_CONN_DI_3 (0x3b38) +#define AFE_CONN_DI_4 (0x3b3c) +#define AFE_CONN176 (0x3ea0) +#define AFE_CONN176_1 (0x3ea4) +#define AFE_CONN176_2 (0x3ea8) +#define AFE_CONN176_3 (0x3eac) +#define AFE_CONN176_4 (0x3eb0) +#define AFE_CONN176_5 (0x3eb4) +#define AFE_CONN177 (0x3eb8) +#define AFE_CONN177_1 (0x3ebc) +#define AFE_CONN177_2 (0x3ec0) +#define AFE_CONN177_3 (0x3ec4) +#define AFE_CONN177_4 (0x3ec8) +#define AFE_CONN177_5 (0x3ecc) +#define AFE_CONN182 (0x3f30) +#define AFE_CONN182_1 (0x3f34) +#define AFE_CONN182_2 (0x3f38) +#define AFE_CONN182_3 (0x3f3c) +#define AFE_CONN182_4 (0x3f40) +#define AFE_CONN182_5 (0x3f44) +#define AFE_CONN183 (0x3f48) +#define AFE_CONN183_1 (0x3f4c) +#define AFE_CONN183_2 (0x3f50) +#define AFE_CONN183_3 (0x3f54) +#define AFE_CONN183_4 (0x3f58) +#define AFE_CONN183_5 (0x3f5c) +#define AFE_SECURE_MASK_CONN0 (0x4000) +#define AFE_SECURE_MASK_CONN0_1 (0x4004) +#define AFE_SECURE_MASK_CONN0_2 (0x4008) +#define AFE_SECURE_MASK_CONN0_3 (0x400c) +#define AFE_SECURE_MASK_CONN0_4 (0x4010) +#define AFE_SECURE_MASK_CONN1 (0x4014) +#define AFE_SECURE_MASK_CONN1_1 (0x4018) +#define AFE_SECURE_MASK_CONN1_2 (0x401c) +#define AFE_SECURE_MASK_CONN1_3 (0x4020) +#define AFE_SECURE_MASK_CONN1_4 (0x4024) +#define AFE_SECURE_MASK_CONN2 (0x4028) +#define AFE_SECURE_MASK_CONN2_1 (0x402c) +#define AFE_SECURE_MASK_CONN2_2 (0x4030) +#define AFE_SECURE_MASK_CONN2_3 (0x4034) +#define AFE_SECURE_MASK_CONN2_4 (0x4038) +#define AFE_SECURE_MASK_CONN3 (0x403c) +#define AFE_SECURE_MASK_CONN3_1 (0x4040) +#define AFE_SECURE_MASK_CONN3_2 (0x4044) +#define AFE_SECURE_MASK_CONN3_3 (0x4048) +#define AFE_SECURE_MASK_CONN3_4 (0x404c) +#define AFE_SECURE_MASK_CONN4 (0x4050) +#define AFE_SECURE_MASK_CONN4_1 (0x4054) +#define AFE_SECURE_MASK_CONN4_2 (0x4058) +#define AFE_SECURE_MASK_CONN4_3 (0x405c) +#define AFE_SECURE_MASK_CONN4_4 (0x4060) +#define AFE_SECURE_MASK_CONN5 (0x4064) +#define AFE_SECURE_MASK_CONN5_1 (0x4068) +#define AFE_SECURE_MASK_CONN5_2 (0x406c) +#define AFE_SECURE_MASK_CONN5_3 (0x4070) +#define AFE_SECURE_MASK_CONN5_4 (0x4074) +#define AFE_SECURE_MASK_CONN6 (0x4078) +#define AFE_SECURE_MASK_CONN6_1 (0x407c) +#define AFE_SECURE_MASK_CONN6_2 (0x4080) +#define AFE_SECURE_MASK_CONN6_3 (0x4084) +#define AFE_SECURE_MASK_CONN6_4 (0x4088) +#define AFE_SECURE_MASK_CONN7 (0x408c) +#define AFE_SECURE_MASK_CONN7_1 (0x4090) +#define AFE_SECURE_MASK_CONN7_2 (0x4094) +#define AFE_SECURE_MASK_CONN7_3 (0x4098) +#define AFE_SECURE_MASK_CONN7_4 (0x409c) +#define AFE_SECURE_MASK_CONN8 (0x40a0) +#define AFE_SECURE_MASK_CONN8_1 (0x40a4) +#define AFE_SECURE_MASK_CONN8_2 (0x40a8) +#define AFE_SECURE_MASK_CONN8_3 (0x40ac) +#define AFE_SECURE_MASK_CONN8_4 (0x40b0) +#define AFE_SECURE_MASK_CONN9 (0x40b4) +#define AFE_SECURE_MASK_CONN9_1 (0x40b8) +#define AFE_SECURE_MASK_CONN9_2 (0x40bc) +#define AFE_SECURE_MASK_CONN9_3 (0x40c0) +#define AFE_SECURE_MASK_CONN9_4 (0x40c4) +#define AFE_SECURE_MASK_CONN10 (0x40c8) +#define AFE_SECURE_MASK_CONN10_1 (0x40cc) +#define AFE_SECURE_MASK_CONN10_2 (0x40d0) +#define AFE_SECURE_MASK_CONN10_3 (0x40d4) +#define AFE_SECURE_MASK_CONN10_4 (0x40d8) +#define AFE_SECURE_MASK_CONN11 (0x40dc) +#define AFE_SECURE_MASK_CONN11_1 (0x40e0) +#define AFE_SECURE_MASK_CONN11_2 (0x40e4) +#define AFE_SECURE_MASK_CONN11_3 (0x40e8) +#define AFE_SECURE_MASK_CONN11_4 (0x40ec) +#define AFE_SECURE_MASK_CONN12 (0x40f0) +#define AFE_SECURE_MASK_CONN12_1 (0x40f4) +#define AFE_SECURE_MASK_CONN12_2 (0x40f8) +#define AFE_SECURE_MASK_CONN12_3 (0x40fc) +#define AFE_SECURE_MASK_CONN12_4 (0x4100) +#define AFE_SECURE_MASK_CONN13 (0x4104) +#define AFE_SECURE_MASK_CONN13_1 (0x4108) +#define AFE_SECURE_MASK_CONN13_2 (0x410c) +#define AFE_SECURE_MASK_CONN13_3 (0x4110) +#define AFE_SECURE_MASK_CONN13_4 (0x4114) +#define AFE_SECURE_MASK_CONN14 (0x4118) +#define AFE_SECURE_MASK_CONN14_1 (0x411c) +#define AFE_SECURE_MASK_CONN14_2 (0x4120) +#define AFE_SECURE_MASK_CONN14_3 (0x4124) +#define AFE_SECURE_MASK_CONN14_4 (0x4128) +#define AFE_SECURE_MASK_CONN15 (0x412c) +#define AFE_SECURE_MASK_CONN15_1 (0x4130) +#define AFE_SECURE_MASK_CONN15_2 (0x4134) +#define AFE_SECURE_MASK_CONN15_3 (0x4138) +#define AFE_SECURE_MASK_CONN15_4 (0x413c) +#define AFE_SECURE_MASK_CONN16 (0x4140) +#define AFE_SECURE_MASK_CONN16_1 (0x4144) +#define AFE_SECURE_MASK_CONN16_2 (0x4148) +#define AFE_SECURE_MASK_CONN16_3 (0x414c) +#define AFE_SECURE_MASK_CONN16_4 (0x4150) +#define AFE_SECURE_MASK_CONN17 (0x4154) +#define AFE_SECURE_MASK_CONN17_1 (0x4158) +#define AFE_SECURE_MASK_CONN17_2 (0x415c) +#define AFE_SECURE_MASK_CONN17_3 (0x4160) +#define AFE_SECURE_MASK_CONN17_4 (0x4164) +#define AFE_SECURE_MASK_CONN18 (0x4168) +#define AFE_SECURE_MASK_CONN18_1 (0x416c) +#define AFE_SECURE_MASK_CONN18_2 (0x4170) +#define AFE_SECURE_MASK_CONN18_3 (0x4174) +#define AFE_SECURE_MASK_CONN18_4 (0x4178) +#define AFE_SECURE_MASK_CONN19 (0x417c) +#define AFE_SECURE_MASK_CONN19_1 (0x4180) +#define AFE_SECURE_MASK_CONN19_2 (0x4184) +#define AFE_SECURE_MASK_CONN19_3 (0x4188) +#define AFE_SECURE_MASK_CONN19_4 (0x418c) +#define AFE_SECURE_MASK_CONN20 (0x4190) +#define AFE_SECURE_MASK_CONN20_1 (0x4194) +#define AFE_SECURE_MASK_CONN20_2 (0x4198) +#define AFE_SECURE_MASK_CONN20_3 (0x419c) +#define AFE_SECURE_MASK_CONN20_4 (0x41a0) +#define AFE_SECURE_MASK_CONN21 (0x41a4) +#define AFE_SECURE_MASK_CONN21_1 (0x41a8) +#define AFE_SECURE_MASK_CONN21_2 (0x41ac) +#define AFE_SECURE_MASK_CONN21_3 (0x41b0) +#define AFE_SECURE_MASK_CONN21_4 (0x41b4) +#define AFE_SECURE_MASK_CONN22 (0x41b8) +#define AFE_SECURE_MASK_CONN22_1 (0x41bc) +#define AFE_SECURE_MASK_CONN22_2 (0x41c0) +#define AFE_SECURE_MASK_CONN22_3 (0x41c4) +#define AFE_SECURE_MASK_CONN22_4 (0x41c8) +#define AFE_SECURE_MASK_CONN23 (0x41cc) +#define AFE_SECURE_MASK_CONN23_1 (0x41d0) +#define AFE_SECURE_MASK_CONN23_2 (0x41d4) +#define AFE_SECURE_MASK_CONN23_3 (0x41d8) +#define AFE_SECURE_MASK_CONN23_4 (0x41dc) +#define AFE_SECURE_MASK_CONN24 (0x41e0) +#define AFE_SECURE_MASK_CONN24_1 (0x41e4) +#define AFE_SECURE_MASK_CONN24_2 (0x41e8) +#define AFE_SECURE_MASK_CONN24_3 (0x41ec) +#define AFE_SECURE_MASK_CONN24_4 (0x41f0) +#define AFE_SECURE_MASK_CONN25 (0x41f4) +#define AFE_SECURE_MASK_CONN25_1 (0x41f8) +#define AFE_SECURE_MASK_CONN25_2 (0x41fc) +#define AFE_SECURE_MASK_CONN25_3 (0x4200) +#define AFE_SECURE_MASK_CONN25_4 (0x4204) +#define AFE_SECURE_MASK_CONN26 (0x4208) +#define AFE_SECURE_MASK_CONN26_1 (0x420c) +#define AFE_SECURE_MASK_CONN26_2 (0x4210) +#define AFE_SECURE_MASK_CONN26_3 (0x4214) +#define AFE_SECURE_MASK_CONN26_4 (0x4218) +#define AFE_SECURE_MASK_CONN27 (0x421c) +#define AFE_SECURE_MASK_CONN27_1 (0x4220) +#define AFE_SECURE_MASK_CONN27_2 (0x4224) +#define AFE_SECURE_MASK_CONN27_3 (0x4228) +#define AFE_SECURE_MASK_CONN27_4 (0x422c) +#define AFE_SECURE_MASK_CONN28 (0x4230) +#define AFE_SECURE_MASK_CONN28_1 (0x4234) +#define AFE_SECURE_MASK_CONN28_2 (0x4238) +#define AFE_SECURE_MASK_CONN28_3 (0x423c) +#define AFE_SECURE_MASK_CONN28_4 (0x4240) +#define AFE_SECURE_MASK_CONN29 (0x4244) +#define AFE_SECURE_MASK_CONN29_1 (0x4248) +#define AFE_SECURE_MASK_CONN29_2 (0x424c) +#define AFE_SECURE_MASK_CONN29_3 (0x4250) +#define AFE_SECURE_MASK_CONN29_4 (0x4254) +#define AFE_SECURE_MASK_CONN30 (0x4258) +#define AFE_SECURE_MASK_CONN30_1 (0x425c) +#define AFE_SECURE_MASK_CONN30_2 (0x4260) +#define AFE_SECURE_MASK_CONN30_3 (0x4264) +#define AFE_SECURE_MASK_CONN30_4 (0x4268) +#define AFE_SECURE_MASK_CONN31 (0x426c) +#define AFE_SECURE_MASK_CONN31_1 (0x4270) +#define AFE_SECURE_MASK_CONN31_2 (0x4274) +#define AFE_SECURE_MASK_CONN31_3 (0x4278) +#define AFE_SECURE_MASK_CONN31_4 (0x427c) +#define AFE_SECURE_MASK_CONN32 (0x4280) +#define AFE_SECURE_MASK_CONN32_1 (0x4284) +#define AFE_SECURE_MASK_CONN32_2 (0x4288) +#define AFE_SECURE_MASK_CONN32_3 (0x428c) +#define AFE_SECURE_MASK_CONN32_4 (0x4290) +#define AFE_SECURE_MASK_CONN33 (0x4294) +#define AFE_SECURE_MASK_CONN33_1 (0x4298) +#define AFE_SECURE_MASK_CONN33_2 (0x429c) +#define AFE_SECURE_MASK_CONN33_3 (0x42a0) +#define AFE_SECURE_MASK_CONN33_4 (0x42a4) +#define AFE_SECURE_MASK_CONN34 (0x42a8) +#define AFE_SECURE_MASK_CONN34_1 (0x42ac) +#define AFE_SECURE_MASK_CONN34_2 (0x42b0) +#define AFE_SECURE_MASK_CONN34_3 (0x42b4) +#define AFE_SECURE_MASK_CONN34_4 (0x42b8) +#define AFE_SECURE_MASK_CONN35 (0x42bc) +#define AFE_SECURE_MASK_CONN35_1 (0x42c0) +#define AFE_SECURE_MASK_CONN35_2 (0x42c4) +#define AFE_SECURE_MASK_CONN35_3 (0x42c8) +#define AFE_SECURE_MASK_CONN35_4 (0x42cc) +#define AFE_SECURE_MASK_CONN36 (0x42d0) +#define AFE_SECURE_MASK_CONN36_1 (0x42d4) +#define AFE_SECURE_MASK_CONN36_2 (0x42d8) +#define AFE_SECURE_MASK_CONN36_3 (0x42dc) +#define AFE_SECURE_MASK_CONN36_4 (0x42e0) +#define AFE_SECURE_MASK_CONN37 (0x42e4) +#define AFE_SECURE_MASK_CONN37_1 (0x42e8) +#define AFE_SECURE_MASK_CONN37_2 (0x42ec) +#define AFE_SECURE_MASK_CONN37_3 (0x42f0) +#define AFE_SECURE_MASK_CONN37_4 (0x42f4) +#define AFE_SECURE_MASK_CONN38 (0x42f8) +#define AFE_SECURE_MASK_CONN38_1 (0x42fc) +#define AFE_SECURE_MASK_CONN38_2 (0x4300) +#define AFE_SECURE_MASK_CONN38_3 (0x4304) +#define AFE_SECURE_MASK_CONN38_4 (0x4308) +#define AFE_SECURE_MASK_CONN39 (0x430c) +#define AFE_SECURE_MASK_CONN39_1 (0x4310) +#define AFE_SECURE_MASK_CONN39_2 (0x4314) +#define AFE_SECURE_MASK_CONN39_3 (0x4318) +#define AFE_SECURE_MASK_CONN39_4 (0x431c) +#define AFE_SECURE_MASK_CONN40 (0x4320) +#define AFE_SECURE_MASK_CONN40_1 (0x4324) +#define AFE_SECURE_MASK_CONN40_2 (0x4328) +#define AFE_SECURE_MASK_CONN40_3 (0x432c) +#define AFE_SECURE_MASK_CONN40_4 (0x4330) +#define AFE_SECURE_MASK_CONN41 (0x4334) +#define AFE_SECURE_MASK_CONN41_1 (0x4338) +#define AFE_SECURE_MASK_CONN41_2 (0x433c) +#define AFE_SECURE_MASK_CONN41_3 (0x4340) +#define AFE_SECURE_MASK_CONN41_4 (0x4344) +#define AFE_SECURE_MASK_CONN42 (0x4348) +#define AFE_SECURE_MASK_CONN42_1 (0x434c) +#define AFE_SECURE_MASK_CONN42_2 (0x4350) +#define AFE_SECURE_MASK_CONN42_3 (0x4354) +#define AFE_SECURE_MASK_CONN42_4 (0x4358) +#define AFE_SECURE_MASK_CONN43 (0x435c) +#define AFE_SECURE_MASK_CONN43_1 (0x4360) +#define AFE_SECURE_MASK_CONN43_2 (0x4364) +#define AFE_SECURE_MASK_CONN43_3 (0x4368) +#define AFE_SECURE_MASK_CONN43_4 (0x436c) +#define AFE_SECURE_MASK_CONN44 (0x4370) +#define AFE_SECURE_MASK_CONN44_1 (0x4374) +#define AFE_SECURE_MASK_CONN44_2 (0x4378) +#define AFE_SECURE_MASK_CONN44_3 (0x437c) +#define AFE_SECURE_MASK_CONN44_4 (0x4380) +#define AFE_SECURE_MASK_CONN45 (0x4384) +#define AFE_SECURE_MASK_CONN45_1 (0x4388) +#define AFE_SECURE_MASK_CONN45_2 (0x438c) +#define AFE_SECURE_MASK_CONN45_3 (0x4390) +#define AFE_SECURE_MASK_CONN45_4 (0x4394) +#define AFE_SECURE_MASK_CONN46 (0x4398) +#define AFE_SECURE_MASK_CONN46_1 (0x439c) +#define AFE_SECURE_MASK_CONN46_2 (0x43a0) +#define AFE_SECURE_MASK_CONN46_3 (0x43a4) +#define AFE_SECURE_MASK_CONN46_4 (0x43a8) +#define AFE_SECURE_MASK_CONN47 (0x43ac) +#define AFE_SECURE_MASK_CONN47_1 (0x43b0) +#define AFE_SECURE_MASK_CONN47_2 (0x43b4) +#define AFE_SECURE_MASK_CONN47_3 (0x43b8) +#define AFE_SECURE_MASK_CONN47_4 (0x43bc) +#define AFE_SECURE_MASK_CONN48 (0x43c0) +#define AFE_SECURE_MASK_CONN48_1 (0x43c4) +#define AFE_SECURE_MASK_CONN48_2 (0x43c8) +#define AFE_SECURE_MASK_CONN48_3 (0x43cc) +#define AFE_SECURE_MASK_CONN48_4 (0x43d0) +#define AFE_SECURE_MASK_CONN49 (0x43d4) +#define AFE_SECURE_MASK_CONN49_1 (0x43d8) +#define AFE_SECURE_MASK_CONN49_2 (0x43dc) +#define AFE_SECURE_MASK_CONN49_3 (0x43e0) +#define AFE_SECURE_MASK_CONN49_4 (0x43e4) +#define AFE_SECURE_MASK_CONN50 (0x43e8) +#define AFE_SECURE_MASK_CONN50_1 (0x43ec) +#define AFE_SECURE_MASK_CONN50_2 (0x43f0) +#define AFE_SECURE_MASK_CONN50_3 (0x43f4) +#define AFE_SECURE_MASK_CONN50_4 (0x43f8) +#define AFE_SECURE_MASK_CONN51 (0x43fc) +#define AFE_SECURE_MASK_CONN51_1 (0x4400) +#define AFE_SECURE_MASK_CONN51_2 (0x4404) +#define AFE_SECURE_MASK_CONN51_3 (0x4408) +#define AFE_SECURE_MASK_CONN51_4 (0x440c) +#define AFE_SECURE_MASK_CONN52 (0x4410) +#define AFE_SECURE_MASK_CONN52_1 (0x4414) +#define AFE_SECURE_MASK_CONN52_2 (0x4418) +#define AFE_SECURE_MASK_CONN52_3 (0x441c) +#define AFE_SECURE_MASK_CONN52_4 (0x4420) +#define AFE_SECURE_MASK_CONN53 (0x4424) +#define AFE_SECURE_MASK_CONN53_1 (0x4428) +#define AFE_SECURE_MASK_CONN53_2 (0x442c) +#define AFE_SECURE_MASK_CONN53_3 (0x4430) +#define AFE_SECURE_MASK_CONN53_4 (0x4434) +#define AFE_SECURE_MASK_CONN54 (0x4438) +#define AFE_SECURE_MASK_CONN54_1 (0x443c) +#define AFE_SECURE_MASK_CONN54_2 (0x4440) +#define AFE_SECURE_MASK_CONN54_3 (0x4444) +#define AFE_SECURE_MASK_CONN54_4 (0x4448) +#define AFE_SECURE_MASK_CONN55 (0x444c) +#define AFE_SECURE_MASK_CONN55_1 (0x4450) +#define AFE_SECURE_MASK_CONN55_2 (0x4454) +#define AFE_SECURE_MASK_CONN55_3 (0x4458) +#define AFE_SECURE_MASK_CONN55_4 (0x445c) +#define AFE_SECURE_MASK_CONN56 (0x4460) +#define AFE_SECURE_MASK_CONN56_1 (0x4464) +#define AFE_SECURE_MASK_CONN56_2 (0x4468) +#define AFE_SECURE_MASK_CONN56_3 (0x446c) +#define AFE_SECURE_MASK_CONN56_4 (0x4470) +#define AFE_SECURE_MASK_CONN57 (0x4474) +#define AFE_SECURE_MASK_CONN57_1 (0x4478) +#define AFE_SECURE_MASK_CONN57_2 (0x447c) +#define AFE_SECURE_MASK_CONN57_3 (0x4480) +#define AFE_SECURE_MASK_CONN57_4 (0x4484) +#define AFE_SECURE_MASK_CONN58 (0x4488) +#define AFE_SECURE_MASK_CONN58_1 (0x448c) +#define AFE_SECURE_MASK_CONN58_2 (0x4490) +#define AFE_SECURE_MASK_CONN58_3 (0x4494) +#define AFE_SECURE_MASK_CONN58_4 (0x4498) +#define AFE_SECURE_MASK_CONN59 (0x449c) +#define AFE_SECURE_MASK_CONN59_1 (0x44a0) +#define AFE_SECURE_MASK_CONN59_2 (0x44a4) +#define AFE_SECURE_MASK_CONN59_3 (0x44a8) +#define AFE_SECURE_MASK_CONN59_4 (0x44ac) +#define AFE_SECURE_MASK_CONN60 (0x44b0) +#define AFE_SECURE_MASK_CONN60_1 (0x44b4) +#define AFE_SECURE_MASK_CONN60_2 (0x44b8) +#define AFE_SECURE_MASK_CONN60_3 (0x44bc) +#define AFE_SECURE_MASK_CONN60_4 (0x44c0) +#define AFE_SECURE_MASK_CONN61 (0x44c4) +#define AFE_SECURE_MASK_CONN61_1 (0x44c8) +#define AFE_SECURE_MASK_CONN61_2 (0x44cc) +#define AFE_SECURE_MASK_CONN61_3 (0x44d0) +#define AFE_SECURE_MASK_CONN61_4 (0x44d4) +#define AFE_SECURE_MASK_CONN62 (0x44d8) +#define AFE_SECURE_MASK_CONN62_1 (0x44dc) +#define AFE_SECURE_MASK_CONN62_2 (0x44e0) +#define AFE_SECURE_MASK_CONN62_3 (0x44e4) +#define AFE_SECURE_MASK_CONN62_4 (0x44e8) +#define AFE_SECURE_MASK_CONN63 (0x44ec) +#define AFE_SECURE_MASK_CONN63_1 (0x44f0) +#define AFE_SECURE_MASK_CONN63_2 (0x44f4) +#define AFE_SECURE_MASK_CONN63_3 (0x44f8) +#define AFE_SECURE_MASK_CONN63_4 (0x44fc) +#define AFE_SECURE_MASK_CONN64 (0x4500) +#define AFE_SECURE_MASK_CONN64_1 (0x4504) +#define AFE_SECURE_MASK_CONN64_2 (0x4508) +#define AFE_SECURE_MASK_CONN64_3 (0x450c) +#define AFE_SECURE_MASK_CONN64_4 (0x4510) +#define AFE_SECURE_MASK_CONN65 (0x4514) +#define AFE_SECURE_MASK_CONN65_1 (0x4518) +#define AFE_SECURE_MASK_CONN65_2 (0x451c) +#define AFE_SECURE_MASK_CONN65_3 (0x4520) +#define AFE_SECURE_MASK_CONN65_4 (0x4524) +#define AFE_SECURE_MASK_CONN66 (0x4528) +#define AFE_SECURE_MASK_CONN66_1 (0x452c) +#define AFE_SECURE_MASK_CONN66_2 (0x4530) +#define AFE_SECURE_MASK_CONN66_3 (0x4534) +#define AFE_SECURE_MASK_CONN66_4 (0x4538) +#define AFE_SECURE_MASK_CONN67 (0x453c) +#define AFE_SECURE_MASK_CONN67_1 (0x4540) +#define AFE_SECURE_MASK_CONN67_2 (0x4544) +#define AFE_SECURE_MASK_CONN67_3 (0x4548) +#define AFE_SECURE_MASK_CONN67_4 (0x454c) +#define AFE_SECURE_MASK_CONN68 (0x4550) +#define AFE_SECURE_MASK_CONN68_1 (0x4554) +#define AFE_SECURE_MASK_CONN68_2 (0x4558) +#define AFE_SECURE_MASK_CONN68_3 (0x455c) +#define AFE_SECURE_MASK_CONN68_4 (0x4560) +#define AFE_SECURE_MASK_CONN69 (0x4564) +#define AFE_SECURE_MASK_CONN69_1 (0x4568) +#define AFE_SECURE_MASK_CONN69_2 (0x456c) +#define AFE_SECURE_MASK_CONN69_3 (0x4570) +#define AFE_SECURE_MASK_CONN69_4 (0x4574) +#define AFE_SECURE_MASK_CONN70 (0x4578) +#define AFE_SECURE_MASK_CONN70_1 (0x457c) +#define AFE_SECURE_MASK_CONN70_2 (0x4580) +#define AFE_SECURE_MASK_CONN70_3 (0x4584) +#define AFE_SECURE_MASK_CONN70_4 (0x4588) +#define AFE_SECURE_MASK_CONN71 (0x458c) +#define AFE_SECURE_MASK_CONN71_1 (0x4590) +#define AFE_SECURE_MASK_CONN71_2 (0x4594) +#define AFE_SECURE_MASK_CONN71_3 (0x4598) +#define AFE_SECURE_MASK_CONN71_4 (0x459c) +#define AFE_SECURE_MASK_CONN72 (0x45a0) +#define AFE_SECURE_MASK_CONN72_1 (0x45a4) +#define AFE_SECURE_MASK_CONN72_2 (0x45a8) +#define AFE_SECURE_MASK_CONN72_3 (0x45ac) +#define AFE_SECURE_MASK_CONN72_4 (0x45b0) +#define AFE_SECURE_MASK_CONN73 (0x45b4) +#define AFE_SECURE_MASK_CONN73_1 (0x45b8) +#define AFE_SECURE_MASK_CONN73_2 (0x45bc) +#define AFE_SECURE_MASK_CONN73_3 (0x45c0) +#define AFE_SECURE_MASK_CONN73_4 (0x45c4) +#define AFE_SECURE_MASK_CONN74 (0x45c8) +#define AFE_SECURE_MASK_CONN74_1 (0x45cc) +#define AFE_SECURE_MASK_CONN74_2 (0x45d0) +#define AFE_SECURE_MASK_CONN74_3 (0x45d4) +#define AFE_SECURE_MASK_CONN74_4 (0x45d8) +#define AFE_SECURE_MASK_CONN75 (0x45dc) +#define AFE_SECURE_MASK_CONN75_1 (0x45e0) +#define AFE_SECURE_MASK_CONN75_2 (0x45e4) +#define AFE_SECURE_MASK_CONN75_3 (0x45e8) +#define AFE_SECURE_MASK_CONN75_4 (0x45ec) +#define AFE_SECURE_MASK_CONN76 (0x45f0) +#define AFE_SECURE_MASK_CONN76_1 (0x45f4) +#define AFE_SECURE_MASK_CONN76_2 (0x45f8) +#define AFE_SECURE_MASK_CONN76_3 (0x45fc) +#define AFE_SECURE_MASK_CONN76_4 (0x4600) +#define AFE_SECURE_MASK_CONN77 (0x4604) +#define AFE_SECURE_MASK_CONN77_1 (0x4608) +#define AFE_SECURE_MASK_CONN77_2 (0x460c) +#define AFE_SECURE_MASK_CONN77_3 (0x4610) +#define AFE_SECURE_MASK_CONN77_4 (0x4614) +#define AFE_SECURE_MASK_CONN78 (0x4618) +#define AFE_SECURE_MASK_CONN78_1 (0x461c) +#define AFE_SECURE_MASK_CONN78_2 (0x4620) +#define AFE_SECURE_MASK_CONN78_3 (0x4624) +#define AFE_SECURE_MASK_CONN78_4 (0x4628) +#define AFE_SECURE_MASK_CONN79 (0x462c) +#define AFE_SECURE_MASK_CONN79_1 (0x4630) +#define AFE_SECURE_MASK_CONN79_2 (0x4634) +#define AFE_SECURE_MASK_CONN79_3 (0x4638) +#define AFE_SECURE_MASK_CONN79_4 (0x463c) +#define AFE_SECURE_MASK_CONN80 (0x4640) +#define AFE_SECURE_MASK_CONN80_1 (0x4644) +#define AFE_SECURE_MASK_CONN80_2 (0x4648) +#define AFE_SECURE_MASK_CONN80_3 (0x464c) +#define AFE_SECURE_MASK_CONN80_4 (0x4650) +#define AFE_SECURE_MASK_CONN81 (0x4654) +#define AFE_SECURE_MASK_CONN81_1 (0x4658) +#define AFE_SECURE_MASK_CONN81_2 (0x465c) +#define AFE_SECURE_MASK_CONN81_3 (0x4660) +#define AFE_SECURE_MASK_CONN81_4 (0x4664) +#define AFE_SECURE_MASK_CONN82 (0x4668) +#define AFE_SECURE_MASK_CONN82_1 (0x466c) +#define AFE_SECURE_MASK_CONN82_2 (0x4670) +#define AFE_SECURE_MASK_CONN82_3 (0x4674) +#define AFE_SECURE_MASK_CONN82_4 (0x4678) +#define AFE_SECURE_MASK_CONN83 (0x467c) +#define AFE_SECURE_MASK_CONN83_1 (0x4680) +#define AFE_SECURE_MASK_CONN83_2 (0x4684) +#define AFE_SECURE_MASK_CONN83_3 (0x4688) +#define AFE_SECURE_MASK_CONN83_4 (0x468c) +#define AFE_SECURE_MASK_CONN84 (0x4690) +#define AFE_SECURE_MASK_CONN84_1 (0x4694) +#define AFE_SECURE_MASK_CONN84_2 (0x4698) +#define AFE_SECURE_MASK_CONN84_3 (0x469c) +#define AFE_SECURE_MASK_CONN84_4 (0x46a0) +#define AFE_SECURE_MASK_CONN85 (0x46a4) +#define AFE_SECURE_MASK_CONN85_1 (0x46a8) +#define AFE_SECURE_MASK_CONN85_2 (0x46ac) +#define AFE_SECURE_MASK_CONN85_3 (0x46b0) +#define AFE_SECURE_MASK_CONN85_4 (0x46b4) +#define AFE_SECURE_MASK_CONN86 (0x46b8) +#define AFE_SECURE_MASK_CONN86_1 (0x46bc) +#define AFE_SECURE_MASK_CONN86_2 (0x46c0) +#define AFE_SECURE_MASK_CONN86_3 (0x46c4) +#define AFE_SECURE_MASK_CONN86_4 (0x46c8) +#define AFE_SECURE_MASK_CONN87 (0x46cc) +#define AFE_SECURE_MASK_CONN87_1 (0x46d0) +#define AFE_SECURE_MASK_CONN87_2 (0x46d4) +#define AFE_SECURE_MASK_CONN87_3 (0x46d8) +#define AFE_SECURE_MASK_CONN87_4 (0x46dc) +#define AFE_SECURE_MASK_CONN88 (0x46e0) +#define AFE_SECURE_MASK_CONN88_1 (0x46e4) +#define AFE_SECURE_MASK_CONN88_2 (0x46e8) +#define AFE_SECURE_MASK_CONN88_3 (0x46ec) +#define AFE_SECURE_MASK_CONN88_4 (0x46f0) +#define AFE_SECURE_MASK_CONN89 (0x46f4) +#define AFE_SECURE_MASK_CONN89_1 (0x46f8) +#define AFE_SECURE_MASK_CONN89_2 (0x46fc) +#define AFE_SECURE_MASK_CONN89_3 (0x4700) +#define AFE_SECURE_MASK_CONN89_4 (0x4704) +#define AFE_SECURE_MASK_CONN90 (0x4708) +#define AFE_SECURE_MASK_CONN90_1 (0x470c) +#define AFE_SECURE_MASK_CONN90_2 (0x4710) +#define AFE_SECURE_MASK_CONN90_3 (0x4714) +#define AFE_SECURE_MASK_CONN90_4 (0x4718) +#define AFE_SECURE_MASK_CONN91 (0x471c) +#define AFE_SECURE_MASK_CONN91_1 (0x4720) +#define AFE_SECURE_MASK_CONN91_2 (0x4724) +#define AFE_SECURE_MASK_CONN91_3 (0x4728) +#define AFE_SECURE_MASK_CONN91_4 (0x472c) +#define AFE_SECURE_MASK_CONN92 (0x4730) +#define AFE_SECURE_MASK_CONN92_1 (0x4734) +#define AFE_SECURE_MASK_CONN92_2 (0x4738) +#define AFE_SECURE_MASK_CONN92_3 (0x473c) +#define AFE_SECURE_MASK_CONN92_4 (0x4740) +#define AFE_SECURE_MASK_CONN93 (0x4744) +#define AFE_SECURE_MASK_CONN93_1 (0x4748) +#define AFE_SECURE_MASK_CONN93_2 (0x474c) +#define AFE_SECURE_MASK_CONN93_3 (0x4750) +#define AFE_SECURE_MASK_CONN93_4 (0x4754) +#define AFE_SECURE_MASK_CONN94 (0x4758) +#define AFE_SECURE_MASK_CONN94_1 (0x475c) +#define AFE_SECURE_MASK_CONN94_2 (0x4760) +#define AFE_SECURE_MASK_CONN94_3 (0x4764) +#define AFE_SECURE_MASK_CONN94_4 (0x4768) +#define AFE_SECURE_MASK_CONN95 (0x476c) +#define AFE_SECURE_MASK_CONN95_1 (0x4770) +#define AFE_SECURE_MASK_CONN95_2 (0x4774) +#define AFE_SECURE_MASK_CONN95_3 (0x4778) +#define AFE_SECURE_MASK_CONN95_4 (0x477c) +#define AFE_SECURE_MASK_CONN96 (0x4780) +#define AFE_SECURE_MASK_CONN96_1 (0x4784) +#define AFE_SECURE_MASK_CONN96_2 (0x4788) +#define AFE_SECURE_MASK_CONN96_3 (0x478c) +#define AFE_SECURE_MASK_CONN96_4 (0x4790) +#define AFE_SECURE_MASK_CONN97 (0x4794) +#define AFE_SECURE_MASK_CONN97_1 (0x4798) +#define AFE_SECURE_MASK_CONN97_2 (0x479c) +#define AFE_SECURE_MASK_CONN97_3 (0x47a0) +#define AFE_SECURE_MASK_CONN97_4 (0x47a4) +#define AFE_SECURE_MASK_CONN98 (0x47a8) +#define AFE_SECURE_MASK_CONN98_1 (0x47ac) +#define AFE_SECURE_MASK_CONN98_2 (0x47b0) +#define AFE_SECURE_MASK_CONN98_3 (0x47b4) +#define AFE_SECURE_MASK_CONN98_4 (0x47b8) +#define AFE_SECURE_MASK_CONN99 (0x47bc) +#define AFE_SECURE_MASK_CONN99_1 (0x47c0) +#define AFE_SECURE_MASK_CONN99_2 (0x47c4) +#define AFE_SECURE_MASK_CONN99_3 (0x47c8) +#define AFE_SECURE_MASK_CONN99_4 (0x47cc) +#define AFE_SECURE_MASK_CONN100 (0x47d0) +#define AFE_SECURE_MASK_CONN100_1 (0x47d4) +#define AFE_SECURE_MASK_CONN100_2 (0x47d8) +#define AFE_SECURE_MASK_CONN100_3 (0x47dc) +#define AFE_SECURE_MASK_CONN100_4 (0x47e0) +#define AFE_SECURE_MASK_CONN101 (0x47e4) +#define AFE_SECURE_MASK_CONN101_1 (0x47e8) +#define AFE_SECURE_MASK_CONN101_2 (0x47ec) +#define AFE_SECURE_MASK_CONN101_3 (0x47f0) +#define AFE_SECURE_MASK_CONN101_4 (0x47f4) +#define AFE_SECURE_MASK_CONN102 (0x47f8) +#define AFE_SECURE_MASK_CONN102_1 (0x47fc) +#define AFE_SECURE_MASK_CONN102_2 (0x4800) +#define AFE_SECURE_MASK_CONN102_3 (0x4804) +#define AFE_SECURE_MASK_CONN102_4 (0x4808) +#define AFE_SECURE_MASK_CONN103 (0x480c) +#define AFE_SECURE_MASK_CONN103_1 (0x4810) +#define AFE_SECURE_MASK_CONN103_2 (0x4814) +#define AFE_SECURE_MASK_CONN103_3 (0x4818) +#define AFE_SECURE_MASK_CONN103_4 (0x481c) +#define AFE_SECURE_MASK_CONN104 (0x4820) +#define AFE_SECURE_MASK_CONN104_1 (0x4824) +#define AFE_SECURE_MASK_CONN104_2 (0x4828) +#define AFE_SECURE_MASK_CONN104_3 (0x482c) +#define AFE_SECURE_MASK_CONN104_4 (0x4830) +#define AFE_SECURE_MASK_CONN105 (0x4834) +#define AFE_SECURE_MASK_CONN105_1 (0x4838) +#define AFE_SECURE_MASK_CONN105_2 (0x483c) +#define AFE_SECURE_MASK_CONN105_3 (0x4840) +#define AFE_SECURE_MASK_CONN105_4 (0x4844) +#define AFE_SECURE_MASK_CONN106 (0x4848) +#define AFE_SECURE_MASK_CONN106_1 (0x484c) +#define AFE_SECURE_MASK_CONN106_2 (0x4850) +#define AFE_SECURE_MASK_CONN106_3 (0x4854) +#define AFE_SECURE_MASK_CONN106_4 (0x4858) +#define AFE_SECURE_MASK_CONN107 (0x485c) +#define AFE_SECURE_MASK_CONN107_1 (0x4860) +#define AFE_SECURE_MASK_CONN107_2 (0x4864) +#define AFE_SECURE_MASK_CONN107_3 (0x4868) +#define AFE_SECURE_MASK_CONN107_4 (0x486c) +#define AFE_SECURE_MASK_CONN108 (0x4870) +#define AFE_SECURE_MASK_CONN108_1 (0x4874) +#define AFE_SECURE_MASK_CONN108_2 (0x4878) +#define AFE_SECURE_MASK_CONN108_3 (0x487c) +#define AFE_SECURE_MASK_CONN108_4 (0x4880) +#define AFE_SECURE_MASK_CONN109 (0x4884) +#define AFE_SECURE_MASK_CONN109_1 (0x4888) +#define AFE_SECURE_MASK_CONN109_2 (0x488c) +#define AFE_SECURE_MASK_CONN109_3 (0x4890) +#define AFE_SECURE_MASK_CONN109_4 (0x4894) +#define AFE_SECURE_MASK_CONN110 (0x4898) +#define AFE_SECURE_MASK_CONN110_1 (0x489c) +#define AFE_SECURE_MASK_CONN110_2 (0x48a0) +#define AFE_SECURE_MASK_CONN110_3 (0x48a4) +#define AFE_SECURE_MASK_CONN110_4 (0x48a8) +#define AFE_SECURE_MASK_CONN111 (0x48ac) +#define AFE_SECURE_MASK_CONN111_1 (0x48b0) +#define AFE_SECURE_MASK_CONN111_2 (0x48b4) +#define AFE_SECURE_MASK_CONN111_3 (0x48b8) +#define AFE_SECURE_MASK_CONN111_4 (0x48bc) +#define AFE_SECURE_MASK_CONN112 (0x48c0) +#define AFE_SECURE_MASK_CONN112_1 (0x48c4) +#define AFE_SECURE_MASK_CONN112_2 (0x48c8) +#define AFE_SECURE_MASK_CONN112_3 (0x48cc) +#define AFE_SECURE_MASK_CONN112_4 (0x48d0) +#define AFE_SECURE_MASK_CONN113 (0x48d4) +#define AFE_SECURE_MASK_CONN113_1 (0x48d8) +#define AFE_SECURE_MASK_CONN113_2 (0x48dc) +#define AFE_SECURE_MASK_CONN113_3 (0x48e0) +#define AFE_SECURE_MASK_CONN113_4 (0x48e4) +#define AFE_SECURE_MASK_CONN114 (0x48e8) +#define AFE_SECURE_MASK_CONN114_1 (0x48ec) +#define AFE_SECURE_MASK_CONN114_2 (0x48f0) +#define AFE_SECURE_MASK_CONN114_3 (0x48f4) +#define AFE_SECURE_MASK_CONN114_4 (0x48f8) +#define AFE_SECURE_MASK_CONN115 (0x48fc) +#define AFE_SECURE_MASK_CONN115_1 (0x4900) +#define AFE_SECURE_MASK_CONN115_2 (0x4904) +#define AFE_SECURE_MASK_CONN115_3 (0x4908) +#define AFE_SECURE_MASK_CONN115_4 (0x490c) +#define AFE_SECURE_MASK_CONN116 (0x4910) +#define AFE_SECURE_MASK_CONN116_1 (0x4914) +#define AFE_SECURE_MASK_CONN116_2 (0x4918) +#define AFE_SECURE_MASK_CONN116_3 (0x491c) +#define AFE_SECURE_MASK_CONN116_4 (0x4920) +#define AFE_SECURE_MASK_CONN117 (0x4924) +#define AFE_SECURE_MASK_CONN117_1 (0x4928) +#define AFE_SECURE_MASK_CONN117_2 (0x492c) +#define AFE_SECURE_MASK_CONN117_3 (0x4930) +#define AFE_SECURE_MASK_CONN117_4 (0x4934) +#define AFE_SECURE_MASK_CONN118 (0x4938) +#define AFE_SECURE_MASK_CONN118_1 (0x493c) +#define AFE_SECURE_MASK_CONN118_2 (0x4940) +#define AFE_SECURE_MASK_CONN118_3 (0x4944) +#define AFE_SECURE_MASK_CONN118_4 (0x4948) +#define AFE_SECURE_MASK_CONN119 (0x494c) +#define AFE_SECURE_MASK_CONN119_1 (0x4950) +#define AFE_SECURE_MASK_CONN119_2 (0x4954) +#define AFE_SECURE_MASK_CONN119_3 (0x4958) +#define AFE_SECURE_MASK_CONN119_4 (0x495c) +#define AFE_SECURE_MASK_CONN120 (0x4960) +#define AFE_SECURE_MASK_CONN120_1 (0x4964) +#define AFE_SECURE_MASK_CONN120_2 (0x4968) +#define AFE_SECURE_MASK_CONN120_3 (0x496c) +#define AFE_SECURE_MASK_CONN120_4 (0x4970) +#define AFE_SECURE_MASK_CONN121 (0x4974) +#define AFE_SECURE_MASK_CONN121_1 (0x4978) +#define AFE_SECURE_MASK_CONN121_2 (0x497c) +#define AFE_SECURE_MASK_CONN121_3 (0x4980) +#define AFE_SECURE_MASK_CONN121_4 (0x4984) +#define AFE_SECURE_MASK_CONN122 (0x4988) +#define AFE_SECURE_MASK_CONN122_1 (0x498c) +#define AFE_SECURE_MASK_CONN122_2 (0x4990) +#define AFE_SECURE_MASK_CONN122_3 (0x4994) +#define AFE_SECURE_MASK_CONN122_4 (0x4998) +#define AFE_SECURE_MASK_CONN123 (0x499c) +#define AFE_SECURE_MASK_CONN123_1 (0x49a0) +#define AFE_SECURE_MASK_CONN123_2 (0x49a4) +#define AFE_SECURE_MASK_CONN123_3 (0x49a8) +#define AFE_SECURE_MASK_CONN123_4 (0x49ac) +#define AFE_SECURE_MASK_CONN124 (0x49b0) +#define AFE_SECURE_MASK_CONN124_1 (0x49b4) +#define AFE_SECURE_MASK_CONN124_2 (0x49b8) +#define AFE_SECURE_MASK_CONN124_3 (0x49bc) +#define AFE_SECURE_MASK_CONN124_4 (0x49c0) +#define AFE_SECURE_MASK_CONN125 (0x49c4) +#define AFE_SECURE_MASK_CONN125_1 (0x49c8) +#define AFE_SECURE_MASK_CONN125_2 (0x49cc) +#define AFE_SECURE_MASK_CONN125_3 (0x49d0) +#define AFE_SECURE_MASK_CONN125_4 (0x49d4) +#define AFE_SECURE_MASK_CONN126 (0x49d8) +#define AFE_SECURE_MASK_CONN126_1 (0x49dc) +#define AFE_SECURE_MASK_CONN126_2 (0x49e0) +#define AFE_SECURE_MASK_CONN126_3 (0x49e4) +#define AFE_SECURE_MASK_CONN126_4 (0x49e8) +#define AFE_SECURE_MASK_CONN127 (0x49ec) +#define AFE_SECURE_MASK_CONN127_1 (0x49f0) +#define AFE_SECURE_MASK_CONN127_2 (0x49f4) +#define AFE_SECURE_MASK_CONN127_3 (0x49f8) +#define AFE_SECURE_MASK_CONN127_4 (0x49fc) +#define AFE_SECURE_MASK_CONN128 (0x4a00) +#define AFE_SECURE_MASK_CONN128_1 (0x4a04) +#define AFE_SECURE_MASK_CONN128_2 (0x4a08) +#define AFE_SECURE_MASK_CONN128_3 (0x4a0c) +#define AFE_SECURE_MASK_CONN128_4 (0x4a10) +#define AFE_SECURE_MASK_CONN129 (0x4a14) +#define AFE_SECURE_MASK_CONN129_1 (0x4a18) +#define AFE_SECURE_MASK_CONN129_2 (0x4a1c) +#define AFE_SECURE_MASK_CONN129_3 (0x4a20) +#define AFE_SECURE_MASK_CONN129_4 (0x4a24) +#define AFE_SECURE_MASK_CONN130 (0x4a28) +#define AFE_SECURE_MASK_CONN130_1 (0x4a2c) +#define AFE_SECURE_MASK_CONN130_2 (0x4a30) +#define AFE_SECURE_MASK_CONN130_3 (0x4a34) +#define AFE_SECURE_MASK_CONN130_4 (0x4a38) +#define AFE_SECURE_MASK_CONN131 (0x4a3c) +#define AFE_SECURE_MASK_CONN131_1 (0x4a40) +#define AFE_SECURE_MASK_CONN131_2 (0x4a44) +#define AFE_SECURE_MASK_CONN131_3 (0x4a48) +#define AFE_SECURE_MASK_CONN131_4 (0x4a4c) +#define AFE_SECURE_MASK_CONN132 (0x4a50) +#define AFE_SECURE_MASK_CONN132_1 (0x4a54) +#define AFE_SECURE_MASK_CONN132_2 (0x4a58) +#define AFE_SECURE_MASK_CONN132_3 (0x4a5c) +#define AFE_SECURE_MASK_CONN132_4 (0x4a60) +#define AFE_SECURE_MASK_CONN133 (0x4a64) +#define AFE_SECURE_MASK_CONN133_1 (0x4a68) +#define AFE_SECURE_MASK_CONN133_2 (0x4a6c) +#define AFE_SECURE_MASK_CONN133_3 (0x4a70) +#define AFE_SECURE_MASK_CONN133_4 (0x4a74) +#define AFE_SECURE_MASK_CONN134 (0x4a78) +#define AFE_SECURE_MASK_CONN134_1 (0x4a7c) +#define AFE_SECURE_MASK_CONN134_2 (0x4a80) +#define AFE_SECURE_MASK_CONN134_3 (0x4a84) +#define AFE_SECURE_MASK_CONN134_4 (0x4a88) +#define AFE_SECURE_MASK_CONN135 (0x4a8c) +#define AFE_SECURE_MASK_CONN135_1 (0x4a90) +#define AFE_SECURE_MASK_CONN135_2 (0x4a94) +#define AFE_SECURE_MASK_CONN135_3 (0x4a98) +#define AFE_SECURE_MASK_CONN135_4 (0x4a9c) +#define AFE_SECURE_MASK_CONN136 (0x4aa0) +#define AFE_SECURE_MASK_CONN136_1 (0x4aa4) +#define AFE_SECURE_MASK_CONN136_2 (0x4aa8) +#define AFE_SECURE_MASK_CONN136_3 (0x4aac) +#define AFE_SECURE_MASK_CONN136_4 (0x4ab0) +#define AFE_SECURE_MASK_CONN137 (0x4ab4) +#define AFE_SECURE_MASK_CONN137_1 (0x4ab8) +#define AFE_SECURE_MASK_CONN137_2 (0x4abc) +#define AFE_SECURE_MASK_CONN137_3 (0x4ac0) +#define AFE_SECURE_MASK_CONN137_4 (0x4ac4) +#define AFE_SECURE_MASK_CONN138 (0x4ac8) +#define AFE_SECURE_MASK_CONN138_1 (0x4acc) +#define AFE_SECURE_MASK_CONN138_2 (0x4ad0) +#define AFE_SECURE_MASK_CONN138_3 (0x4ad4) +#define AFE_SECURE_MASK_CONN138_4 (0x4ad8) +#define AFE_SECURE_MASK_CONN139 (0x4adc) +#define AFE_SECURE_MASK_CONN139_1 (0x4ae0) +#define AFE_SECURE_MASK_CONN139_2 (0x4ae4) +#define AFE_SECURE_MASK_CONN139_3 (0x4ae8) +#define AFE_SECURE_MASK_CONN139_4 (0x4aec) +#define AFE_SECURE_MASK_CONN_RS (0x4af0) +#define AFE_SECURE_MASK_CONN_RS_1 (0x4af4) +#define AFE_SECURE_MASK_CONN_RS_2 (0x4af8) +#define AFE_SECURE_MASK_CONN_RS_3 (0x4afc) +#define AFE_SECURE_MASK_CONN_RS_4 (0x4b00) +#define AFE_SECURE_MASK_CONN_16BIT (0x4b04) +#define AFE_SECURE_MASK_CONN_16BIT_1 (0x4b08) +#define AFE_SECURE_MASK_CONN_16BIT_2 (0x4b0c) +#define AFE_SECURE_MASK_CONN_16BIT_3 (0x4b10) +#define AFE_SECURE_MASK_CONN_16BIT_4 (0x4b14) +#define AFE_SECURE_MASK_CONN_24BIT (0x4b18) +#define AFE_SECURE_MASK_CONN_24BIT_1 (0x4b1c) +#define AFE_SECURE_MASK_CONN_24BIT_2 (0x4b20) +#define AFE_SECURE_MASK_CONN_24BIT_3 (0x4b24) +#define AFE_SECURE_MASK_CONN_24BIT_4 (0x4b28) +#define AFE_GASRC0_NEW_CON0 (0x4c40) +#define AFE_GASRC0_NEW_CON1 (0x4c44) +#define AFE_GASRC0_NEW_CON2 (0x4c48) +#define AFE_GASRC0_NEW_CON3 (0x4c4c) +#define AFE_GASRC0_NEW_CON4 (0x4c50) +#define AFE_GASRC0_NEW_CON5 (0x4c54) +#define AFE_GASRC0_NEW_CON6 (0x4c58) +#define AFE_GASRC0_NEW_CON7 (0x4c5c) +#define AFE_GASRC0_NEW_CON8 (0x4c60) +#define AFE_GASRC0_NEW_CON9 (0x4c64) +#define AFE_GASRC0_NEW_CON10 (0x4c68) +#define AFE_GASRC0_NEW_CON11 (0x4c6c) +#define AFE_GASRC0_NEW_CON12 (0x4c70) +#define AFE_GASRC0_NEW_CON13 (0x4c74) +#define AFE_GASRC0_NEW_CON14 (0x4c78) +#define AFE_GASRC1_NEW_CON0 (0x4c80) +#define AFE_GASRC1_NEW_CON1 (0x4c84) +#define AFE_GASRC1_NEW_CON2 (0x4c88) +#define AFE_GASRC1_NEW_CON3 (0x4c8c) +#define AFE_GASRC1_NEW_CON4 (0x4c90) +#define AFE_GASRC1_NEW_CON5 (0x4c94) +#define AFE_GASRC1_NEW_CON6 (0x4c98) +#define AFE_GASRC1_NEW_CON7 (0x4c9c) +#define AFE_GASRC1_NEW_CON8 (0x4ca0) +#define AFE_GASRC1_NEW_CON9 (0x4ca4) +#define AFE_GASRC1_NEW_CON10 (0x4ca8) +#define AFE_GASRC1_NEW_CON11 (0x4cac) +#define AFE_GASRC1_NEW_CON12 (0x4cb0) +#define AFE_GASRC1_NEW_CON13 (0x4cb4) +#define AFE_GASRC1_NEW_CON14 (0x4cb8) +#define AFE_GASRC2_NEW_CON0 (0x4cc0) +#define AFE_GASRC2_NEW_CON1 (0x4cc4) +#define AFE_GASRC2_NEW_CON2 (0x4cc8) +#define AFE_GASRC2_NEW_CON3 (0x4ccc) +#define AFE_GASRC2_NEW_CON4 (0x4cd0) +#define AFE_GASRC2_NEW_CON5 (0x4cd4) +#define AFE_GASRC2_NEW_CON6 (0x4cd8) +#define AFE_GASRC2_NEW_CON7 (0x4cdc) +#define AFE_GASRC2_NEW_CON8 (0x4ce0) +#define AFE_GASRC2_NEW_CON9 (0x4ce4) +#define AFE_GASRC2_NEW_CON10 (0x4ce8) +#define AFE_GASRC2_NEW_CON11 (0x4cec) +#define AFE_GASRC2_NEW_CON12 (0x4cf0) +#define AFE_GASRC2_NEW_CON13 (0x4cf4) +#define AFE_GASRC2_NEW_CON14 (0x4cf8) +#define AFE_GASRC3_NEW_CON0 (0x4d00) +#define AFE_GASRC3_NEW_CON1 (0x4d04) +#define AFE_GASRC3_NEW_CON2 (0x4d08) +#define AFE_GASRC3_NEW_CON3 (0x4d0c) +#define AFE_GASRC3_NEW_CON4 (0x4d10) +#define AFE_GASRC3_NEW_CON5 (0x4d14) +#define AFE_GASRC3_NEW_CON6 (0x4d18) +#define AFE_GASRC3_NEW_CON7 (0x4d1c) +#define AFE_GASRC3_NEW_CON8 (0x4d20) +#define AFE_GASRC3_NEW_CON9 (0x4d24) +#define AFE_GASRC3_NEW_CON10 (0x4d28) +#define AFE_GASRC3_NEW_CON11 (0x4d2c) +#define AFE_GASRC3_NEW_CON12 (0x4d30) +#define AFE_GASRC3_NEW_CON13 (0x4d34) +#define AFE_GASRC3_NEW_CON14 (0x4d38) +#define AFE_GASRC4_NEW_CON0 (0x4d40) +#define AFE_GASRC4_NEW_CON1 (0x4d44) +#define AFE_GASRC4_NEW_CON2 (0x4d48) +#define AFE_GASRC4_NEW_CON3 (0x4d4c) +#define AFE_GASRC4_NEW_CON4 (0x4d50) +#define AFE_GASRC4_NEW_CON5 (0x4d54) +#define AFE_GASRC4_NEW_CON6 (0x4d58) +#define AFE_GASRC4_NEW_CON7 (0x4d5c) +#define AFE_GASRC4_NEW_CON8 (0x4d60) +#define AFE_GASRC4_NEW_CON9 (0x4d64) +#define AFE_GASRC4_NEW_CON10 (0x4d68) +#define AFE_GASRC4_NEW_CON11 (0x4d6c) +#define AFE_GASRC4_NEW_CON12 (0x4d70) +#define AFE_GASRC4_NEW_CON13 (0x4d74) +#define AFE_GASRC4_NEW_CON14 (0x4d78) +#define AFE_GASRC5_NEW_CON0 (0x4d80) +#define AFE_GASRC5_NEW_CON1 (0x4d84) +#define AFE_GASRC5_NEW_CON2 (0x4d88) +#define AFE_GASRC5_NEW_CON3 (0x4d8c) +#define AFE_GASRC5_NEW_CON4 (0x4d90) +#define AFE_GASRC5_NEW_CON5 (0x4d94) +#define AFE_GASRC5_NEW_CON6 (0x4d98) +#define AFE_GASRC5_NEW_CON7 (0x4d9c) +#define AFE_GASRC5_NEW_CON8 (0x4da0) +#define AFE_GASRC5_NEW_CON9 (0x4da4) +#define AFE_GASRC5_NEW_CON10 (0x4da8) +#define AFE_GASRC5_NEW_CON11 (0x4dac) +#define AFE_GASRC5_NEW_CON12 (0x4db0) +#define AFE_GASRC5_NEW_CON13 (0x4db4) +#define AFE_GASRC5_NEW_CON14 (0x4db8) +#define AFE_GASRC6_NEW_CON0 (0x4dc0) +#define AFE_GASRC6_NEW_CON1 (0x4dc4) +#define AFE_GASRC6_NEW_CON2 (0x4dc8) +#define AFE_GASRC6_NEW_CON3 (0x4dcc) +#define AFE_GASRC6_NEW_CON4 (0x4dd0) +#define AFE_GASRC6_NEW_CON5 (0x4dd4) +#define AFE_GASRC6_NEW_CON6 (0x4dd8) +#define AFE_GASRC6_NEW_CON7 (0x4ddc) +#define AFE_GASRC6_NEW_CON8 (0x4de0) +#define AFE_GASRC6_NEW_CON9 (0x4de4) +#define AFE_GASRC6_NEW_CON10 (0x4de8) +#define AFE_GASRC6_NEW_CON11 (0x4dec) +#define AFE_GASRC6_NEW_CON12 (0x4df0) +#define AFE_GASRC6_NEW_CON13 (0x4df4) +#define AFE_GASRC6_NEW_CON14 (0x4df8) +#define AFE_GASRC7_NEW_CON0 (0x4e00) +#define AFE_GASRC7_NEW_CON1 (0x4e04) +#define AFE_GASRC7_NEW_CON2 (0x4e08) +#define AFE_GASRC7_NEW_CON3 (0x4e0c) +#define AFE_GASRC7_NEW_CON4 (0x4e10) +#define AFE_GASRC7_NEW_CON5 (0x4e14) +#define AFE_GASRC7_NEW_CON6 (0x4e18) +#define AFE_GASRC7_NEW_CON7 (0x4e1c) +#define AFE_GASRC7_NEW_CON8 (0x4e20) +#define AFE_GASRC7_NEW_CON9 (0x4e24) +#define AFE_GASRC7_NEW_CON10 (0x4e28) +#define AFE_GASRC7_NEW_CON11 (0x4e2c) +#define AFE_GASRC7_NEW_CON12 (0x4e30) +#define AFE_GASRC7_NEW_CON13 (0x4e34) +#define AFE_GASRC7_NEW_CON14 (0x4e38) +#define AFE_GASRC8_NEW_CON0 (0x4e40) +#define AFE_GASRC8_NEW_CON1 (0x4e44) +#define AFE_GASRC8_NEW_CON2 (0x4e48) +#define AFE_GASRC8_NEW_CON3 (0x4e4c) +#define AFE_GASRC8_NEW_CON4 (0x4e50) +#define AFE_GASRC8_NEW_CON5 (0x4e54) +#define AFE_GASRC8_NEW_CON6 (0x4e58) +#define AFE_GASRC8_NEW_CON7 (0x4e5c) +#define AFE_GASRC8_NEW_CON8 (0x4e60) +#define AFE_GASRC8_NEW_CON9 (0x4e64) +#define AFE_GASRC8_NEW_CON10 (0x4e68) +#define AFE_GASRC8_NEW_CON11 (0x4e6c) +#define AFE_GASRC8_NEW_CON12 (0x4e70) +#define AFE_GASRC8_NEW_CON13 (0x4e74) +#define AFE_GASRC8_NEW_CON14 (0x4e78) +#define AFE_GASRC9_NEW_CON0 (0x4e80) +#define AFE_GASRC9_NEW_CON1 (0x4e84) +#define AFE_GASRC9_NEW_CON2 (0x4e88) +#define AFE_GASRC9_NEW_CON3 (0x4e8c) +#define AFE_GASRC9_NEW_CON4 (0x4e90) +#define AFE_GASRC9_NEW_CON5 (0x4e94) +#define AFE_GASRC9_NEW_CON6 (0x4e98) +#define AFE_GASRC9_NEW_CON7 (0x4e9c) +#define AFE_GASRC9_NEW_CON8 (0x4ea0) +#define AFE_GASRC9_NEW_CON9 (0x4ea4) +#define AFE_GASRC9_NEW_CON10 (0x4ea8) +#define AFE_GASRC9_NEW_CON11 (0x4eac) +#define AFE_GASRC9_NEW_CON12 (0x4eb0) +#define AFE_GASRC9_NEW_CON13 (0x4eb4) +#define AFE_GASRC9_NEW_CON14 (0x4eb8) +#define AFE_GASRC10_NEW_CON0 (0x4ec0) +#define AFE_GASRC10_NEW_CON1 (0x4ec4) +#define AFE_GASRC10_NEW_CON2 (0x4ec8) +#define AFE_GASRC10_NEW_CON3 (0x4ecc) +#define AFE_GASRC10_NEW_CON4 (0x4ed0) +#define AFE_GASRC10_NEW_CON5 (0x4ed4) +#define AFE_GASRC10_NEW_CON6 (0x4ed8) +#define AFE_GASRC10_NEW_CON7 (0x4edc) +#define AFE_GASRC10_NEW_CON8 (0x4ee0) +#define AFE_GASRC10_NEW_CON9 (0x4ee4) +#define AFE_GASRC10_NEW_CON10 (0x4ee8) +#define AFE_GASRC10_NEW_CON11 (0x4eec) +#define AFE_GASRC10_NEW_CON12 (0x4ef0) +#define AFE_GASRC10_NEW_CON13 (0x4ef4) +#define AFE_GASRC10_NEW_CON14 (0x4ef8) +#define AFE_GASRC11_NEW_CON0 (0x4f00) +#define AFE_GASRC11_NEW_CON1 (0x4f04) +#define AFE_GASRC11_NEW_CON2 (0x4f08) +#define AFE_GASRC11_NEW_CON3 (0x4f0c) +#define AFE_GASRC11_NEW_CON4 (0x4f10) +#define AFE_GASRC11_NEW_CON5 (0x4f14) +#define AFE_GASRC11_NEW_CON6 (0x4f18) +#define AFE_GASRC11_NEW_CON7 (0x4f1c) +#define AFE_GASRC11_NEW_CON8 (0x4f20) +#define AFE_GASRC11_NEW_CON9 (0x4f24) +#define AFE_GASRC11_NEW_CON10 (0x4f28) +#define AFE_GASRC11_NEW_CON11 (0x4f2c) +#define AFE_GASRC11_NEW_CON12 (0x4f30) +#define AFE_GASRC11_NEW_CON13 (0x4f34) +#define AFE_GASRC11_NEW_CON14 (0x4f38) +#define AFE_GASRC12_NEW_CON0 (0x4f40) +#define AFE_GASRC12_NEW_CON1 (0x4f44) +#define AFE_GASRC12_NEW_CON2 (0x4f48) +#define AFE_GASRC12_NEW_CON3 (0x4f4c) +#define AFE_GASRC12_NEW_CON4 (0x4f50) +#define AFE_GASRC12_NEW_CON5 (0x4f54) +#define AFE_GASRC12_NEW_CON6 (0x4f58) +#define AFE_GASRC12_NEW_CON7 (0x4f5c) +#define AFE_GASRC12_NEW_CON8 (0x4f60) +#define AFE_GASRC12_NEW_CON9 (0x4f64) +#define AFE_GASRC12_NEW_CON10 (0x4f68) +#define AFE_GASRC12_NEW_CON11 (0x4f6c) +#define AFE_GASRC12_NEW_CON12 (0x4f70) +#define AFE_GASRC12_NEW_CON13 (0x4f74) +#define AFE_GASRC12_NEW_CON14 (0x4f78) +#define AFE_GASRC13_NEW_CON0 (0x4f80) +#define AFE_GASRC13_NEW_CON1 (0x4f84) +#define AFE_GASRC13_NEW_CON2 (0x4f88) +#define AFE_GASRC13_NEW_CON3 (0x4f8c) +#define AFE_GASRC13_NEW_CON4 (0x4f90) +#define AFE_GASRC13_NEW_CON5 (0x4f94) +#define AFE_GASRC13_NEW_CON6 (0x4f98) +#define AFE_GASRC13_NEW_CON7 (0x4f9c) +#define AFE_GASRC13_NEW_CON8 (0x4fa0) +#define AFE_GASRC13_NEW_CON9 (0x4fa4) +#define AFE_GASRC13_NEW_CON10 (0x4fa8) +#define AFE_GASRC13_NEW_CON11 (0x4fac) +#define AFE_GASRC13_NEW_CON12 (0x4fb0) +#define AFE_GASRC13_NEW_CON13 (0x4fb4) +#define AFE_GASRC13_NEW_CON14 (0x4fb8) +#define AFE_GASRC14_NEW_CON0 (0x4fc0) +#define AFE_GASRC14_NEW_CON1 (0x4fc4) +#define AFE_GASRC14_NEW_CON2 (0x4fc8) +#define AFE_GASRC14_NEW_CON3 (0x4fcc) +#define AFE_GASRC14_NEW_CON4 (0x4fd0) +#define AFE_GASRC14_NEW_CON5 (0x4fd4) +#define AFE_GASRC14_NEW_CON6 (0x4fd8) +#define AFE_GASRC14_NEW_CON7 (0x4fdc) +#define AFE_GASRC14_NEW_CON8 (0x4fe0) +#define AFE_GASRC14_NEW_CON9 (0x4fe4) +#define AFE_GASRC14_NEW_CON10 (0x4fe8) +#define AFE_GASRC14_NEW_CON11 (0x4fec) +#define AFE_GASRC14_NEW_CON12 (0x4ff0) +#define AFE_GASRC14_NEW_CON13 (0x4ff4) +#define AFE_GASRC14_NEW_CON14 (0x4ff8) +#define AFE_GASRC15_NEW_CON0 (0x5000) +#define AFE_GASRC15_NEW_CON1 (0x5004) +#define AFE_GASRC15_NEW_CON2 (0x5008) +#define AFE_GASRC15_NEW_CON3 (0x500c) +#define AFE_GASRC15_NEW_CON4 (0x5010) +#define AFE_GASRC15_NEW_CON5 (0x5014) +#define AFE_GASRC15_NEW_CON6 (0x5018) +#define AFE_GASRC15_NEW_CON7 (0x501c) +#define AFE_GASRC15_NEW_CON8 (0x5020) +#define AFE_GASRC15_NEW_CON9 (0x5024) +#define AFE_GASRC15_NEW_CON10 (0x5028) +#define AFE_GASRC15_NEW_CON11 (0x502c) +#define AFE_GASRC15_NEW_CON12 (0x5030) +#define AFE_GASRC15_NEW_CON13 (0x5034) +#define AFE_GASRC15_NEW_CON14 (0x5038) +#define AFE_GASRC16_NEW_CON0 (0x5040) +#define AFE_GASRC16_NEW_CON1 (0x5044) +#define AFE_GASRC16_NEW_CON2 (0x5048) +#define AFE_GASRC16_NEW_CON3 (0x504c) +#define AFE_GASRC16_NEW_CON4 (0x5050) +#define AFE_GASRC16_NEW_CON5 (0x5054) +#define AFE_GASRC16_NEW_CON6 (0x5058) +#define AFE_GASRC16_NEW_CON7 (0x505c) +#define AFE_GASRC16_NEW_CON8 (0x5060) +#define AFE_GASRC16_NEW_CON9 (0x5064) +#define AFE_GASRC16_NEW_CON10 (0x5068) +#define AFE_GASRC16_NEW_CON11 (0x506c) +#define AFE_GASRC16_NEW_CON12 (0x5070) +#define AFE_GASRC16_NEW_CON13 (0x5074) +#define AFE_GASRC16_NEW_CON14 (0x5078) +#define AFE_GASRC17_NEW_CON0 (0x5080) +#define AFE_GASRC17_NEW_CON1 (0x5084) +#define AFE_GASRC17_NEW_CON2 (0x5088) +#define AFE_GASRC17_NEW_CON3 (0x508c) +#define AFE_GASRC17_NEW_CON4 (0x5090) +#define AFE_GASRC17_NEW_CON5 (0x5094) +#define AFE_GASRC17_NEW_CON6 (0x5098) +#define AFE_GASRC17_NEW_CON7 (0x509c) +#define AFE_GASRC17_NEW_CON8 (0x50a0) +#define AFE_GASRC17_NEW_CON9 (0x50a4) +#define AFE_GASRC17_NEW_CON10 (0x50a8) +#define AFE_GASRC17_NEW_CON11 (0x50ac) +#define AFE_GASRC17_NEW_CON12 (0x50b0) +#define AFE_GASRC17_NEW_CON13 (0x50b4) +#define AFE_GASRC17_NEW_CON14 (0x50b8) +#define AFE_GASRC18_NEW_CON0 (0x50c0) +#define AFE_GASRC18_NEW_CON1 (0x50c4) +#define AFE_GASRC18_NEW_CON2 (0x50c8) +#define AFE_GASRC18_NEW_CON3 (0x50cc) +#define AFE_GASRC18_NEW_CON4 (0x50d0) +#define AFE_GASRC18_NEW_CON5 (0x50d4) +#define AFE_GASRC18_NEW_CON6 (0x50d8) +#define AFE_GASRC18_NEW_CON7 (0x50dc) +#define AFE_GASRC18_NEW_CON8 (0x50e0) +#define AFE_GASRC18_NEW_CON9 (0x50e4) +#define AFE_GASRC18_NEW_CON10 (0x50e8) +#define AFE_GASRC18_NEW_CON11 (0x50ec) +#define AFE_GASRC18_NEW_CON12 (0x50f0) +#define AFE_GASRC18_NEW_CON13 (0x50f4) +#define AFE_GASRC18_NEW_CON14 (0x50f8) +#define AFE_GASRC19_NEW_CON0 (0x5100) +#define AFE_GASRC19_NEW_CON1 (0x5104) +#define AFE_GASRC19_NEW_CON2 (0x5108) +#define AFE_GASRC19_NEW_CON3 (0x510c) +#define AFE_GASRC19_NEW_CON4 (0x5110) +#define AFE_GASRC19_NEW_CON5 (0x5114) +#define AFE_GASRC19_NEW_CON6 (0x5118) +#define AFE_GASRC19_NEW_CON7 (0x511c) +#define AFE_GASRC19_NEW_CON8 (0x5120) +#define AFE_GASRC19_NEW_CON9 (0x5124) +#define AFE_GASRC19_NEW_CON10 (0x5128) +#define AFE_GASRC19_NEW_CON11 (0x512c) +#define AFE_GASRC19_NEW_CON12 (0x5130) +#define AFE_GASRC19_NEW_CON13 (0x5134) +#define AFE_GASRC19_NEW_CON14 (0x5138) + +#define AFE_MAX_REGISTER (AFE_GASRC19_NEW_CON14) + +/* ASYS_TOP_CON */ +#define ASYS_TOP_CON_A1SYS_TIMING_ON BIT(0) +#define ASYS_TOP_CON_A2SYS_TIMING_ON BIT(1) +#define ASYS_TOP_CON_A3SYS_TIMING_ON BIT(4) +#define ASYS_TOP_CON_A4SYS_TIMING_ON BIT(5) +#define ASYS_TOP_CON_26M_TIMING_ON BIT(2) + +/* PWR2_TOP_CON0 */ +#define PWR2_TOP_CON_DMIC8_SRC_SEL_MASK GENMASK(31, 29) +#define PWR2_TOP_CON_DMIC7_SRC_SEL_MASK GENMASK(28, 26) +#define PWR2_TOP_CON_DMIC6_SRC_SEL_MASK GENMASK(25, 23) +#define PWR2_TOP_CON_DMIC5_SRC_SEL_MASK GENMASK(22, 20) +#define PWR2_TOP_CON_DMIC4_SRC_SEL_MASK GENMASK(19, 17) +#define PWR2_TOP_CON_DMIC3_SRC_SEL_MASK GENMASK(16, 14) +#define PWR2_TOP_CON_DMIC2_SRC_SEL_MASK GENMASK(13, 11) +#define PWR2_TOP_CON_DMIC1_SRC_SEL_MASK GENMASK(10, 8) +#define PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(x) ((x) << 29) +#define PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(x) ((x) << 26) +#define PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(x) ((x) << 23) +#define PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(x) ((x) << 20) +#define PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(x) ((x) << 17) +#define PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(x) ((x) << 14) +#define PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(x) ((x) << 11) +#define PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(x) ((x) << 8) + +/* PWR2_TOP_CON1 */ +#define PWR2_TOP_CON1_DMIC_CKDIV_ON BIT(1) + +/* PCM_INTF_CON1 */ +#define PCM_INTF_CON1_SYNC_OUT_INV BIT(23) +#define PCM_INTF_CON1_BCLK_OUT_INV BIT(22) +#define PCM_INTF_CON1_CLK_OUT_INV_MASK GENMASK(23, 22) +#define PCM_INTF_CON1_SYNC_IN_INV BIT(21) +#define PCM_INTF_CON1_BCLK_IN_INV BIT(20) +#define PCM_INTF_CON1_CLK_IN_INV_MASK GENMASK(21, 20) +#define PCM_INTF_CON1_PCM_24BIT (0x1 << 16) +#define PCM_INTF_CON1_PCM_16BIT (0x0 << 16) +#define PCM_INTF_CON1_PCM_BIT_MASK BIT(16) +#define PCM_INTF_CON1_PCM_WLEN_32BCK (0x0 << 14) +#define PCM_INTF_CON1_PCM_WLEN_64BCK (0x1 << 14) +#define PCM_INTF_CON1_PCM_WLEN_MASK BIT(14) +#define PCM_INTF_CON1_SYNC_LENGTH(x) (((x) & 0x1f) << 9) +#define PCM_INTF_CON1_SYNC_LENGTH_MASK (0x1f << 9) +#define PCM_INTF_CON1_PCM_SLAVE (0x1 << 5) +#define PCM_INTF_CON1_PCM_MASTER (0x0 << 5) +#define PCM_INTF_CON1_PCM_M_S_MASK BIT(5) +#define PCM_INTF_CON1_PCM_MODE(x) (((x) & 0x3) << 3) +#define PCM_INTF_CON1_PCM_MODE_MASK (0x3 << 3) +#define PCM_INTF_CON1_PCM_FMT(x) (((x) & 0x3) << 1) +#define PCM_INTF_CON1_PCM_FMT_MASK (0x3 << 1) +#define PCM_INTF_CON1_PCM_EN BIT(0) + +/* PCM_INTF_CON2 */ +#define PCM_INTF_CON2_CLK_DOMAIN_SEL(x) (((x) & 0x3) << 23) +#define PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK (0x3 << 23) +#define PCM_INTF_CON2_SYNC_FREQ_MODE(x) (((x) & 0x1f) << 12) +#define PCM_INTF_CON2_SYNC_FREQ_MODE_MASK (0x1f << 12) +#define PCM_INTF_CON2_PCM_TX2RX_LPBK BIT(8) + +/* AFE_MPHONE_MULTIx_CON0 */ +#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP BIT(3) +#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP_MASK BIT(3) +#define AFE_MPHONE_MULTI_CON0_24BIT_DATA (0x1 << 1) +#define AFE_MPHONE_MULTI_CON0_16BIT_DATA (0x0 << 1) +#define AFE_MPHONE_MULIT_CON0_24BIT_DATA_MASK BIT(1) +#define AFE_MPHONE_MULTI_CON0_EN BIT(0) +#define AFE_MPHONE_MULTI_CON0_EN_MASK BIT(0) + +/* AFE_MPHONE_MULTIx_CON1 */ +#define AFE_MPHONE_MULTI_CON1_SYNC_ON BIT(24) +#define AFE_MPHONE_MULTI_CON1_SYNC_ON_MASK BIT(24) +#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS BIT(22) +#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS_MASK BIT(22) +#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE (0x1 << 19) +#define AFE_MPHONE_MULTI_CON1_COMPACT_MODE (0x0 << 19) +#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE_MASK BIT(19) +#define AFE_MPHONE_MULTI_CON1_HBR_MODE BIT(18) +#define AFE_MPHONE_MULTI_CON1_HBR_MODE_MASK BIT(18) +#define AFE_MPHONE_MULTI_CON1_LRCK_32_CYCLE (0x2 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_24_CYCLE (0x1 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_16_CYCLE (0x0 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_CYCLE_SEL_MASK GENMASK(17, 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_INV BIT(15) +#define AFE_MPHONE_MULTI_CON1_LRCK_INV_MASK BIT(15) +#define AFE_MPHONE_MULTI_CON1_DELAY_DATA BIT(14) +#define AFE_MPHONE_MULTI_CON1_DELAY_DATA_MASK BIT(14) +#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN BIT(13) +#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN_MASK BIT(13) +#define AFE_MPHONE_MULTI_CON1_BIT_NUM(x) ((((x) - 1) & 0x1f) << 8) +#define AFE_MPHONE_MULTI_CON1_BIT_NUM_MASK GENMASK(12, 8) +#define AFE_MPHONE_MULTI_CON1_BCK_INV BIT(6) +#define AFE_MPHONE_MULTI_CON1_BCK_INV_MASK BIT(6) +#define AFE_MPHONE_MULTI_CON1_CH_NUM(x) ((((x) >> 1) - 1) & 0x3) +#define AFE_MPHONE_MULTI_CON1_CH_NUM_MASK GENMASK(1, 0) + +/* AFE_MPHONE_MULTIx_CON2 */ +#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN BIT(19) +#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN_MASK BIT(19) + +/* AFE_AUD_PAD_TOP */ +#define RG_RX_PROTOCOL2 BIT(3) +#define RG_RX_FIFO_ON BIT(0) + +/* AFE_ADDA_MTKAIF_CFG0 */ +#define MTKAIF_RXIF_CLKINV_ADC BIT(31) +#define MTKAIF_RXIF_PROTOCOL2 BIT(16) +#define MTKAIF_TXIF_PROTOCOL2 BIT(4) +#define MTKAIF_TXIF_8TO5 BIT(2) +#define MTKAIF_RXIF_8TO5 BIT(1) +#define MTKAIF_IF_LOOPBACK1 BIT(0) + +/* AFE_ADDA_MTKAIF_RX_CFG2 */ +#define MTKAIF_RXIF_DELAY_CYCLE(x) ((x) << 12) +#define MTKAIF_RXIF_DELAY_CYCLE_MASK GENMASK(15, 12) +#define MTKAIF_RXIF_DELAY_DATA BIT(8) +#define MTKAIF_RXIF_DELAY_DATA_SHIFT 8 + +/* AFE_ADDA_MTKAIF_SYNCWORD_CFG */ +#define ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE BIT(23) + +/* AFE_DMICx_UL_SRC_CON0 */ +#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(x) (((x) & 0x7) << 27) +#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(x) (((x) & 0x7) << 24) +#define AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL BIT(23) +#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL BIT(22) +#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL BIT(21) +#define AFE_DMIC_UL_VOICE_MODE(x) (((x) & 0x7) << 17) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_8K AFE_DMIC_UL_VOICE_MODE(0) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_16K AFE_DMIC_UL_VOICE_MODE(1) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_32K AFE_DMIC_UL_VOICE_MODE(2) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_48K AFE_DMIC_UL_VOICE_MODE(3) +#define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(x) (((x) & 0x7) << 7) +#define AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL BIT(10) +#define AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL BIT(1) +#define AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL BIT(0) + +/* ETDM_INx_AFIFO_CON */ +#define ETDM_IN_USE_AFIFO BIT(8) +#define ETDM_IN_AFIFO_CLOCK(x) ((x) << 5) +#define ETDM_IN_AFIFO_CLOCK_MASK GENMASK(7, 5) +#define ETDM_IN_AFIFO_MODE(x) ((x) << 0) +#define ETDM_IN_AFIFO_MODE_MASK GENMASK(4, 0) + +/* ETDM_COWORK_CON0 */ +#define ETDM_OUT1_SLAVE_SEL(x) ((x) << 20) +#define ETDM_OUT1_SLAVE_SEL_MASK GENMASK(23, 20) +#define ETDM_OUT1_SLAVE_SEL_SHIFT 20 + +/* ETDM_COWORK_CON1 */ +#define ETDM_IN1_SDATA_SEL(x) ((x) << 20) +#define ETDM_IN1_SDATA_SEL_MASK GENMASK(23, 20) +#define ETDM_IN1_SDATA_SEL_SHIFT 20 +#define ETDM_IN1_SDATA0_SEL(x) ((x) << 16) +#define ETDM_IN1_SDATA0_SEL_MASK GENMASK(19, 16) +#define ETDM_IN1_SDATA0_SEL_SHIFT 16 +#define ETDM_IN1_SLAVE_SEL(x) ((x) << 8) +#define ETDM_IN1_SLAVE_SEL_MASK GENMASK(11, 8) +#define ETDM_IN1_SLAVE_SEL_SHIFT 8 + +/* ETDM_COWORK_CON2 */ +#define ETDM_IN2_SLAVE_SEL(x) ((x) << 24) +#define ETDM_IN2_SLAVE_SEL_MASK GENMASK(27, 24) +#define ETDM_IN2_SLAVE_SEL_SHIFT 24 +#define ETDM_OUT3_SLAVE_SEL(x) ((x) << 20) +#define ETDM_OUT3_SLAVE_SEL_MASK GENMASK(23, 20) +#define ETDM_OUT3_SLAVE_SEL_SHIFT 20 +#define ETDM_OUT2_SLAVE_SEL(x) ((x) << 8) +#define ETDM_OUT2_SLAVE_SEL_MASK GENMASK(11, 8) +#define ETDM_OUT2_SLAVE_SEL_SHIFT 8 + +/* ETDM_COWORK_CON3 */ +#define ETDM_IN2_SDATA_SEL(x) ((x) << 4) +#define ETDM_IN2_SDATA_SEL_MASK GENMASK(7, 4) +#define ETDM_IN2_SDATA_SEL_SHIFT 4 +#define ETDM_IN2_SDATA0_SEL(x) ((x) << 0) +#define ETDM_IN2_SDATA0_SEL_MASK GENMASK(3, 0) +#define ETDM_IN2_SDATA0_SEL_SHIFT 0 + +/* ETDM_x_CONx */ +#define ETDM_CON0_CH_NUM(x) (((x) - 1) << 23) +#define ETDM_CON0_CH_NUM_MASK GENMASK(27, 23) +#define ETDM_CON0_WORD_LEN(x) (((x) - 1) << 16) +#define ETDM_CON0_WORD_LEN_MASK GENMASK(20, 16) +#define ETDM_CON0_BIT_LEN(x) (((x) - 1) << 11) +#define ETDM_CON0_BIT_LEN_MASK GENMASK(15, 11) +#define ETDM_CON0_FORMAT(x) ((x) << 6) +#define ETDM_CON0_FORMAT_MASK GENMASK(8, 6) +#define ETDM_CON0_SLAVE_MODE BIT(5) +#define ETDM_CON0_EN BIT(0) + +#define ETDM_OUT_CON0_RELATCH_DOMAIN(x) ((x) << 28) +#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28) + +#define ETDM_CON1_MCLK_OUTPUT BIT(16) +#define ETDM_IN_CON1_LRCK_AUTO_MODE BIT(31) +#define ETDM_IN_CON1_LRCK_WIDTH(x) (((x) - 1) << 20) +#define ETDM_IN_CON1_LRCK_WIDTH_MASK GENMASK(29, 20) +#define ETDM_OUT_CON1_LRCK_AUTO_MODE BIT(29) +#define ETDM_OUT_CON1_LRCK_WIDTH(x) (((x) - 1) << 19) +#define ETDM_OUT_CON1_LRCK_WIDTH_MASK GENMASK(28, 19) + +#define ETDM_IN_CON2_MULTI_IP_2CH_MODE BIT(31) +#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH(x) (((x) - 1) << 15) +#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK GENMASK(19, 15) +#define ETDM_IN_CON2_CLOCK(x) ((x) << 10) +#define ETDM_IN_CON2_CLOCK_MASK GENMASK(12, 10) +#define ETDM_IN_CON2_CLOCK_SHIFT 10 +#define ETDM_IN_CON2_UPDATE_GAP(x) ((x) << 5) +#define ETDM_IN_CON2_UPDATE_GAP_MASK GENMASK(9, 5) + +#define ETDM_OUT_CON2_LRCK_DELAY_BCK_INV BIT(30) +#define ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN BIT(29) + +#define ETDM_IN_CON3_FS(x) ((x) << 26) +#define ETDM_IN_CON3_FS_MASK GENMASK(30, 26) +#define ETDM_IN_CON3_DISABLE_OUT(x) BIT(((x) & 0xf)) +#define ETDM_IN_CON3_DISABLE_OUT_MASK GENMASK(15, 0) + +#define ETDM_IN_CON4_MASTER_LRCK_INV BIT(19) +#define ETDM_IN_CON4_MASTER_BCK_INV BIT(18) +#define ETDM_IN_CON4_SLAVE_LRCK_INV BIT(17) +#define ETDM_IN_CON4_SLAVE_BCK_INV BIT(16) + +#define ETDM_OUT_CON4_RELATCH_EN(x) ((x) << 24) +#define ETDM_OUT_CON4_RELATCH_EN_MASK GENMASK(28, 24) +#define ETDM_OUT_CON4_CLOCK(x) ((x) << 6) +#define ETDM_OUT_CON4_CLOCK_MASK GENMASK(8, 6) +#define ETDM_OUT_CON4_CLOCK_SHIFT 6 +#define ETDM_OUT_CON4_FS(x) ((x) << 0) +#define ETDM_OUT_CON4_FS_MASK GENMASK(4, 0) + +#define ETDM_IN_CON5_LR_SWAP(x) BIT(((x) & 0xf) + 16) +#define ETDM_IN_CON5_LR_SWAP_MASK GENMASK(31, 16) +#define ETDM_IN_CON5_ENABLE_ODD(x) BIT(((x) & 0xf)) +#define ETDM_IN_CON5_ENABLE_ODD_MASK GENMASK(15, 0) + +#define ETDM_OUT_CON5_MASTER_LRCK_INV BIT(10) +#define ETDM_OUT_CON5_MASTER_BCK_INV BIT(9) +#define ETDM_OUT_CON5_SLAVE_LRCK_INV BIT(8) +#define ETDM_OUT_CON5_SLAVE_BCK_INV BIT(7) + +/* AFE_DPTX_CON */ +#define AFE_DPTX_CON_CH_EN(x) (((x) & 0xff) << 8) +#define AFE_DPTX_CON_CH_EN_2CH (AFE_DPTX_CON_CH_EN(GENMASK(1, 0))) +#define AFE_DPTX_CON_CH_EN_4CH (AFE_DPTX_CON_CH_EN(GENMASK(3, 0))) +#define AFE_DPTX_CON_CH_EN_6CH (AFE_DPTX_CON_CH_EN(GENMASK(5, 0))) +#define AFE_DPTX_CON_CH_EN_8CH (AFE_DPTX_CON_CH_EN(GENMASK(7, 0))) +#define AFE_DPTX_CON_CH_EN_MASK GENMASK(15, 8) +#define AFE_DPTX_CON_16BIT (0x1 << 2) +#define AFE_DPTX_CON_24BIT (0x0 << 2) +#define AFE_DPTX_CON_16BIT_MASK BIT(2) +#define AFE_DPTX_CON_CH_NUM(x) (((x) & 0x1) << 1) +#define AFE_DPTX_CON_CH_NUM_2CH (AFE_DPTX_CON_CH_NUM(0)) +#define AFE_DPTX_CON_CH_NUM_8CH (AFE_DPTX_CON_CH_NUM(1)) +#define AFE_DPTX_CON_CH_NUM_MASK (0x1 << 1) +#define AFE_DPTX_CON_ON BIT(0) +#define AFE_DPTX_CON_ON_MASK BIT(0) + +/* AFE_ADDA_UL_DL_CON0 */ +#define ADDA_AFE_ON_SHIFT 0 + +/* AFE_ADDA_DL_SRC2_CON0 */ +#define DL_2_INPUT_MODE_CTL(x) ((x) << 28) +#define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28) +#define DL_2_CH1_SATURATION_EN_CTL BIT(27) +#define DL_2_CH2_SATURATION_EN_CTL BIT(26) +#define DL_2_MUTE_CH1_OFF_CTL_PRE BIT(12) +#define DL_2_MUTE_CH2_OFF_CTL_PRE BIT(11) +#define DL_2_VOICE_MODE_CTL_PRE BIT(5) +#define DL_2_GAIN_ON_CTL_PRE_SHIFT 1 +#define DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT 0 + +/* AFE_ADDA_DL_SRC2_CON1 */ +#define DL_2_GAIN_CTL_PRE(x) ((x) << 16) +#define DL_2_GAIN_CTL_PRE_MASK GENMASK(31, 16) +#define DL_2_GAIN_CTL_PRE_SHIFT 16 + +/* AFE_ADDA_TOP_CON0 */ +#define C_LOOPBACK_MODE_CTL_MASK GENMASK(15, 12) +#define DL_INPUT_FROM_SINEGEN (4 << 12) + +/* AFE_ADDA_DL_SDM_DCCOMP_CON */ +#define DL_USE_NEW_2ND_SDM BIT(30) +#define ATTGAIN_CTL_MASK GENMASK(5, 0) + +/* AFE_ADDA_UL_SRC_CON0 */ +#define UL_MODE_3P25M_CH2_CTL BIT(22) +#define UL_MODE_3P25M_CH1_CTL BIT(21) +#define UL_VOICE_MODE_CTL(x) ((x) << 17) +#define UL_VOICE_MODE_CTL_MASK GENMASK(19, 17) +#define UL_LOOPBACK_MODE_CTL BIT(2) +#define UL_SDM3_LEVEL_CTL BIT(1) +#define UL_SRC_ON_TMP_CTL_SHIFT 0 + +#endif diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index b941adcbb8f9..939e7e28486a 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -61,22 +61,6 @@ static void dump_registers(struct ssp_device *ssp) pxa_ssp_read_reg(ssp, SSACD)); } -static void pxa_ssp_enable(struct ssp_device *ssp) -{ - uint32_t sscr0; - - sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE; - __raw_writel(sscr0, ssp->mmio_base + SSCR0); -} - -static void pxa_ssp_disable(struct ssp_device *ssp) -{ - uint32_t sscr0; - - sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE; - __raw_writel(sscr0, ssp->mmio_base + SSCR0); -} - static void pxa_ssp_set_dma_params(struct ssp_device *ssp, int width4, int out, struct snd_dmaengine_dai_dma_data *dma) { diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 08a05f0ecad7..ba2a98268ee4 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -30,6 +30,13 @@ struct apq8016_sbc_data { #define MIC_CTRL_QUA_WS_SLAVE_SEL_10 BIT(17) #define MIC_CTRL_TLMM_SCLK_EN BIT(1) #define SPKR_CTL_PRI_WS_SLAVE_SEL_11 (BIT(17) | BIT(16)) +#define SPKR_CTL_TLMM_MCLK_EN BIT(1) +#define SPKR_CTL_TLMM_SCLK_EN BIT(2) +#define SPKR_CTL_TLMM_DATA1_EN BIT(3) +#define SPKR_CTL_TLMM_WS_OUT_SEL_MASK GENMASK(7, 6) +#define SPKR_CTL_TLMM_WS_OUT_SEL_SEC BIT(6) +#define SPKR_CTL_TLMM_WS_EN_SEL_MASK GENMASK(19, 18) +#define SPKR_CTL_TLMM_WS_EN_SEL_SEC BIT(18) #define DEFAULT_MCLK_RATE 9600000 static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) @@ -40,6 +47,7 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card); int i, rval; + u32 value; switch (cpu_dai->id) { case MI2S_PRIMARY: @@ -53,6 +61,15 @@ static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd) MIC_CTRL_TLMM_SCLK_EN, pdata->mic_iomux); break; + case MI2S_SECONDARY: + /* Clear TLMM_WS_OUT_SEL and TLMM_WS_EN_SEL fields */ + value = readl(pdata->spkr_iomux) & + ~(SPKR_CTL_TLMM_WS_OUT_SEL_MASK | SPKR_CTL_TLMM_WS_EN_SEL_MASK); + /* Configure the Sec MI2S to TLMM */ + writel(value | SPKR_CTL_TLMM_MCLK_EN | SPKR_CTL_TLMM_SCLK_EN | + SPKR_CTL_TLMM_DATA1_EN | SPKR_CTL_TLMM_WS_OUT_SEL_SEC | + SPKR_CTL_TLMM_WS_EN_SEL_SEC, pdata->spkr_iomux); + break; case MI2S_TERTIARY: writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL | MIC_CTRL_TLMM_SCLK_EN, diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index 1855b805eba2..3d831b635524 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -465,7 +465,7 @@ int q6adm_matrix_map(struct device *dev, int path, struct apr_pkt *pkt; uint16_t *copps_list; int pkt_size, ret, i, copp_idx; - void *matrix_map = NULL; + void *matrix_map; struct q6copp *copp; /* Assumes port_ids have already been validated during adm_open */ diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 36bf8bd4edd7..9251d8548965 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -1624,7 +1624,7 @@ EXPORT_SYMBOL_GPL(q6asm_write_async); static void q6asm_reset_buf_state(struct audio_client *ac) { - struct audio_port_data *port = NULL; + struct audio_port_data *port; unsigned long flags; spin_lock_irqsave(&ac->lock, flags); diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig index d610b553ea3b..053097b73e28 100644 --- a/sound/soc/rockchip/Kconfig +++ b/sound/soc/rockchip/Kconfig @@ -9,7 +9,7 @@ config SND_SOC_ROCKCHIP config SND_SOC_ROCKCHIP_I2S tristate "Rockchip I2S Device Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for I2S driver for @@ -18,7 +18,7 @@ config SND_SOC_ROCKCHIP_I2S config SND_SOC_ROCKCHIP_PDM tristate "Rockchip PDM Controller Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM select RATIONAL help @@ -28,7 +28,7 @@ config SND_SOC_ROCKCHIP_PDM config SND_SOC_ROCKCHIP_SPDIF tristate "Rockchip SPDIF Device Driver" - depends on CLKDEV_LOOKUP && SND_SOC_ROCKCHIP + depends on HAVE_CLK && SND_SOC_ROCKCHIP select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for SPDIF driver for @@ -36,7 +36,7 @@ config SND_SOC_ROCKCHIP_SPDIF config SND_SOC_ROCKCHIP_MAX98090 tristate "ASoC support for Rockchip boards using a MAX98090 codec" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_MAX98090 select SND_SOC_TS3A227E @@ -47,7 +47,7 @@ config SND_SOC_ROCKCHIP_MAX98090 config SND_SOC_ROCKCHIP_RT5645 tristate "ASoC support for Rockchip boards using a RT5645/RT5650 codec" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_RT5645 help @@ -56,7 +56,7 @@ config SND_SOC_ROCKCHIP_RT5645 config SND_SOC_RK3288_HDMI_ANALOG tristate "ASoC support multiple codecs for Rockchip RK3288 boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK select SND_SOC_ROCKCHIP_I2S select SND_SOC_HDMI_CODEC select SND_SOC_ES8328_I2C @@ -68,7 +68,7 @@ config SND_SOC_RK3288_HDMI_ANALOG config SND_SOC_RK3399_GRU_SOUND tristate "ASoC support multiple codecs for Rockchip RK3399 GRU boards" - depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && CLKDEV_LOOKUP && SPI + depends on SND_SOC_ROCKCHIP && I2C && GPIOLIB && HAVE_CLK && SPI select SND_SOC_ROCKCHIP_I2S select SND_SOC_MAX98357A select SND_SOC_RT5514 diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c index 0ac5956ba270..313ab650f8d9 100644 --- a/sound/soc/samsung/aries_wm8994.c +++ b/sound/soc/samsung/aries_wm8994.c @@ -310,7 +310,7 @@ static int aries_hw_free(struct snd_pcm_substream *substream) /* * Main DAI operations */ -static struct snd_soc_ops aries_ops = { +static const struct snd_soc_ops aries_ops = { .hw_params = aries_hw_params, .hw_free = aries_hw_free, }; diff --git a/sound/soc/samsung/arndale.c b/sound/soc/samsung/arndale.c index 28587375813a..606ac5e33a8e 100644 --- a/sound/soc/samsung/arndale.c +++ b/sound/soc/samsung/arndale.c @@ -48,7 +48,7 @@ static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops arndale_rt5631_ops = { +static const struct snd_soc_ops arndale_rt5631_ops = { .hw_params = arndale_rt5631_hw_params, }; @@ -80,7 +80,7 @@ static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream, rclk + 1, SND_SOC_CLOCK_IN); } -static struct snd_soc_ops arndale_wm1811_ops = { +static const struct snd_soc_ops arndale_wm1811_ops = { .hw_params = arndale_wm1811_hw_params, }; diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index 8aa78ff640f5..c994e67d1eaf 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -112,7 +112,7 @@ static int h1940_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops h1940_ops = { +static const struct snd_soc_ops h1940_ops = { .startup = h1940_startup, .hw_params = h1940_hw_params, }; diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c index a1ff1400857e..390f2dd735ad 100644 --- a/sound/soc/samsung/littlemill.c +++ b/sound/soc/samsung/littlemill.c @@ -130,7 +130,7 @@ static int littlemill_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops littlemill_ops = { +static const struct snd_soc_ops littlemill_ops = { .hw_params = littlemill_hw_params, }; diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index 1f9a553edf19..a2019535a0b1 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -129,7 +129,7 @@ static int midas_aif1_hw_params(struct snd_pcm_substream *substream, return midas_start_fll1(rtd, pll_out); } -static struct snd_soc_ops midas_aif1_ops = { +static const struct snd_soc_ops midas_aif1_ops = { .hw_params = midas_aif1_hw_params, }; diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 9266070e0181..c98b68567a89 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -106,7 +106,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) /* * Neo1973 WM8753 HiFi DAI opserations. */ -static struct snd_soc_ops neo1973_hifi_ops = { +static const struct snd_soc_ops neo1973_hifi_ops = { .hw_params = neo1973_hifi_hw_params, .hw_free = neo1973_hifi_hw_free, }; @@ -158,7 +158,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); } -static struct snd_soc_ops neo1973_voice_ops = { +static const struct snd_soc_ops neo1973_voice_ops = { .hw_params = neo1973_voice_hw_params, .hw_free = neo1973_voice_hw_free, }; diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 400a7f77c711..6ea1c8cc9167 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -62,7 +62,7 @@ static struct snd_soc_jack_gpio hp_jack_gpios[] = { }, }; -static struct snd_soc_ops rx1950_ops = { +static const struct snd_soc_ops rx1950_ops = { .startup = rx1950_startup, .hw_params = rx1950_hw_params, }; diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index c95629becbc3..cee39ad16667 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c @@ -70,7 +70,7 @@ static int smartq_hifi_hw_params(struct snd_pcm_substream *substream, /* * SmartQ WM8987 HiFi DAI operations. */ -static struct snd_soc_ops smartq_hifi_ops = { +static const struct snd_soc_ops smartq_hifi_ops = { .hw_params = smartq_hifi_hw_params, }; diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index ed753a2f202e..78703d095a6f 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c @@ -86,7 +86,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, /* * SMDK WM8580 DAI operations. */ -static struct snd_soc_ops smdk_ops = { +static const struct snd_soc_ops smdk_ops = { .hw_params = smdk_hw_params, }; diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 39a7a449f554..7661b637946d 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -73,7 +73,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, /* * SMDK WM8994 DAI operations. */ -static struct snd_soc_ops smdk_ops = { +static const struct snd_soc_ops smdk_ops = { .hw_params = smdk_hw_params, }; diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c index a01640576f71..029448f5bedb 100644 --- a/sound/soc/samsung/smdk_wm8994pcm.c +++ b/sound/soc/samsung/smdk_wm8994pcm.c @@ -85,7 +85,7 @@ static int smdk_wm8994_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops smdk_wm8994_pcm_ops = { +static const struct snd_soc_ops smdk_wm8994_pcm_ops = { .hw_params = smdk_wm8994_pcm_hw_params, }; diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 84c2c63d5a87..a2c77e6defec 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -126,7 +126,7 @@ static int tm2_aif1_hw_params(struct snd_pcm_substream *substream, return tm2_start_sysclk(rtd->card); } -static struct snd_soc_ops tm2_aif1_ops = { +static const struct snd_soc_ops tm2_aif1_ops = { .hw_params = tm2_aif1_hw_params, }; @@ -200,7 +200,7 @@ static int tm2_aif2_hw_free(struct snd_pcm_substream *substream) return ret; } -static struct snd_soc_ops tm2_aif2_ops = { +static const struct snd_soc_ops tm2_aif2_ops = { .hw_params = tm2_aif2_hw_params, .hw_free = tm2_aif2_hw_free, }; @@ -254,7 +254,7 @@ static int tm2_hdmi_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops tm2_hdmi_ops = { +static const struct snd_soc_ops tm2_hdmi_ops = { .hw_params = tm2_hdmi_hw_params, }; diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c index c962d2c2a7f7..15223d860cb7 100644 --- a/sound/soc/samsung/tobermory.c +++ b/sound/soc/samsung/tobermory.c @@ -105,7 +105,7 @@ static int tobermory_hw_params(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_ops tobermory_ops = { +static const struct snd_soc_ops tobermory_ops = { .hw_params = tobermory_hw_params, }; diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 346c806ba390..ae46f187cc2a 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -45,6 +45,12 @@ config SND_SOC_RCAR help This option enables R-Car SRU/SCU/SSIU/SSI sound support +config SND_SOC_RZ + tristate "RZ/G2L series SSIF-2 support" + depends on ARCH_R9A07G044 || COMPILE_TEST + help + This option enables RZ/G2L SSIF-2 sound support. + ## ## Boards ## diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index 51bd7c81671c..f6fd79948f6a 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -22,3 +22,7 @@ snd-soc-migor-objs := migor.o obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o + +# RZ/G2L +snd-soc-rz-ssi-objs := rz-ssi.o +obj-$(CONFIG_SND_SOC_RZ) += snd-soc-rz-ssi.o diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 0ebee1ed06a9..5f1e72edfee0 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -391,9 +391,9 @@ static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv, struct clk *clk; clk = clk_register_fixed_rate(dev, name, parent, 0, 0); - if (IS_ERR(clk)) { + if (IS_ERR_OR_NULL(clk)) { dev_err(dev, "create null clk error\n"); - return NULL; + return ERR_CAST(clk); } return clk; @@ -430,9 +430,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv) for (i = 0; i < CLKMAX; i++) { clk = devm_clk_get(dev, clk_name[i]); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) clk = rsnd_adg_null_clk_get(priv); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) goto err; adg->clk[i] = clk; @@ -582,7 +582,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) if (!count) { clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT], parent_clk_name, 0, req_rate[0]); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) goto err; adg->clkout[CLKOUT] = clk; @@ -596,7 +596,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) clk = clk_register_fixed_rate(dev, clkout_name[i], parent_clk_name, 0, req_rate[0]); - if (IS_ERR(clk)) + if (IS_ERR_OR_NULL(clk)) goto err; adg->clkout[i] = clk; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 5e382b5c9d45..978bd0406729 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -426,19 +426,19 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - enum rsnd_mod_type playback_mods[] = { + static const enum rsnd_mod_type playback_mods[] = { RSND_MOD_SRC, RSND_MOD_CMD, RSND_MOD_SSIU, }; - enum rsnd_mod_type capture_mods[] = { + static const enum rsnd_mod_type capture_mods[] = { RSND_MOD_CMD, RSND_MOD_SRC, RSND_MOD_SSIU, }; struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_mod *tmod = NULL; - enum rsnd_mod_type *mods = + const enum rsnd_mod_type *mods = rsnd_io_is_play(io) ? playback_mods : capture_mods; int i; diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 82d16e037d9a..16c6e0265749 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -102,7 +102,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); if (dmaen->chan) - dmaengine_terminate_all(dmaen->chan); + dmaengine_terminate_sync(dmaen->chan); return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 27f34ca6059d..87e606f688d3 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -165,7 +165,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) { - enum rsnd_mod_type types[] = { + static const enum rsnd_mod_type types[] = { RSND_MOD_SSIM1, RSND_MOD_SSIM2, RSND_MOD_SSIM3, @@ -228,7 +228,7 @@ unsigned int rsnd_ssi_clk_query(struct rsnd_dai *rdai, int param1, int param2, int *idx) { struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); - int ssi_clk_mul_table[] = { + static const int ssi_clk_mul_table[] = { 1, 2, 4, 8, 16, 6, 12, }; int j, ret; @@ -1079,7 +1079,7 @@ static void rsnd_ssi_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_dai *rdai = rsnd_io_to_rdai(io); - enum rsnd_mod_type types[] = { + static const enum rsnd_mod_type types[] = { RSND_MOD_SSI, RSND_MOD_SSIM1, RSND_MOD_SSIM2, diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c new file mode 100644 index 000000000000..fa0cc08f70ec --- /dev/null +++ b/sound/soc/sh/rz-ssi.c @@ -0,0 +1,1074 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver +// +// Copyright (C) 2021 Renesas Electronics Corp. +// Copyright (C) 2019 Chris Brandt. +// + +#include <linux/clk.h> +#include <linux/dmaengine.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <sound/soc.h> + +/* REGISTER OFFSET */ +#define SSICR 0x000 +#define SSISR 0x004 +#define SSIFCR 0x010 +#define SSIFSR 0x014 +#define SSIFTDR 0x018 +#define SSIFRDR 0x01c +#define SSIOFR 0x020 +#define SSISCR 0x024 + +/* SSI REGISTER BITS */ +#define SSICR_DWL(x) (((x) & 0x7) << 19) +#define SSICR_SWL(x) (((x) & 0x7) << 16) +#define SSICR_MST BIT(14) +#define SSICR_CKDV(x) (((x) & 0xf) << 4) + +#define SSICR_CKS BIT(30) +#define SSICR_TUIEN BIT(29) +#define SSICR_TOIEN BIT(28) +#define SSICR_RUIEN BIT(27) +#define SSICR_ROIEN BIT(26) +#define SSICR_MST BIT(14) +#define SSICR_BCKP BIT(13) +#define SSICR_LRCKP BIT(12) +#define SSICR_CKDV(x) (((x) & 0xf) << 4) +#define SSICR_TEN BIT(1) +#define SSICR_REN BIT(0) + +#define SSISR_TUIRQ BIT(29) +#define SSISR_TOIRQ BIT(28) +#define SSISR_RUIRQ BIT(27) +#define SSISR_ROIRQ BIT(26) +#define SSISR_IIRQ BIT(25) + +#define SSIFCR_AUCKE BIT(31) +#define SSIFCR_SSIRST BIT(16) +#define SSIFCR_TIE BIT(3) +#define SSIFCR_RIE BIT(2) +#define SSIFCR_TFRST BIT(1) +#define SSIFCR_RFRST BIT(0) + +#define SSIFSR_TDC_MASK 0x3f +#define SSIFSR_TDC_SHIFT 24 +#define SSIFSR_RDC_MASK 0x3f +#define SSIFSR_RDC_SHIFT 8 + +#define SSIFSR_TDC(x) (((x) & 0x1f) << 24) +#define SSIFSR_TDE BIT(16) +#define SSIFSR_RDC(x) (((x) & 0x1f) << 8) +#define SSIFSR_RDF BIT(0) + +#define SSIOFR_LRCONT BIT(8) + +#define SSISCR_TDES(x) (((x) & 0x1f) << 8) +#define SSISCR_RDFS(x) (((x) & 0x1f) << 0) + +/* Pre allocated buffers sizes */ +#define PREALLOC_BUFFER (SZ_32K) +#define PREALLOC_BUFFER_MAX (SZ_32K) + +#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */ +#define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE +#define SSI_CHAN_MIN 2 +#define SSI_CHAN_MAX 2 +#define SSI_FIFO_DEPTH 32 + +struct rz_ssi_priv; + +struct rz_ssi_stream { + struct rz_ssi_priv *priv; + struct snd_pcm_substream *substream; + int fifo_sample_size; /* sample capacity of SSI FIFO */ + int dma_buffer_pos; /* The address for the next DMA descriptor */ + int period_counter; /* for keeping track of periods transferred */ + int sample_width; + int buffer_pos; /* current frame position in the buffer */ + int running; /* 0=stopped, 1=running */ + + int uerr_num; + int oerr_num; + + struct dma_chan *dma_ch; + + int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm); +}; + +struct rz_ssi_priv { + void __iomem *base; + struct platform_device *pdev; + struct reset_control *rstc; + struct device *dev; + struct clk *sfr_clk; + struct clk *clk; + + phys_addr_t phys; + int irq_int; + int irq_tx; + int irq_rx; + + spinlock_t lock; + + /* + * The SSI supports full-duplex transmission and reception. + * However, if an error occurs, channel reset (both transmission + * and reception reset) is required. + * So it is better to use as half-duplex (playing and recording + * should be done on separate channels). + */ + struct rz_ssi_stream playback; + struct rz_ssi_stream capture; + + /* clock */ + unsigned long audio_mck; + unsigned long audio_clk_1; + unsigned long audio_clk_2; + + bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */ + bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */ + bool dma_rt; +}; + +static void rz_ssi_dma_complete(void *data); + +static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data) +{ + writel(data, (priv->base + reg)); +} + +static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg) +{ + return readl(priv->base + reg); +} + +static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg, + u32 bclr, u32 bset) +{ + u32 val; + + val = readl(priv->base + reg); + val = (val & ~bclr) | bset; + writel(val, (priv->base + reg)); +} + +static inline struct snd_soc_dai * +rz_ssi_get_dai(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + + return asoc_rtd_to_cpu(rtd, 0); +} + +static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi, + struct snd_pcm_substream *substream) +{ + return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; +} + +static inline struct rz_ssi_stream * +rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) +{ + struct rz_ssi_stream *stream = &ssi->playback; + + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) + stream = &ssi->capture; + + return stream; +} + +static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi) +{ + return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch)); +} + +static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&ssi->lock, flags); + ret = !!(strm->substream && strm->substream->runtime); + spin_unlock_irqrestore(&ssi->lock, flags); + + return ret; +} + +static int rz_ssi_stream_init(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + strm->substream = substream; + strm->sample_width = samples_to_bytes(runtime, 1); + strm->dma_buffer_pos = 0; + strm->period_counter = 0; + strm->buffer_pos = 0; + + strm->oerr_num = 0; + strm->uerr_num = 0; + strm->running = 0; + + /* fifo init */ + strm->fifo_sample_size = SSI_FIFO_DEPTH; + + return 0; +} + +static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream); + unsigned long flags; + + spin_lock_irqsave(&ssi->lock, flags); + strm->substream = NULL; + spin_unlock_irqrestore(&ssi->lock, flags); + + if (strm->oerr_num > 0) + dev_info(dai->dev, "overrun = %d\n", strm->oerr_num); + + if (strm->uerr_num > 0) + dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); +} + +static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, + unsigned int channels) +{ + static s8 ckdv[16] = { 1, 2, 4, 8, 16, 32, 64, 128, + 6, 12, 24, 48, 96, -1, -1, -1 }; + unsigned int channel_bits = 32; /* System Word Length */ + unsigned long bclk_rate = rate * channels * channel_bits; + unsigned int div; + unsigned int i; + u32 ssicr = 0; + u32 clk_ckdv; + + /* Clear AUCKE so we can set MST */ + rz_ssi_reg_writel(ssi, SSIFCR, 0); + + /* Continue to output LRCK pin even when idle */ + rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT); + if (ssi->audio_clk_1 && ssi->audio_clk_2) { + if (ssi->audio_clk_1 % bclk_rate) + ssi->audio_mck = ssi->audio_clk_2; + else + ssi->audio_mck = ssi->audio_clk_1; + } + + /* Clock setting */ + ssicr |= SSICR_MST; + if (ssi->audio_mck == ssi->audio_clk_1) + ssicr |= SSICR_CKS; + if (ssi->bckp_rise) + ssicr |= SSICR_BCKP; + if (ssi->lrckp_fsync_fall) + ssicr |= SSICR_LRCKP; + + /* Determine the clock divider */ + clk_ckdv = 0; + div = ssi->audio_mck / bclk_rate; + /* try to find an match */ + for (i = 0; i < ARRAY_SIZE(ckdv); i++) { + if (ckdv[i] == div) { + clk_ckdv = i; + break; + } + } + + if (i == ARRAY_SIZE(ckdv)) { + dev_err(ssi->dev, "Rate not divisible by audio clock source\n"); + return -EINVAL; + } + + /* + * DWL: Data Word Length = 16 bits + * SWL: System Word Length = 32 bits + */ + ssicr |= SSICR_CKDV(clk_ckdv); + ssicr |= SSICR_DWL(1) | SSICR_SWL(3); + rz_ssi_reg_writel(ssi, SSICR, ssicr); + rz_ssi_reg_writel(ssi, SSIFCR, + (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST)); + + return 0; +} + +static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); + u32 ssicr, ssifcr; + + ssicr = rz_ssi_reg_readl(ssi, SSICR); + ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF; + + /* FIFO interrupt thresholds */ + if (rz_ssi_is_dma_enabled(ssi)) + rz_ssi_reg_writel(ssi, SSISCR, 0); + else + rz_ssi_reg_writel(ssi, SSISCR, + SSISCR_TDES(strm->fifo_sample_size / 2 - 1) | + SSISCR_RDFS(0)); + + /* enable IRQ */ + if (is_play) { + ssicr |= SSICR_TUIEN | SSICR_TOIEN; + ssifcr |= SSIFCR_TIE | SSIFCR_RFRST; + } else { + ssicr |= SSICR_RUIEN | SSICR_ROIEN; + ssifcr |= SSIFCR_RIE | SSIFCR_TFRST; + } + + rz_ssi_reg_writel(ssi, SSICR, ssicr); + rz_ssi_reg_writel(ssi, SSIFCR, ssifcr); + + /* Clear all error flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ), 0); + + strm->running = 1; + ssicr |= is_play ? SSICR_TEN : SSICR_REN; + rz_ssi_reg_writel(ssi, SSICR, ssicr); + + return 0; +} + +static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + int timeout; + + strm->running = 0; + + /* Disable TX/RX */ + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); + + /* Cancel all remaining DMA transactions */ + if (rz_ssi_is_dma_enabled(ssi)) + dmaengine_terminate_async(strm->dma_ch); + + /* Disable irqs */ + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | + SSICR_RUIEN | SSICR_ROIEN, 0); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0); + + /* Clear all error flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ), 0); + + /* Wait for idle */ + timeout = 100; + while (--timeout) { + if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ) + break; + udelay(1); + } + + if (!timeout) + dev_info(ssi->dev, "timeout waiting for SSI idle\n"); + + /* Hold FIFOs in reset */ + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, + SSIFCR_TFRST | SSIFCR_RFRST); + + return 0; +} + +static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames) +{ + struct snd_pcm_substream *substream = strm->substream; + struct snd_pcm_runtime *runtime; + int current_period; + + if (!strm->running || !substream || !substream->runtime) + return; + + runtime = substream->runtime; + strm->buffer_pos += frames; + WARN_ON(strm->buffer_pos > runtime->buffer_size); + + /* ring buffer */ + if (strm->buffer_pos == runtime->buffer_size) + strm->buffer_pos = 0; + + current_period = strm->buffer_pos / runtime->period_size; + if (strm->period_counter != current_period) { + snd_pcm_period_elapsed(strm->substream); + strm->period_counter = current_period; + } +} + +static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + struct snd_pcm_substream *substream = strm->substream; + struct snd_pcm_runtime *runtime; + u16 *buf; + int fifo_samples; + int frames_left; + int samples = 0; + int i; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + runtime = substream->runtime; + /* frames left in this period */ + frames_left = runtime->period_size - (strm->buffer_pos % + runtime->period_size); + if (frames_left == 0) + frames_left = runtime->period_size; + + /* Samples in RX FIFO */ + fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >> + SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK; + + /* Only read full frames at a time */ + while (frames_left && (fifo_samples >= runtime->channels)) { + samples += runtime->channels; + fifo_samples -= runtime->channels; + frames_left--; + } + + /* not enough samples yet */ + if (samples == 0) + return 0; + + /* calculate new buffer index */ + buf = (u16 *)(runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + /* Note, only supports 16-bit samples */ + for (i = 0; i < samples; i++) + *buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16); + + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + rz_ssi_pointer_update(strm, samples / runtime->channels); + + /* + * If we finished this period, but there are more samples in + * the RX FIFO, call this function again + */ + if (frames_left == 0 && fifo_samples >= runtime->channels) + rz_ssi_pio_recv(ssi, strm); + + return 0; +} + +static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) +{ + struct snd_pcm_substream *substream = strm->substream; + struct snd_pcm_runtime *runtime = substream->runtime; + int sample_space; + int samples = 0; + int frames_left; + int i; + u32 ssifsr; + u16 *buf; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + /* frames left in this period */ + frames_left = runtime->period_size - (strm->buffer_pos % + runtime->period_size); + if (frames_left == 0) + frames_left = runtime->period_size; + + sample_space = strm->fifo_sample_size; + ssifsr = rz_ssi_reg_readl(ssi, SSIFSR); + sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK; + + /* Only add full frames at a time */ + while (frames_left && (sample_space >= runtime->channels)) { + samples += runtime->channels; + sample_space -= runtime->channels; + frames_left--; + } + + /* no space to send anything right now */ + if (samples == 0) + return 0; + + /* calculate new buffer index */ + buf = (u16 *)(runtime->dma_area); + buf += strm->buffer_pos * runtime->channels; + + /* Note, only supports 16-bit samples */ + for (i = 0; i < samples; i++) + rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16)); + + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0); + rz_ssi_pointer_update(strm, samples / runtime->channels); + + return 0; +} + +static irqreturn_t rz_ssi_interrupt(int irq, void *data) +{ + struct rz_ssi_stream *strm = NULL; + struct rz_ssi_priv *ssi = data; + u32 ssisr = rz_ssi_reg_readl(ssi, SSISR); + + if (ssi->playback.substream) + strm = &ssi->playback; + else if (ssi->capture.substream) + strm = &ssi->capture; + else + return IRQ_HANDLED; /* Left over TX/RX interrupt */ + + if (irq == ssi->irq_int) { /* error or idle */ + if (ssisr & SSISR_TUIRQ) + strm->uerr_num++; + if (ssisr & SSISR_TOIRQ) + strm->oerr_num++; + if (ssisr & SSISR_RUIRQ) + strm->uerr_num++; + if (ssisr & SSISR_ROIRQ) + strm->oerr_num++; + + if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ | + SSISR_ROIRQ)) { + /* Error handling */ + /* You must reset (stop/restart) after each interrupt */ + rz_ssi_stop(ssi, strm); + + /* Clear all flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | + SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ, 0); + + /* Add/remove more data */ + strm->transfer(ssi, strm); + + /* Resume */ + rz_ssi_start(ssi, strm); + } + } + + if (!strm->running) + return IRQ_HANDLED; + + /* tx data empty */ + if (irq == ssi->irq_tx) + strm->transfer(ssi, &ssi->playback); + + /* rx data full */ + if (irq == ssi->irq_rx) { + strm->transfer(ssi, &ssi->capture); + rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); + } + + return IRQ_HANDLED; +} + +static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi, + struct dma_chan *dma_ch, bool is_play) +{ + struct dma_slave_config cfg; + + memset(&cfg, 0, sizeof(cfg)); + + cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + cfg.dst_addr = ssi->phys + SSIFTDR; + cfg.src_addr = ssi->phys + SSIFRDR; + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + + return dmaengine_slave_config(dma_ch, &cfg); +} + +static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, + struct rz_ssi_stream *strm) +{ + struct snd_pcm_substream *substream = strm->substream; + struct dma_async_tx_descriptor *desc; + struct snd_pcm_runtime *runtime; + enum dma_transfer_direction dir; + u32 dma_paddr, dma_size; + int amount; + + if (!rz_ssi_stream_is_valid(ssi, strm)) + return -EINVAL; + + runtime = substream->runtime; + if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + /* + * Stream is ending, so do not queue up any more DMA + * transfers otherwise we play partial sound clips + * because we can't shut off the DMA quick enough. + */ + return 0; + + dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + + /* Always transfer 1 period */ + amount = runtime->period_size; + + /* DMA physical address and size */ + dma_paddr = runtime->dma_addr + frames_to_bytes(runtime, + strm->dma_buffer_pos); + dma_size = frames_to_bytes(runtime, amount); + desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size, + dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n"); + return -ENOMEM; + } + + desc->callback = rz_ssi_dma_complete; + desc->callback_param = strm; + + if (dmaengine_submit(desc) < 0) { + dev_err(ssi->dev, "dmaengine_submit() fail\n"); + return -EIO; + } + + /* Update DMA pointer */ + strm->dma_buffer_pos += amount; + if (strm->dma_buffer_pos >= runtime->buffer_size) + strm->dma_buffer_pos = 0; + + /* Start DMA */ + dma_async_issue_pending(strm->dma_ch); + + return 0; +} + +static void rz_ssi_dma_complete(void *data) +{ + struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data; + + if (!strm->running || !strm->substream || !strm->substream->runtime) + return; + + /* Note that next DMA transaction has probably already started */ + rz_ssi_pointer_update(strm, strm->substream->runtime->period_size); + + /* Queue up another DMA transaction */ + rz_ssi_dma_transfer(strm->priv, strm); +} + +static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi) +{ + if (ssi->playback.dma_ch) { + dma_release_channel(ssi->playback.dma_ch); + ssi->playback.dma_ch = NULL; + if (ssi->dma_rt) + ssi->dma_rt = false; + } + + if (ssi->capture.dma_ch) { + dma_release_channel(ssi->capture.dma_ch); + ssi->capture.dma_ch = NULL; + } +} + +static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) +{ + ssi->playback.dma_ch = dma_request_chan(dev, "tx"); + if (IS_ERR(ssi->playback.dma_ch)) + ssi->playback.dma_ch = NULL; + + ssi->capture.dma_ch = dma_request_chan(dev, "rx"); + if (IS_ERR(ssi->capture.dma_ch)) + ssi->capture.dma_ch = NULL; + + if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) { + ssi->playback.dma_ch = dma_request_chan(dev, "rt"); + if (IS_ERR(ssi->playback.dma_ch)) { + ssi->playback.dma_ch = NULL; + goto no_dma; + } + + ssi->dma_rt = true; + } + + if (!rz_ssi_is_dma_enabled(ssi)) + goto no_dma; + + if (ssi->playback.dma_ch && + (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0)) + goto no_dma; + + if (ssi->capture.dma_ch && + (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0)) + goto no_dma; + + return 0; + +no_dma: + rz_ssi_release_dma_channels(ssi); + + return -ENODEV; +} + +static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); + int ret = 0, i, num_transfer = 1; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* Soft Reset */ + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); + udelay(5); + + ret = rz_ssi_stream_init(ssi, strm, substream); + if (ret) + goto done; + + if (ssi->dma_rt) { + bool is_playback; + + is_playback = rz_ssi_stream_is_play(ssi, substream); + ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, + is_playback); + /* Fallback to pio */ + if (ret < 0) { + ssi->playback.transfer = rz_ssi_pio_send; + ssi->capture.transfer = rz_ssi_pio_recv; + rz_ssi_release_dma_channels(ssi); + } + } + + /* For DMA, queue up multiple DMA descriptors */ + if (rz_ssi_is_dma_enabled(ssi)) + num_transfer = 4; + + for (i = 0; i < num_transfer; i++) { + ret = strm->transfer(ssi, strm); + if (ret) + goto done; + } + + ret = rz_ssi_start(ssi, strm); + break; + case SNDRV_PCM_TRIGGER_STOP: + rz_ssi_stop(ssi, strm); + rz_ssi_stream_quit(ssi, strm); + break; + } + +done: + return ret; +} + +static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + break; + default: + dev_err(ssi->dev, "Codec should be clk and frame consumer\n"); + return -EINVAL; + } + + /* + * set clock polarity + * + * "normal" BCLK = Signal is available at rising edge of BCLK + * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge + */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + ssi->bckp_rise = false; + ssi->lrckp_fsync_fall = false; + break; + case SND_SOC_DAIFMT_NB_IF: + ssi->bckp_rise = false; + ssi->lrckp_fsync_fall = true; + break; + case SND_SOC_DAIFMT_IB_NF: + ssi->bckp_rise = true; + ssi->lrckp_fsync_fall = false; + break; + case SND_SOC_DAIFMT_IB_IF: + ssi->bckp_rise = true; + ssi->lrckp_fsync_fall = true; + break; + default: + return -EINVAL; + } + + /* only i2s support */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + default: + dev_err(ssi->dev, "Only I2S mode is supported.\n"); + return -EINVAL; + } + + return 0; +} + +static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + unsigned int sample_bits = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; + unsigned int channels = params_channels(params); + + if (sample_bits != 16) { + dev_err(ssi->dev, "Unsupported sample width: %d\n", + sample_bits); + return -EINVAL; + } + + if (channels != 2) { + dev_err(ssi->dev, "Number of channels not matched: %d\n", + channels); + return -EINVAL; + } + + return rz_ssi_clk_setup(ssi, params_rate(params), + params_channels(params)); +} + +static const struct snd_soc_dai_ops rz_ssi_dai_ops = { + .trigger = rz_ssi_dai_trigger, + .set_fmt = rz_ssi_dai_set_fmt, + .hw_params = rz_ssi_dai_hw_params, +}; + +static const struct snd_pcm_hardware rz_ssi_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = PREALLOC_BUFFER, + .period_bytes_min = 32, + .period_bytes_max = 8192, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + .periods_min = 1, + .periods_max = 32, + .fifo_size = 32 * 2, +}; + +static int rz_ssi_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware); + + return snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); +} + +static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_dai *dai = rz_ssi_get_dai(substream); + struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); + + return strm->buffer_pos; +} + +static int rz_ssi_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, + PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); + return 0; +} + +static struct snd_soc_dai_driver rz_ssi_soc_dai[] = { + { + .name = "rz-ssi-dai", + .playback = { + .rates = SSI_RATES, + .formats = SSI_FMTS, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + }, + .capture = { + .rates = SSI_RATES, + .formats = SSI_FMTS, + .channels_min = SSI_CHAN_MIN, + .channels_max = SSI_CHAN_MAX, + }, + .ops = &rz_ssi_dai_ops, + }, +}; + +static const struct snd_soc_component_driver rz_ssi_soc_component = { + .name = "rz-ssi", + .open = rz_ssi_pcm_open, + .pointer = rz_ssi_pcm_pointer, + .pcm_construct = rz_ssi_pcm_new, +}; + +static int rz_ssi_probe(struct platform_device *pdev) +{ + struct rz_ssi_priv *ssi; + struct clk *audio_clk; + struct resource *res; + int ret; + + ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); + if (!ssi) + return -ENOMEM; + + ssi->pdev = pdev; + ssi->dev = &pdev->dev; + ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(ssi->base)) + return PTR_ERR(ssi->base); + + ssi->phys = res->start; + ssi->clk = devm_clk_get(&pdev->dev, "ssi"); + if (IS_ERR(ssi->clk)) + return PTR_ERR(ssi->clk); + + ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr"); + if (IS_ERR(ssi->sfr_clk)) + return PTR_ERR(ssi->sfr_clk); + + audio_clk = devm_clk_get(&pdev->dev, "audio_clk1"); + if (IS_ERR(audio_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), + "no audio clk1"); + + ssi->audio_clk_1 = clk_get_rate(audio_clk); + audio_clk = devm_clk_get(&pdev->dev, "audio_clk2"); + if (IS_ERR(audio_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), + "no audio clk2"); + + ssi->audio_clk_2 = clk_get_rate(audio_clk); + if (!(ssi->audio_clk_1 || ssi->audio_clk_2)) + return dev_err_probe(&pdev->dev, -EINVAL, + "no audio clk1 or audio clk2"); + + ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2; + + /* Detect DMA support */ + ret = rz_ssi_dma_request(ssi, &pdev->dev); + if (ret < 0) { + dev_warn(&pdev->dev, "DMA not available, using PIO\n"); + ssi->playback.transfer = rz_ssi_pio_send; + ssi->capture.transfer = rz_ssi_pio_recv; + } else { + dev_info(&pdev->dev, "DMA enabled"); + ssi->playback.transfer = rz_ssi_dma_transfer; + ssi->capture.transfer = rz_ssi_dma_transfer; + } + + ssi->playback.priv = ssi; + ssi->capture.priv = ssi; + + /* Error Interrupt */ + ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); + if (ssi->irq_int < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI int_req IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt, + 0, dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (int_req)\n"); + + if (!rz_ssi_is_dma_enabled(ssi)) { + /* Tx and Rx interrupts (pio only) */ + ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx"); + if (ssi->irq_tx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_tx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_tx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_tx)\n"); + + ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx"); + if (ssi->irq_rx < 0) + return dev_err_probe(&pdev->dev, -ENODEV, + "Unable to get SSI dma_rx IRQ\n"); + + ret = devm_request_irq(&pdev->dev, ssi->irq_rx, + &rz_ssi_interrupt, 0, + dev_name(&pdev->dev), ssi); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "irq request error (dma_rx)\n"); + } + + ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(ssi->rstc)) + return PTR_ERR(ssi->rstc); + + reset_control_deassert(ssi->rstc); + pm_runtime_enable(&pdev->dev); + pm_runtime_resume_and_get(&pdev->dev); + + spin_lock_init(&ssi->lock); + dev_set_drvdata(&pdev->dev, ssi); + ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, + rz_ssi_soc_dai, + ARRAY_SIZE(rz_ssi_soc_dai)); + if (ret < 0) { + rz_ssi_release_dma_channels(ssi); + + pm_runtime_put(ssi->dev); + pm_runtime_disable(ssi->dev); + reset_control_assert(ssi->rstc); + dev_err(&pdev->dev, "failed to register snd component\n"); + } + + return ret; +} + +static int rz_ssi_remove(struct platform_device *pdev) +{ + struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev); + + rz_ssi_release_dma_channels(ssi); + + pm_runtime_put(ssi->dev); + pm_runtime_disable(ssi->dev); + reset_control_assert(ssi->rstc); + + return 0; +} + +static const struct of_device_id rz_ssi_of_match[] = { + { .compatible = "renesas,rz-ssi", }, + {/* Sentinel */}, +}; +MODULE_DEVICE_TABLE(of, rz_ssi_of_match); + +static struct platform_driver rz_ssi_driver = { + .driver = { + .name = "rz-ssi-pcm-audio", + .of_match_table = rz_ssi_of_match, + }, + .probe = rz_ssi_probe, + .remove = rz_ssi_remove, +}; + +module_platform_driver(rz_ssi_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface Driver"); +MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c index 65db083e242b..5f49e3dec3fc 100644 --- a/sound/soc/soc-ac97.c +++ b/sound/soc/soc-ac97.c @@ -34,14 +34,6 @@ struct snd_ac97_reset_cfg { int gpio_reset; }; -struct snd_ac97_gpio_priv { -#ifdef CONFIG_GPIOLIB - struct gpio_chip gpio_chip; -#endif - unsigned int gpios_set; - struct snd_soc_component *component; -}; - static struct snd_ac97_bus soc_ac97_bus = { .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ }; @@ -52,6 +44,12 @@ static void soc_ac97_device_release(struct device *dev) } #ifdef CONFIG_GPIOLIB +struct snd_ac97_gpio_priv { + struct gpio_chip gpio_chip; + unsigned int gpios_set; + struct snd_soc_component *component; +}; + static inline struct snd_soc_component *gpio_to_component(struct gpio_chip *chip) { struct snd_ac97_gpio_priv *gpio_priv = gpiochip_get_data(chip); diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index c8dfd0de30e4..8e8d917d22f8 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -1171,10 +1171,10 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, void *stream) { struct snd_soc_component *component; - int i, ret; + int i; for_each_rtd_components(rtd, i, component) { - ret = pm_runtime_get_sync(component->dev); + int ret = pm_runtime_get_sync(component->dev); if (ret < 0 && ret != -EACCES) { pm_runtime_put_noidle(component->dev); return soc_component_ret(component, ret); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 11974d27060e..c830e96afba2 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -580,7 +580,7 @@ int snd_soc_suspend(struct device *dev) * Due to the resume being scheduled into a workqueue we could * suspend before that's finished - wait for it to complete. */ - snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); + snd_power_wait(card->snd_card); /* we're going to block userspace touching us until resume completes */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); @@ -1718,7 +1718,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str) */ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) { - const char *vendor, *product, *product_version, *board; + const char *vendor, *product, *board; if (card->long_name) return 0; /* long name already set by driver or from DMI */ @@ -1738,13 +1738,14 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) product = dmi_get_system_info(DMI_PRODUCT_NAME); if (product && is_dmi_valid(product)) { + const char *product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); + append_dmi_string(card, product); /* * some vendors like Lenovo may only put a self-explanatory * name in the product version field */ - product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); if (product_version && is_dmi_valid(product_version)) append_dmi_string(card, product_version); } @@ -2236,13 +2237,12 @@ static int snd_soc_add_controls(struct snd_card *card, struct device *dev, const struct snd_kcontrol_new *controls, int num_controls, const char *prefix, void *data) { - int err, i; + int i; for (i = 0; i < num_controls; i++) { const struct snd_kcontrol_new *control = &controls[i]; - - err = snd_ctl_add(card, snd_soc_cnew(control, data, - control->name, prefix)); + int err = snd_ctl_add(card, snd_soc_cnew(control, data, + control->name, prefix)); if (err < 0) { dev_err(dev, "ASoC: Failed to add %s: %d\n", control->name, err); @@ -2716,11 +2716,10 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver); */ void snd_soc_unregister_component(struct device *dev) { - struct snd_soc_component *component; - mutex_lock(&client_mutex); while (1) { - component = snd_soc_lookup_component_nolocked(dev, NULL); + struct snd_soc_component *component = snd_soc_lookup_component_nolocked(dev, NULL); + if (!component) break; @@ -2774,7 +2773,7 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, struct device_node *np = card->dev->of_node; struct snd_soc_dapm_widget *widgets; const char *template, *wname; - int i, j, num_widgets, ret; + int i, j, num_widgets; num_widgets = of_property_count_strings(np, propname); if (num_widgets < 0) { @@ -2804,8 +2803,8 @@ int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, } for (i = 0; i < num_widgets; i++) { - ret = of_property_read_string_index(np, propname, - 2 * i, &template); + int ret = of_property_read_string_index(np, propname, + 2 * i, &template); if (ret) { dev_err(card->dev, "ASoC: Property '%s' index %d read error:%d\n", @@ -2928,7 +2927,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, struct device_node *np = card->dev->of_node; int num_routes; struct snd_soc_dapm_route *routes; - int i, ret; + int i; num_routes = of_property_count_strings(np, propname); if (num_routes < 0 || num_routes & 1) { @@ -2948,8 +2947,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, } for (i = 0; i < num_routes; i++) { - ret = of_property_read_string_index(np, propname, - 2 * i, &routes[i].sink); + int ret = of_property_read_string_index(np, propname, + 2 * i, &routes[i].sink); if (ret) { dev_err(card->dev, "ASoC: Property '%s' index %d could not be read: %d\n", @@ -3053,7 +3052,7 @@ EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_from_bitmap); unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix) { - int ret, i; + int ret; char prop[128]; unsigned int format = 0; int bit, frame; @@ -3087,6 +3086,8 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np, ret = of_property_read_string(np, prop, &str); } if (ret == 0) { + int i; + for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) { if (strcmp(str, of_fmt_table[i].name) == 0) { format |= of_fmt_table[i].val; @@ -3200,12 +3201,11 @@ int snd_soc_get_dai_name(const struct of_phandle_args *args, const char **dai_name) { struct snd_soc_component *pos; - struct device_node *component_of_node; int ret = -EPROBE_DEFER; mutex_lock(&client_mutex); for_each_component(pos) { - component_of_node = soc_component_to_node(pos); + struct device_node *component_of_node = soc_component_to_node(pos); if (component_of_node != args->np) continue; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index a56dcc8d6fb7..3db0fcf24385 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -492,18 +492,16 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) */ void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link) { - struct snd_soc_dai_link_component *cpu; - struct snd_soc_dai_link_component *codec; - struct snd_soc_dai *dai; bool supported[SNDRV_PCM_STREAM_LAST + 1]; - bool supported_cpu; - bool supported_codec; int direction; - int i; for_each_pcm_streams(direction) { - supported_cpu = false; - supported_codec = false; + struct snd_soc_dai_link_component *cpu; + struct snd_soc_dai_link_component *codec; + struct snd_soc_dai *dai; + bool supported_cpu = false; + bool supported_codec = false; + int i; for_each_link_cpus(dai_link, i, cpu) { dai = snd_soc_find_dai_with_mutex(cpu); @@ -597,11 +595,11 @@ int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order) int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *dai; - int i, ret = 0; + int i; for_each_rtd_dais(rtd, i, dai) { if (dai->driver->pcm_new) { - ret = dai->driver->pcm_new(rtd, dai); + int ret = dai->driver->pcm_new(rtd, dai); if (ret < 0) return soc_dai_ret(dai, ret); } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 91bf939d5233..7b67f1e19ae9 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -650,12 +650,11 @@ static struct snd_soc_dapm_widget * dapm_wcache_lookup(struct snd_soc_dapm_wcache *wcache, const char *name) { struct snd_soc_dapm_widget *w = wcache->widget; - struct list_head *wlist; - const int depth = 2; - int i = 0; if (w) { - wlist = &w->dapm->card->widgets; + struct list_head *wlist = &w->dapm->card->widgets; + const int depth = 2; + int i = 0; list_for_each_entry_from(w, wlist, list) { if (!strcmp(name, w->name)) @@ -748,10 +747,11 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, { const struct snd_kcontrol_new *kcontrol = &w->kcontrol_news[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, item; + unsigned int item; int i; if (e->reg != SND_SOC_NOPM) { + unsigned int val; val = soc_dapm_read(dapm, e->reg); val = (val >> e->shift_l) & e->mask; item = snd_soc_enum_val_to_item(e, val); @@ -782,14 +782,14 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i, struct soc_mixer_control *mc = (struct soc_mixer_control *) p->sink->kcontrol_news[i].private_value; unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val; if (reg != SND_SOC_NOPM) { - val = soc_dapm_read(p->sink->dapm, reg); + unsigned int shift = mc->shift; + unsigned int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int val = soc_dapm_read(p->sink->dapm, reg); + /* * The nth_path argument allows this function to know * which path of a kcontrol it is setting the initial @@ -1060,10 +1060,10 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) /* create new dapm volume control */ static int dapm_new_pga(struct snd_soc_dapm_widget *w) { - int i, ret; + int i; for (i = 0; i < w->num_kcontrols; i++) { - ret = dapm_create_or_share_kcontrol(w, i); + int ret = dapm_create_or_share_kcontrol(w, i); if (ret < 0) return ret; } @@ -1074,10 +1074,7 @@ static int dapm_new_pga(struct snd_soc_dapm_widget *w) /* create new dapm dai link control */ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w) { - int i, ret; - struct snd_kcontrol *kcontrol; - struct snd_soc_dapm_context *dapm = w->dapm; - struct snd_card *card = dapm->card->snd_card; + int i; struct snd_soc_pcm_runtime *rtd = w->priv; /* create control for links with > 1 config */ @@ -1086,9 +1083,12 @@ static int dapm_new_dai_link(struct snd_soc_dapm_widget *w) /* add kcontrol */ for (i = 0; i < w->num_kcontrols; i++) { - kcontrol = snd_soc_cnew(&w->kcontrol_news[i], w, - w->name, NULL); - ret = snd_ctl_add(card, kcontrol); + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_card *card = dapm->card->snd_card; + struct snd_kcontrol *kcontrol = snd_soc_cnew(&w->kcontrol_news[i], + w, w->name, NULL); + int ret = snd_ctl_add(card, kcontrol); + if (ret < 0) { dev_err(dapm->dev, "ASoC: failed to add widget %s dapm kcontrol %s: %d\n", @@ -1528,7 +1528,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card, struct snd_soc_dapm_widget *w, int event) { const char *ev_name; - int power, ret; + int power; switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1564,6 +1564,8 @@ static void dapm_seq_check_event(struct snd_soc_card *card, return; if (w->event && (w->event_flags & event)) { + int ret; + pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n", w->name, ev_name); soc_dapm_async_complete(w->dapm); @@ -1645,7 +1647,7 @@ static void dapm_seq_run(struct snd_soc_card *card, int cur_subseq = -1; int cur_reg = SND_SOC_NOPM; struct snd_soc_dapm_context *cur_dapm = NULL; - int ret, i; + int i; int *sort; if (power_up) @@ -1654,7 +1656,7 @@ static void dapm_seq_run(struct snd_soc_card *card, sort = dapm_down_seq; list_for_each_entry_safe(w, n, list, power_list) { - ret = 0; + int ret = 0; /* Do we need to apply any queued changes? */ if (sort[w->id] != cur_sort || w->reg != cur_reg || @@ -3004,7 +3006,6 @@ err: static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route) { - struct snd_soc_dapm_widget *wsource, *wsink; struct snd_soc_dapm_path *path, *p; const char *sink; const char *source; @@ -3042,8 +3043,8 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, } if (path) { - wsource = path->source; - wsink = path->sink; + struct snd_soc_dapm_widget *wsource = path->source; + struct snd_soc_dapm_widget *wsink = path->sink; dapm_mark_dirty(wsource, "Route removed"); dapm_mark_dirty(wsink, "Route removed"); @@ -3079,11 +3080,11 @@ static int snd_soc_dapm_del_route(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route, int num) { - int i, r, ret = 0; + int i, ret = 0; mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); for (i = 0; i < num; i++) { - r = snd_soc_dapm_add_route(dapm, route); + int r = snd_soc_dapm_add_route(dapm, route); if (r < 0) { dev_err(dapm->dev, "ASoC: Failed to add route %s -> %s -> %s\n", route->source, @@ -3187,12 +3188,12 @@ static int snd_soc_dapm_weak_route(struct snd_soc_dapm_context *dapm, int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_route *route, int num) { - int i, err; + int i; int ret = 0; mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { - err = snd_soc_dapm_weak_route(dapm, route); + int err = snd_soc_dapm_weak_route(dapm, route); if (err) ret = err; route++; @@ -3783,13 +3784,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, const struct snd_soc_dapm_widget *widget, int num) { - struct snd_soc_dapm_widget *w; int i; int ret = 0; mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_INIT); for (i = 0; i < num; i++) { - w = snd_soc_dapm_new_control_unlocked(dapm, widget); + struct snd_soc_dapm_widget *w = snd_soc_dapm_new_control_unlocked(dapm, widget); if (IS_ERR(w)) { ret = PTR_ERR(w); break; @@ -4365,11 +4365,12 @@ static void soc_dapm_dai_stream_event(struct snd_soc_dai *dai, int stream, int event) { struct snd_soc_dapm_widget *w; - unsigned int ep; w = snd_soc_dai_get_widget(dai, stream); if (w) { + unsigned int ep; + dapm_mark_dirty(w, "stream event"); if (w->id == snd_soc_dapm_dai_in) { diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 9ef80a48707e..4aa48c74f21a 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -79,7 +79,6 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config); struct dma_slave_config slave_config; - int ret; memset(&slave_config, 0, sizeof(slave_config)); @@ -89,7 +88,7 @@ static int dmaengine_pcm_hw_params(struct snd_soc_component *component, prepare_slave_config = pcm->config->prepare_slave_config; if (prepare_slave_config) { - ret = prepare_slave_config(substream, params, &slave_config); + int ret = prepare_slave_config(substream, params, &slave_config); if (ret) return ret; @@ -230,7 +229,6 @@ static int dmaengine_pcm_new(struct snd_soc_component *component, struct dmaengine_pcm *pcm = soc_component_to_pcm(component); const struct snd_dmaengine_pcm_config *config = pcm->config; struct device *dev = component->dev; - struct snd_pcm_substream *substream; size_t prealloc_buffer_size; size_t max_buffer_size; unsigned int i; @@ -244,7 +242,7 @@ static int dmaengine_pcm_new(struct snd_soc_component *component, } for_each_pcm_streams(i) { - substream = rtd->pcm->streams[i].substream; + struct snd_pcm_substream *substream = rtd->pcm->streams[i].substream; if (!substream) continue; @@ -307,14 +305,13 @@ static int dmaengine_copy_user(struct snd_soc_component *component, bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; void *dma_ptr = runtime->dma_area + hwoff + channel * (runtime->dma_bytes / runtime->channels); - int ret; if (is_playback) if (copy_from_user(dma_ptr, buf, bytes)) return -EFAULT; if (process) { - ret = process(substream, channel, hwoff, (__force void *)buf, bytes); + int ret = process(substream, channel, hwoff, (__force void *)buf, bytes); if (ret < 0) return ret; } diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 0f1820f36b4d..d798765d168c 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -17,12 +17,6 @@ #include <linux/suspend.h> #include <trace/events/asoc.h> -struct jack_gpio_tbl { - int count; - struct snd_soc_jack *jack; - struct snd_soc_jack_gpio *gpios; -}; - /** * snd_soc_jack_report - Report the current status for a jack * @@ -42,7 +36,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) struct snd_soc_dapm_context *dapm; struct snd_soc_jack_pin *pin; unsigned int sync = 0; - int enable; if (!jack) return; @@ -58,7 +51,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) trace_snd_soc_jack_notify(jack, status); list_for_each_entry(pin, &jack->pins, list) { - enable = pin->mask & jack->status; + int enable = pin->mask & jack->status; if (pin->invert) enable = !enable; @@ -208,6 +201,12 @@ void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister); #ifdef CONFIG_GPIOLIB +struct jack_gpio_tbl { + int count; + struct snd_soc_jack *jack; + struct snd_soc_jack_gpio *gpios; +}; + /* gpio detect */ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) { diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 58527247df83..08eaa9ddf191 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -407,7 +407,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, int min = mc->min; unsigned int mask = (1U << (fls(min + max) - 1)) - 1; int err = 0; - unsigned int val, val_mask, val2; + unsigned int val, val_mask; val_mask = mask << shift; val = (ucontrol->value.integer.value[0] + min) & mask; @@ -418,6 +418,8 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, return err; if (snd_soc_volsw_is_stereo(mc)) { + unsigned int val2; + val_mask = mask << rshift; val2 = (ucontrol->value.integer.value[1] + min) & mask; val2 = val2 << rshift; @@ -573,7 +575,6 @@ int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max) { struct snd_kcontrol *kctl; - struct soc_mixer_control *mc; int ret = -EINVAL; /* Sanity check for name and max */ @@ -582,7 +583,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card, kctl = snd_soc_card_get_kcontrol(card, name); if (kctl) { - mc = (struct soc_mixer_control *)kctl->private_value; + struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; if (max <= mc->max) { mc->platform_max = max; ret = 0; @@ -811,11 +812,10 @@ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, long min = mc->min; long max = mc->max; long val = 0; - unsigned int regval; unsigned int i; for (i = 0; i < regcount; i++) { - regval = snd_soc_component_read(component, regbase+i); + unsigned int regval = snd_soc_component_read(component, regbase+i); val |= (regval & regwmask) << (regwshift*(regcount-i-1)); } val &= mask; @@ -856,17 +856,16 @@ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, unsigned long mask = (1UL<<mc->nbits)-1; long max = mc->max; long val = ucontrol->value.integer.value[0]; - unsigned int i, regval, regmask; - int err; + unsigned int i; if (invert) val = max - val; val &= mask; for (i = 0; i < regcount; i++) { - regval = (val >> (regwshift*(regcount-i-1))) & regwmask; - regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; - err = snd_soc_component_update_bits(component, regbase+i, - regmask, regval); + unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask; + unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; + int err = snd_soc_component_update_bits(component, regbase+i, + regmask, regval); if (err < 0) return err; } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d1c570ca21ea..48f71bb81a2f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -449,13 +449,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; - struct snd_soc_pcm_stream *pcm_codec, *pcm_cpu; int stream = substream->stream; int i; unsigned int bits = 0, cpu_bits = 0; for_each_rtd_codec_dais(rtd, i, codec_dai) { - pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); + struct snd_soc_pcm_stream *pcm_codec = snd_soc_dai_get_pcm_stream(codec_dai, stream); if (pcm_codec->sig_bits == 0) { bits = 0; @@ -465,7 +464,7 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream) } for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); + struct snd_soc_pcm_stream *pcm_cpu = snd_soc_dai_get_pcm_stream(cpu_dai, stream); if (pcm_cpu->sig_bits == 0) { cpu_bits = 0; @@ -634,10 +633,10 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_component *component; - int i, r, ret = 0; + int i, ret = 0; for_each_rtd_components(rtd, i, component) { - r = snd_soc_component_close(component, substream, rollback); + int r = snd_soc_component_close(component, substream, rollback); if (r < 0) ret = r; /* use last ret */ @@ -1318,13 +1317,12 @@ void dpcm_path_put(struct snd_soc_dapm_widget_list **list) static bool dpcm_be_is_active(struct snd_soc_dpcm *dpcm, int stream, struct snd_soc_dapm_widget_list *list) { - struct snd_soc_dapm_widget *widget; struct snd_soc_dai *dai; unsigned int i; /* is there a valid DAI widget for this BE */ for_each_rtd_dais(dpcm->be, i, dai) { - widget = snd_soc_dai_get_widget(dai, stream); + struct snd_soc_dapm_widget *widget = snd_soc_dai_get_widget(dai, stream); /* * The BE is pruned only if none of the dai @@ -1637,7 +1635,6 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream) for_each_dpcm_be(fe, stream, dpcm) { struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_soc_pcm_stream *codec_stream; struct snd_soc_pcm_stream *cpu_stream; struct snd_soc_dai *dai; int i; @@ -1660,7 +1657,8 @@ static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream) * DAIs connected to a single CPU DAI, use CPU DAI's directly */ if (be->num_codecs == 1) { - codec_stream = snd_soc_dai_get_pcm_stream(asoc_rtd_to_codec(be, 0), stream); + struct snd_soc_pcm_stream *codec_stream = snd_soc_dai_get_pcm_stream( + asoc_rtd_to_codec(be, 0), stream); soc_pcm_hw_update_chan(hw, codec_stream); } @@ -2591,9 +2589,7 @@ open_end: static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, int *playback, int *capture) { - struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; - int stream; int i; if (rtd->dai_link->dynamic && rtd->num_cpus > 1) { @@ -2603,6 +2599,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, } if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { + int stream; + if (rtd->dai_link->dpcm_playback) { stream = SNDRV_PCM_STREAM_PLAYBACK; @@ -2637,6 +2635,8 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd, } } } else { + struct snd_soc_dai *codec_dai; + /* Adapt stream for codec2codec links */ int cpu_capture = rtd->dai_link->params ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 0a24d0d409d2..f6e5ac3e0314 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1035,7 +1035,6 @@ err_denum: static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_ctl_hdr *control_hdr; int ret; int i; @@ -1043,8 +1042,7 @@ static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg, soc_tplg_get_offset(tplg)); for (i = 0; i < le32_to_cpu(hdr->count); i++) { - - control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; + struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) { dev_err(tplg->dev, "ASoC: invalid control size\n"); @@ -1583,15 +1581,16 @@ err: static int soc_tplg_dapm_widget_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_dapm_widget *widget; - int ret, count, i; + int count, i; count = le32_to_cpu(hdr->count); dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); for (i = 0; i < count; i++) { - widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; + struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; + int ret; + if (le32_to_cpu(widget->size) != sizeof(*widget)) { dev_err(tplg->dev, "ASoC: invalid widget size\n"); return -EINVAL; @@ -2125,10 +2124,9 @@ static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card, const char *stream_name) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_dai_link *link; for_each_card_rtds(card, rtd) { - link = rtd->dai_link; + struct snd_soc_dai_link *link = rtd->dai_link; if (link->id != id) continue; @@ -2346,15 +2344,16 @@ err: static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_dai *dai; int count; - int i, ret; + int i; count = le32_to_cpu(hdr->count); /* config the existing BE DAIs */ for (i = 0; i < count; i++) { - dai = (struct snd_soc_tplg_dai *)tplg->pos; + struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos; + int ret; + if (le32_to_cpu(dai->size) != sizeof(*dai)) { dev_err(tplg->dev, "ASoC: invalid physical DAI size\n"); return -EINVAL; @@ -2572,13 +2571,13 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, /* process the topology file headers */ static int soc_tplg_process_headers(struct soc_tplg *tplg) { - struct snd_soc_tplg_hdr *hdr; int ret; tplg->pass = SOC_TPLG_PASS_START; /* process the header types from start to end */ while (tplg->pass <= SOC_TPLG_PASS_END) { + struct snd_soc_tplg_hdr *hdr; tplg->hdr_pos = tplg->fw->data; hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 4447f515e8b1..88b6176af021 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -249,16 +249,6 @@ config SND_SOC_SOF_HDA_PROBES Say Y if you want to enable probes. If unsure, select "N". -config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1 - bool "SOF enable DMI Link L1" - help - This option enables DMI L1 for both playback and capture - and disables known workarounds for specific HDAudio platforms. - Only use to look into power optimizations on platforms not - affected by DMI L1 issues. This option is not recommended. - Say Y if you want to enable DMI Link L1. - If unsure, select "N". - endif ## SND_SOC_SOF_HDA_COMMON config SND_SOC_SOF_HDA_LINK_BASELINE diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 821f25fbcf08..e115e12a856f 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -347,6 +347,9 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .rom_init_timeout = 300, .ssp_count = CNL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); @@ -363,5 +366,8 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index df00db8369c7..cc8ddef37f37 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -15,6 +15,7 @@ * Hardware interface for generic Intel audio DSP HDA IP */ +#include <linux/moduleparam.h> #include <sound/hda_register.h> #include <sound/pcm_params.h> #include "../sof-audio.h" @@ -27,6 +28,10 @@ #define SDnFMT_BITS(x) ((x) << 4) #define SDnFMT_CHAN(x) ((x) << 0) +static bool hda_always_enable_dmi_l1; +module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444); +MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1"); + u32 hda_dsp_get_mult_div(struct snd_sof_dev *sdev, int rate) { switch (rate) { @@ -216,6 +221,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *scomp = sdev->component; struct hdac_ext_stream *dsp_stream; struct snd_sof_pcm *spcm; @@ -228,8 +234,14 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, return -EINVAL; } - /* All playback and D0i3 compatible streams are DMI L1 capable */ - if (direction == SNDRV_PCM_STREAM_PLAYBACK || + /* + * All playback streams are DMI L1 capable, capture streams need + * pause push/release to be disabled + */ + if (hda_always_enable_dmi_l1 && direction == SNDRV_PCM_STREAM_CAPTURE) + runtime->hw.info &= ~SNDRV_PCM_INFO_PAUSE; + + if (hda_always_enable_dmi_l1 || spcm->stream[substream->stream].d0i3_compatible) flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 40a3993ae2cb..63c367478f1c 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -197,11 +197,10 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) * Workaround to address a known issue with host DMA that results * in xruns during pause/release in capture scenarios. */ - if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1)) - if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) - snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, - HDA_VS_INTEL_EM2, - HDA_VS_INTEL_EM2_L1SEN, 0); + if (!(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, + HDA_VS_INTEL_EM2, + HDA_VS_INTEL_EM2_L1SEN, 0); return stream; } @@ -240,7 +239,7 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) spin_unlock_irq(&bus->reg_lock); /* Enable DMI L1 if permitted */ - if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable) + if (dmi_l1_enable) snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2, HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 891e6e1b9121..f60e2c57d3d0 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -41,6 +41,17 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 +static const struct sof_intel_dsp_desc + *get_chip_info(struct snd_sof_pdata *pdata) +{ + const struct sof_dev_desc *desc = pdata->desc; + const struct sof_intel_dsp_desc *chip_info; + + chip_info = desc->chip_info; + + return chip_info; +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -155,6 +166,8 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev) memset(&res, 0, sizeof(res)); res.mmio_base = sdev->bar[HDA_DSP_BAR]; + res.shim_base = hdev->desc->sdw_shim_base; + res.alh_base = hdev->desc->sdw_alh_base; res.irq = sdev->ipc_irq; res.handle = hdev->info.handle; res.parent = sdev->dev; @@ -215,7 +228,7 @@ static int hda_sdw_exit(struct snd_sof_dev *sdev) return 0; } -static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) +bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hdev; bool ret = false; @@ -241,6 +254,17 @@ out: return ret; } +static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->check_sdw_irq) + return chip->check_sdw_irq(sdev); + + return false; +} + static irqreturn_t hda_dsp_sdw_thread(int irq, void *context) { return sdw_intel_thread(irq, context); @@ -253,7 +277,7 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) hdev = sdev->pdata->hw_pdata; if (hdev->sdw && snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_DSP_REG_SNDW_WAKE_STS)) + hdev->desc->sdw_shim_base + SDW_SHIM_WAKESTS)) return true; return false; @@ -672,17 +696,6 @@ skip_soundwire: return 0; } -static const struct sof_intel_dsp_desc - *get_chip_info(struct snd_sof_pdata *pdata) -{ - const struct sof_dev_desc *desc = pdata->desc; - const struct sof_intel_dsp_desc *chip_info; - - chip_info = desc->chip_info; - - return chip_info; -} - static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) { struct snd_sof_dev *sdev = context; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 4d44f8910393..4fdfb108645c 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -233,7 +233,6 @@ #define HDA_DSP_REG_ADSPIS2 (HDA_DSP_GEN_BASE + 0x14) #define HDA_DSP_REG_ADSPIS2_SNDW BIT(5) -#define HDA_DSP_REG_SNDW_WAKE_STS 0x2C192 /* Intel HD Audio Inter-Processor Communication Registers */ #define HDA_DSP_IPC_BASE 0x40 @@ -692,6 +691,7 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd); int hda_sdw_startup(struct snd_sof_dev *sdev); void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable); void hda_sdw_process_wakeen(struct snd_sof_dev *sdev); +bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev); #else @@ -737,6 +737,12 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) static inline void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) { } + +static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) +{ + return false; +} + #endif /* common dai driver */ diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 88a74be8a0c1..ee095b8f2d01 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -142,5 +142,8 @@ const struct sof_intel_dsp_desc icl_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index 4ee1da397d4e..4bded668b672 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -15,7 +15,6 @@ #include <sound/sof.h> #include "../ops.h" #include "atom.h" -#include "shim.h" #include "../sof-pci-dev.h" #include "../sof-audio.h" diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 529f68d0ca47..e9f7d4d7fcce 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -164,6 +164,9 @@ struct sof_intel_dsp_desc { int rom_init_timeout; int ssp_count; /* ssp count of the platform */ int ssp_base_offset; /* base address of the SSPs */ + u32 sdw_shim_base; + u32 sdw_alh_base; + bool (*check_sdw_irq)(struct snd_sof_dev *sdev); }; extern const struct snd_sof_dsp_ops sof_tng_ops; diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 2ed788304414..199d41a7dc9b 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -137,6 +137,9 @@ const struct sof_intel_dsp_desc tgl_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); @@ -153,6 +156,9 @@ const struct sof_intel_dsp_desc tglh_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(tglh_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); @@ -169,6 +175,9 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(ehl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); @@ -185,5 +194,8 @@ const struct sof_intel_dsp_desc adls_chip_info = { .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, + .sdw_shim_base = SDW_SHIM_BASE, + .sdw_alh_base = SDW_ALH_BASE, + .check_sdw_irq = hda_common_check_sdw_irq, }; EXPORT_SYMBOL_NS(adls_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 510883cd9107..989912f2b739 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -433,11 +433,10 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, return NULL; } -/* - * Helper to get SSP MCLK from a pcm_runtime. - * Return 0 if not exist. - */ -int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) +#define SOF_DAI_CLK_INTEL_SSP_MCLK 0 +#define SOF_DAI_CLK_INTEL_SSP_BCLK 1 + +static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type) { struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); @@ -450,17 +449,46 @@ int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) switch (dai->dai_config->type) { case SOF_DAI_INTEL_SSP: - return dai->dai_config->ssp.mclk_rate; + switch (clk_type) { + case SOF_DAI_CLK_INTEL_SSP_MCLK: + return dai->dai_config->ssp.mclk_rate; + case SOF_DAI_CLK_INTEL_SSP_BCLK: + return dai->dai_config->ssp.bclk_rate; + default: + dev_err(rtd->dev, "fail to get SSP clk %d rate\n", + clk_type); + return -EINVAL; + } + break; default: /* not yet implemented for platforms other than the above */ - dev_err(rtd->dev, "mclk for dai_config->type %d not supported yet!\n", + dev_err(rtd->dev, "DAI type %d not supported yet!\n", dai->dai_config->type); return -EINVAL; } } + +/* + * Helper to get SSP MCLK from a pcm_runtime. + * Return 0 if not exist. + */ +int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) +{ + return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_MCLK); +} EXPORT_SYMBOL(sof_dai_get_mclk); /* + * Helper to get SSP BCLK from a pcm_runtime. + * Return 0 if not exist. + */ +int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd) +{ + return sof_dai_get_clk(rtd, SOF_DAI_CLK_INTEL_SSP_BCLK); +} +EXPORT_SYMBOL(sof_dai_get_bclk); + +/* * SOF Driver enumeration. */ int sof_machine_check(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index 03119462f9e2..bc9e70765678 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -50,6 +50,15 @@ static const struct dmi_system_id sof_tplg_table[] = { }, .driver_data = "sof-tgl-rt5682-ssp0-max98373-ssp2.tplg", }, + { + .callback = sof_tplg_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), + DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"), + }, + .driver_data = "sof-adl-rt5682-ssp0-max98373-ssp2.tplg", + }, {} }; diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index b3e1df693381..ef011a488ceb 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -512,16 +512,14 @@ static const struct of_device_id tegra30_ahub_of_match[] = { static int tegra30_ahub_probe(struct platform_device *pdev) { - const struct of_device_id *match; const struct tegra30_ahub_soc_data *soc_data; struct resource *res0; void __iomem *regs_apbif, *regs_ahub; int ret = 0; - match = of_match_device(tegra30_ahub_of_match, &pdev->dev); - if (!match) + soc_data = of_device_get_match_data(&pdev->dev); + if (!soc_data) return -EINVAL; - soc_data = match->data; ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), GFP_KERNEL); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 36344f0a64c1..084a533bf4f2 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -406,7 +406,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = { static int tegra30_i2s_platform_probe(struct platform_device *pdev) { struct tegra30_i2s *i2s; - const struct of_device_id *match; + const struct tegra30_i2s_soc_data *soc_data; u32 cif_ids[2]; void __iomem *regs; int ret; @@ -418,13 +418,13 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, i2s); - match = of_match_device(tegra30_i2s_of_match, &pdev->dev); - if (!match) { + soc_data = of_device_get_match_data(&pdev->dev); + if (!soc_data) { dev_err(&pdev->dev, "Error: No device match found\n"); ret = -ENODEV; goto err; } - i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data; + i2s->soc_data = soc_data; i2s->dai = tegra30_i2s_dai_template; i2s->dai.name = dev_name(&pdev->dev); diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig index 698d7bc84dcf..1d9fe3fca193 100644 --- a/sound/soc/ti/Kconfig +++ b/sound/soc/ti/Kconfig @@ -35,6 +35,7 @@ config SND_SOC_DAVINCI_MCASP various Texas Instruments SoCs like: - daVinci devices - Sitara line of SoCs (AM335x, AM438x, etc) + - OMAP4 - DRA7x devices - Keystone devices - K3 devices (am654, j721e) diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index aba0017e870b..ecd24d412a9b 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -337,8 +337,8 @@ static int cx81801_hangup(struct tty_struct *tty) } /* Line discipline .receive_buf() */ -static void cx81801_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) +static void cx81801_receive(struct tty_struct *tty, const unsigned char *cp, + const char *fp, int count) { struct snd_soc_component *component = tty->disc_data; const unsigned char *c; @@ -396,6 +396,7 @@ static void cx81801_wakeup(struct tty_struct *tty) static struct tty_ldisc_ops cx81801_ops = { .name = "cx81801", + .num = N_V253, .owner = THIS_MODULE, .open = cx81801_open, .close = cx81801_close, @@ -503,7 +504,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) } /* Register optional line discipline for over the modem control */ - ret = tty_register_ldisc(N_V253, &cx81801_ops); + ret = tty_register_ldisc(&cx81801_ops); if (ret) { dev_warn(card->dev, "Failed to register line discipline, " @@ -582,9 +583,7 @@ static int ams_delta_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - if (tty_unregister_ldisc(N_V253) != 0) - dev_warn(&pdev->dev, - "failed to unregister V253 line discipline\n"); + tty_unregister_ldisc(&cx81801_ops); snd_soc_unregister_card(card); card->dev = NULL; diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 017a5a5e56cd..56a19eeec5c7 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -83,6 +83,8 @@ struct davinci_mcasp { struct snd_pcm_substream *substreams[2]; unsigned int dai_fmt; + u32 iec958_status; + /* Audio can not be enabled due to missing parameter(s) */ bool missing_audio_param; @@ -757,6 +759,9 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai, { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) + return 0; + dev_dbg(mcasp->dev, "%s() tx_mask 0x%08x rx_mask 0x%08x slots %d width %d\n", __func__, tx_mask, rx_mask, slots, slot_width); @@ -827,6 +832,20 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp, mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate), RXROT(7)); mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask); + } else { + /* + * according to the TRM it should be TXROT=0, this one works: + * 16 bit to 23-8 (TXROT=6, rotate 24 bits) + * 24 bit to 23-0 (TXROT=0, rotate 0 bits) + * + * TXROT = 0 only works with 24bit samples + */ + tx_rotate = (sample_width / 4 + 2) & 0x7; + + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate), + TXROT(7)); + mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15), + TXSSZ(0x0F)); } mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask); @@ -842,10 +861,16 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream, u8 tx_ser = 0; u8 rx_ser = 0; u8 slots = mcasp->tdm_slots; - u8 max_active_serializers = (channels + slots - 1) / slots; - u8 max_rx_serializers, max_tx_serializers; + u8 max_active_serializers, max_rx_serializers, max_tx_serializers; int active_serializers, numevt; u32 reg; + + /* In DIT mode we only allow maximum of one serializers for now */ + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) + max_active_serializers = 1; + else + max_active_serializers = (channels + slots - 1) / slots; + /* Default configuration */ if (mcasp->version < MCASP_VERSION_3) mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); @@ -1031,16 +1056,18 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream, static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, unsigned int rate) { - u32 cs_value = 0; - u8 *cs_bytes = (u8*) &cs_value; + u8 *cs_bytes = (u8 *)&mcasp->iec958_status; - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15)); + if (!mcasp->dat_port) + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL); + else + mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSEL); /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180)); + mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, 0xFFFF); + /* Set the TX tdm : for all the slots */ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); @@ -1049,16 +1076,8 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); - /* Set S/PDIF channel status bits */ - cs_bytes[0] = IEC958_AES0_CON_NOT_COPYRIGHT; - cs_bytes[1] = IEC958_AES1_CON_PCM_CODER; - + cs_bytes[3] &= ~IEC958_AES3_CON_FS; switch (rate) { case 22050: cs_bytes[3] |= IEC958_AES3_CON_FS_22050; @@ -1088,12 +1107,15 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp, cs_bytes[3] |= IEC958_AES3_CON_FS_192000; break; default: - printk(KERN_WARNING "unsupported sampling rate: %d\n", rate); + dev_err(mcasp->dev, "unsupported sampling rate: %d\n", rate); return -EINVAL; } - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, cs_value); - mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, cs_value); + mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRA_REG, mcasp->iec958_status); + mcasp_set_reg(mcasp, DAVINCI_MCASP_DITCSRB_REG, mcasp->iec958_status); + + /* Enable the DIT */ + mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN); return 0; } @@ -1237,12 +1259,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int slots = mcasp->tdm_slots; int rate = params_rate(params); int sbits = params_width(params); + unsigned int bclk_target; if (mcasp->slot_width) sbits = mcasp->slot_width; + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) + bclk_target = rate * sbits * slots; + else + bclk_target = rate * 128; + davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq, - rate * sbits * slots, true); + bclk_target, true); } ret = mcasp_common_hw_param(mcasp, substream->stream, @@ -1598,6 +1626,77 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .set_tdm_slot = davinci_mcasp_set_tdm_slot, }; +static int davinci_mcasp_iec958_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + + return 0; +} + +static int davinci_mcasp_iec958_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memcpy(uctl->value.iec958.status, &mcasp->iec958_status, + sizeof(mcasp->iec958_status)); + + return 0; +} + +static int davinci_mcasp_iec958_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uctl) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memcpy(&mcasp->iec958_status, uctl->value.iec958.status, + sizeof(mcasp->iec958_status)); + + return 0; +} + +static int davinci_mcasp_iec958_con_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); + struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai); + + memset(ucontrol->value.iec958.status, 0xff, sizeof(mcasp->iec958_status)); + return 0; +} + +static const struct snd_kcontrol_new davinci_mcasp_iec958_ctls[] = { + { + .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_VOLATILE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), + .info = davinci_mcasp_iec958_info, + .get = davinci_mcasp_iec958_get, + .put = davinci_mcasp_iec958_put, + }, { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), + .info = davinci_mcasp_iec958_info, + .get = davinci_mcasp_iec958_con_mask_get, + }, +}; + +static void davinci_mcasp_init_iec958_status(struct davinci_mcasp *mcasp) +{ + unsigned char *cs = (u8 *)&mcasp->iec958_status; + + cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; + cs[1] = IEC958_AES1_CON_PCM_CODER; + cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; + cs[3] = IEC958_AES3_CON_CLOCK_1000PPM; +} + static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) { struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai); @@ -1605,6 +1704,12 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai) dai->playback_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dai->capture_dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE]; + if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) { + davinci_mcasp_init_iec958_status(mcasp); + snd_soc_add_dai_controls(dai, davinci_mcasp_iec958_ctls, + ARRAY_SIZE(davinci_mcasp_iec958_ctls)); + } + return 0; } @@ -1651,7 +1756,8 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { .channels_min = 1, .channels_max = 384, .rates = DAVINCI_MCASP_RATES, - .formats = DAVINCI_MCASP_PCM_FMTS, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, }, .ops = &davinci_mcasp_dai_ops, }, @@ -1688,6 +1794,12 @@ static struct davinci_mcasp_pdata dra7_mcasp_pdata = { .version = MCASP_VERSION_4, }; +static struct davinci_mcasp_pdata omap_mcasp_pdata = { + .tx_dma_offset = 0x200, + .rx_dma_offset = 0, + .version = MCASP_VERSION_OMAP, +}; + static const struct of_device_id mcasp_dt_ids[] = { { .compatible = "ti,dm646x-mcasp-audio", @@ -1705,6 +1817,10 @@ static const struct of_device_id mcasp_dt_ids[] = { .compatible = "ti,dra7-mcasp-audio", .data = &dra7_mcasp_pdata, }, + { + .compatible = "ti,omap4-mcasp-audio", + .data = &omap_mcasp_pdata, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mcasp_dt_ids); @@ -1871,6 +1987,8 @@ out: } else { mcasp->tdm_slots = pdata->tdm_slots; } + } else { + mcasp->tdm_slots = 32; } mcasp->num_serializer = pdata->num_serializer; @@ -2242,10 +2360,17 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_data = &mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dma_data->filter_data = "tx"; - if (dat) + if (dat) { dma_data->addr = dat->start; - else + /* + * According to the TRM there should be 0x200 offset added to + * the DAT port address + */ + if (mcasp->version == MCASP_VERSION_OMAP) + dma_data->addr += davinci_mcasp_txdma_offset(mcasp->pdata); + } else { dma_data->addr = mem->start + davinci_mcasp_txdma_offset(mcasp->pdata); + } /* RX is not valid in DIT mode */ @@ -2310,7 +2435,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev) ret = edma_pcm_platform_register(&pdev->dev); break; case PCM_SDMA: - ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); + if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) + ret = sdma_pcm_platform_register(&pdev->dev, "tx", "rx"); + else + ret = sdma_pcm_platform_register(&pdev->dev, "tx", NULL); break; case PCM_UDMA: ret = udma_pcm_platform_register(&pdev->dev); diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c index 265bbc5a2f96..9347f982c3e1 100644 --- a/sound/soc/ti/j721e-evm.c +++ b/sound/soc/ti/j721e-evm.c @@ -23,8 +23,11 @@ */ #define J721E_CODEC_CONF_COUNT 5 -#define J721E_AUDIO_DOMAIN_CPB 0 -#define J721E_AUDIO_DOMAIN_IVI 1 +enum j721e_audio_domain_id { + J721E_AUDIO_DOMAIN_CPB = 0, + J721E_AUDIO_DOMAIN_IVI, + J721E_AUDIO_DOMAIN_LAST, +}; #define J721E_CLK_PARENT_48000 0 #define J721E_CLK_PARENT_44100 1 @@ -78,7 +81,7 @@ struct j721e_priv { u32 pll_rates[2]; unsigned int hsdiv_rates[2]; - struct j721e_audio_domain audio_domains[2]; + struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST]; struct mutex mutex; }; @@ -199,9 +202,8 @@ static int j721e_configure_refclk(struct j721e_priv *priv, if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) { dev_dbg(priv->dev, - "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", - audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI", - rate, + "domain%u configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", + audio_domain, rate, clk_id == J721E_CLK_PARENT_48000 ? "PLL4" : "PLL15", ratios_for_pcm3168a[i], scki); @@ -263,10 +265,11 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream) domain->active++; - if (priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate) - active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].rate; - else - active_rate = priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].rate; + for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) { + active_rate = priv->audio_domains[i].rate; + if (active_rate) + break; + } if (active_rate) ret = snd_pcm_hw_constraint_single(substream->runtime, @@ -825,7 +828,7 @@ static int j721e_soc_probe(struct platform_device *pdev) struct snd_soc_card *card; const struct of_device_id *match; struct j721e_priv *priv; - int link_cnt, conf_cnt, ret; + int link_cnt, conf_cnt, ret, i; if (!node) { dev_err(&pdev->dev, "of node is missing.\n"); @@ -849,8 +852,9 @@ static int j721e_soc_probe(struct platform_device *pdev) if (!priv->dai_links) return -ENOMEM; - priv->audio_domains[J721E_AUDIO_DOMAIN_CPB].parent_clk_id = -1; - priv->audio_domains[J721E_AUDIO_DOMAIN_IVI].parent_clk_id = -1; + for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) + priv->audio_domains[i].parent_clk_id = -1; + priv->dev = &pdev->dev; card = &priv->card; card->dev = &pdev->dev; diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 91cc9a4f44d7..2e3d1eea77c1 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -292,11 +292,6 @@ static int omap_abe_probe(struct platform_device *pdev) card->fully_routed = 1; - if (!priv->mclk_freq) { - dev_err(&pdev->dev, "MCLK frequency missing\n"); - return -ENODEV; - } - card->dai_link = priv->dai_links; card->num_links = num_links; diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c index cf9814130067..4e8d5f7532ba 100644 --- a/sound/soc/uniphier/aio-cpu.c +++ b/sound/soc/uniphier/aio-cpu.c @@ -128,8 +128,8 @@ static const struct uniphier_aio_spec *find_spec(struct uniphier_aio *aio, static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq) { struct uniphier_aio_pll *pll; - int mul[] = { 1, 1, 1, 2, }; - int div[] = { 2, 3, 1, 3, }; + static const int mul[] = { 1, 1, 1, 2, }; + static const int div[] = { 2, 3, 1, 3, }; int i; if (!is_valid_pll(aio->chip, pll_id)) diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index d24ae00878f5..c434b69a83f1 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -975,8 +975,9 @@ static int snd_amd7930_create(struct snd_card *card, spin_unlock_irqrestore(&amd->lock, flags); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - amd, &snd_amd7930_dev_ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + amd, &snd_amd7930_dev_ops); + if (err < 0) { snd_amd7930_free(amd); return err; } @@ -1019,13 +1020,16 @@ static int amd7930_sbus_probe(struct platform_device *op) irq, dev_num, &amd)) < 0) goto out_err; - if ((err = snd_amd7930_pcm(amd)) < 0) + err = snd_amd7930_pcm(amd); + if (err < 0) goto out_err; - if ((err = snd_amd7930_mixer(amd)) < 0) + err = snd_amd7930_mixer(amd); + if (err < 0) goto out_err; - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto out_err; amd->next = amd7930_list; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 35c17803a430..2942c8c7a236 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1828,8 +1828,9 @@ static int snd_cs4231_sbus_create(struct snd_card *card, } snd_cs4231_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &snd_cs4231_sbus_dev_ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + chip, &snd_cs4231_sbus_dev_ops); + if (err < 0) { snd_cs4231_sbus_free(chip); return err; } @@ -2020,8 +2021,9 @@ static int snd_cs4231_ebus_create(struct snd_card *card, } snd_cs4231_init(chip); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, - chip, &snd_cs4231_ebus_dev_ops)) < 0) { + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, + chip, &snd_cs4231_ebus_dev_ops); + if (err < 0) { snd_cs4231_ebus_free(chip); return err; } diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index b055f5839578..6b84f66e4af4 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -2226,11 +2226,12 @@ static int snd_dbri_pcm(struct snd_card *card) struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(card, - /* ID */ "sun_dbri", - /* device */ 0, - /* playback count */ 1, - /* capture count */ 1, &pcm)) < 0) + err = snd_pcm_new(card, + /* ID */ "sun_dbri", + /* device */ 0, + /* playback count */ 1, + /* capture count */ 1, &pcm); + if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index f65e6c7b139f..49d1976a132c 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -104,7 +104,8 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch if (emu->sflist == NULL) return -ENOMEM; - if ((err = snd_emux_init_hwdep(emu)) < 0) + err = snd_emux_init_hwdep(emu); + if (err < 0) return err; snd_emux_init_voices(emu); diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c index afd119b11f39..3c7314f5fb19 100644 --- a/sound/synth/emux/emux_effect.c +++ b/sound/synth/emux/emux_effect.c @@ -181,7 +181,10 @@ snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan, fx->flag[type] = mode; /* do we need to modify the register in realtime ? */ - if (! parm_defs[type].update || (offset = parm_defs[type].offset) < 0) + if (!parm_defs[type].update) + return; + offset = parm_defs[type].offset; + if (offset < 0) return; #ifdef SNDRV_LITTLE_ENDIAN @@ -223,13 +226,17 @@ snd_emux_setup_effect(struct snd_emux_voice *vp) unsigned char *srcp; int i; - if (! (fx = chan->private)) + fx = chan->private; + if (!fx) return; /* modify the register values via effect table */ for (i = 0; i < EMUX_FX_END; i++) { int offset; - if (! fx->flag[i] || (offset = parm_defs[i].offset) < 0) + if (!fx->flag[i]) + continue; + offset = parm_defs[i].offset; + if (offset < 0) continue; #ifdef SNDRV_LITTLE_ENDIAN if (parm_defs[i].type & PARM_IS_ALIGN_HI) diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c index 8a965e2f160a..81719bfb8ed7 100644 --- a/sound/synth/emux/emux_hwdep.c +++ b/sound/synth/emux/emux_hwdep.c @@ -116,7 +116,8 @@ snd_emux_init_hwdep(struct snd_emux *emu) struct snd_hwdep *hw; int err; - if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0) + err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw); + if (err < 0) return err; emu->hwdep = hw; strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); @@ -127,7 +128,8 @@ snd_emux_init_hwdep(struct snd_emux *emu) hw->ops.ioctl_compat = snd_emux_hwdep_ioctl; hw->exclusive = 1; hw->private_data = emu; - if ((err = snd_card_register(emu->card)) < 0) + err = snd_card_register(emu->card); + if (err < 0) return err; return 0; diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c index 7eed5791972c..8056422ed7c5 100644 --- a/sound/synth/emux/emux_nrpn.c +++ b/sound/synth/emux/emux_nrpn.c @@ -69,7 +69,7 @@ static const int gs_sense[] = DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY }; -/* effect sensitivies for XG controls: +/* effect sensitivities for XG controls: * adjusted for chaos 8MB soundfonts */ static const int xg_sense[] = diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 9ebc711afa6b..16f00097cb95 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -108,7 +108,7 @@ snd_soundfont_close_check(struct snd_sf_list *sflist, int client) * Deal with a soundfont patch. Any driver could use these routines * although it was designed for the AWE64. * - * The sample_write and callargs pararameters allow a callback into + * The sample_write and callargs parameters allow a callback into * the actual driver to write sample data to the board or whatever * it wants to do with it. */ @@ -349,7 +349,8 @@ sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) { struct snd_sf_zone *zp; - if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL) + zp = kzalloc(sizeof(*zp), GFP_KERNEL); + if (!zp) return NULL; zp->next = sf->zones; sf->zones = zp; @@ -381,7 +382,8 @@ sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) { struct snd_sf_sample *sp; - if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL) + sp = kzalloc(sizeof(*sp), GFP_KERNEL); + if (!sp) return NULL; sp->next = sf->samples; @@ -451,7 +453,8 @@ load_map(struct snd_sf_list *sflist, const void __user *data, int count) } /* create a new zone */ - if ((zp = sf_zone_new(sflist, sf)) == NULL) + zp = sf_zone_new(sflist, sf); + if (!zp) return -ENOMEM; zp->bank = map.map_bank; @@ -514,7 +517,8 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) int i; /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) + sf = sflist->currsf; + if (!sf) return -EINVAL; if (is_special_type(sf->type)) @@ -579,9 +583,9 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) init_voice_parm(&tmpzone.v.parm); /* create a new zone */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { + zone = sf_zone_new(sflist, sf); + if (!zone) return -ENOMEM; - } /* copy the temporary data */ zone->bank = tmpzone.bank; @@ -700,7 +704,8 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) long off; /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) + sf = sflist->currsf; + if (!sf) return -EINVAL; if (is_special_type(sf->type)) @@ -723,7 +728,8 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) } /* Allocate a new sample structure */ - if ((sp = sf_sample_new(sflist, sf)) == NULL) + sp = sf_sample_new(sflist, sf); + if (!sp) return -ENOMEM; sp->v = sample_info; @@ -793,7 +799,7 @@ snd_sf_linear_to_log(unsigned int amount, int offset, int ratio) amount <<= 1; s = (amount >> 24) & 0x7f; low = (amount >> 16) & 0xff; - /* linear approxmimation by lower 8 bit */ + /* linear approximation by lower 8 bit */ v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8; v -= offset; v = (v * ratio) >> 16; @@ -958,7 +964,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL); if (sf == NULL) return -ENOMEM; - if ((smp = sf_sample_new(sflist, sf)) == NULL) + smp = sf_sample_new(sflist, sf); + if (!smp) return -ENOMEM; sample_id = sflist->sample_counter; smp->v.sample = sample_id; @@ -996,7 +1003,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, smp->v.sf_id = sf->id; /* set up voice info */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { + zone = sf_zone_new(sflist, sf); + if (!zone) { sf_sample_delete(sflist, sf, smp); return -ENOMEM; } @@ -1181,7 +1189,8 @@ add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur) } /* prepend this zone */ - if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0) + index = get_index(cur->bank, cur->instr, cur->v.low); + if (index < 0) return; cur->next_zone = zone; /* zone link */ cur->next_instr = sflist->presets[index]; /* preset table link */ @@ -1197,7 +1206,8 @@ delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp) int index; struct snd_sf_zone *p; - if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0) + index = get_index(zp->bank, zp->instr, zp->v.low); + if (index < 0) return; for (p = sflist->presets[index]; p; p = p->next_instr) { while (p->next_instr == zp) { @@ -1257,7 +1267,8 @@ search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key) int index; struct snd_sf_zone *zp; - if ((index = get_index(bank, preset, key)) < 0) + index = get_index(bank, preset, key); + if (index < 0) return NULL; for (zp = sflist->presets[index]; zp; zp = zp->next_instr) { if (zp->instr == preset && zp->bank == bank) @@ -1386,7 +1397,8 @@ snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr) { struct snd_sf_list *sflist; - if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL) + sflist = kzalloc(sizeof(*sflist), GFP_KERNEL); + if (!sflist) return NULL; mutex_init(&sflist->presets_mutex); @@ -1421,7 +1433,7 @@ snd_sf_free(struct snd_sf_list *sflist) /* * Remove all samples - * The soundcard should be silet before calling this function. + * The soundcard should be silent before calling this function. */ int snd_soundfont_remove_samples(struct snd_sf_list *sflist) diff --git a/sound/usb/card.h b/sound/usb/card.h index a741e7da83a2..6c0a052a28f9 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -19,7 +19,7 @@ struct audioformat { unsigned char iface; /* interface number */ unsigned char altsetting; /* corresponding alternate setting */ unsigned char ep_idx; /* endpoint array index */ - unsigned char altset_idx; /* array index of altenate setting */ + unsigned char altset_idx; /* array index of alternate setting */ unsigned char attributes; /* corresponding attributes of cs endpoint */ unsigned char endpoint; /* endpoint */ unsigned char ep_attr; /* endpoint attributes */ @@ -54,6 +54,7 @@ struct snd_urb_ctx { struct snd_usb_endpoint *ep; int index; /* index for urb array */ int packets; /* number of packets per urb */ + int queued; /* queued data bytes by this urb */ int packet_size[MAX_PACKS_HS]; /* size of packets for next submission */ struct list_head ready_list; }; @@ -157,9 +158,12 @@ struct snd_usb_substream { unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */ unsigned int running: 1; /* running status */ + unsigned int period_elapsed_pending; /* delay period handling */ + unsigned int buffer_bytes; /* buffer size in bytes */ + unsigned int inflight_bytes; /* in-flight data bytes on buffer (for playback) */ unsigned int hwptr_done; /* processed byte position in the buffer */ - unsigned int transfer_done; /* processed frames since last period update */ + unsigned int transfer_done; /* processed frames since last period update */ unsigned int frame_limit; /* limits number of packets in URB */ /* data and sync endpoints for this stream */ @@ -174,8 +178,7 @@ struct snd_usb_substream { struct list_head fmt_list; /* format list */ spinlock_t lock; - int last_frame_number; /* stored frame number */ - int last_delay; /* stored delay */ + unsigned int last_frame_number; /* stored frame number */ struct { int marker; diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 17bbde73d4d1..52de52288e10 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -21,82 +21,77 @@ #include "clock.h" #include "quirks.h" +union uac23_clock_source_desc { + struct uac_clock_source_descriptor v2; + struct uac3_clock_source_descriptor v3; +}; + +union uac23_clock_selector_desc { + struct uac_clock_selector_descriptor v2; + struct uac3_clock_selector_descriptor v3; +}; + +union uac23_clock_multiplier_desc { + struct uac_clock_multiplier_descriptor v2; + struct uac_clock_multiplier_descriptor v3; +}; + +#define GET_VAL(p, proto, field) \ + ((proto) == UAC_VERSION_3 ? (p)->v3.field : (p)->v2.field) + static void *find_uac_clock_desc(struct usb_host_interface *iface, int id, - bool (*validator)(void *, int), u8 type) + bool (*validator)(void *, int, int), + u8 type, int proto) { void *cs = NULL; while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen, cs, type))) { - if (validator(cs, id)) + if (validator(cs, id, proto)) return cs; } return NULL; } -static bool validate_clock_source_v2(void *p, int id) +static bool validate_clock_source(void *p, int id, int proto) { - struct uac_clock_source_descriptor *cs = p; - return cs->bClockID == id; -} + union uac23_clock_source_desc *cs = p; -static bool validate_clock_source_v3(void *p, int id) -{ - struct uac3_clock_source_descriptor *cs = p; - return cs->bClockID == id; + return GET_VAL(cs, proto, bClockID) == id; } -static bool validate_clock_selector_v2(void *p, int id) +static bool validate_clock_selector(void *p, int id, int proto) { - struct uac_clock_selector_descriptor *cs = p; - return cs->bClockID == id; -} + union uac23_clock_selector_desc *cs = p; -static bool validate_clock_selector_v3(void *p, int id) -{ - struct uac3_clock_selector_descriptor *cs = p; - return cs->bClockID == id; + return GET_VAL(cs, proto, bClockID) == id; } -static bool validate_clock_multiplier_v2(void *p, int id) +static bool validate_clock_multiplier(void *p, int id, int proto) { - struct uac_clock_multiplier_descriptor *cs = p; - return cs->bClockID == id; -} + union uac23_clock_multiplier_desc *cs = p; -static bool validate_clock_multiplier_v3(void *p, int id) -{ - struct uac3_clock_multiplier_descriptor *cs = p; - return cs->bClockID == id; + return GET_VAL(cs, proto, bClockID) == id; } -#define DEFINE_FIND_HELPER(name, obj, validator, type) \ -static obj *name(struct usb_host_interface *iface, int id) \ -{ \ - return find_uac_clock_desc(iface, id, validator, type); \ +#define DEFINE_FIND_HELPER(name, obj, validator, type2, type3) \ +static obj *name(struct snd_usb_audio *chip, int id, int proto) \ +{ \ + return find_uac_clock_desc(chip->ctrl_intf, id, validator, \ + proto == UAC_VERSION_3 ? (type3) : (type2), \ + proto); \ } DEFINE_FIND_HELPER(snd_usb_find_clock_source, - struct uac_clock_source_descriptor, - validate_clock_source_v2, UAC2_CLOCK_SOURCE); -DEFINE_FIND_HELPER(snd_usb_find_clock_source_v3, - struct uac3_clock_source_descriptor, - validate_clock_source_v3, UAC3_CLOCK_SOURCE); - + union uac23_clock_source_desc, validate_clock_source, + UAC2_CLOCK_SOURCE, UAC3_CLOCK_SOURCE); DEFINE_FIND_HELPER(snd_usb_find_clock_selector, - struct uac_clock_selector_descriptor, - validate_clock_selector_v2, UAC2_CLOCK_SELECTOR); -DEFINE_FIND_HELPER(snd_usb_find_clock_selector_v3, - struct uac3_clock_selector_descriptor, - validate_clock_selector_v3, UAC3_CLOCK_SELECTOR); - + union uac23_clock_selector_desc, validate_clock_selector, + UAC2_CLOCK_SELECTOR, UAC3_CLOCK_SELECTOR); DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier, - struct uac_clock_multiplier_descriptor, - validate_clock_multiplier_v2, UAC2_CLOCK_MULTIPLIER); -DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier_v3, - struct uac3_clock_multiplier_descriptor, - validate_clock_multiplier_v3, UAC3_CLOCK_MULTIPLIER); + union uac23_clock_multiplier_desc, validate_clock_multiplier, + UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER); static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) { @@ -159,14 +154,13 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, int count; unsigned char data; struct usb_device *dev = chip->dev; + union uac23_clock_source_desc *cs_desc; - if (fmt->protocol == UAC_VERSION_2) { - struct uac_clock_source_descriptor *cs_desc = - snd_usb_find_clock_source(chip->ctrl_intf, source_id); - - if (!cs_desc) - return false; + cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); + if (!cs_desc) + return false; + if (fmt->protocol == UAC_VERSION_2) { /* * Assume the clock is valid if clock source supports only one * single sample rate, the terminal is connected directly to it @@ -175,8 +169,8 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, * reports that clock is invalid. */ if (fmt->nr_rates == 1 && - (fmt->clock & 0xff) == cs_desc->bClockID && - (cs_desc->bmAttributes & 0x3) != + (fmt->clock & 0xff) == cs_desc->v2.bClockID && + (cs_desc->v2.bmAttributes & 0x3) != UAC_CLOCK_SOURCE_TYPE_EXT) return true; } @@ -222,22 +216,16 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, unsigned char data; struct usb_device *dev = chip->dev; u32 bmControls; + union uac23_clock_source_desc *cs_desc; - if (fmt->protocol == UAC_VERSION_3) { - struct uac3_clock_source_descriptor *cs_desc = - snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id); - - if (!cs_desc) - return false; - bmControls = le32_to_cpu(cs_desc->bmControls); - } else { /* UAC_VERSION_1/2 */ - struct uac_clock_source_descriptor *cs_desc = - snd_usb_find_clock_source(chip->ctrl_intf, source_id); + cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); + if (!cs_desc) + return false; - if (!cs_desc) - return false; - bmControls = cs_desc->bmControls; - } + if (fmt->protocol == UAC_VERSION_3) + bmControls = le32_to_cpu(cs_desc->v3.bmControls); + else + bmControls = cs_desc->v2.bmControls; /* If a clock source can't tell us whether it's valid, we assume it is */ if (!uac_v2v3_control_is_readable(bmControls, @@ -267,9 +255,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, const struct audioformat *fmt, int entity_id, unsigned long *visited, bool validate) { - struct uac_clock_source_descriptor *source; - struct uac_clock_selector_descriptor *selector; - struct uac_clock_multiplier_descriptor *multiplier; + union uac23_clock_source_desc *source; + union uac23_clock_selector_desc *selector; + union uac23_clock_multiplier_desc *multiplier; + int ret, i, cur, err, pins, clock_id; + const u8 *sources; + int proto = fmt->protocol; entity_id &= 0xff; @@ -281,9 +272,9 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, } /* first, see if the ID we're looking for is a clock source already */ - source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); + source = snd_usb_find_clock_source(chip, entity_id, proto); if (source) { - entity_id = source->bClockID; + entity_id = GET_VAL(source, proto, bClockID); if (validate && !uac_clock_source_is_valid(chip, fmt, entity_id)) { usb_audio_err(chip, @@ -294,35 +285,43 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, return entity_id; } - selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); + selector = snd_usb_find_clock_selector(chip, entity_id, proto); if (selector) { - int ret, i, cur, err; + pins = GET_VAL(selector, proto, bNrInPins); + clock_id = GET_VAL(selector, proto, bClockID); + sources = GET_VAL(selector, proto, baCSourceID); + cur = 0; - if (selector->bNrInPins == 1) { + if (pins == 1) { ret = 1; goto find_source; } /* the entity ID we are looking for is a selector. * find out what it currently selects */ - ret = uac_clock_selector_get_val(chip, selector->bClockID); - if (ret < 0) - return ret; + ret = uac_clock_selector_get_val(chip, clock_id); + if (ret < 0) { + if (!chip->autoclock) + return ret; + goto find_others; + } /* Selector values are one-based */ - if (ret > selector->bNrInPins || ret < 1) { + if (ret > pins || ret < 1) { usb_audio_err(chip, "%s(): selector reported illegal value, id %d, ret %d\n", - __func__, selector->bClockID, ret); + __func__, clock_id, ret); - return -EINVAL; + if (!chip->autoclock) + return -EINVAL; + goto find_others; } find_source: cur = ret; ret = __uac_clock_find_source(chip, fmt, - selector->baCSourceID[ret - 1], + sources[ret - 1], visited, validate); if (ret > 0) { err = uac_clock_selector_set_val(chip, entity_id, cur); @@ -333,13 +332,14 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, if (!validate || ret > 0 || !chip->autoclock) return ret; + find_others: /* The current clock source is invalid, try others. */ - for (i = 1; i <= selector->bNrInPins; i++) { + for (i = 1; i <= pins; i++) { if (i == cur) continue; ret = __uac_clock_find_source(chip, fmt, - selector->baCSourceID[i - 1], + sources[i - 1], visited, true); if (ret < 0) continue; @@ -358,116 +358,15 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, } /* FIXME: multipliers only act as pass-thru element for now */ - multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); + multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto); if (multiplier) return __uac_clock_find_source(chip, fmt, - multiplier->bCSourceID, + GET_VAL(multiplier, proto, bCSourceID), visited, validate); return -EINVAL; } -static int __uac3_clock_find_source(struct snd_usb_audio *chip, - const struct audioformat *fmt, int entity_id, - unsigned long *visited, bool validate) -{ - struct uac3_clock_source_descriptor *source; - struct uac3_clock_selector_descriptor *selector; - struct uac3_clock_multiplier_descriptor *multiplier; - - entity_id &= 0xff; - - if (test_and_set_bit(entity_id, visited)) { - usb_audio_warn(chip, - "%s(): recursive clock topology detected, id %d.\n", - __func__, entity_id); - return -EINVAL; - } - - /* first, see if the ID we're looking for is a clock source already */ - source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id); - if (source) { - entity_id = source->bClockID; - if (validate && !uac_clock_source_is_valid(chip, fmt, - entity_id)) { - usb_audio_err(chip, - "clock source %d is not valid, cannot use\n", - entity_id); - return -ENXIO; - } - return entity_id; - } - - selector = snd_usb_find_clock_selector_v3(chip->ctrl_intf, entity_id); - if (selector) { - int ret, i, cur, err; - - /* the entity ID we are looking for is a selector. - * find out what it currently selects */ - ret = uac_clock_selector_get_val(chip, selector->bClockID); - if (ret < 0) - return ret; - - /* Selector values are one-based */ - - if (ret > selector->bNrInPins || ret < 1) { - usb_audio_err(chip, - "%s(): selector reported illegal value, id %d, ret %d\n", - __func__, selector->bClockID, ret); - - return -EINVAL; - } - - cur = ret; - ret = __uac3_clock_find_source(chip, fmt, - selector->baCSourceID[ret - 1], - visited, validate); - if (ret > 0) { - err = uac_clock_selector_set_val(chip, entity_id, cur); - if (err < 0) - return err; - } - - if (!validate || ret > 0 || !chip->autoclock) - return ret; - - /* The current clock source is invalid, try others. */ - for (i = 1; i <= selector->bNrInPins; i++) { - int err; - - if (i == cur) - continue; - - ret = __uac3_clock_find_source(chip, fmt, - selector->baCSourceID[i - 1], - visited, true); - if (ret < 0) - continue; - - err = uac_clock_selector_set_val(chip, entity_id, i); - if (err < 0) - continue; - - usb_audio_info(chip, - "found and selected valid clock source %d\n", - ret); - return ret; - } - - return -ENXIO; - } - - /* FIXME: multipliers only act as pass-thru element for now */ - multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf, - entity_id); - if (multiplier) - return __uac3_clock_find_source(chip, fmt, - multiplier->bCSourceID, - visited, validate); - - return -EINVAL; -} - /* * For all kinds of sample rate settings and other device queries, * the clock source (end-leaf) must be used. However, clock selectors, @@ -487,10 +386,8 @@ int snd_usb_clock_find_source(struct snd_usb_audio *chip, switch (fmt->protocol) { case UAC_VERSION_2: - return __uac_clock_find_source(chip, fmt, fmt->clock, visited, - validate); case UAC_VERSION_3: - return __uac3_clock_find_source(chip, fmt, fmt->clock, visited, + return __uac_clock_find_source(chip, fmt, fmt->clock, visited, validate); default: return -EINVAL; @@ -593,18 +490,13 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, u32 bmControls; __le32 data; int err; + union uac23_clock_source_desc *cs_desc; - if (fmt->protocol == UAC_VERSION_3) { - struct uac3_clock_source_descriptor *cs_desc; - - cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock); - bmControls = le32_to_cpu(cs_desc->bmControls); - } else { - struct uac_clock_source_descriptor *cs_desc; - - cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock); - bmControls = cs_desc->bmControls; - } + cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol); + if (fmt->protocol == UAC_VERSION_3) + bmControls = le32_to_cpu(cs_desc->v3.bmControls); + else + bmControls = cs_desc->v2.bmControls; writeable = uac_v2v3_control_is_writeable(bmControls, UAC2_CS_CONTROL_SAM_FREQ); @@ -642,6 +534,13 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, * rate. */ clock = snd_usb_clock_find_source(chip, fmt, false); + + /* Denon DN-X1600 hardcoded + * Sample rate seems to be set on the hardware itself + */ + if (chip->usb_id == USB_ID(0x154e, 0x500e)) + return 0; + if (clock < 0) return clock; } diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 014c43862826..4f856771216b 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -275,6 +275,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, urb->number_of_packets = ctx->packets; urb->transfer_buffer_length = offs * ep->stride + ctx->packets * extra; + ctx->queued = 0; } /* @@ -644,7 +645,7 @@ static bool endpoint_compatible(struct snd_usb_endpoint *ep, } /* - * Check whether the given fp and hw params are compatbile with the current + * Check whether the given fp and hw params are compatible with the current * setup of the target EP for implicit feedback sync */ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, @@ -1244,7 +1245,7 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, * * This function sets up the EP to be fully usable state. * It's called either from hw_params or prepare callback. - * The function checks need_setup flag, and perfoms nothing unless needed, + * The function checks need_setup flag, and performs nothing unless needed, * so it's safe to call this multiple times. * * This returns zero if unchanged, 1 if the configuration has changed, diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index eea4ca49876d..a668f675b52b 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -19,7 +19,6 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep); int snd_usb_endpoint_configure(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep); -void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep); bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep, diff --git a/sound/usb/format.c b/sound/usb/format.c index 2287f8c65315..eb216fef4ba7 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -223,9 +223,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof continue; /* C-Media CM6501 mislabels its 96 kHz altsetting */ /* Terratec Aureon 7.1 USB C-Media 6206, too */ + /* Ozone Z90 USB C-Media, too */ if (rate == 48000 && nr_rates == 1 && (chip->usb_id == USB_ID(0x0d8c, 0x0201) || chip->usb_id == USB_ID(0x0d8c, 0x0102) || + chip->usb_id == USB_ID(0x0d8c, 0x0078) || chip->usb_id == USB_ID(0x0ccd, 0x00b1)) && fp->altsetting == 5 && fp->maxpacksize == 392) rate = 96000; diff --git a/sound/usb/media.c b/sound/usb/media.c index 812017eacbcf..840f42cb9272 100644 --- a/sound/usb/media.c +++ b/sound/usb/media.c @@ -285,7 +285,7 @@ snd_mixer_init: ret); if (!media_devnode_is_registered(mdev->devnode)) { - /* dont'register if snd_media_mixer_init() failed */ + /* don't register if snd_media_mixer_init() failed */ if (ret) goto create_fail; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 428d581f988f..30b3e128e28d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3294,8 +3294,9 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, struct usb_mixer_elem_list *list) { struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); - static const char * const val_types[] = {"BOOLEAN", "INV_BOOLEAN", - "S8", "U8", "S16", "U16"}; + static const char * const val_types[] = { + "BOOLEAN", "INV_BOOLEAN", "S8", "U8", "S16", "U16", "S32", "U32", + }; snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " "channels=%i, type=\"%s\"\n", cval->head.id, cval->control, cval->cmask, cval->channels, @@ -3605,6 +3606,9 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); int c, err, idx; + if (cval->val_type == USB_MIXER_BESPOKEN) + return 0; + if (cval->cmask) { idx = 0; for (c = 0; c < MAX_CHANNELS; c++) { diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index e5a01f17bf3c..ea41e7a1f7bf 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -55,6 +55,7 @@ enum { USB_MIXER_U16, USB_MIXER_S32, USB_MIXER_U32, + USB_MIXER_BESPOKEN, /* non-standard type */ }; typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 37ad77524c0b..0a3cb8fd7d00 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -3060,6 +3060,12 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */ case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */ case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */ + case USB_ID(0x1235, 0x8211): /* Focusrite Scarlett Solo 3rd Gen */ + case USB_ID(0x1235, 0x8210): /* Focusrite Scarlett 2i2 3rd Gen */ + case USB_ID(0x1235, 0x8212): /* Focusrite Scarlett 4i4 3rd Gen */ + case USB_ID(0x1235, 0x8213): /* Focusrite Scarlett 8i6 3rd Gen */ + case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */ + case USB_ID(0x1235, 0x8215): /* Focusrite Scarlett 18i20 3rd Gen */ err = snd_scarlett_gen2_init(mixer); break; diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c index c53a9773f310..0255089c9efb 100644 --- a/sound/usb/mixer_s1810c.c +++ b/sound/usb/mixer_s1810c.c @@ -163,7 +163,7 @@ snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a, } /* - * When opening Universal Control the program periodicaly + * When opening Universal Control the program periodically * sends and receives state packets for syncinc state between * the device and the host. * diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index 691b95466d0f..0d6e4f15bf77 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c @@ -21,7 +21,7 @@ * Auto-detection via UAC2 is not feasible to properly discover the vast * majority of features. It's related to both Linux/ALSA's UAC2 as well as * Focusrite's implementation of it. Eventually quirks may be sufficient but - * right now it's a major headache to work arount these things. + * right now it's a major headache to work around these things. * * NB. Neither the OSX nor the win driver provided by Focusrite performs * discovery, they seem to operate the same as this driver. diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 4caf379d5b99..f9d698a37153 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -1,8 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Focusrite Scarlett 6i6/18i8/18i20 Gen 2 Driver for ALSA + * Focusrite Scarlett Gen 2/3 Driver for ALSA * - * Copyright (c) 2018-2019 by Geoffrey D. Bennett <g at b4.vu> + * Supported models: + * - 6i6/18i8/18i20 Gen 2 + * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3 + * + * Copyright (c) 2018-2021 by Geoffrey D. Bennett <g at b4.vu> + * Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com> * * Based on the Scarlett (Gen 1) Driver for ALSA: * @@ -19,10 +24,6 @@ * David Henningsson <david.henningsson at canonical.com> */ -/* Mixer Interface for the Focusrite Scarlett 6i6/18i8/18i20 Gen 2 audio - * interface. Based on the Gen 1 driver and rewritten. - */ - /* The protocol was reverse engineered by looking at the communication * between Focusrite Control 2.3.4 and the Focusrite(R) Scarlett 18i20 * (firmware 1083) using usbmon in July-August 2018. @@ -32,12 +33,33 @@ * Scarlett 6i6 support added in June 2019 (thanks to Martin Wittmann * for providing usbmon output and testing). * - * This ALSA mixer gives access to: + * Scarlett 4i4/8i6 Gen 3 support added in May 2020 (thanks to Laurent + * Debricon for donating a 4i4 and to Fredrik Unger for providing 8i6 + * usbmon output and testing). + * + * Scarlett 18i8/18i20 Gen 3 support added in June 2020 (thanks to + * Darren Jaeckel, Alex Sedlack, and Clovis Lunel for providing usbmon + * output, protocol traces and testing). + * + * Support for loading mixer volume and mux configuration from the + * interface during driver initialisation added in May 2021 (thanks to + * Vladimir Sadovnikov for figuring out how). + * + * Support for Solo/2i2 Gen 3 added in May 2021 (thanks to Alexander + * Vorona for 2i2 protocol traces). + * + * Support for phantom power, direct monitoring, speaker switching, + * and talkback added in May-June 2021. + * + * This ALSA mixer gives access to (model-dependent): * - input, output, mixer-matrix muxes - * - 18x10 mixer-matrix gain stages - * - gain/volume controls + * - mixer-matrix gain stages + * - gain/volume/mute controls * - level meters - * - line/inst level and pad controls + * - line/inst level, pad, and air controls + * - phantom power, direct monitor, speaker switching, and talkback + * controls + * - disable/enable MSD mode * * <ditaa> * /--------------\ 18chn 20chn /--------------\ @@ -90,6 +112,14 @@ * \--------------/ * </ditaa> * + * Gen 3 devices have a Mass Storage Device (MSD) mode where a small + * disk with registration and driver download information is presented + * to the host. To access the full functionality of the device without + * proprietary software, MSD mode can be disabled by: + * - holding down the 48V button for five seconds while powering on + * the device, or + * - using this driver and alsamixer to change the "MSD Mode" setting + * to Off and power-cycling the device */ #include <linux/slab.h> @@ -108,6 +138,9 @@ /* device_setup value to enable */ #define SCARLETT2_ENABLE 0x01 +/* device_setup value to allow turning MSD mode back on */ +#define SCARLETT2_MSD_ENABLE 0x02 + /* some gui mixers can't handle negative ctl values */ #define SCARLETT2_VOLUME_BIAS 127 @@ -117,11 +150,12 @@ #define SCARLETT2_MIXER_MAX_DB 6 #define SCARLETT2_MIXER_MAX_VALUE \ ((SCARLETT2_MIXER_MAX_DB - SCARLETT2_MIXER_MIN_DB) * 2) +#define SCARLETT2_MIXER_VALUE_COUNT (SCARLETT2_MIXER_MAX_VALUE + 1) /* map from (dB + 80) * 2 to mixer value * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20))) */ -static const u16 scarlett2_mixer_values[173] = { +static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, @@ -143,23 +177,23 @@ static const u16 scarlett2_mixer_values[173] = { /* Maximum number of level and pad switches */ #define SCARLETT2_LEVEL_SWITCH_MAX 2 -#define SCARLETT2_PAD_SWITCH_MAX 4 +#define SCARLETT2_PAD_SWITCH_MAX 8 +#define SCARLETT2_AIR_SWITCH_MAX 8 +#define SCARLETT2_PHANTOM_SWITCH_MAX 2 /* Maximum number of inputs to the mixer */ -#define SCARLETT2_INPUT_MIX_MAX 18 +#define SCARLETT2_INPUT_MIX_MAX 25 /* Maximum number of outputs from the mixer */ -#define SCARLETT2_OUTPUT_MIX_MAX 10 +#define SCARLETT2_OUTPUT_MIX_MAX 12 /* Maximum size of the data in the USB mux assignment message: - * 18 inputs, 20 outputs, 18 matrix inputs, 8 spare + * 20 inputs, 20 outputs, 25 matrix inputs, 12 spare */ -#define SCARLETT2_MUX_MAX 64 +#define SCARLETT2_MUX_MAX 77 -/* Number of meters: - * 18 inputs, 20 outputs, 18 matrix inputs - */ -#define SCARLETT2_NUM_METERS 56 +/* Maximum number of meters (sum of output port counts) */ +#define SCARLETT2_MAX_METERS 65 /* Hardware port types: * - None (no input to mux) @@ -170,74 +204,219 @@ static const u16 scarlett2_mixer_values[173] = { * - PCM I/O */ enum { - SCARLETT2_PORT_TYPE_NONE = 0, + SCARLETT2_PORT_TYPE_NONE = 0, SCARLETT2_PORT_TYPE_ANALOGUE = 1, - SCARLETT2_PORT_TYPE_SPDIF = 2, - SCARLETT2_PORT_TYPE_ADAT = 3, - SCARLETT2_PORT_TYPE_MIX = 4, - SCARLETT2_PORT_TYPE_PCM = 5, - SCARLETT2_PORT_TYPE_COUNT = 6, + SCARLETT2_PORT_TYPE_SPDIF = 2, + SCARLETT2_PORT_TYPE_ADAT = 3, + SCARLETT2_PORT_TYPE_MIX = 4, + SCARLETT2_PORT_TYPE_PCM = 5, + SCARLETT2_PORT_TYPE_COUNT = 6, }; -/* Count of total I/O and number available at each sample rate */ +/* I/O count of each port type kept in struct scarlett2_ports */ enum { - SCARLETT2_PORT_IN = 0, - SCARLETT2_PORT_OUT = 1, - SCARLETT2_PORT_OUT_44 = 2, - SCARLETT2_PORT_OUT_88 = 3, - SCARLETT2_PORT_OUT_176 = 4, - SCARLETT2_PORT_DIRECTIONS = 5, + SCARLETT2_PORT_IN = 0, + SCARLETT2_PORT_OUT = 1, + SCARLETT2_PORT_DIRNS = 2, }; -/* Hardware buttons on the 18i20 */ -#define SCARLETT2_BUTTON_MAX 2 +/* Dim/Mute buttons on the 18i20 */ +enum { + SCARLETT2_BUTTON_MUTE = 0, + SCARLETT2_BUTTON_DIM = 1, + SCARLETT2_DIM_MUTE_COUNT = 2, +}; -static const char *const scarlett2_button_names[SCARLETT2_BUTTON_MAX] = { +static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = { "Mute", "Dim" }; /* Description of each hardware port type: - * - id: hardware ID for this port type - * - num: number of sources/destinations of this port type + * - id: hardware ID of this port type * - src_descr: printf format string for mux input selections * - src_num_offset: added to channel number for the fprintf * - dst_descr: printf format string for mixer controls */ -struct scarlett2_ports { +struct scarlett2_port { u16 id; - int num[SCARLETT2_PORT_DIRECTIONS]; const char * const src_descr; int src_num_offset; const char * const dst_descr; }; +static const struct scarlett2_port scarlett2_ports[SCARLETT2_PORT_TYPE_COUNT] = { + [SCARLETT2_PORT_TYPE_NONE] = { + .id = 0x000, + .src_descr = "Off" + }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { + .id = 0x080, + .src_descr = "Analogue %d", + .src_num_offset = 1, + .dst_descr = "Analogue Output %02d Playback" + }, + [SCARLETT2_PORT_TYPE_SPDIF] = { + .id = 0x180, + .src_descr = "S/PDIF %d", + .src_num_offset = 1, + .dst_descr = "S/PDIF Output %d Playback" + }, + [SCARLETT2_PORT_TYPE_ADAT] = { + .id = 0x200, + .src_descr = "ADAT %d", + .src_num_offset = 1, + .dst_descr = "ADAT Output %d Playback" + }, + [SCARLETT2_PORT_TYPE_MIX] = { + .id = 0x300, + .src_descr = "Mix %c", + .src_num_offset = 'A', + .dst_descr = "Mixer Input %02d Capture" + }, + [SCARLETT2_PORT_TYPE_PCM] = { + .id = 0x600, + .src_descr = "PCM %d", + .src_num_offset = 1, + .dst_descr = "PCM %02d Capture" + }, +}; + +/* Number of mux tables: one for each band of sample rates + * (44.1/48kHz, 88.2/96kHz, and 176.4/176kHz) + */ +#define SCARLETT2_MUX_TABLES 3 + +/* Maximum number of entries in a mux table */ +#define SCARLETT2_MAX_MUX_ENTRIES 10 + +/* One entry within mux_assignment defines the port type and range of + * ports to add to the set_mux message. The end of the list is marked + * with count == 0. + */ +struct scarlett2_mux_entry { + u8 port_type; + u8 start; + u8 count; +}; + struct scarlett2_device_info { - u8 line_out_hw_vol; /* line out hw volume is sw controlled */ - u8 button_count; /* number of buttons */ - u8 level_input_count; /* inputs with level selectable */ - u8 pad_input_count; /* inputs with pad selectable */ + u32 usb_id; /* USB device identifier */ + + /* Gen 3 devices have an internal MSD mode switch that needs + * to be disabled in order to access the full functionality of + * the device. + */ + u8 has_msd_mode; + + /* Gen 3 devices without a mixer have a different + * configuration set + */ + u8 has_mixer; + + /* line out hw volume is sw controlled */ + u8 line_out_hw_vol; + + /* support for main/alt speaker switching */ + u8 has_speaker_switching; + + /* support for talkback microphone */ + u8 has_talkback; + + /* the number of analogue inputs with a software switchable + * level control that can be set to line or instrument + */ + u8 level_input_count; + + /* the first input with a level control (0-based) */ + u8 level_input_first; + + /* the number of analogue inputs with a software switchable + * 10dB pad control + */ + u8 pad_input_count; + + /* the number of analogue inputs with a software switchable + * "air" control + */ + u8 air_input_count; + + /* the number of phantom (48V) software switchable controls */ + u8 phantom_count; + + /* the number of inputs each phantom switch controls */ + u8 inputs_per_phantom; + + /* the number of direct monitor options + * (0 = none, 1 = mono only, 2 = mono/stereo) + */ + u8 direct_monitor; + + /* remap analogue outputs; 18i8 Gen 3 has "line 3/4" connected + * internally to the analogue 7/8 outputs + */ + u8 line_out_remap_enable; + u8 line_out_remap[SCARLETT2_ANALOGUE_MAX]; + + /* additional description for the line out volume controls */ const char * const line_out_descrs[SCARLETT2_ANALOGUE_MAX]; - struct scarlett2_ports ports[SCARLETT2_PORT_TYPE_COUNT]; + + /* number of sources/destinations of each port type */ + const int port_count[SCARLETT2_PORT_TYPE_COUNT][SCARLETT2_PORT_DIRNS]; + + /* layout/order of the entries in the set_mux message */ + struct scarlett2_mux_entry mux_assignment[SCARLETT2_MUX_TABLES] + [SCARLETT2_MAX_MUX_ENTRIES]; }; -struct scarlett2_mixer_data { +struct scarlett2_data { struct usb_mixer_interface *mixer; struct mutex usb_mutex; /* prevent sending concurrent USB requests */ struct mutex data_mutex; /* lock access to this data */ struct delayed_work work; const struct scarlett2_device_info *info; + __u8 bInterfaceNumber; + __u8 bEndpointAddress; + __u16 wMaxPacketSize; + __u8 bInterval; int num_mux_srcs; + int num_mux_dsts; u16 scarlett2_seq; + u8 sync_updated; u8 vol_updated; + u8 input_other_updated; + u8 monitor_other_updated; + u8 mux_updated; + u8 speaker_switching_switched; + u8 sync; u8 master_vol; u8 vol[SCARLETT2_ANALOGUE_MAX]; u8 vol_sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; + u8 mute_switch[SCARLETT2_ANALOGUE_MAX]; u8 level_switch[SCARLETT2_LEVEL_SWITCH_MAX]; u8 pad_switch[SCARLETT2_PAD_SWITCH_MAX]; - u8 buttons[SCARLETT2_BUTTON_MAX]; + u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; + u8 air_switch[SCARLETT2_AIR_SWITCH_MAX]; + u8 phantom_switch[SCARLETT2_PHANTOM_SWITCH_MAX]; + u8 phantom_persistence; + u8 direct_monitor_switch; + u8 speaker_switching_switch; + u8 talkback_switch; + u8 talkback_map[SCARLETT2_OUTPUT_MIX_MAX]; + u8 msd_switch; + struct snd_kcontrol *sync_ctl; struct snd_kcontrol *master_vol_ctl; struct snd_kcontrol *vol_ctls[SCARLETT2_ANALOGUE_MAX]; - struct snd_kcontrol *button_ctls[SCARLETT2_BUTTON_MAX]; + struct snd_kcontrol *sw_hw_ctls[SCARLETT2_ANALOGUE_MAX]; + struct snd_kcontrol *mute_ctls[SCARLETT2_ANALOGUE_MAX]; + struct snd_kcontrol *dim_mute_ctls[SCARLETT2_DIM_MUTE_COUNT]; + struct snd_kcontrol *level_ctls[SCARLETT2_LEVEL_SWITCH_MAX]; + struct snd_kcontrol *pad_ctls[SCARLETT2_PAD_SWITCH_MAX]; + struct snd_kcontrol *air_ctls[SCARLETT2_AIR_SWITCH_MAX]; + struct snd_kcontrol *phantom_ctls[SCARLETT2_PHANTOM_SWITCH_MAX]; + struct snd_kcontrol *mux_ctls[SCARLETT2_MUX_MAX]; + struct snd_kcontrol *direct_monitor_ctl; + struct snd_kcontrol *speaker_switching_ctl; + struct snd_kcontrol *talkback_ctl; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_INPUT_MIX_MAX * SCARLETT2_OUTPUT_MIX_MAX]; }; @@ -245,66 +424,56 @@ struct scarlett2_mixer_data { /*** Model-specific data ***/ static const struct scarlett2_device_info s6i6_gen2_info = { - /* The first two analogue inputs can be switched between line - * and instrument levels. - */ - .level_input_count = 2, + .usb_id = USB_ID(0x1235, 0x8203), - /* The first two analogue inputs have an optional pad. */ + .has_mixer = 1, + .level_input_count = 2, .pad_input_count = 2, .line_out_descrs = { - "Monitor L", - "Monitor R", - "Headphones L", - "Headphones R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0, 8, 8, 8 }, - .src_descr = "Off", - .src_num_offset = 0, - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 4, 4, 4, 4, 4 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - .id = 0x180, - .num = { 2, 2, 2, 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 6, 6, 6, 6, 6 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 6, 6 }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + } }, }; static const struct scarlett2_device_info s18i8_gen2_info = { - /* The first two analogue inputs can be switched between line - * and instrument levels. - */ - .level_input_count = 2, + .usb_id = USB_ID(0x1235, 0x8204), - /* The first four analogue inputs have an optional pad. */ + .has_mixer = 1, + .level_input_count = 2, .pad_input_count = 4, .line_out_descrs = { @@ -316,62 +485,44 @@ static const struct scarlett2_device_info s18i8_gen2_info = { "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0, 8, 8, 4 }, - .src_descr = "Off", - .src_num_offset = 0, - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 8, 6, 6, 6, 6 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - .id = 0x180, - /* S/PDIF outputs aren't available at 192kHz - * but are included in the USB mux I/O - * assignment message anyway - */ - .num = { 2, 2, 2, 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_ADAT] = { - .id = 0x200, - .num = { 8, 0, 0, 0, 0 }, - .src_descr = "ADAT %d", - .src_num_offset = 1, - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 20, 18, 18, 14, 10 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 6 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 8, 18 }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 18 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 14 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 4 }, + { 0, 0, 0 }, + } }, }; static const struct scarlett2_device_info s18i20_gen2_info = { - /* The analogue line outputs on the 18i20 can be switched - * between software and hardware volume control - */ - .line_out_hw_vol = 1, + .usb_id = USB_ID(0x1235, 0x8201), - /* Mute and dim buttons */ - .button_count = 2, + .has_mixer = 1, + .line_out_hw_vol = 1, .line_out_descrs = { "Monitor L", @@ -386,99 +537,364 @@ static const struct scarlett2_device_info s18i20_gen2_info = { "Headphones 2 R", }, - .ports = { - [SCARLETT2_PORT_TYPE_NONE] = { - .id = 0x000, - .num = { 1, 0, 8, 8, 6 }, - .src_descr = "Off", - .src_num_offset = 0, - }, - [SCARLETT2_PORT_TYPE_ANALOGUE] = { - .id = 0x080, - .num = { 8, 10, 10, 10, 10 }, - .src_descr = "Analogue %d", - .src_num_offset = 1, - .dst_descr = "Analogue Output %02d Playback" - }, - [SCARLETT2_PORT_TYPE_SPDIF] = { - /* S/PDIF outputs aren't available at 192kHz - * but are included in the USB mux I/O - * assignment message anyway - */ - .id = 0x180, - .num = { 2, 2, 2, 2, 2 }, - .src_descr = "S/PDIF %d", - .src_num_offset = 1, - .dst_descr = "S/PDIF Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_ADAT] = { - .id = 0x200, - .num = { 8, 8, 8, 4, 0 }, - .src_descr = "ADAT %d", - .src_num_offset = 1, - .dst_descr = "ADAT Output %d Playback" - }, - [SCARLETT2_PORT_TYPE_MIX] = { - .id = 0x300, - .num = { 10, 18, 18, 18, 18 }, - .src_descr = "Mix %c", - .src_num_offset = 65, - .dst_descr = "Mixer Input %02d Capture" - }, - [SCARLETT2_PORT_TYPE_PCM] = { - .id = 0x600, - .num = { 20, 18, 18, 14, 10 }, - .src_descr = "PCM %d", - .src_num_offset = 1, - .dst_descr = "PCM %02d Capture" - }, + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 10 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 }, + [SCARLETT2_PORT_TYPE_PCM] = { 20, 18 }, }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 18 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 14 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 8 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 18 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 6 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info solo_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8211), + + .has_msd_mode = 1, + .level_input_count = 1, + .level_input_first = 1, + .air_input_count = 1, + .phantom_count = 1, + .inputs_per_phantom = 1, + .direct_monitor = 1, +}; + +static const struct scarlett2_device_info s2i2_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8210), + + .has_msd_mode = 1, + .level_input_count = 2, + .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, + .direct_monitor = 2, +}; + +static const struct scarlett2_device_info s4i4_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8212), + + .has_msd_mode = 1, + .has_mixer = 1, + .level_input_count = 2, + .pad_input_count = 2, + .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Headphones L", + "Headphones R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 4, 4 }, + [SCARLETT2_PORT_TYPE_MIX] = { 6, 8 }, + [SCARLETT2_PORT_TYPE_PCM] = { 4, 6 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 6 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 16 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s8i6_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8213), + + .has_msd_mode = 1, + .has_mixer = 1, + .level_input_count = 2, + .pad_input_count = 2, + .air_input_count = 2, + .phantom_count = 1, + .inputs_per_phantom = 2, + + .line_out_descrs = { + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 6, 4 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_MIX] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_PCM] = { 6, 10 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 8 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 18 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s18i8_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8214), + + .has_msd_mode = 1, + .has_mixer = 1, + .line_out_hw_vol = 1, + .has_speaker_switching = 1, + .level_input_count = 2, + .pad_input_count = 4, + .air_input_count = 4, + .phantom_count = 2, + .inputs_per_phantom = 2, + + .line_out_remap_enable = 1, + .line_out_remap = { 0, 1, 6, 7, 2, 3, 4, 5 }, + + .line_out_descrs = { + "Monitor L", + "Monitor R", + "Alt Monitor L", + "Alt Monitor R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 }, + [SCARLETT2_PORT_TYPE_MIX] = { 10, 20 }, + [SCARLETT2_PORT_TYPE_PCM] = { 8, 20 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_PCM, 12, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_PCM, 12, 4 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 6, 2 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 2, 4 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 20 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info s18i20_gen3_info = { + .usb_id = USB_ID(0x1235, 0x8215), + + .has_msd_mode = 1, + .has_mixer = 1, + .line_out_hw_vol = 1, + .has_speaker_switching = 1, + .has_talkback = 1, + .level_input_count = 2, + .pad_input_count = 8, + .air_input_count = 8, + .phantom_count = 2, + .inputs_per_phantom = 4, + + .line_out_descrs = { + "Monitor 1 L", + "Monitor 1 R", + "Monitor 2 L", + "Monitor 2 R", + NULL, + NULL, + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", + }, + + .port_count = { + [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 }, + [SCARLETT2_PORT_TYPE_ANALOGUE] = { 9, 10 }, + [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 }, + [SCARLETT2_PORT_TYPE_ADAT] = { 8, 8 }, + [SCARLETT2_PORT_TYPE_MIX] = { 12, 25 }, + [SCARLETT2_PORT_TYPE_PCM] = { 20, 20 }, + }, + + .mux_assignment = { { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 25 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 12 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 10, 8 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_ADAT, 0, 8 }, + { SCARLETT2_PORT_TYPE_PCM, 8, 2 }, + { SCARLETT2_PORT_TYPE_MIX, 0, 25 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 10 }, + { 0, 0, 0 }, + }, { + { SCARLETT2_PORT_TYPE_PCM, 0, 10 }, + { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 10 }, + { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 }, + { SCARLETT2_PORT_TYPE_NONE, 0, 24 }, + { 0, 0, 0 }, + } }, +}; + +static const struct scarlett2_device_info *scarlett2_devices[] = { + /* Supported Gen 2 devices */ + &s6i6_gen2_info, + &s18i8_gen2_info, + &s18i20_gen2_info, + + /* Supported Gen 3 devices */ + &solo_gen3_info, + &s2i2_gen3_info, + &s4i4_gen3_info, + &s8i6_gen3_info, + &s18i8_gen3_info, + &s18i20_gen3_info, + + /* End of list */ + NULL }; /* get the starting port index number for a given port type/direction */ -static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, - int direction, int port_type) +static int scarlett2_get_port_start_num( + const int port_count[][SCARLETT2_PORT_DIRNS], + int direction, int port_type) { int i, num = 0; for (i = 0; i < port_type; i++) - num += ports[i].num[direction]; + num += port_count[i][direction]; return num; } /*** USB Interactions ***/ -/* Vendor-Specific Interface, Endpoint, MaxPacketSize, Interval */ -#define SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE 5 -#define SCARLETT2_USB_INTERRUPT_ENDPOINT 4 -#define SCARLETT2_USB_INTERRUPT_MAX_DATA 64 -#define SCARLETT2_USB_INTERRUPT_INTERVAL 3 - -/* Interrupt flags for volume and mute/dim button changes */ -#define SCARLETT2_USB_INTERRUPT_VOL_CHANGE 0x400000 -#define SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE 0x200000 +/* Notifications from the interface */ +#define SCARLETT2_USB_NOTIFY_SYNC 0x00000008 +#define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 +#define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 +#define SCARLETT2_USB_NOTIFY_INPUT_OTHER 0x00800000 +#define SCARLETT2_USB_NOTIFY_MONITOR_OTHER 0x01000000 /* Commands for sending/receiving requests/responses */ -#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ 2 -#define SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP 3 - -#define SCARLETT2_USB_INIT_SEQ 0x00000000 -#define SCARLETT2_USB_GET_METER_LEVELS 0x00001001 -#define SCARLETT2_USB_SET_MIX 0x00002002 -#define SCARLETT2_USB_SET_MUX 0x00003002 -#define SCARLETT2_USB_GET_DATA 0x00800000 -#define SCARLETT2_USB_SET_DATA 0x00800001 -#define SCARLETT2_USB_DATA_CMD 0x00800002 +#define SCARLETT2_USB_CMD_INIT 0 +#define SCARLETT2_USB_CMD_REQ 2 +#define SCARLETT2_USB_CMD_RESP 3 + +#define SCARLETT2_USB_INIT_1 0x00000000 +#define SCARLETT2_USB_INIT_2 0x00000002 +#define SCARLETT2_USB_GET_METER 0x00001001 +#define SCARLETT2_USB_GET_MIX 0x00002001 +#define SCARLETT2_USB_SET_MIX 0x00002002 +#define SCARLETT2_USB_GET_MUX 0x00003001 +#define SCARLETT2_USB_SET_MUX 0x00003002 +#define SCARLETT2_USB_GET_SYNC 0x00006004 +#define SCARLETT2_USB_GET_DATA 0x00800000 +#define SCARLETT2_USB_SET_DATA 0x00800001 +#define SCARLETT2_USB_DATA_CMD 0x00800002 + #define SCARLETT2_USB_CONFIG_SAVE 6 #define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31 #define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1 -/* volume status is read together (matches scarlett2_config_items[]) */ +/* volume status is read together (matches scarlett2_config_items[1]) */ struct scarlett2_usb_volume_status { - /* mute & dim buttons */ - u8 buttons[SCARLETT2_BUTTON_MAX]; + /* dim/mute buttons */ + u8 dim_mute[SCARLETT2_DIM_MUTE_COUNT]; u8 pad1; @@ -488,7 +904,8 @@ struct scarlett2_usb_volume_status { /* actual volume of output inc. dim (-18dB) */ s16 hw_vol[SCARLETT2_ANALOGUE_MAX]; - u8 pad2[SCARLETT2_ANALOGUE_MAX]; + /* internal mute buttons */ + u8 mute_switch[SCARLETT2_ANALOGUE_MAX]; /* sw (0) or hw (1) controlled */ u8 sw_hw_switch[SCARLETT2_ANALOGUE_MAX]; @@ -501,16 +918,25 @@ struct scarlett2_usb_volume_status { /* Configuration parameters that can be read and written */ enum { - SCARLETT2_CONFIG_BUTTONS = 0, + SCARLETT2_CONFIG_DIM_MUTE = 0, SCARLETT2_CONFIG_LINE_OUT_VOLUME = 1, - SCARLETT2_CONFIG_SW_HW_SWITCH = 2, - SCARLETT2_CONFIG_LEVEL_SWITCH = 3, - SCARLETT2_CONFIG_PAD_SWITCH = 4, - SCARLETT2_CONFIG_COUNT = 5 + SCARLETT2_CONFIG_MUTE_SWITCH = 2, + SCARLETT2_CONFIG_SW_HW_SWITCH = 3, + SCARLETT2_CONFIG_LEVEL_SWITCH = 4, + SCARLETT2_CONFIG_PAD_SWITCH = 5, + SCARLETT2_CONFIG_MSD_SWITCH = 6, + SCARLETT2_CONFIG_AIR_SWITCH = 7, + SCARLETT2_CONFIG_PHANTOM_SWITCH = 8, + SCARLETT2_CONFIG_PHANTOM_PERSISTENCE = 9, + SCARLETT2_CONFIG_DIRECT_MONITOR = 10, + SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH = 11, + SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE = 12, + SCARLETT2_CONFIG_TALKBACK_MAP = 13, + SCARLETT2_CONFIG_COUNT = 14 }; /* Location, size, and activation command number for the configuration - * parameters + * parameters. Size is in bits and may be 1, 8, or 16. */ struct scarlett2_config { u8 offset; @@ -518,43 +944,73 @@ struct scarlett2_config { u8 activate; }; +/* scarlett2_config_items[0] is for devices without a mixer + * scarlett2_config_items[1] is for devices with a mixer + */ static const struct scarlett2_config - scarlett2_config_items[SCARLETT2_CONFIG_COUNT] = { - /* Mute/Dim Buttons */ - { - .offset = 0x31, - .size = 1, - .activate = 2 - }, + scarlett2_config_items[2][SCARLETT2_CONFIG_COUNT] = - /* Line Out Volume */ - { - .offset = 0x34, - .size = 2, - .activate = 1 - }, +/* Devices without a mixer (Solo and 2i2 Gen 3) */ +{ { + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x04, .size = 8, .activate = 6 }, - /* SW/HW Volume Switch */ - { - .offset = 0x66, - .size = 1, - .activate = 3 - }, + [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = { + .offset = 0x05, .size = 8, .activate = 6 }, - /* Level Switch */ - { - .offset = 0x7c, - .size = 1, - .activate = 7 - }, + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x06, .size = 8, .activate = 3 }, - /* Pad Switch */ - { - .offset = 0x84, - .size = 1, - .activate = 8 - } -}; + [SCARLETT2_CONFIG_DIRECT_MONITOR] = { + .offset = 0x07, .size = 8, .activate = 4 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x08, .size = 1, .activate = 7 }, + + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x09, .size = 1, .activate = 8 }, + +/* Devices with a mixer (Gen 2 and all other Gen 3) */ +}, { + [SCARLETT2_CONFIG_DIM_MUTE] = { + .offset = 0x31, .size = 8, .activate = 2 }, + + [SCARLETT2_CONFIG_LINE_OUT_VOLUME] = { + .offset = 0x34, .size = 16, .activate = 1 }, + + [SCARLETT2_CONFIG_MUTE_SWITCH] = { + .offset = 0x5c, .size = 8, .activate = 1 }, + + [SCARLETT2_CONFIG_SW_HW_SWITCH] = { + .offset = 0x66, .size = 8, .activate = 3 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x7c, .size = 8, .activate = 7 }, + + [SCARLETT2_CONFIG_PAD_SWITCH] = { + .offset = 0x84, .size = 8, .activate = 8 }, + + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x8c, .size = 8, .activate = 8 }, + + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x9c, .size = 1, .activate = 8 }, + + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x9d, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_PHANTOM_PERSISTENCE] = { + .offset = 0x9e, .size = 8, .activate = 6 }, + + [SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH] = { + .offset = 0x9f, .size = 1, .activate = 10 }, + + [SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE] = { + .offset = 0xa0, .size = 1, .activate = 10 }, + + [SCARLETT2_CONFIG_TALKBACK_MAP] = { + .offset = 0xb0, .size = 16, .activate = 10 }, +} }; /* proprietary request/response format */ struct scarlett2_usb_packet { @@ -566,9 +1022,7 @@ struct scarlett2_usb_packet { u8 data[]; }; -#define SCARLETT2_USB_PACKET_LEN (sizeof(struct scarlett2_usb_packet)) - -static void scarlett2_fill_request_header(struct scarlett2_mixer_data *private, +static void scarlett2_fill_request_header(struct scarlett2_data *private, struct scarlett2_usb_packet *req, u32 cmd, u16 req_size) { @@ -582,16 +1036,35 @@ static void scarlett2_fill_request_header(struct scarlett2_mixer_data *private, req->pad = 0; } +static int scarlett2_usb_tx(struct usb_device *dev, int interface, + void *buf, u16 size) +{ + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + SCARLETT2_USB_CMD_REQ, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + 0, interface, buf, size); +} + +static int scarlett2_usb_rx(struct usb_device *dev, int interface, + u32 usb_req, void *buf, u16 size) +{ + return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), + usb_req, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + 0, interface, buf, size); +} + /* Send a proprietary format request to the Scarlett interface */ static int scarlett2_usb( struct usb_mixer_interface *mixer, u32 cmd, void *req_data, u16 req_size, void *resp_data, u16 resp_size) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; + struct usb_device *dev = mixer->chip->dev; u16 req_buf_size = sizeof(struct scarlett2_usb_packet) + req_size; u16 resp_buf_size = sizeof(struct scarlett2_usb_packet) + resp_size; - struct scarlett2_usb_packet *req = NULL, *resp = NULL; - int err = 0; + struct scarlett2_usb_packet *req, *resp = NULL; + int err; req = kmalloc(req_buf_size, GFP_KERNEL); if (!req) { @@ -614,19 +1087,13 @@ static int scarlett2_usb( if (req_size) memcpy(req->data, req_data, req_size); - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_sndctrlpipe(mixer->chip->dev, 0), - SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - 0, - SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, - req, - req_buf_size); + err = scarlett2_usb_tx(dev, private->bInterfaceNumber, + req, req_buf_size); if (err != req_buf_size) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB request result cmd %x was %d\n", + "Scarlett Gen 2/3 USB request result cmd %x was %d\n", cmd, err); err = -EINVAL; goto unlock; @@ -634,34 +1101,34 @@ static int scarlett2_usb( /* send a second message to get the response */ - err = snd_usb_ctl_msg(mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), - SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP, - USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - 0, - SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, - resp, - resp_buf_size); + err = scarlett2_usb_rx(dev, private->bInterfaceNumber, + SCARLETT2_USB_CMD_RESP, + resp, resp_buf_size); /* validate the response */ if (err != resp_buf_size) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB response result cmd %x was %d\n", - cmd, err); + "Scarlett Gen 2/3 USB response result cmd %x was %d " + "expected %d\n", + cmd, err, resp_buf_size); err = -EINVAL; goto unlock; } + /* cmd/seq/size should match except when initialising + * seq sent = 1, response = 0 + */ if (resp->cmd != req->cmd || - resp->seq != req->seq || + (resp->seq != req->seq && + (le16_to_cpu(req->seq) != 1 || resp->seq != 0)) || resp_size != le16_to_cpu(resp->size) || resp->error || resp->pad) { usb_audio_err( mixer->chip, - "Scarlett Gen 2 USB invalid response; " + "Scarlett Gen 2/3 USB invalid response; " "cmd tx/rx %d/%d seq %d/%d size %d/%d " "error %d pad %d\n", le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd), @@ -673,7 +1140,7 @@ static int scarlett2_usb( goto unlock; } - if (resp_size > 0) + if (resp_data && resp_size > 0) memcpy(resp_data, resp->data, resp_size); unlock: @@ -684,6 +1151,63 @@ error: return err; } +/* Send a USB message to get data; result placed in *buf */ +static int scarlett2_usb_get( + struct usb_mixer_interface *mixer, + int offset, void *buf, int size) +{ + struct { + __le32 offset; + __le32 size; + } __packed req; + + req.offset = cpu_to_le32(offset); + req.size = cpu_to_le32(size); + return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, + &req, sizeof(req), buf, size); +} + +/* Send a USB message to get configuration parameters; result placed in *buf */ +static int scarlett2_usb_get_config( + struct usb_mixer_interface *mixer, + int config_item_num, int count, void *buf) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_config *config_item = + &scarlett2_config_items[info->has_mixer][config_item_num]; + int size, err, i; + u8 *buf_8; + u8 value; + + /* For byte-sized parameters, retrieve directly into buf */ + if (config_item->size >= 8) { + size = config_item->size / 8 * count; + err = scarlett2_usb_get(mixer, config_item->offset, buf, size); + if (err < 0) + return err; + if (size == 2) { + u16 *buf_16 = buf; + + for (i = 0; i < count; i++, buf_16++) + *buf_16 = le16_to_cpu(*(__le16 *)buf_16); + } + return 0; + } + + /* For bit-sized parameters, retrieve into value */ + err = scarlett2_usb_get(mixer, config_item->offset, &value, 1); + if (err < 0) + return err; + + /* then unpack from value into buf[] */ + buf_8 = buf; + for (i = 0; i < 8 && i < count; i++, value >>= 1) + *buf_8++ = value & 1; + + return 0; +} + /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */ static void scarlett2_config_save(struct usb_mixer_interface *mixer) { @@ -697,82 +1221,97 @@ static void scarlett2_config_save(struct usb_mixer_interface *mixer) /* Delayed work to save config */ static void scarlett2_config_save_work(struct work_struct *work) { - struct scarlett2_mixer_data *private = - container_of(work, struct scarlett2_mixer_data, work.work); + struct scarlett2_data *private = + container_of(work, struct scarlett2_data, work.work); scarlett2_config_save(private->mixer); } -/* Send a USB message to set a configuration parameter (volume level, - * sw/hw volume switch, line/inst level switch, or pad switch) - */ +/* Send a USB message to set a SCARLETT2_CONFIG_* parameter */ static int scarlett2_usb_set_config( struct usb_mixer_interface *mixer, int config_item_num, int index, int value) { - const struct scarlett2_config config_item = - scarlett2_config_items[config_item_num]; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const struct scarlett2_config *config_item = + &scarlett2_config_items[info->has_mixer][config_item_num]; struct { __le32 offset; __le32 bytes; __le32 value; } __packed req; __le32 req2; + int offset, size; int err; - struct scarlett2_mixer_data *private = mixer->private_data; /* Cancel any pending NVRAM save */ cancel_delayed_work_sync(&private->work); + /* Convert config_item->size in bits to size in bytes and + * calculate offset + */ + if (config_item->size >= 8) { + size = config_item->size / 8; + offset = config_item->offset + index * size; + + /* If updating a bit, retrieve the old value, set/clear the + * bit as needed, and update value + */ + } else { + u8 tmp; + + size = 1; + offset = config_item->offset; + + scarlett2_usb_get(mixer, offset, &tmp, 1); + if (value) + tmp |= (1 << index); + else + tmp &= ~(1 << index); + + value = tmp; + } + /* Send the configuration parameter data */ - req.offset = cpu_to_le32(config_item.offset + index * config_item.size); - req.bytes = cpu_to_le32(config_item.size); + req.offset = cpu_to_le32(offset); + req.bytes = cpu_to_le32(size); req.value = cpu_to_le32(value); err = scarlett2_usb(mixer, SCARLETT2_USB_SET_DATA, - &req, sizeof(u32) * 2 + config_item.size, + &req, sizeof(u32) * 2 + size, NULL, 0); if (err < 0) return err; /* Activate the change */ - req2 = cpu_to_le32(config_item.activate); + req2 = cpu_to_le32(config_item->activate); err = scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD, &req2, sizeof(req2), NULL, 0); if (err < 0) return err; /* Schedule the change to be written to NVRAM */ - schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); + if (config_item->activate != SCARLETT2_USB_CONFIG_SAVE) + schedule_delayed_work(&private->work, msecs_to_jiffies(2000)); return 0; } -/* Send a USB message to get data; result placed in *buf */ -static int scarlett2_usb_get( +/* Send a USB message to get sync status; result placed in *sync */ +static int scarlett2_usb_get_sync_status( struct usb_mixer_interface *mixer, - int offset, void *buf, int size) + u8 *sync) { - struct { - __le32 offset; - __le32 size; - } __packed req; - - req.offset = cpu_to_le32(offset); - req.size = cpu_to_le32(size); - return scarlett2_usb(mixer, SCARLETT2_USB_GET_DATA, - &req, sizeof(req), buf, size); -} + __le32 data; + int err; -/* Send a USB message to get configuration parameters; result placed in *buf */ -static int scarlett2_usb_get_config( - struct usb_mixer_interface *mixer, - int config_item_num, int count, void *buf) -{ - const struct scarlett2_config config_item = - scarlett2_config_items[config_item_num]; - int size = config_item.size * count; + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_SYNC, + NULL, 0, &data, sizeof(data)); + if (err < 0) + return err; - return scarlett2_usb_get(mixer, config_item.offset, buf, size); + *sync = !!data; + return 0; } /* Send a USB message to get volume status; result placed in *buf */ @@ -784,13 +1323,56 @@ static int scarlett2_usb_get_volume_status( buf, sizeof(*buf)); } +/* Send a USB message to get the volumes for all inputs of one mix + * and put the values into private->mix[] + */ +static int scarlett2_usb_get_mix(struct usb_mixer_interface *mixer, + int mix_num) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + int num_mixer_in = + info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; + int err, i, j, k; + + struct { + __le16 mix_num; + __le16 count; + } __packed req; + + __le16 data[SCARLETT2_INPUT_MIX_MAX]; + + req.mix_num = cpu_to_le16(mix_num); + req.count = cpu_to_le16(num_mixer_in); + + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MIX, + &req, sizeof(req), + data, num_mixer_in * sizeof(u16)); + if (err < 0) + return err; + + for (i = 0, j = mix_num * num_mixer_in; i < num_mixer_in; i++, j++) { + u16 mixer_value = le16_to_cpu(data[i]); + + for (k = 0; k < SCARLETT2_MIXER_VALUE_COUNT; k++) + if (scarlett2_mixer_values[k] >= mixer_value) + break; + if (k == SCARLETT2_MIXER_VALUE_COUNT) + k = SCARLETT2_MIXER_MAX_VALUE; + private->mix[j] = k; + } + + return 0; +} + /* Send a USB message to set the volumes for all inputs of one mix * (values obtained from private->mix[]) */ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, - int mix_num) + int mix_num) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; struct { @@ -800,7 +1382,7 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, int i, j; int num_mixer_in = - info->ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; + info->port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; req.mix_num = cpu_to_le16(mix_num); @@ -814,40 +1396,120 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer, NULL, 0); } -/* Convert a port number index (per info->ports) to a hardware ID */ -static u32 scarlett2_mux_src_num_to_id(const struct scarlett2_ports *ports, - int num) +/* Convert a port number index (per info->port_count) to a hardware ID */ +static u32 scarlett2_mux_src_num_to_id( + const int port_count[][SCARLETT2_PORT_DIRNS], int num) +{ + int port_type; + + for (port_type = 0; + port_type < SCARLETT2_PORT_TYPE_COUNT; + port_type++) { + if (num < port_count[port_type][SCARLETT2_PORT_IN]) + return scarlett2_ports[port_type].id | num; + num -= port_count[port_type][SCARLETT2_PORT_IN]; + } + + /* Oops */ + return 0; +} + +/* Convert a hardware ID to a port number index */ +static u32 scarlett2_mux_id_to_num( + const int port_count[][SCARLETT2_PORT_DIRNS], int direction, u32 id) { int port_type; + int port_num = 0; for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - if (num < ports[port_type].num[SCARLETT2_PORT_IN]) - return ports[port_type].id | num; - num -= ports[port_type].num[SCARLETT2_PORT_IN]; + int base = scarlett2_ports[port_type].id; + int count = port_count[port_type][direction]; + + if (id >= base && id < base + count) + return port_num + id - base; + port_num += count; } /* Oops */ + return -1; +} + +/* Convert one mux entry from the interface and load into private->mux[] */ +static void scarlett2_usb_populate_mux(struct scarlett2_data *private, + u32 mux_entry) +{ + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + + int dst_idx, src_idx; + + dst_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_OUT, + mux_entry & 0xFFF); + if (dst_idx < 0) + return; + + if (dst_idx >= private->num_mux_dsts) { + usb_audio_err(private->mixer->chip, + "BUG: scarlett2_mux_id_to_num(%06x, OUT): %d >= %d", + mux_entry, dst_idx, private->num_mux_dsts); + return; + } + + src_idx = scarlett2_mux_id_to_num(port_count, SCARLETT2_PORT_IN, + mux_entry >> 12); + if (src_idx < 0) + return; + + if (src_idx >= private->num_mux_srcs) { + usb_audio_err(private->mixer->chip, + "BUG: scarlett2_mux_id_to_num(%06x, IN): %d >= %d", + mux_entry, src_idx, private->num_mux_srcs); + return; + } + + private->mux[dst_idx] = src_idx; +} + +/* Send USB message to get mux inputs and then populate private->mux[] */ +static int scarlett2_usb_get_mux(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + int count = private->num_mux_dsts; + int err, i; + + struct { + __le16 num; + __le16 count; + } __packed req; + + __le32 data[SCARLETT2_MUX_MAX]; + + private->mux_updated = 0; + + req.num = 0; + req.count = cpu_to_le16(count); + + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_MUX, + &req, sizeof(req), + data, count * sizeof(u32)); + if (err < 0) + return err; + + for (i = 0; i < count; i++) + scarlett2_usb_populate_mux(private, le32_to_cpu(data[i])); + return 0; } /* Send USB messages to set mux inputs */ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; - int rate, port_dir_rate; - - static const int assignment_order[SCARLETT2_PORT_TYPE_COUNT] = { - SCARLETT2_PORT_TYPE_PCM, - SCARLETT2_PORT_TYPE_ANALOGUE, - SCARLETT2_PORT_TYPE_SPDIF, - SCARLETT2_PORT_TYPE_ADAT, - SCARLETT2_PORT_TYPE_MIX, - SCARLETT2_PORT_TYPE_NONE, - }; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int table; struct { __le16 pad; @@ -857,43 +1519,44 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) req.pad = 0; - /* mux settings for each rate */ - for (rate = 0, port_dir_rate = SCARLETT2_PORT_OUT_44; - port_dir_rate <= SCARLETT2_PORT_OUT_176; - rate++, port_dir_rate++) { - int order_num, i, err; - - req.num = cpu_to_le16(rate); - - for (order_num = 0, i = 0; - order_num < SCARLETT2_PORT_TYPE_COUNT; - order_num++) { - int port_type = assignment_order[order_num]; - int j = scarlett2_get_port_start_num(ports, - SCARLETT2_PORT_OUT, - port_type); - int port_id = ports[port_type].id; - int channel; - - for (channel = 0; - channel < ports[port_type].num[port_dir_rate]; - channel++, i++, j++) - /* lower 12 bits for the destination and - * next 12 bits for the source - */ - req.data[i] = !port_id - ? 0 - : cpu_to_le32( - port_id | - channel | - scarlett2_mux_src_num_to_id( - ports, private->mux[j] - ) << 12 - ); - - /* skip private->mux[j] entries not output */ - j += ports[port_type].num[SCARLETT2_PORT_OUT] - - ports[port_type].num[port_dir_rate]; + /* set mux settings for each rate */ + for (table = 0; table < SCARLETT2_MUX_TABLES; table++) { + const struct scarlett2_mux_entry *entry; + + /* i counts over the output array */ + int i = 0, err; + + req.num = cpu_to_le16(table); + + /* loop through each entry */ + for (entry = info->mux_assignment[table]; + entry->count; + entry++) { + int j; + int port_type = entry->port_type; + int port_idx = entry->start; + int mux_idx = scarlett2_get_port_start_num(port_count, + SCARLETT2_PORT_OUT, port_type) + port_idx; + int dst_id = scarlett2_ports[port_type].id + port_idx; + + /* Empty slots */ + if (!dst_id) { + for (j = 0; j < entry->count; j++) + req.data[i++] = 0; + continue; + } + + /* Non-empty mux slots use the lower 12 bits + * for the destination and next 12 bits for + * the source + */ + for (j = 0; j < entry->count; j++) { + int src_id = scarlett2_mux_src_num_to_id( + port_count, private->mux[mux_idx++]); + req.data[i++] = cpu_to_le32(dst_id | + src_id << 12); + dst_id++; + } } err = scarlett2_usb(mixer, SCARLETT2_USB_SET_MUX, @@ -908,26 +1571,26 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer) /* Send USB message to get meter levels */ static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer, - u16 *levels) + u16 num_meters, u16 *levels) { struct { __le16 pad; __le16 num_meters; __le32 magic; } __packed req; - u32 resp[SCARLETT2_NUM_METERS]; + u32 resp[SCARLETT2_MAX_METERS]; int i, err; req.pad = 0; - req.num_meters = cpu_to_le16(SCARLETT2_NUM_METERS); + req.num_meters = cpu_to_le16(num_meters); req.magic = cpu_to_le32(SCARLETT2_USB_METER_LEVELS_GET_MAGIC); - err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER_LEVELS, - &req, sizeof(req), resp, sizeof(resp)); + err = scarlett2_usb(mixer, SCARLETT2_USB_GET_METER, + &req, sizeof(req), resp, num_meters * sizeof(u32)); if (err < 0) return err; /* copy, convert to u16 */ - for (i = 0; i < SCARLETT2_NUM_METERS; i++) + for (i = 0; i < num_meters; i++) levels[i] = resp[i]; return 0; @@ -949,10 +1612,15 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, if (!elem) return -ENOMEM; + /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code + * ignores them for resume and other operations. + * Also, the head.id field is set to 0, as we don't use this field. + */ elem->head.mixer = mixer; elem->control = index; - elem->head.id = index; + elem->head.id = 0; elem->channels = channels; + elem->val_type = USB_MIXER_BESPOKEN; kctl = snd_ctl_new1(ncontrol, elem); if (!kctl) { @@ -973,6 +1641,64 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, return 0; } +/*** Sync Control ***/ + +/* Update sync control after receiving notification that the status + * has changed + */ +static int scarlett2_update_sync(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->sync_updated = 0; + return scarlett2_usb_get_sync_status(mixer, &private->sync); +} + +static int scarlett2_sync_ctl_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *uinfo) +{ + static const char *texts[2] = { + "Unlocked", "Locked" + }; + return snd_ctl_enum_info(uinfo, 1, 2, texts); +} + +static int scarlett2_sync_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->sync_updated) + scarlett2_update_sync(mixer); + ucontrol->value.enumerated.item[0] = private->sync; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static const struct snd_kcontrol_new scarlett2_sync_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .name = "", + .info = scarlett2_sync_ctl_info, + .get = scarlett2_sync_ctl_get +}; + +static int scarlett2_add_sync_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + /* devices without a mixer also don't support reporting sync status */ + if (!private->info->has_mixer) + return 0; + + return scarlett2_add_new_ctl(mixer, &scarlett2_sync_ctl, + 0, 1, "Sync Status", &private->sync_ctl); +} + /*** Analogue Line Out Volume Controls ***/ /* Update hardware volume controls after receiving notification that @@ -980,12 +1706,14 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, */ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; struct scarlett2_usb_volume_status volume_status; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int err, i; + int mute; private->vol_updated = 0; @@ -997,13 +1725,17 @@ static int scarlett2_update_volumes(struct usb_mixer_interface *mixer) volume_status.master_vol + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); - for (i = 0; i < num_line_out; i++) { - if (private->vol_sw_hw_switch[i]) - private->vol[i] = private->master_vol; - } + if (info->line_out_hw_vol) + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) + private->dim_mute[i] = !!volume_status.dim_mute[i]; - for (i = 0; i < private->info->button_count; i++) - private->buttons[i] = !!volume_status.buttons[i]; + mute = private->dim_mute[SCARLETT2_BUTTON_MUTE]; + + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[i]) { + private->vol[i] = private->master_vol; + private->mute_switch[i] = mute; + } return 0; } @@ -1026,31 +1758,38 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; - if (private->vol_updated) { - mutex_lock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->vol_updated) scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); - } + mutex_unlock(&private->data_mutex); ucontrol->value.integer.value[0] = private->master_vol; return 0; } +static int line_out_remap(struct scarlett2_data *private, int index) +{ + const struct scarlett2_device_info *info = private->info; + + if (!info->line_out_remap_enable) + return index; + return info->line_out_remap[index]; +} + static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; - int index = elem->control; + struct scarlett2_data *private = mixer->private_data; + int index = line_out_remap(private, elem->control); - if (private->vol_updated) { - mutex_lock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->vol_updated) scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); - } + mutex_unlock(&private->data_mutex); ucontrol->value.integer.value[0] = private->vol[index]; return 0; @@ -1061,8 +1800,8 @@ static int scarlett2_volume_ctl_put(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; - int index = elem->control; + struct scarlett2_data *private = mixer->private_data; + int index = line_out_remap(private, elem->control); int oval, val, err = 0; mutex_lock(&private->data_mutex); @@ -1111,8 +1850,71 @@ static const struct snd_kcontrol_new scarlett2_line_out_volume_ctl = { .tlv = { .p = db_scale_scarlett2_gain } }; +/*** Mute Switch Controls ***/ + +static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + int index = line_out_remap(private, elem->control); + + ucontrol->value.integer.value[0] = private->mute_switch[index]; + return 0; +} + +static int scarlett2_mute_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + int index = line_out_remap(private, elem->control); + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->mute_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->mute_switch[index] = val; + + /* Send mute change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MUTE_SWITCH, + index, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_mute_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_mute_ctl_get, + .put = scarlett2_mute_ctl_put, +}; + /*** HW/SW Volume Switch Controls ***/ +static void scarlett2_sw_hw_ctl_ro(struct scarlett2_data *private, int index) +{ + private->sw_hw_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; +} + +static void scarlett2_sw_hw_ctl_rw(struct scarlett2_data *private, int index) +{ + private->sw_hw_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; +} + static int scarlett2_sw_hw_enum_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { @@ -1127,60 +1929,97 @@ static int scarlett2_sw_hw_enum_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + int index = line_out_remap(private, elem->control); - ucontrol->value.enumerated.item[0] = - private->vol_sw_hw_switch[elem->control]; + ucontrol->value.enumerated.item[0] = private->vol_sw_hw_switch[index]; return 0; } -static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *ucontrol) +static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer, + int index, int value) { - struct usb_mixer_elem_info *elem = kctl->private_data; - struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; - - int index = elem->control; - int oval, val, err = 0; + struct scarlett2_data *private = mixer->private_data; + struct snd_card *card = mixer->chip->card; - mutex_lock(&private->data_mutex); + /* Set/Clear write bits */ + if (value) { + private->vol_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; + private->mute_ctls[index]->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_WRITE; + } else { + private->vol_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + private->mute_ctls[index]->vd[0].access &= + ~SNDRV_CTL_ELEM_ACCESS_WRITE; + } - oval = private->vol_sw_hw_switch[index]; - val = !!ucontrol->value.integer.value[0]; + /* Notify of write bit change */ + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->vol_ctls[index]->id); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->mute_ctls[index]->id); +} - if (oval == val) - goto unlock; +static int scarlett2_sw_hw_change(struct usb_mixer_interface *mixer, + int ctl_index, int val) +{ + struct scarlett2_data *private = mixer->private_data; + int index = line_out_remap(private, ctl_index); + int err; private->vol_sw_hw_switch[index] = val; /* Change access mode to RO (hardware controlled volume) * or RW (software controlled volume) */ - if (val) - private->vol_ctls[index]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_WRITE; - else - private->vol_ctls[index]->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_WRITE; + scarlett2_vol_ctl_set_writable(mixer, ctl_index, !val); - /* Reset volume to master volume */ + /* Reset volume/mute to master volume/mute */ private->vol[index] = private->master_vol; + private->mute_switch[index] = private->dim_mute[SCARLETT2_BUTTON_MUTE]; /* Set SW volume to current HW volume */ err = scarlett2_usb_set_config( mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME, index, private->master_vol - SCARLETT2_VOLUME_BIAS); if (err < 0) - goto unlock; + return err; - /* Notify of RO/RW change */ - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_INFO, - &private->vol_ctls[index]->id); + /* Set SW mute to current HW mute */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MUTE_SWITCH, + index, private->dim_mute[SCARLETT2_BUTTON_MUTE]); + if (err < 0) + return err; /* Send SW/HW switch change to the device */ - err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, - index, val); + return scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, + index, val); +} + +static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + int ctl_index = elem->control; + int index = line_out_remap(private, ctl_index); + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->vol_sw_hw_switch[index]; + val = !!ucontrol->value.enumerated.item[0]; + + if (oval == val) + goto unlock; + + err = scarlett2_sw_hw_change(mixer, ctl_index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1197,6 +2036,55 @@ static const struct snd_kcontrol_new scarlett2_sw_hw_enum_ctl = { /*** Line Level/Instrument Level Switch Controls ***/ +static int scarlett2_update_input_other(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + private->input_other_updated = 0; + + if (info->level_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, + info->level_input_count + info->level_input_first, + private->level_switch); + if (err < 0) + return err; + } + + if (info->pad_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PAD_SWITCH, + info->pad_input_count, private->pad_switch); + if (err < 0) + return err; + } + + if (info->air_input_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_AIR_SWITCH, + info->air_input_count, private->air_switch); + if (err < 0) + return err; + } + + if (info->phantom_count) { + int err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH, + info->phantom_count, private->phantom_switch); + if (err < 0) + return err; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, + 1, &private->phantom_persistence); + if (err < 0) + return err; + } + + return 0; +} + static int scarlett2_level_enum_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { @@ -1211,10 +2099,18 @@ static int scarlett2_level_enum_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + int index = elem->control + info->level_input_first; + + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.enumerated.item[0] = private->level_switch[index]; + mutex_unlock(&private->data_mutex); - ucontrol->value.enumerated.item[0] = - private->level_switch[elem->control]; return 0; } @@ -1223,15 +2119,16 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; - int index = elem->control; + int index = elem->control + info->level_input_first; int oval, val, err = 0; mutex_lock(&private->data_mutex); oval = private->level_switch[index]; - val = !!ucontrol->value.integer.value[0]; + val = !!ucontrol->value.enumerated.item[0]; if (oval == val) goto unlock; @@ -1241,6 +2138,8 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1261,10 +2160,16 @@ static int scarlett2_pad_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; - ucontrol->value.enumerated.item[0] = + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.integer.value[0] = private->pad_switch[elem->control]; + mutex_unlock(&private->data_mutex); + return 0; } @@ -1273,7 +2178,7 @@ static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; int index = elem->control; int oval, val, err = 0; @@ -1291,6 +2196,8 @@ static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1305,71 +2212,734 @@ static const struct snd_kcontrol_new scarlett2_pad_ctl = { .put = scarlett2_pad_ctl_put, }; -/*** Mute/Dim Controls ***/ +/*** Air Switch Controls ***/ -static int scarlett2_button_ctl_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *ucontrol) +static int scarlett2_air_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; - if (private->vol_updated) { - mutex_lock(&private->data_mutex); - scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.integer.value[0] = private->air_switch[elem->control]; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_air_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->air_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->air_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_AIR_SWITCH, + index, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_air_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_air_ctl_get, + .put = scarlett2_air_ctl_put, +}; + +/*** Phantom Switch Controls ***/ + +static int scarlett2_phantom_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->input_other_updated) + scarlett2_update_input_other(mixer); + ucontrol->value.integer.value[0] = + private->phantom_switch[elem->control]; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_phantom_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->phantom_switch[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->phantom_switch[index] = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PHANTOM_SWITCH, + index, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_phantom_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_phantom_ctl_get, + .put = scarlett2_phantom_ctl_put, +}; + +/*** Phantom Persistence Control ***/ + +static int scarlett2_phantom_persistence_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0] = private->phantom_persistence; + return 0; +} + +static int scarlett2_phantom_persistence_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int index = elem->control; + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->phantom_persistence; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->phantom_persistence = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_PHANTOM_PERSISTENCE, index, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_phantom_persistence_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_phantom_persistence_ctl_get, + .put = scarlett2_phantom_persistence_ctl_put, +}; + +/*** Direct Monitor Control ***/ + +static int scarlett2_update_monitor_other(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int err; + + /* monitor_other_enable[0] enables speaker switching + * monitor_other_enable[1] enables talkback + */ + u8 monitor_other_enable[2]; + + /* monitor_other_switch[0] activates the alternate speakers + * monitor_other_switch[1] activates talkback + */ + u8 monitor_other_switch[2]; + + private->monitor_other_updated = 0; + + if (info->direct_monitor) + return scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, + 1, &private->direct_monitor_switch); + + /* if it doesn't do speaker switching then it also doesn't do + * talkback + */ + if (!info->has_speaker_switching) + return 0; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 2, monitor_other_enable); + if (err < 0) + return err; + + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 2, monitor_other_switch); + if (err < 0) + return err; + + if (!monitor_other_enable[0]) + private->speaker_switching_switch = 0; + else + private->speaker_switching_switch = monitor_other_switch[0] + 1; + + if (info->has_talkback) { + const int (*port_count)[SCARLETT2_PORT_DIRNS] = + info->port_count; + int num_mixes = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + u16 bitmap; + int i; + + if (!monitor_other_enable[1]) + private->talkback_switch = 0; + else + private->talkback_switch = monitor_other_switch[1] + 1; + + err = scarlett2_usb_get_config(mixer, + SCARLETT2_CONFIG_TALKBACK_MAP, + 1, &bitmap); + for (i = 0; i < num_mixes; i++, bitmap >>= 1) + private->talkback_map[i] = bitmap & 1; } - ucontrol->value.enumerated.item[0] = private->buttons[elem->control]; return 0; } -static int scarlett2_button_ctl_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *ucontrol) +static int scarlett2_direct_monitor_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = elem->head.mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->direct_monitor_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_direct_monitor_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; int index = elem->control; int oval, val, err = 0; mutex_lock(&private->data_mutex); - oval = private->buttons[index]; + oval = private->direct_monitor_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->direct_monitor_switch = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_DIRECT_MONITOR, index, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static int scarlett2_direct_monitor_stereo_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Off", "Mono", "Stereo" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +/* Direct Monitor for Solo is mono-only and only needs a boolean control + * Direct Monitor for 2i2 is selectable between Off/Mono/Stereo + */ +static const struct snd_kcontrol_new scarlett2_direct_monitor_ctl[2] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_direct_monitor_ctl_get, + .put = scarlett2_direct_monitor_ctl_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_direct_monitor_stereo_enum_ctl_info, + .get = scarlett2_direct_monitor_ctl_get, + .put = scarlett2_direct_monitor_ctl_put, + } +}; + +static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->direct_monitor) + return 0; + + return scarlett2_add_new_ctl( + mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1], + 0, 1, "Direct Monitor Playback Switch", + &private->direct_monitor_ctl); +} + +/*** Speaker Switching Control ***/ + +static int scarlett2_speaker_switch_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Off", "Main", "Alt" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +static int scarlett2_speaker_switch_enum_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->speaker_switching_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +/* when speaker switching gets enabled, switch the main/alt speakers + * to HW volume and disable those controls + */ +static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i, err; + + for (i = 0; i < 4; i++) { + int index = line_out_remap(private, i); + + /* switch the main/alt speakers to HW volume */ + if (!private->vol_sw_hw_switch[index]) { + err = scarlett2_sw_hw_change(private->mixer, i, 1); + if (err < 0) + return err; + } + + /* disable the line out SW/HW switch */ + scarlett2_sw_hw_ctl_ro(private, i); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->sw_hw_ctls[i]->id); + } + + /* when the next monitor-other notify comes in, update the mux + * configuration + */ + private->speaker_switching_switched = 1; + + return 0; +} + +/* when speaker switching gets disabled, reenable the hw/sw controls + * and invalidate the routing + */ +static void scarlett2_speaker_switch_disable(struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + int i; + + /* enable the line out SW/HW switch */ + for (i = 0; i < 4; i++) { + scarlett2_sw_hw_ctl_rw(private, i); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, + &private->sw_hw_ctls[i]->id); + } + + /* when the next monitor-other notify comes in, update the mux + * configuration + */ + private->speaker_switching_switched = 1; +} + +static int scarlett2_speaker_switch_enum_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->speaker_switching_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->speaker_switching_switch = val; + + /* enable/disable speaker switching */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 0, !!val); + if (err < 0) + goto unlock; + + /* if speaker switching is enabled, select main or alt */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 0, val == 2); + if (err < 0) + goto unlock; + + /* update controls if speaker switching gets enabled or disabled */ + if (!oval && val) + err = scarlett2_speaker_switch_enable(mixer); + else if (oval && !val) + scarlett2_speaker_switch_disable(mixer); + + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_speaker_switch_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_speaker_switch_enum_ctl_info, + .get = scarlett2_speaker_switch_enum_ctl_get, + .put = scarlett2_speaker_switch_enum_ctl_put, +}; + +static int scarlett2_add_speaker_switch_ctl( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->has_speaker_switching) + return 0; + + return scarlett2_add_new_ctl( + mixer, &scarlett2_speaker_switch_enum_ctl, + 0, 1, "Speaker Switching Playback Enum", + &private->speaker_switching_ctl); +} + +/*** Talkback and Talkback Map Controls ***/ + +static int scarlett2_talkback_enum_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + static const char *const values[3] = { + "Disabled", "Off", "On" + }; + + return snd_ctl_enum_info(uinfo, 1, 3, values); +} + +static int scarlett2_talkback_enum_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->monitor_other_updated) + scarlett2_update_monitor_other(mixer); + ucontrol->value.enumerated.item[0] = private->talkback_switch; + mutex_unlock(&private->data_mutex); + + return 0; +} + +static int scarlett2_talkback_enum_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->talkback_switch; + val = min(ucontrol->value.enumerated.item[0], 2U); + + if (oval == val) + goto unlock; + + private->talkback_switch = val; + + /* enable/disable talkback */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_ENABLE, + 1, !!val); + if (err < 0) + goto unlock; + + /* if talkback is enabled, select main or alt */ + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_MONITOR_OTHER_SWITCH, + 1, val == 2); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_talkback_enum_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = scarlett2_talkback_enum_ctl_info, + .get = scarlett2_talkback_enum_ctl_get, + .put = scarlett2_talkback_enum_ctl_put, +}; + +static int scarlett2_talkback_map_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + int index = elem->control; + + ucontrol->value.integer.value[0] = private->talkback_map[index]; + + return 0; +} + +static int scarlett2_talkback_map_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = + private->info->port_count; + int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + + int index = elem->control; + int oval, val, err = 0, i; + u16 bitmap = 0; + + mutex_lock(&private->data_mutex); + + oval = private->talkback_map[index]; val = !!ucontrol->value.integer.value[0]; if (oval == val) goto unlock; - private->buttons[index] = val; + private->talkback_map[index] = val; + + for (i = 0; i < num_mixes; i++) + bitmap |= private->talkback_map[i] << i; + + /* Send updated bitmap to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_TALKBACK_MAP, + 0, bitmap); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_talkback_map_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_talkback_map_ctl_get, + .put = scarlett2_talkback_map_ctl_put, +}; + +static int scarlett2_add_talkback_ctls( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int num_mixes = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; + int err, i; + char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + + if (!info->has_talkback) + return 0; + + err = scarlett2_add_new_ctl( + mixer, &scarlett2_talkback_enum_ctl, + 0, 1, "Talkback Playback Enum", + &private->talkback_ctl); + if (err < 0) + return err; + + for (i = 0; i < num_mixes; i++) { + snprintf(s, sizeof(s), + "Talkback Mix %c Playback Switch", i + 'A'); + err = scarlett2_add_new_ctl(mixer, &scarlett2_talkback_map_ctl, + i, 1, s, NULL); + if (err < 0) + return err; + } + + return 0; +} + +/*** Dim/Mute Controls ***/ + +static int scarlett2_dim_mute_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + mutex_lock(&private->data_mutex); + if (private->vol_updated) + scarlett2_update_volumes(mixer); + mutex_unlock(&private->data_mutex); + + ucontrol->value.integer.value[0] = private->dim_mute[elem->control]; + return 0; +} + +static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int num_line_out = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; + + int index = elem->control; + int oval, val, err = 0, i; + + mutex_lock(&private->data_mutex); + + oval = private->dim_mute[index]; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->dim_mute[index] = val; /* Send switch change to the device */ - err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BUTTONS, + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_DIM_MUTE, index, val); + if (err == 0) + err = 1; + + if (index == SCARLETT2_BUTTON_MUTE) + for (i = 0; i < num_line_out; i++) { + int line_index = line_out_remap(private, i); + + if (private->vol_sw_hw_switch[line_index]) { + private->mute_switch[line_index] = val; + snd_ctl_notify(mixer->chip->card, + SNDRV_CTL_EVENT_MASK_INFO, + &private->mute_ctls[i]->id); + } + } unlock: mutex_unlock(&private->data_mutex); return err; } -static const struct snd_kcontrol_new scarlett2_button_ctl = { +static const struct snd_kcontrol_new scarlett2_dim_mute_ctl = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "", .info = snd_ctl_boolean_mono_info, - .get = scarlett2_button_ctl_get, - .put = scarlett2_button_ctl_put + .get = scarlett2_dim_mute_ctl_get, + .put = scarlett2_dim_mute_ctl_put }; /*** Create the analogue output controls ***/ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int err, i; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -1385,6 +2955,7 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) /* Add volume controls */ for (i = 0; i < num_line_out; i++) { + int index = line_out_remap(private, i); /* Fader */ if (info->line_out_descrs[i]) @@ -1401,10 +2972,22 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) if (err < 0) return err; - /* Make the fader read-only if the SW/HW switch is set to HW */ - if (private->vol_sw_hw_switch[i]) - private->vol_ctls[i]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_WRITE; + /* Mute Switch */ + snprintf(s, sizeof(s), + "Line %02d Mute Playback Switch", + i + 1); + err = scarlett2_add_new_ctl(mixer, + &scarlett2_mute_ctl, + i, 1, s, + &private->mute_ctls[i]); + if (err < 0) + return err; + + /* Make the fader and mute controls read-only if the + * SW/HW switch is set to HW + */ + if (private->vol_sw_hw_switch[index]) + scarlett2_vol_ctl_set_writable(mixer, i, 0); /* SW/HW Switch */ if (info->line_out_hw_vol) { @@ -1413,20 +2996,29 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) i + 1); err = scarlett2_add_new_ctl(mixer, &scarlett2_sw_hw_enum_ctl, - i, 1, s, NULL); + i, 1, s, + &private->sw_hw_ctls[i]); if (err < 0) return err; + + /* Make the switch read-only if the line is + * involved in speaker switching + */ + if (private->speaker_switching_switch && i < 4) + scarlett2_sw_hw_ctl_ro(private, i); } } - /* Add HW button controls */ - for (i = 0; i < private->info->button_count; i++) { - err = scarlett2_add_new_ctl(mixer, &scarlett2_button_ctl, - i, 1, scarlett2_button_names[i], - &private->button_ctls[i]); - if (err < 0) - return err; - } + /* Add dim/mute controls */ + if (info->line_out_hw_vol) + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_dim_mute_ctl, + i, 1, scarlett2_dim_mute_names[i], + &private->dim_mute_ctls[i]); + if (err < 0) + return err; + } return 0; } @@ -1435,25 +3027,70 @@ static int scarlett2_add_line_out_ctls(struct usb_mixer_interface *mixer) static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; int err, i; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + const char *fmt = "Line In %d %s Capture %s"; + const char *fmt2 = "Line In %d-%d %s Capture %s"; /* Add input level (line/inst) controls */ for (i = 0; i < info->level_input_count; i++) { - snprintf(s, sizeof(s), "Line In %d Level Capture Enum", i + 1); + snprintf(s, sizeof(s), fmt, i + 1 + info->level_input_first, + "Level", "Enum"); err = scarlett2_add_new_ctl(mixer, &scarlett2_level_enum_ctl, - i, 1, s, NULL); + i, 1, s, &private->level_ctls[i]); if (err < 0) return err; } /* Add input pad controls */ for (i = 0; i < info->pad_input_count; i++) { - snprintf(s, sizeof(s), "Line In %d Pad Capture Switch", i + 1); + snprintf(s, sizeof(s), fmt, i + 1, "Pad", "Switch"); err = scarlett2_add_new_ctl(mixer, &scarlett2_pad_ctl, - i, 1, s, NULL); + i, 1, s, &private->pad_ctls[i]); + if (err < 0) + return err; + } + + /* Add input air controls */ + for (i = 0; i < info->air_input_count; i++) { + snprintf(s, sizeof(s), fmt, i + 1, "Air", "Switch"); + err = scarlett2_add_new_ctl(mixer, &scarlett2_air_ctl, + i, 1, s, &private->air_ctls[i]); + if (err < 0) + return err; + } + + /* Add input phantom controls */ + if (info->inputs_per_phantom == 1) { + for (i = 0; i < info->phantom_count; i++) { + snprintf(s, sizeof(s), fmt, i + 1, + "Phantom Power", "Switch"); + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_ctl, + i, 1, s, &private->phantom_ctls[i]); + if (err < 0) + return err; + } + } else if (info->inputs_per_phantom > 1) { + for (i = 0; i < info->phantom_count; i++) { + int from = i * info->inputs_per_phantom + 1; + int to = (i + 1) * info->inputs_per_phantom; + + snprintf(s, sizeof(s), fmt2, from, to, + "Phantom Power", "Switch"); + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_ctl, + i, 1, s, &private->phantom_ctls[i]); + if (err < 0) + return err; + } + } + if (info->phantom_count) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_phantom_persistence_ctl, 0, 1, + "Phantom Power Persistence Capture Switch", NULL); if (err < 0) return err; } @@ -1480,7 +3117,7 @@ static int scarlett2_mixer_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; ucontrol->value.integer.value[0] = private->mix[elem->control]; return 0; @@ -1491,22 +3128,23 @@ static int scarlett2_mixer_ctl_put(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int oval, val, num_mixer_in, mix_num, err = 0; + int index = elem->control; mutex_lock(&private->data_mutex); - oval = private->mix[elem->control]; + oval = private->mix[index]; val = ucontrol->value.integer.value[0]; - num_mixer_in = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; - mix_num = elem->control / num_mixer_in; + num_mixer_in = port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; + mix_num = index / num_mixer_in; if (oval == val) goto unlock; - private->mix[elem->control] = val; + private->mix[index] = val; err = scarlett2_usb_set_mix(mixer, mix_num); if (err == 0) err = 1; @@ -1536,16 +3174,19 @@ static const struct snd_kcontrol_new scarlett2_mixer_ctl = { static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int err, i, j; int index; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - int num_inputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_OUT]; - int num_outputs = ports[SCARLETT2_PORT_TYPE_MIX].num[SCARLETT2_PORT_IN]; + int num_inputs = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT]; + int num_outputs = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; - for (i = 0, index = 0; i < num_outputs; i++) { + for (i = 0, index = 0; i < num_outputs; i++) for (j = 0; j < num_inputs; j++, index++) { snprintf(s, sizeof(s), "Mix %c Input %02d Playback Volume", @@ -1555,7 +3196,6 @@ static int scarlett2_add_mixer_ctls(struct usb_mixer_interface *mixer) if (err < 0) return err; } - } return 0; } @@ -1566,8 +3206,9 @@ static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + struct scarlett2_data *private = elem->head.mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; unsigned int item = uinfo->value.enumerated.item; int items = private->num_mux_srcs; int port_type; @@ -1582,13 +3223,15 @@ static int scarlett2_mux_src_enum_ctl_info(struct snd_kcontrol *kctl, for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { - if (item < ports[port_type].num[SCARLETT2_PORT_IN]) { + if (item < port_count[port_type][SCARLETT2_PORT_IN]) { + const struct scarlett2_port *port = + &scarlett2_ports[port_type]; + sprintf(uinfo->value.enumerated.name, - ports[port_type].src_descr, - item + ports[port_type].src_num_offset); + port->src_descr, item + port->src_num_offset); return 0; } - item -= ports[port_type].num[SCARLETT2_PORT_IN]; + item -= port_count[port_type][SCARLETT2_PORT_IN]; } return -EINVAL; @@ -1598,9 +3241,23 @@ static int scarlett2_mux_src_enum_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - struct scarlett2_mixer_data *private = elem->head.mixer->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int line_out_count = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; + int index = elem->control; + + if (index < line_out_count) + index = line_out_remap(private, index); + + mutex_lock(&private->data_mutex); + if (private->mux_updated) + scarlett2_usb_get_mux(mixer); + ucontrol->value.enumerated.item[0] = private->mux[index]; + mutex_unlock(&private->data_mutex); - ucontrol->value.enumerated.item[0] = private->mux[elem->control]; return 0; } @@ -1609,15 +3266,22 @@ static int scarlett2_mux_src_enum_ctl_put(struct snd_kcontrol *kctl, { struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_interface *mixer = elem->head.mixer; - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int line_out_count = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int index = elem->control; int oval, val, err = 0; + if (index < line_out_count) + index = line_out_remap(private, index); + mutex_lock(&private->data_mutex); oval = private->mux[index]; - val = clamp(ucontrol->value.integer.value[0], - 0L, private->num_mux_srcs - 1L); + val = min(ucontrol->value.enumerated.item[0], + private->num_mux_srcs - 1U); if (oval == val) goto unlock; @@ -1642,26 +3306,29 @@ static const struct snd_kcontrol_new scarlett2_mux_src_enum_ctl = { static int scarlett2_add_mux_enums(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int port_type, channel, i; for (i = 0, port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; port_type++) { for (channel = 0; - channel < ports[port_type].num[SCARLETT2_PORT_OUT]; + channel < port_count[port_type][SCARLETT2_PORT_OUT]; channel++, i++) { int err; char s[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - const char *const descr = ports[port_type].dst_descr; + const char *const descr = + scarlett2_ports[port_type].dst_descr; snprintf(s, sizeof(s) - 5, descr, channel + 1); strcat(s, " Enum"); err = scarlett2_add_new_ctl(mixer, &scarlett2_mux_src_enum_ctl, - i, 1, s, NULL); + i, 1, s, + &private->mux_ctls[i]); if (err < 0) return err; } @@ -1689,10 +3356,11 @@ static int scarlett2_meter_ctl_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *elem = kctl->private_data; - u16 meter_levels[SCARLETT2_NUM_METERS]; + u16 meter_levels[SCARLETT2_MAX_METERS]; int i, err; - err = scarlett2_usb_get_meter_levels(elem->head.mixer, meter_levels); + err = scarlett2_usb_get_meter_levels(elem->head.mixer, elem->channels, + meter_levels); if (err < 0) return err; @@ -1712,16 +3380,89 @@ static const struct snd_kcontrol_new scarlett2_meter_ctl = { static int scarlett2_add_meter_ctl(struct usb_mixer_interface *mixer) { + struct scarlett2_data *private = mixer->private_data; + + /* devices without a mixer also don't support reporting levels */ + if (!private->info->has_mixer) + return 0; + return scarlett2_add_new_ctl(mixer, &scarlett2_meter_ctl, - 0, SCARLETT2_NUM_METERS, + 0, private->num_mux_dsts, "Level Meter", NULL); } +/*** MSD Controls ***/ + +static int scarlett2_msd_ctl_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0] = private->msd_switch; + return 0; +} + +static int scarlett2_msd_ctl_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + + int oval, val, err = 0; + + mutex_lock(&private->data_mutex); + + oval = private->msd_switch; + val = !!ucontrol->value.integer.value[0]; + + if (oval == val) + goto unlock; + + private->msd_switch = val; + + /* Send switch change to the device */ + err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_MSD_SWITCH, + 0, val); + if (err == 0) + err = 1; + +unlock: + mutex_unlock(&private->data_mutex); + return err; +} + +static const struct snd_kcontrol_new scarlett2_msd_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "", + .info = snd_ctl_boolean_mono_info, + .get = scarlett2_msd_ctl_get, + .put = scarlett2_msd_ctl_put, +}; + +static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + if (!info->has_msd_mode) + return 0; + + /* If MSD mode is off, hide the switch by default */ + if (!private->msd_switch && !(mixer->chip->setup & SCARLETT2_MSD_ENABLE)) + return 0; + + /* Add MSD control */ + return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl, + 0, 1, "MSD Mode", NULL); +} + /*** Cleanup/Suspend Callbacks ***/ static void scarlett2_private_free(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; cancel_delayed_work_sync(&private->work); kfree(private); @@ -1730,7 +3471,7 @@ static void scarlett2_private_free(struct usb_mixer_interface *mixer) static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; if (cancel_delayed_work_sync(&private->work)) scarlett2_config_save(private->mixer); @@ -1738,77 +3479,61 @@ static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) /*** Initialisation ***/ -static int scarlett2_count_mux_srcs(const struct scarlett2_ports *ports) +static void scarlett2_count_mux_io(struct scarlett2_data *private) { - int port_type, count = 0; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int port_type, srcs = 0, dsts = 0; for (port_type = 0; port_type < SCARLETT2_PORT_TYPE_COUNT; - port_type++) - count += ports[port_type].num[SCARLETT2_PORT_IN]; + port_type++) { + srcs += port_count[port_type][SCARLETT2_PORT_IN]; + dsts += port_count[port_type][SCARLETT2_PORT_OUT]; + } - return count; + private->num_mux_srcs = srcs; + private->num_mux_dsts = dsts; } -/* Default routing connects PCM outputs and inputs to Analogue, - * S/PDIF, then ADAT +/* Look through the interface descriptors for the Focusrite Control + * interface (bInterfaceClass = 255 Vendor Specific Class) and set + * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval + * in private */ -static void scarlett2_init_routing(u8 *mux, - const struct scarlett2_ports *ports) +static int scarlett2_find_fc_interface(struct usb_device *dev, + struct scarlett2_data *private) { - int i, input_num, input_count, port_type; - int output_num, output_count, port_type_connect_num; + struct usb_host_config *config = dev->actconfig; + int i; - static const int connect_order[] = { - SCARLETT2_PORT_TYPE_ANALOGUE, - SCARLETT2_PORT_TYPE_SPDIF, - SCARLETT2_PORT_TYPE_ADAT, - -1 - }; + for (i = 0; i < config->desc.bNumInterfaces; i++) { + struct usb_interface *intf = config->interface[i]; + struct usb_interface_descriptor *desc = + &intf->altsetting[0].desc; + struct usb_endpoint_descriptor *epd; - /* Assign PCM inputs (routing outputs) */ - output_num = scarlett2_get_port_start_num(ports, - SCARLETT2_PORT_OUT, - SCARLETT2_PORT_TYPE_PCM); - output_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_OUT]; - - for (port_type = connect_order[port_type_connect_num = 0]; - port_type >= 0; - port_type = connect_order[++port_type_connect_num]) { - input_num = scarlett2_get_port_start_num( - ports, SCARLETT2_PORT_IN, port_type); - input_count = ports[port_type].num[SCARLETT2_PORT_IN]; - for (i = 0; - i < input_count && output_count; - i++, output_count--) - mux[output_num++] = input_num++; - } + if (desc->bInterfaceClass != 255) + continue; - /* Assign PCM outputs (routing inputs) */ - input_num = scarlett2_get_port_start_num(ports, - SCARLETT2_PORT_IN, - SCARLETT2_PORT_TYPE_PCM); - input_count = ports[SCARLETT2_PORT_TYPE_PCM].num[SCARLETT2_PORT_IN]; - - for (port_type = connect_order[port_type_connect_num = 0]; - port_type >= 0; - port_type = connect_order[++port_type_connect_num]) { - output_num = scarlett2_get_port_start_num( - ports, SCARLETT2_PORT_OUT, port_type); - output_count = ports[port_type].num[SCARLETT2_PORT_OUT]; - for (i = 0; - i < output_count && input_count; - i++, input_count--) - mux[output_num++] = input_num++; + epd = get_endpoint(intf->altsetting, 0); + private->bInterfaceNumber = desc->bInterfaceNumber; + private->bEndpointAddress = epd->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize); + private->bInterval = epd->bInterval; + return 0; } + + return -EINVAL; } -/* Initialise private data, routing, sequence number */ +/* Initialise private data */ static int scarlett2_init_private(struct usb_mixer_interface *mixer, const struct scarlett2_device_info *info) { - struct scarlett2_mixer_data *private = - kzalloc(sizeof(struct scarlett2_mixer_data), GFP_KERNEL); + struct scarlett2_data *private = + kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL); if (!private) return -ENOMEM; @@ -1816,68 +3541,102 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer, mutex_init(&private->usb_mutex); mutex_init(&private->data_mutex); INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work); - private->info = info; - private->num_mux_srcs = scarlett2_count_mux_srcs(info->ports); - private->scarlett2_seq = 0; - private->mixer = mixer; + mixer->private_data = private; mixer->private_free = scarlett2_private_free; mixer->private_suspend = scarlett2_private_suspend; - /* Setup default routing */ - scarlett2_init_routing(private->mux, info->ports); + private->info = info; + scarlett2_count_mux_io(private); + private->scarlett2_seq = 0; + private->mixer = mixer; - /* Initialise the sequence number used for the proprietary commands */ - return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0); + return scarlett2_find_fc_interface(mixer->chip->dev, private); } -/* Read line-in config and line-out volume settings on start */ +/* Cargo cult proprietary initialisation sequence */ +static int scarlett2_usb_init(struct usb_mixer_interface *mixer) +{ + struct usb_device *dev = mixer->chip->dev; + struct scarlett2_data *private = mixer->private_data; + u8 buf[24]; + int err; + + if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0))) + return -EINVAL; + + /* step 0 */ + err = scarlett2_usb_rx(dev, private->bInterfaceNumber, + SCARLETT2_USB_CMD_INIT, buf, sizeof(buf)); + if (err < 0) + return err; + + /* step 1 */ + private->scarlett2_seq = 1; + err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0); + if (err < 0) + return err; + + /* step 2 */ + private->scarlett2_seq = 1; + return scarlett2_usb(mixer, SCARLETT2_USB_INIT_2, NULL, 0, NULL, 84); +} + +/* Read configuration from the interface on start */ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; - const struct scarlett2_ports *ports = info->ports; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; - u8 level_switches[SCARLETT2_LEVEL_SWITCH_MAX]; - u8 pad_switches[SCARLETT2_PAD_SWITCH_MAX]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; + int num_mixer_out = + port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN]; struct scarlett2_usb_volume_status volume_status; int err, i; - if (info->level_input_count) { + if (info->has_msd_mode) { err = scarlett2_usb_get_config( - mixer, - SCARLETT2_CONFIG_LEVEL_SWITCH, - info->level_input_count, - level_switches); + mixer, SCARLETT2_CONFIG_MSD_SWITCH, + 1, &private->msd_switch); if (err < 0) return err; - for (i = 0; i < info->level_input_count; i++) - private->level_switch[i] = level_switches[i]; - } - if (info->pad_input_count) { - err = scarlett2_usb_get_config( - mixer, - SCARLETT2_CONFIG_PAD_SWITCH, - info->pad_input_count, - pad_switches); - if (err < 0) - return err; - for (i = 0; i < info->pad_input_count; i++) - private->pad_switch[i] = pad_switches[i]; + /* no other controls are created if MSD mode is on */ + if (private->msd_switch) + return 0; } + err = scarlett2_update_input_other(mixer); + if (err < 0) + return err; + + err = scarlett2_update_monitor_other(mixer); + if (err < 0) + return err; + + /* the rest of the configuration is for devices with a mixer */ + if (!info->has_mixer) + return 0; + + err = scarlett2_update_sync(mixer); + if (err < 0) + return err; + err = scarlett2_usb_get_volume_status(mixer, &volume_status); if (err < 0) return err; + if (info->line_out_hw_vol) + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) + private->dim_mute[i] = !!volume_status.dim_mute[i]; + private->master_vol = clamp( volume_status.master_vol + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); for (i = 0; i < num_line_out; i++) { - int volume; + int volume, mute; private->vol_sw_hw_switch[i] = info->line_out_hw_vol @@ -1889,72 +3648,178 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) volume = clamp(volume + SCARLETT2_VOLUME_BIAS, 0, SCARLETT2_VOLUME_BIAS); private->vol[i] = volume; + + mute = private->vol_sw_hw_switch[i] + ? private->dim_mute[SCARLETT2_BUTTON_MUTE] + : volume_status.mute_switch[i]; + private->mute_switch[i] = mute; + } + + for (i = 0; i < num_mixer_out; i++) { + err = scarlett2_usb_get_mix(mixer, i); + if (err < 0) + return err; } - for (i = 0; i < info->button_count; i++) - private->buttons[i] = !!volume_status.buttons[i]; + return scarlett2_usb_get_mux(mixer); +} - return 0; +/* Notify on sync change */ +static void scarlett2_notify_sync( + struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + + private->sync_updated = 1; + + snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->sync_ctl->id); } -/* Notify on volume change */ -static void scarlett2_mixer_interrupt_vol_change( +/* Notify on monitor change */ +static void scarlett2_notify_monitor( struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; - const struct scarlett2_ports *ports = private->info->ports; + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int num_line_out = - ports[SCARLETT2_PORT_TYPE_ANALOGUE].num[SCARLETT2_PORT_OUT]; + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int i; + /* if line_out_hw_vol is 0, there are no controls to update */ + if (!info->line_out_hw_vol) + return; + private->vol_updated = 1; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &private->master_vol_ctl->id); - for (i = 0; i < num_line_out; i++) { - if (!private->vol_sw_hw_switch[i]) - continue; - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->vol_ctls[i]->id); - } + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->vol_ctls[i]->id); } -/* Notify on button change */ -static void scarlett2_mixer_interrupt_button_change( +/* Notify on dim/mute change */ +static void scarlett2_notify_dim_mute( struct usb_mixer_interface *mixer) { - struct scarlett2_mixer_data *private = mixer->private_data; + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; + int num_line_out = + port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT]; int i; private->vol_updated = 1; - for (i = 0; i < private->info->button_count; i++) - snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &private->button_ctls[i]->id); + if (!info->line_out_hw_vol) + return; + + for (i = 0; i < SCARLETT2_DIM_MUTE_COUNT; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->dim_mute_ctls[i]->id); + + for (i = 0; i < num_line_out; i++) + if (private->vol_sw_hw_switch[line_out_remap(private, i)]) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mute_ctls[i]->id); +} + +/* Notify on "input other" change (level/pad/air) */ +static void scarlett2_notify_input_other( + struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + int i; + + private->input_other_updated = 1; + + for (i = 0; i < info->level_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->level_ctls[i]->id); + for (i = 0; i < info->pad_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->pad_ctls[i]->id); + for (i = 0; i < info->air_input_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->air_ctls[i]->id); + for (i = 0; i < info->phantom_count; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->phantom_ctls[i]->id); +} + +/* Notify on "monitor other" change (direct monitor, speaker + * switching, talkback) + */ +static void scarlett2_notify_monitor_other( + struct usb_mixer_interface *mixer) +{ + struct snd_card *card = mixer->chip->card; + struct scarlett2_data *private = mixer->private_data; + const struct scarlett2_device_info *info = private->info; + + private->monitor_other_updated = 1; + + if (info->direct_monitor) { + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->direct_monitor_ctl->id); + return; + } + + if (info->has_speaker_switching) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->speaker_switching_ctl->id); + + if (info->has_talkback) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->talkback_ctl->id); + + /* if speaker switching was recently enabled or disabled, + * invalidate the dim/mute and mux enum controls + */ + if (private->speaker_switching_switched) { + int i; + + scarlett2_notify_dim_mute(mixer); + + private->speaker_switching_switched = 0; + private->mux_updated = 1; + + for (i = 0; i < private->num_mux_dsts; i++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &private->mux_ctls[i]->id); + } } /* Interrupt callback */ -static void scarlett2_mixer_interrupt(struct urb *urb) +static void scarlett2_notify(struct urb *urb) { struct usb_mixer_interface *mixer = urb->context; int len = urb->actual_length; int ustatus = urb->status; u32 data; - if (ustatus != 0) + if (ustatus != 0 || len != 8) goto requeue; - if (len == 8) { - data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); - if (data & SCARLETT2_USB_INTERRUPT_VOL_CHANGE) - scarlett2_mixer_interrupt_vol_change(mixer); - if (data & SCARLETT2_USB_INTERRUPT_BUTTON_CHANGE) - scarlett2_mixer_interrupt_button_change(mixer); - } else { - usb_audio_err(mixer->chip, - "scarlett mixer interrupt length %d\n", len); - } + data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); + if (data & SCARLETT2_USB_NOTIFY_SYNC) + scarlett2_notify_sync(mixer); + if (data & SCARLETT2_USB_NOTIFY_MONITOR) + scarlett2_notify_monitor(mixer); + if (data & SCARLETT2_USB_NOTIFY_DIM_MUTE) + scarlett2_notify_dim_mute(mixer); + if (data & SCARLETT2_USB_NOTIFY_INPUT_OTHER) + scarlett2_notify_input_other(mixer); + if (data & SCARLETT2_USB_NOTIFY_MONITOR_OTHER) + scarlett2_notify_monitor_other(mixer); requeue: if (ustatus != -ENOENT && @@ -1965,11 +3830,11 @@ requeue: } } -static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer) +static int scarlett2_init_notify(struct usb_mixer_interface *mixer) { struct usb_device *dev = mixer->chip->dev; - unsigned int pipe = usb_rcvintpipe(dev, - SCARLETT2_USB_INTERRUPT_ENDPOINT); + struct scarlett2_data *private = mixer->private_data; + unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress); void *transfer_buffer; if (mixer->urb) { @@ -1985,25 +3850,35 @@ static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer) if (!mixer->urb) return -ENOMEM; - transfer_buffer = kmalloc(SCARLETT2_USB_INTERRUPT_MAX_DATA, GFP_KERNEL); + transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); if (!transfer_buffer) return -ENOMEM; usb_fill_int_urb(mixer->urb, dev, pipe, - transfer_buffer, SCARLETT2_USB_INTERRUPT_MAX_DATA, - scarlett2_mixer_interrupt, mixer, - SCARLETT2_USB_INTERRUPT_INTERVAL); + transfer_buffer, private->wMaxPacketSize, + scarlett2_notify, mixer, private->bInterval); return usb_submit_urb(mixer->urb, GFP_KERNEL); } -static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, - const struct scarlett2_device_info *info) +static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer) { + const struct scarlett2_device_info **info = scarlett2_devices; int err; - /* Initialise private data, routing, sequence number */ - err = scarlett2_init_private(mixer, info); + /* Find device in scarlett2_devices */ + while (*info && (*info)->usb_id != mixer->chip->usb_id) + info++; + if (!*info) + return -EINVAL; + + /* Initialise private data */ + err = scarlett2_init_private(mixer, *info); + if (err < 0) + return err; + + /* Send proprietary USB initialisation sequence */ + err = scarlett2_usb_init(mixer); if (err < 0) return err; @@ -2012,6 +3887,15 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, if (err < 0) return err; + /* Create the MSD control */ + err = scarlett2_add_msd_ctl(mixer); + if (err < 0) + return err; + + /* If MSD mode is enabled, don't create any other controls */ + if (((struct scarlett2_data *)mixer->private_data)->msd_switch) + return 0; + /* Create the analogue output controls */ err = scarlett2_add_line_out_ctls(mixer); if (err < 0) @@ -2037,12 +3921,30 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, if (err < 0) return err; - /* Set up the interrupt polling if there are hardware buttons */ - if (info->button_count) { - err = scarlett2_mixer_status_create(mixer); - if (err < 0) - return err; - } + /* Create the sync control */ + err = scarlett2_add_sync_ctl(mixer); + if (err < 0) + return err; + + /* Create the direct monitor control */ + err = scarlett2_add_direct_monitor_ctl(mixer); + if (err < 0) + return err; + + /* Create the speaker switching control */ + err = scarlett2_add_speaker_switch_ctl(mixer); + if (err < 0) + return err; + + /* Create the talkback controls */ + err = scarlett2_add_talkback_ctls(mixer); + if (err < 0) + return err; + + /* Set up the interrupt polling */ + err = scarlett2_init_notify(mixer); + if (err < 0) + return err; return 0; } @@ -2050,30 +3952,15 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) { struct snd_usb_audio *chip = mixer->chip; - const struct scarlett2_device_info *info; int err; /* only use UAC_VERSION_2 */ if (!mixer->protocol) return 0; - switch (chip->usb_id) { - case USB_ID(0x1235, 0x8203): - info = &s6i6_gen2_info; - break; - case USB_ID(0x1235, 0x8204): - info = &s18i8_gen2_info; - break; - case USB_ID(0x1235, 0x8201): - info = &s18i20_gen2_info; - break; - default: /* device not (yet) supported */ - return -EINVAL; - } - if (!(chip->setup & SCARLETT2_ENABLE)) { usb_audio_info(chip, - "Focusrite Scarlett Gen 2 Mixer Driver disabled; " + "Focusrite Scarlett Gen 2/3 Mixer Driver disabled; " "use options snd_usb_audio vid=0x%04x pid=0x%04x " "device_setup=1 to enable and report any issues " "to g@b4.vu", @@ -2083,10 +3970,10 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer) } usb_audio_info(chip, - "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x", + "Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x%04x", USB_ID_PRODUCT(chip->usb_id)); - err = snd_scarlett_gen2_controls_create(mixer, info); + err = snd_scarlett_gen2_controls_create(mixer); if (err < 0) usb_audio_err(mixer->chip, "Error initialising Scarlett Mixer Driver: %d", diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e5311b6bb3f6..4e5031a68064 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -29,15 +29,21 @@ #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 /* return the estimated delay based on USB frame counters */ -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate) +static snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, + struct snd_pcm_runtime *runtime) { - int current_frame_number; - int frame_diff; + unsigned int current_frame_number; + unsigned int frame_diff; int est_delay; + int queued; - if (!subs->last_delay) - return 0; /* short path */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + queued = bytes_to_frames(runtime, subs->inflight_bytes); + if (!queued) + return 0; + } else if (!subs->running) { + return 0; + } current_frame_number = usb_get_current_frame_number(subs->dev); /* @@ -49,14 +55,14 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, /* Approximation based on number of samples per USB frame (ms), some truncation for 44.1 but the estimate is good enough */ - est_delay = frame_diff * rate / 1000; - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - est_delay = subs->last_delay - est_delay; - else - est_delay = subs->last_delay + est_delay; + est_delay = frame_diff * runtime->rate / 1000; + + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { + est_delay = queued - est_delay; + if (est_delay < 0) + est_delay = 0; + } - if (est_delay < 0) - est_delay = 0; return est_delay; } @@ -65,17 +71,17 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, */ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_usb_substream *subs = substream->runtime->private_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_usb_substream *subs = runtime->private_data; unsigned int hwptr_done; if (atomic_read(&subs->stream->chip->shutdown)) return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; - substream->runtime->delay = snd_usb_pcm_delay(subs, - substream->runtime->rate); + runtime->delay = snd_usb_pcm_delay(subs, runtime); spin_unlock(&subs->lock); - return hwptr_done / (substream->runtime->frame_bits >> 3); + return bytes_to_frames(runtime, hwptr_done); } /* @@ -600,17 +606,14 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; /* reset the pointer */ + subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); + subs->inflight_bytes = 0; subs->hwptr_done = 0; subs->transfer_done = 0; - subs->last_delay = 0; subs->last_frame_number = 0; + subs->period_elapsed_pending = 0; runtime->delay = 0; - /* for playback, submit the URBs now; otherwise, the first hwptr_done - * updates for all URBs would happen at the same time when starting */ - if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) - ret = start_endpoints(subs); - unlock: snd_usb_unlock_shutdown(chip); return ret; @@ -1147,28 +1150,23 @@ static void retire_capture_urb(struct snd_usb_substream *subs, spin_lock_irqsave(&subs->lock, flags); oldptr = subs->hwptr_done; subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; frames = (bytes + (oldptr % stride)) / stride; subs->transfer_done += frames; if (subs->transfer_done >= runtime->period_size) { subs->transfer_done -= runtime->period_size; period_elapsed = 1; } - /* capture delay is by construction limited to one URB, - * reset delays here - */ - runtime->delay = subs->last_delay = 0; /* realign last_frame_number */ subs->last_frame_number = current_frame_number; - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ spin_unlock_irqrestore(&subs->lock, flags); /* copy a data chunk */ - if (oldptr + bytes > runtime->buffer_size * stride) { - unsigned int bytes1 = - runtime->buffer_size * stride - oldptr; + if (oldptr + bytes > subs->buffer_bytes) { + unsigned int bytes1 = subs->buffer_bytes - oldptr; + memcpy(runtime->dma_area + oldptr, cp, bytes1); memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1); } else { @@ -1180,17 +1178,29 @@ static void retire_capture_urb(struct snd_usb_substream *subs, snd_pcm_period_elapsed(subs->pcm_substream); } +static void urb_ctx_queue_advance(struct snd_usb_substream *subs, + struct urb *urb, unsigned int bytes) +{ + struct snd_urb_ctx *ctx = urb->context; + + ctx->queued += bytes; + subs->inflight_bytes += bytes; + subs->hwptr_done += bytes; + if (subs->hwptr_done >= subs->buffer_bytes) + subs->hwptr_done -= subs->buffer_bytes; +} + static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, struct urb *urb, unsigned int bytes) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - unsigned int stride = runtime->frame_bits >> 3; unsigned int dst_idx = 0; unsigned int src_idx = subs->hwptr_done; - unsigned int wrap = runtime->buffer_size * stride; + unsigned int wrap = subs->buffer_bytes; u8 *dst = urb->transfer_buffer; u8 *src = runtime->dma_area; u8 marker[] = { 0x05, 0xfa }; + unsigned int queued = 0; /* * The DSP DOP format defines a way to transport DSD samples over @@ -1229,12 +1239,29 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, dst[dst_idx++] = bitrev8(src[idx]); else dst[dst_idx++] = src[idx]; - - subs->hwptr_done++; + queued++; } } - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + + urb_ctx_queue_advance(subs, urb, queued); +} + +/* copy bit-reversed bytes onto transfer buffer */ +static void fill_playback_urb_dsd_bitrev(struct snd_usb_substream *subs, + struct urb *urb, unsigned int bytes) +{ + struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; + const u8 *src = runtime->dma_area; + u8 *buf = urb->transfer_buffer; + int i, ofs = subs->hwptr_done; + + for (i = 0; i < bytes; i++) { + *buf++ = bitrev8(src[ofs]); + if (++ofs >= subs->buffer_bytes) + ofs = 0; + } + + urb_ctx_queue_advance(subs, urb, bytes); } static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, @@ -1242,10 +1269,10 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { + if (subs->hwptr_done + bytes > subs->buffer_bytes) { /* err, the transferred area goes over buffer boundary. */ - unsigned int bytes1 = - runtime->buffer_size * stride - subs->hwptr_done; + unsigned int bytes1 = subs->buffer_bytes - subs->hwptr_done; + memcpy(urb->transfer_buffer + offset, runtime->dma_area + subs->hwptr_done, bytes1); memcpy(urb->transfer_buffer + offset + bytes1, @@ -1254,9 +1281,8 @@ static void copy_to_urb(struct snd_usb_substream *subs, struct urb *urb, memcpy(urb->transfer_buffer + offset, runtime->dma_area + subs->hwptr_done, bytes); } - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + + urb_ctx_queue_advance(subs, urb, bytes); } static unsigned int copy_to_urb_quirk(struct snd_usb_substream *subs, @@ -1295,17 +1321,18 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, int i, stride, period_elapsed = 0; unsigned long flags; - stride = runtime->frame_bits >> 3; + stride = ep->stride; frames = 0; + ctx->queued = 0; urb->number_of_packets = 0; spin_lock_irqsave(&subs->lock, flags); subs->frame_limit += ep->max_urb_frames; for (i = 0; i < ctx->packets; i++) { counts = snd_usb_endpoint_next_packet_size(ep, ctx, i); /* set up descriptor */ - urb->iso_frame_desc[i].offset = frames * ep->stride; - urb->iso_frame_desc[i].length = counts * ep->stride; + urb->iso_frame_desc[i].offset = frames * stride; + urb->iso_frame_desc[i].length = counts * stride; frames += counts; urb->number_of_packets++; subs->transfer_done += counts; @@ -1320,14 +1347,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, frames -= subs->transfer_done; counts -= subs->transfer_done; urb->iso_frame_desc[i].length = - counts * ep->stride; + counts * stride; subs->transfer_done = 0; } i++; if (i < ctx->packets) { /* add a transfer delimiter */ urb->iso_frame_desc[i].offset = - frames * ep->stride; + frames * stride; urb->iso_frame_desc[i].length = 0; urb->number_of_packets++; } @@ -1340,24 +1367,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, !snd_usb_endpoint_implicit_feedback_sink(ep)) break; } - bytes = frames * ep->stride; + bytes = frames * stride; if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && subs->cur_audiofmt->dsd_dop)) { fill_playback_urb_dsd_dop(subs, urb, bytes); } else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 && subs->cur_audiofmt->dsd_bitrev)) { - /* bit-reverse the bytes */ - u8 *buf = urb->transfer_buffer; - for (i = 0; i < bytes; i++) { - int idx = (subs->hwptr_done + i) - % (runtime->buffer_size * stride); - buf[i] = bitrev8(runtime->dma_area[idx]); - } - - subs->hwptr_done += bytes; - if (subs->hwptr_done >= runtime->buffer_size * stride) - subs->hwptr_done -= runtime->buffer_size * stride; + fill_playback_urb_dsd_bitrev(subs, urb, bytes); } else { /* usual PCM */ if (!subs->tx_length_quirk) @@ -1367,14 +1384,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, /* bytes is now amount of outgoing data */ } - /* update delay with exact number of samples queued */ - runtime->delay = subs->last_delay; - runtime->delay += frames; - subs->last_delay = runtime->delay; - - /* realign last_frame_number */ subs->last_frame_number = usb_get_current_frame_number(subs->dev); - subs->last_frame_number &= 0xFF; /* keep 8 LSBs */ if (subs->trigger_tstamp_pending_update) { /* this is the first actual URB submitted, @@ -1384,6 +1394,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, subs->trigger_tstamp_pending_update = false; } + if (period_elapsed && !subs->running) { + subs->period_elapsed_pending = 1; + period_elapsed = 0; + } spin_unlock_irqrestore(&subs->lock, flags); urb->transfer_buffer_length = bytes; if (period_elapsed) @@ -1398,55 +1412,32 @@ static void retire_playback_urb(struct snd_usb_substream *subs, struct urb *urb) { unsigned long flags; - struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - struct snd_usb_endpoint *ep = subs->data_endpoint; - int processed = urb->transfer_buffer_length / ep->stride; - int est_delay; - - /* ignore the delay accounting when processed=0 is given, i.e. - * silent payloads are processed before handling the actual data - */ - if (!processed) - return; + struct snd_urb_ctx *ctx = urb->context; + bool period_elapsed = false; spin_lock_irqsave(&subs->lock, flags); - if (!subs->last_delay) - goto out; /* short path */ - - est_delay = snd_usb_pcm_delay(subs, runtime->rate); - /* update delay with exact number of samples played */ - if (processed > subs->last_delay) - subs->last_delay = 0; - else - subs->last_delay -= processed; - runtime->delay = subs->last_delay; - - /* - * Report when delay estimate is off by more than 2ms. - * The error should be lower than 2ms since the estimate relies - * on two reads of a counter updated every ms. - */ - if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2) - dev_dbg_ratelimited(&subs->dev->dev, - "delay: estimated %d, actual %d\n", - est_delay, subs->last_delay); - - if (!subs->running) { - /* update last_frame_number for delay counting here since - * prepare_playback_urb won't be called during pause - */ - subs->last_frame_number = - usb_get_current_frame_number(subs->dev) & 0xff; + if (ctx->queued) { + if (subs->inflight_bytes >= ctx->queued) + subs->inflight_bytes -= ctx->queued; + else + subs->inflight_bytes = 0; } - out: + subs->last_frame_number = usb_get_current_frame_number(subs->dev); + if (subs->running) { + period_elapsed = subs->period_elapsed_pending; + subs->period_elapsed_pending = 0; + } spin_unlock_irqrestore(&subs->lock, flags); + if (period_elapsed) + snd_pcm_period_elapsed(subs->pcm_substream); } static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_usb_substream *subs = substream->runtime->private_data; + int err; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -1457,6 +1448,14 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea prepare_playback_urb, retire_playback_urb, subs); + if (cmd == SNDRV_PCM_TRIGGER_START) { + err = start_endpoints(subs); + if (err < 0) { + snd_usb_endpoint_set_callback(subs->data_endpoint, + NULL, NULL, NULL); + return err; + } + } subs->running = 1; dev_dbg(&subs->dev->dev, "%d:%d Start Playback PCM\n", subs->cur_audiofmt->iface, @@ -1504,6 +1503,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, retire_capture_urb, subs); + subs->last_frame_number = usb_get_current_frame_number(subs->dev); subs->running = 1; dev_dbg(&subs->dev->dev, "%d:%d Start Capture PCM\n", subs->cur_audiofmt->iface, diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h index 06c586467d3f..493a4e34d78d 100644 --- a/sound/usb/pcm.h +++ b/sound/usb/pcm.h @@ -2,9 +2,6 @@ #ifndef __USBAUDIO_PCM_H #define __USBAUDIO_PCM_H -snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs, - unsigned int rate); - void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream); int snd_usb_pcm_suspend(struct snd_usb_stream *as); int snd_usb_pcm_resume(struct snd_usb_stream *as); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index bdba37d0faab..19bb499c17da 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3044,6 +3044,76 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } }, +/* Denon DN-X1600 */ +{ + USB_AUDIO_DEVICE(0x154e, 0x500e), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Denon", + .product_name = "DN-X1600", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]){ + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE, + }, + { + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 1, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x0, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ADAPTIVE, + .maxpacksize = 0x138, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 8, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x0, + .endpoint = 0x85, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ADAPTIVE, + .maxpacksize = 0x138, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_STANDARD_INTERFACE, + }, + { + .ifnum = -1 + } + } + } +}, + /* Microsoft XboxLive Headset/Xbox Communicator */ { USB_DEVICE(0x045e, 0x0283), diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 6e1bfe894dd5..e558931cce16 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -49,7 +49,7 @@ static int us122l_create_usbmidi(struct snd_card *card) static const struct snd_usb_audio_quirk quirk = { .vendor_name = "US122L", .product_name = NAME_ALLCAPS, - .ifnum = 1, + .ifnum = 1, .type = QUIRK_MIDI_US122L, .data = &quirk_data }; @@ -71,7 +71,7 @@ static int us144_create_usbmidi(struct snd_card *card) static const struct snd_usb_audio_quirk quirk = { .vendor_name = "US144", .product_name = NAME_ALLCAPS, - .ifnum = 0, + .ifnum = 0, .type = QUIRK_MIDI_US122L, .data = &quirk_data }; @@ -95,6 +95,7 @@ static void pt_info_set(struct usb_device *dev, u8 v) static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) { struct us122l *us122l = area->vm_private_data; + atomic_inc(&us122l->mmap_count); snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } @@ -113,9 +114,9 @@ static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf) goto unlock; offset = vmf->pgoff << PAGE_SHIFT; - if (offset < PAGE_ALIGN(s->read_size)) + if (offset < PAGE_ALIGN(s->read_size)) { vaddr = (char *)s + offset; - else { + } else { offset -= PAGE_ALIGN(s->read_size); if (offset >= PAGE_ALIGN(s->write_size)) goto unlock; @@ -138,6 +139,7 @@ unlock: static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) { struct us122l *us122l = area->vm_private_data; + atomic_dec(&us122l->mmap_count); snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } @@ -148,11 +150,11 @@ static const struct vm_operations_struct usb_stream_hwdep_vm_ops = { .close = usb_stream_hwdep_vm_close, }; - static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) { struct us122l *us122l = hw->private_data; struct usb_interface *iface; + snd_printdd(KERN_DEBUG "%p %p\n", hw, file); if (hw->used >= 2) return -EBUSY; @@ -173,6 +175,7 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) { struct us122l *us122l = hw->private_data; struct usb_interface *iface; + snd_printdd(KERN_DEBUG "%p %p\n", hw, file); if (us122l->is_us144) { @@ -235,7 +238,7 @@ static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) { struct us122l *us122l = hw->private_data; - unsigned *polled; + unsigned int *polled; __poll_t mask; poll_wait(file, &us122l->sk.sleep, wait); @@ -243,6 +246,7 @@ static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw, mask = EPOLLIN | EPOLLOUT | EPOLLWRNORM | EPOLLERR; if (mutex_trylock(&us122l->mutex)) { struct usb_stream *s = us122l->sk.s; + if (s && s->state == usb_stream_ready) { if (us122l->first == file) polled = &s->periods_polled; @@ -251,8 +255,9 @@ static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw, if (*polled != s->periods_done) { *polled = s->periods_done; mask = EPOLLIN | EPOLLOUT | EPOLLWRNORM; - } else + } else { mask = 0; + } } mutex_unlock(&us122l->mutex); } @@ -262,6 +267,7 @@ static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw, static void us122l_stop(struct us122l *us122l) { struct list_head *p; + list_for_each(p, &us122l->midi_list) snd_usbmidi_input_stop(p); @@ -289,11 +295,11 @@ static int us122l_set_sample_rate(struct usb_device *dev, int rate) } static bool us122l_start(struct us122l *us122l, - unsigned rate, unsigned period_frames) + unsigned int rate, unsigned int period_frames) { struct list_head *p; int err; - unsigned use_packsize = 0; + unsigned int use_packsize = 0; bool success = false; if (us122l->dev->speed == USB_SPEED_HIGH) { @@ -320,13 +326,13 @@ static bool us122l_start(struct us122l *us122l, err = us122l_set_sample_rate(us122l->dev, rate); if (err < 0) { us122l_stop(us122l); - snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); + snd_printk(KERN_ERR "us122l_set_sample_rate error\n"); goto out; } err = usb_stream_start(&us122l->sk); if (err < 0) { us122l_stop(us122l); - snd_printk(KERN_ERR "us122l_start error %i \n", err); + snd_printk(KERN_ERR "%s error %i\n", __func__, err); goto out; } list_for_each(p, &us122l->midi_list) @@ -337,12 +343,12 @@ out: } static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, - unsigned cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct usb_stream_config cfg; struct us122l *us122l = hw->private_data; struct usb_stream *s; - unsigned min_period_frames; + unsigned int min_period_frames; int err = 0; bool high_speed; @@ -379,13 +385,13 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, if (cfg.period_frames < min_period_frames) return -EINVAL; - snd_power_wait(hw->card, SNDRV_CTL_POWER_D0); + snd_power_wait(hw->card); mutex_lock(&us122l->mutex); s = us122l->sk.s; - if (!us122l->master) + if (!us122l->master) { us122l->master = file; - else if (us122l->master != file) { + } else if (us122l->master != file) { if (!s || memcmp(&cfg, &s->cfg, sizeof(cfg))) { err = -EIO; goto unlock; @@ -431,7 +437,6 @@ static int usb_stream_hwdep_new(struct snd_card *card) return 0; } - static bool us122l_create_card(struct snd_card *card) { int err; @@ -440,13 +445,13 @@ static bool us122l_create_card(struct snd_card *card) if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error\n"); return false; } } err = usb_set_interface(us122l->dev, 1, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error\n"); return false; } @@ -461,13 +466,14 @@ static bool us122l_create_card(struct snd_card *card) else err = us122l_create_usbmidi(card); if (err < 0) { - snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err); + snd_printk(KERN_ERR "us122l_create_usbmidi error %i\n", err); goto stop; } err = usb_stream_hwdep_new(card); if (err < 0) { -/* release the midi resources */ + /* release the midi resources */ struct list_head *p; + list_for_each(p, &us122l->midi_list) snd_usbmidi_disconnect(p); @@ -484,7 +490,8 @@ static void snd_us122l_free(struct snd_card *card) { struct us122l *us122l = US122L(card); int index = us122l->card_index; - if (index >= 0 && index < SNDRV_CARDS) + + if (index >= 0 && index < SNDRV_CARDS) snd_us122l_card_used[index] = 0; } @@ -565,7 +572,7 @@ static int snd_us122l_probe(struct usb_interface *intf, if (id->driver_info & US122L_FLAG_US144 && device->speed == USB_SPEED_HIGH) { - snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n"); + snd_printk(KERN_ERR "disable ehci-hcd to run US-144\n"); return -ENODEV; } @@ -601,7 +608,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf) us122l_stop(us122l); mutex_unlock(&us122l->mutex); -/* release the midi resources */ + /* release the midi resources */ list_for_each(p, &us122l->midi_list) { snd_usbmidi_disconnect(p); } @@ -661,13 +668,13 @@ static int snd_us122l_resume(struct usb_interface *intf) if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error\n"); goto unlock; } } err = usb_set_interface(us122l->dev, 1, 1); if (err) { - snd_printk(KERN_ERR "usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error\n"); goto unlock; } @@ -677,7 +684,7 @@ static int snd_us122l_resume(struct usb_interface *intf) err = us122l_set_sample_rate(us122l->dev, us122l->sk.s->cfg.sample_rate); if (err < 0) { - snd_printk(KERN_ERR "us122l_set_sample_rate error \n"); + snd_printk(KERN_ERR "us122l_set_sample_rate error\n"); goto unlock; } err = usb_stream_start(&us122l->sk); @@ -717,8 +724,8 @@ static const struct usb_device_id snd_us122l_usb_id_table[] = { }, { /* terminator */ } }; - MODULE_DEVICE_TABLE(usb, snd_us122l_usb_id_table); + static struct usb_driver snd_us122l_usb_driver = { .name = "snd-usb-us122l", .probe = snd_us122l_probe, diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h index 34bea99d343c..c32ae5e981e9 100644 --- a/sound/usb/usx2y/us122l.h +++ b/sound/usb/usx2y/us122l.h @@ -11,7 +11,7 @@ struct us122l { struct mutex mutex; struct file *first; - unsigned second_periods_polled; + unsigned int second_periods_polled; struct file *master; struct file *slave; struct list_head midi_list; diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 22412cd69e98..c29da0341bc5 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -21,15 +21,15 @@ static vm_fault_t snd_us428ctls_vm_fault(struct vm_fault *vmf) { unsigned long offset; - struct page * page; + struct page *page; void *vaddr; snd_printdd("ENTER, start %lXh, pgoff %ld\n", vmf->vma->vm_start, vmf->pgoff); - + offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; page = virt_to_page(vaddr); get_page(page); vmf->page = page; @@ -44,30 +44,22 @@ static const struct vm_operations_struct us428ctls_vm_ops = { .fault = snd_us428ctls_vm_fault, }; -static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) +static int snd_us428ctls_mmap(struct snd_hwdep *hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; // FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs? // so as long as the device isn't fully initialised yet we return -EBUSY here. - if (!(us428->chip_status & USX2Y_STAT_CHIP_INIT)) + if (!(us428->chip_status & USX2Y_STAT_CHIP_INIT)) return -EBUSY; - /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct us428ctls_sharedmem))) { - snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(struct us428ctls_sharedmem)); - return -EINVAL; + /* if userspace tries to mmap beyond end of our buffer, fail */ + if (size > US428_SHAREDMEM_PAGES) { + snd_printd("%lu > %lu\n", size, (unsigned long)US428_SHAREDMEM_PAGES); + return -EINVAL; } - if (!us428->us428ctls_sharedmem) { - init_waitqueue_head(&us428->us428ctls_wait_queue_head); - us428->us428ctls_sharedmem = alloc_pages_exact(sizeof(struct us428ctls_sharedmem), GFP_KERNEL); - if (!us428->us428ctls_sharedmem) - return -ENOMEM; - memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); - us428->us428ctls_sharedmem->CtlSnapShotLast = -2; - } area->vm_ops = &us428ctls_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; area->vm_private_data = hw->private_data; @@ -77,21 +69,22 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v static __poll_t snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) { __poll_t mask = 0; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; struct us428ctls_sharedmem *shm = us428->us428ctls_sharedmem; + if (us428->chip_status & USX2Y_STAT_CHIP_HUP) return EPOLLHUP; poll_wait(file, &us428->us428ctls_wait_queue_head, wait); - if (shm != NULL && shm->CtlSnapShotLast != shm->CtlSnapShotRed) + if (shm && shm->ctl_snapshot_last != shm->ctl_snapshot_red) mask |= EPOLLIN; return mask; } -static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { static const char * const type_ids[USX2Y_TYPE_NUMS] = { @@ -99,7 +92,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, [USX2Y_TYPE_224] = "us224", [USX2Y_TYPE_428] = "us428", }; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; int id = -1; switch (le16_to_cpu(us428->dev->descriptor.idProduct)) { @@ -113,7 +106,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, id = USX2Y_TYPE_428; break; } - if (0 > id) + if (id < 0) return -ENODEV; strcpy(info->id, type_ids[id]); info->num_dsps = 2; // 0: Prepad Data, 1: FPGA Code @@ -123,8 +116,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, return 0; } - -static int usX2Y_create_usbmidi(struct snd_card *card) +static int usx2y_create_usbmidi(struct snd_card *card) { static const struct snd_usb_midi_endpoint_info quirk_data_1 = { .out_ep = 0x06, @@ -135,8 +127,8 @@ static int usX2Y_create_usbmidi(struct snd_card *card) static const struct snd_usb_audio_quirk quirk_1 = { .vendor_name = "TASCAM", .product_name = NAME_ALLCAPS, - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_1 }; static const struct snd_usb_midi_endpoint_info quirk_data_2 = { @@ -148,49 +140,50 @@ static int usX2Y_create_usbmidi(struct snd_card *card) static const struct snd_usb_audio_quirk quirk_2 = { .vendor_name = "TASCAM", .product_name = "US428", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, + .ifnum = 0, + .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_2 }; - struct usb_device *dev = usX2Y(card)->dev; + struct usb_device *dev = usx2y(card)->dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 0); const struct snd_usb_audio_quirk *quirk = le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1; - snd_printdd("usX2Y_create_usbmidi \n"); - return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk); + snd_printdd("%s\n", __func__); + return snd_usbmidi_create(card, iface, &usx2y(card)->midi_list, quirk); } -static int usX2Y_create_alsa_devices(struct snd_card *card) +static int usx2y_create_alsa_devices(struct snd_card *card) { int err; - do { - if ((err = usX2Y_create_usbmidi(card)) < 0) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); - break; - } - if ((err = usX2Y_audio_create(card)) < 0) - break; - if ((err = usX2Y_hwdep_pcm_new(card)) < 0) - break; - if ((err = snd_card_register(card)) < 0) - break; - } while (0); - - return err; -} + err = usx2y_create_usbmidi(card); + if (err < 0) { + snd_printk(KERN_ERR "%s: usx2y_create_usbmidi error %i\n", __func__, err); + return err; + } + err = usx2y_audio_create(card); + if (err < 0) + return err; + err = usx2y_hwdep_pcm_new(card); + if (err < 0) + return err; + err = snd_card_register(card); + if (err < 0) + return err; + return 0; +} -static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_load(struct snd_hwdep *hw, struct snd_hwdep_dsp_image *dsp) { - struct usX2Ydev *priv = hw->private_data; - struct usb_device* dev = priv->dev; + struct usx2ydev *priv = hw->private_data; + struct usb_device *dev = priv->dev; int lret, err; char *buf; - snd_printdd( "dsp_load %s\n", dsp->name); + snd_printdd("dsp_load %s\n", dsp->name); buf = memdup_user(dsp->image, dsp->length); if (IS_ERR(buf)) @@ -198,7 +191,7 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, err = usb_set_interface(dev, 0, 1); if (err) - snd_printk(KERN_ERR "usb_set_interface error \n"); + snd_printk(KERN_ERR "usb_set_interface error\n"); else err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000); kfree(buf); @@ -206,45 +199,51 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, return err; if (dsp->index == 1) { msleep(250); // give the device some time - err = usX2Y_AsyncSeq04_init(priv); + err = usx2y_async_seq04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); + snd_printk(KERN_ERR "usx2y_async_seq04_init error\n"); return err; } - err = usX2Y_In04_init(priv); + err = usx2y_in04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_In04_init error \n"); + snd_printk(KERN_ERR "usx2y_in04_init error\n"); return err; } - err = usX2Y_create_alsa_devices(hw->card); + err = usx2y_create_alsa_devices(hw->card); if (err) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); - snd_card_free(hw->card); + snd_printk(KERN_ERR "usx2y_create_alsa_devices error %i\n", err); return err; } - priv->chip_status |= USX2Y_STAT_CHIP_INIT; + priv->chip_status |= USX2Y_STAT_CHIP_INIT; snd_printdd("%s: alsa all started\n", hw->name); } return err; } - -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) +int usx2y_hwdep_new(struct snd_card *card, struct usb_device *device) { int err; struct snd_hwdep *hw; + struct usx2ydev *us428 = usx2y(card); - if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0) + err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw); + if (err < 0) return err; hw->iface = SNDRV_HWDEP_IFACE_USX2Y; - hw->private_data = usX2Y(card); - hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; - hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; + hw->private_data = us428; + hw->ops.dsp_status = snd_usx2y_hwdep_dsp_status; + hw->ops.dsp_load = snd_usx2y_hwdep_dsp_load; hw->ops.mmap = snd_us428ctls_mmap; hw->ops.poll = snd_us428ctls_poll; hw->exclusive = 1; sprintf(hw->name, "/dev/bus/usb/%03d/%03d", device->bus->busnum, device->devnum); + + us428->us428ctls_sharedmem = alloc_pages_exact(US428_SHAREDMEM_PAGES, GFP_KERNEL); + if (!us428->us428ctls_sharedmem) + return -ENOMEM; + memset(us428->us428ctls_sharedmem, -1, US428_SHAREDMEM_PAGES); + us428->us428ctls_sharedmem->ctl_snapshot_last = -2; + return 0; } - diff --git a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h index 457199b5ed03..0c9946d9cd99 100644 --- a/sound/usb/usx2y/usX2Yhwdep.h +++ b/sound/usb/usx2y/usX2Yhwdep.h @@ -2,6 +2,6 @@ #ifndef USX2YHWDEP_H #define USX2YHWDEP_H -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device); +int usx2y_hwdep_new(struct snd_card *card, struct usb_device *device); #endif diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 091c071b270a..9d0e44793896 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -8,12 +8,12 @@ #include "usb_stream.h" - /* setup */ -static unsigned usb_stream_next_packet_size(struct usb_stream_kernel *sk) +static unsigned int usb_stream_next_packet_size(struct usb_stream_kernel *sk) { struct usb_stream *s = sk->s; + sk->out_phase_peeked = (sk->out_phase & 0xffff) + sk->freqn; return (sk->out_phase_peeked >> 16) * s->cfg.frame_size; } @@ -25,6 +25,7 @@ static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) for (pack = 0; pack < sk->n_o_ps; pack++) { int l = usb_stream_next_packet_size(sk); + if (s->idle_outsize + lb + l > s->period_size) goto check; @@ -43,9 +44,10 @@ check: lb, s->period_size); } -static int init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, - struct urb **urbs, char *transfer, - struct usb_device *dev, int pipe) +static int init_pipe_urbs(struct usb_stream_kernel *sk, + unsigned int use_packsize, + struct urb **urbs, char *transfer, + struct usb_device *dev, int pipe) { int u, p; int maxpacket = use_packsize ? @@ -56,6 +58,7 @@ static int init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, ++u, transfer += transfer_length) { struct urb *urb = urbs[u]; struct usb_iso_packet_descriptor *desc; + urb->transfer_buffer = transfer; urb->dev = dev; urb->pipe = pipe; @@ -80,13 +83,12 @@ static int init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, return 0; } -static int init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, - struct usb_device *dev, int in_pipe, int out_pipe) +static int init_urbs(struct usb_stream_kernel *sk, unsigned int use_packsize, + struct usb_device *dev, int in_pipe, int out_pipe) { struct usb_stream *s = sk->s; - char *indata = (char *)s + sizeof(*s) + - sizeof(struct usb_stream_packet) * - s->inpackets; + char *indata = + (char *)s + sizeof(*s) + sizeof(struct usb_stream_packet) * s->inpackets; int u; for (u = 0; u < USB_STREAM_NURBS; ++u) { @@ -107,12 +109,11 @@ static int init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, return 0; } - /* * convert a sampling rate into our full speed format (fs/1000 in Q16.16) * this will overflow at approx 524 kHz */ -static inline unsigned get_usb_full_speed_rate(unsigned rate) +static inline unsigned int get_usb_full_speed_rate(unsigned int rate) { return ((rate << 13) + 62) / 125; } @@ -121,7 +122,7 @@ static inline unsigned get_usb_full_speed_rate(unsigned rate) * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) * this will overflow at approx 4 MHz */ -static inline unsigned get_usb_high_speed_rate(unsigned rate) +static inline unsigned int get_usb_high_speed_rate(unsigned int rate) { return ((rate << 10) + 62) / 125; } @@ -129,7 +130,7 @@ static inline unsigned get_usb_high_speed_rate(unsigned rate) void usb_stream_free(struct usb_stream_kernel *sk) { struct usb_stream *s; - unsigned u; + unsigned int u; for (u = 0; u < USB_STREAM_NURBS; ++u) { usb_free_urb(sk->inurb[u]); @@ -142,17 +143,23 @@ void usb_stream_free(struct usb_stream_kernel *sk) if (!s) return; - free_pages_exact(sk->write_page, s->write_size); - sk->write_page = NULL; + if (sk->write_page) { + free_pages_exact(sk->write_page, s->write_size); + sk->write_page = NULL; + } + free_pages_exact(s, s->read_size); sk->s = NULL; } struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, struct usb_device *dev, - unsigned in_endpoint, unsigned out_endpoint, - unsigned sample_rate, unsigned use_packsize, - unsigned period_frames, unsigned frame_size) + unsigned int in_endpoint, + unsigned int out_endpoint, + unsigned int sample_rate, + unsigned int use_packsize, + unsigned int period_frames, + unsigned int frame_size) { int packets, max_packsize; int in_pipe, out_pipe; @@ -231,12 +238,12 @@ out: return sk->s; } - /* start */ static bool balance_check(struct usb_stream_kernel *sk, struct urb *urb) { bool r; + if (unlikely(urb->status)) { if (urb->status != -ESHUTDOWN && urb->status != -ENOENT) snd_printk(KERN_WARNING "status=%i\n", urb->status); @@ -267,6 +274,7 @@ static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) for (u = 0; u < USB_STREAM_NURBS; u++) { struct urb *urb = urbs[u]; + urb->complete = complete; } } @@ -284,6 +292,7 @@ static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, for (; s->sync_packet < 0; ++p, ++s->sync_packet) { struct urb *ii = sk->completed_inurb; + id = ii->iso_frame_desc + ii->number_of_packets + s->sync_packet; l = id->actual_length; @@ -351,6 +360,7 @@ static int submit_urbs(struct usb_stream_kernel *sk, struct urb *inurb, struct urb *outurb) { int err; + prepare_inurb(sk->idle_outurb->number_of_packets, sk->idle_inurb); err = usb_submit_urb(sk->idle_inurb, GFP_ATOMIC); if (err < 0) @@ -447,6 +457,7 @@ static void stream_idle(struct usb_stream_kernel *sk, for (p = 0; p < inurb->number_of_packets; ++p) { struct usb_iso_packet_descriptor *id = inurb->iso_frame_desc; + l = id[p].actual_length; if (unlikely(l == 0 || id[p].status)) { snd_printk(KERN_WARNING "underrun, status=%u\n", @@ -503,6 +514,7 @@ err_out: static void i_capture_idle(struct urb *urb) { struct usb_stream_kernel *sk = urb->context; + if (balance_capture(sk, urb)) stream_idle(sk, urb, sk->i_urb); } @@ -510,6 +522,7 @@ static void i_capture_idle(struct urb *urb) static void i_playback_idle(struct urb *urb) { struct usb_stream_kernel *sk = urb->context; + if (balance_playback(sk, urb)) stream_idle(sk, sk->i_urb, urb); } @@ -518,10 +531,12 @@ static void stream_start(struct usb_stream_kernel *sk, struct urb *inurb, struct urb *outurb) { struct usb_stream *s = sk->s; + if (s->state >= usb_stream_sync1) { int l, p, max_diff, max_diff_0; int urb_size = 0; - unsigned frames_per_packet, min_frames = 0; + unsigned int frames_per_packet, min_frames = 0; + frames_per_packet = (s->period_size - s->idle_insize); frames_per_packet <<= 8; frames_per_packet /= @@ -536,6 +551,7 @@ static void stream_start(struct usb_stream_kernel *sk, max_diff = max_diff_0; for (p = 0; p < inurb->number_of_packets; ++p) { int diff; + l = inurb->iso_frame_desc[p].actual_length; urb_size += l; @@ -561,7 +577,8 @@ static void stream_start(struct usb_stream_kernel *sk, (s->inpacket_head + 1) % s->inpackets; s->next_inpacket_split_at = 0; } else { - unsigned split = s->inpacket_head; + unsigned int split = s->inpacket_head; + l = s->idle_insize; while (l > s->inpacket[split].length) { l -= s->inpacket[split].length; @@ -609,6 +626,7 @@ static void i_capture_start(struct urb *urb) for (p = 0; p < urb->number_of_packets; ++p) { int l = id[p].actual_length; + if (l < s->cfg.frame_size) { ++empty; if (s->state >= usb_stream_sync0) { @@ -628,6 +646,7 @@ static void i_capture_start(struct urb *urb) urb->iso_frame_desc[0].actual_length); for (pack = 1; pack < urb->number_of_packets; ++pack) { int l = urb->iso_frame_desc[pack].actual_length; + printk(KERN_CONT " %i", l); } printk(KERN_CONT "\n"); @@ -643,6 +662,7 @@ static void i_capture_start(struct urb *urb) static void i_playback_start(struct urb *urb) { struct usb_stream_kernel *sk = urb->context; + if (balance_playback(sk, urb)) stream_start(sk, sk->i_urb, urb); } @@ -671,6 +691,7 @@ dotry: for (u = 0; u < 2; u++) { struct urb *inurb = sk->inurb[u]; struct urb *outurb = sk->outurb[u]; + playback_prep_freqn(sk, outurb); inurb->number_of_packets = outurb->number_of_packets; inurb->transfer_buffer_length = @@ -680,6 +701,7 @@ dotry: if (u == 0) { int now; struct usb_device *dev = inurb->dev; + frame = usb_get_current_frame_number(dev); do { now = usb_get_current_frame_number(dev); @@ -688,14 +710,16 @@ dotry: } err = usb_submit_urb(inurb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR"usb_submit_urb(sk->inurb[%i])" - " returned %i\n", u, err); + snd_printk(KERN_ERR + "usb_submit_urb(sk->inurb[%i]) returned %i\n", + u, err); return err; } err = usb_submit_urb(outurb, GFP_ATOMIC); if (err < 0) { - snd_printk(KERN_ERR"usb_submit_urb(sk->outurb[%i])" - " returned %i\n", u, err); + snd_printk(KERN_ERR + "usb_submit_urb(sk->outurb[%i]) returned %i\n", + u, err); return err; } @@ -716,8 +740,8 @@ check_retry: snd_printd(KERN_DEBUG "goto dotry;\n"); goto dotry; } - snd_printk(KERN_WARNING"couldn't start" - " all urbs on the same start_frame.\n"); + snd_printk(KERN_WARNING + "couldn't start all urbs on the same start_frame.\n"); return -EFAULT; } @@ -729,6 +753,7 @@ check_retry: /* wait, check */ { int wait_ms = 3000; + while (s->state != usb_stream_ready && wait_ms > 0) { snd_printdd(KERN_DEBUG "%i\n", s->state); msleep(200); @@ -745,6 +770,7 @@ check_retry: void usb_stream_stop(struct usb_stream_kernel *sk) { int u; + if (!sk->s) return; for (u = 0; u < USB_STREAM_NURBS; ++u) { diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h index 851358a8d709..73e57b341adc 100644 --- a/sound/usb/usx2y/usb_stream.h +++ b/sound/usb/usx2y/usb_stream.h @@ -12,7 +12,7 @@ struct usb_stream_kernel { void *write_page; - unsigned n_o_ps; + unsigned int n_o_ps; struct urb *inurb[USB_STREAM_NURBS]; struct urb *idle_inurb; @@ -26,18 +26,21 @@ struct usb_stream_kernel { wait_queue_head_t sleep; - unsigned out_phase; - unsigned out_phase_peeked; - unsigned freqn; + unsigned int out_phase; + unsigned int out_phase_peeked; + unsigned int freqn; }; struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, struct usb_device *dev, - unsigned in_endpoint, unsigned out_endpoint, - unsigned sample_rate, unsigned use_packsize, - unsigned period_frames, unsigned frame_size); -void usb_stream_free(struct usb_stream_kernel *); -int usb_stream_start(struct usb_stream_kernel *); -void usb_stream_stop(struct usb_stream_kernel *); + unsigned int in_endpoint, + unsigned int out_endpoint, + unsigned int sample_rate, + unsigned int use_packsize, + unsigned int period_frames, + unsigned int frame_size); +void usb_stream_free(struct usb_stream_kernel *sk); +int usb_stream_start(struct usb_stream_kernel *sk); +void usb_stream_stop(struct usb_stream_kernel *sk); #endif /* __USB_STREAM_H */ diff --git a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h index 5a7518ea3aeb..9ba15d974e63 100644 --- a/sound/usb/usx2y/usbus428ctldefs.h +++ b/sound/usb/usx2y/usbus428ctldefs.h @@ -4,28 +4,28 @@ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de> */ -enum E_In84{ - eFader0 = 0, - eFader1, - eFader2, - eFader3, - eFader4, - eFader5, - eFader6, - eFader7, - eFaderM, - eTransport, - eModifier = 10, - eFilterSelect, - eSelect, - eMute, +enum E_IN84 { + E_FADER_0 = 0, + E_FADER_1, + E_FADER_2, + E_FADER_3, + E_FADER_4, + E_FADER_5, + E_FADER_6, + E_FADER_7, + E_FADER_M, + E_TRANSPORT, + E_MODIFIER = 10, + E_FILTER_SELECT, + E_SELECT, + E_MUTE, - eSwitch = 15, - eWheelGain, - eWheelFreq, - eWheelQ, - eWheelPan, - eWheel = 20 + E_SWITCH = 15, + E_WHEEL_GAIN, + E_WHEEL_FREQ, + E_WHEEL_Q, + E_WHEEL_PAN, + E_WHEEL = 20 }; #define T_RECORD 1 @@ -39,53 +39,55 @@ enum E_In84{ struct us428_ctls { - unsigned char Fader[9]; - unsigned char Transport; - unsigned char Modifier; - unsigned char FilterSelect; - unsigned char Select; - unsigned char Mute; - unsigned char UNKNOWN; - unsigned char Switch; - unsigned char Wheel[5]; + unsigned char fader[9]; + unsigned char transport; + unsigned char modifier; + unsigned char filters_elect; + unsigned char select; + unsigned char mute; + unsigned char unknown; + unsigned char wswitch; + unsigned char wheel[5]; }; -struct us428_setByte { - unsigned char Offset, - Value; +struct us428_set_byte { + unsigned char offset, + value; }; enum { - eLT_Volume = 0, - eLT_Light + ELT_VOLUME = 0, + ELT_LIGHT }; -struct usX2Y_volume { - unsigned char Channel, - LH, - LL, - RH, - RL; +struct usx2y_volume { + unsigned char channel, + lh, + ll, + rh, + rl; }; struct us428_lights { - struct us428_setByte Light[7]; + struct us428_set_byte light[7]; }; struct us428_p4out { char type; union { - struct usX2Y_volume vol; + struct usx2y_volume vol; struct us428_lights lights; } val; }; -#define N_us428_ctl_BUFS 16 -#define N_us428_p4out_BUFS 16 -struct us428ctls_sharedmem{ - struct us428_ctls CtlSnapShot[N_us428_ctl_BUFS]; - int CtlSnapShotDiffersAt[N_us428_ctl_BUFS]; - int CtlSnapShotLast, CtlSnapShotRed; - struct us428_p4out p4out[N_us428_p4out_BUFS]; - int p4outLast, p4outSent; +#define N_US428_CTL_BUFS 16 +#define N_US428_P4OUT_BUFS 16 +struct us428ctls_sharedmem { + struct us428_ctls ctl_snapshot[N_US428_CTL_BUFS]; + int ctl_snapshot_differs_at[N_US428_CTL_BUFS]; + int ctl_snapshot_last, ctl_snapshot_red; + struct us428_p4out p4out[N_US428_P4OUT_BUFS]; + int p4out_last, p4out_sent; }; + +#define US428_SHAREDMEM_PAGES PAGE_ALIGN(sizeof(struct us428ctls_sharedmem)) diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 3cd28d24f0a7..099bee662af6 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -17,7 +17,7 @@ 2004-10-26 Karsten Wiese Version 0.8.6: - wake_up() process waiting in usX2Y_urbs_start() on error. + wake_up() process waiting in usx2y_urbs_start() on error. 2004-10-21 Karsten Wiese Version 0.8.5: @@ -48,7 +48,7 @@ 2004-06-12 Karsten Wiese Version 0.6.3: Made it thus the following rule is enforced: - "All pcm substreams of one usX2Y have to operate at the same rate & format." + "All pcm substreams of one usx2y have to operate at the same rate & format." 2004-04-06 Karsten Wiese Version 0.6.0: @@ -70,7 +70,7 @@ 2003-11-03 Karsten Wiese Version 0.3: - 24Bit support. + 24Bit support. "arecord -D hw:1 -c 2 -r 48000 -M -f S24_3LE|aplay -D hw:1 -c 2 -r 48000 -M -f S24_3LE" works. 2003-08-22 Karsten Wiese @@ -94,16 +94,15 @@ This helped me much on my slowish PII 400 & PIII 500. ACPI yet untested but might cause the same bad behaviour. Use a kernel with lowlatency and preemptiv patches applied. - To autoload snd-usb-midi append a line + To autoload snd-usb-midi append a line post-install snd-usb-us428 modprobe snd-usb-midi to /etc/modules.conf. known problems: sliders, knobs, lights not yet handled except MASTER Volume slider. - "pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does. + "pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does. KDE3: "Enable full duplex operation" deadlocks. - 2002-08-31 Karsten Wiese Version 0.0.3: audio also simplex; simplifying: iso urbs only 1 packet, melted structs. @@ -115,7 +114,7 @@ The firmware has been sniffed from win2k us-428 driver 3.09. * Copyright (c) 2002 - 2004 Karsten Wiese -*/ + */ #include <linux/init.h> #include <linux/module.h> @@ -132,14 +131,12 @@ #include "usbusx2y.h" #include "usX2Yhwdep.h" - - MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); MODULE_LICENSE("GPL"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ -static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ module_param_array(index, int, NULL, 0444); @@ -149,305 +146,321 @@ MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); +static int snd_usx2y_card_used[SNDRV_CARDS]; -static int snd_usX2Y_card_used[SNDRV_CARDS]; +static void snd_usx2y_card_private_free(struct snd_card *card); +static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s); -static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr); -static void snd_usX2Y_card_private_free(struct snd_card *card); - -/* - * pipe 4 is used for switching the lamps, setting samplerate, volumes .... +/* + * pipe 4 is used for switching the lamps, setting samplerate, volumes .... */ -static void i_usX2Y_Out04Int(struct urb *urb) +static void i_usx2y_out04_int(struct urb *urb) { #ifdef CONFIG_SND_DEBUG if (urb->status) { - int i; - struct usX2Ydev *usX2Y = urb->context; - for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++); - snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status); + int i; + struct usx2ydev *usx2y = urb->context; + + for (i = 0; i < 10 && usx2y->as04.urb[i] != urb; i++) + ; + snd_printdd("%s urb %i status=%i\n", __func__, i, urb->status); } #endif } -static void i_usX2Y_In04Int(struct urb *urb) +static void i_usx2y_in04_int(struct urb *urb) { int err = 0; - struct usX2Ydev *usX2Y = urb->context; - struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem; + struct usx2ydev *usx2y = urb->context; + struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem; + struct us428_p4out *p4out; + int i, j, n, diff, send; - usX2Y->In04IntCalls++; + usx2y->in04_int_calls++; if (urb->status) { snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); return; } - // printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? + // printk("%i:0x%02X ", 8, (int)((unsigned char*)usx2y->in04_buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? if (us428ctls) { - int diff = -1; - if (-2 == us428ctls->CtlSnapShotLast) { + diff = -1; + if (us428ctls->ctl_snapshot_last == -2) { diff = 0; - memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last)); - us428ctls->CtlSnapShotLast = -1; + memcpy(usx2y->in04_last, usx2y->in04_buf, sizeof(usx2y->in04_last)); + us428ctls->ctl_snapshot_last = -1; } else { - int i; for (i = 0; i < 21; i++) { - if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) { + if (usx2y->in04_last[i] != ((char *)usx2y->in04_buf)[i]) { if (diff < 0) diff = i; - usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i]; + usx2y->in04_last[i] = ((char *)usx2y->in04_buf)[i]; } } } - if (0 <= diff) { - int n = us428ctls->CtlSnapShotLast + 1; - if (n >= N_us428_ctl_BUFS || n < 0) + if (diff >= 0) { + n = us428ctls->ctl_snapshot_last + 1; + if (n >= N_US428_CTL_BUFS || n < 0) n = 0; - memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0])); - us428ctls->CtlSnapShotDiffersAt[n] = diff; - us428ctls->CtlSnapShotLast = n; - wake_up(&usX2Y->us428ctls_wait_queue_head); + memcpy(us428ctls->ctl_snapshot + n, usx2y->in04_buf, sizeof(us428ctls->ctl_snapshot[0])); + us428ctls->ctl_snapshot_differs_at[n] = diff; + us428ctls->ctl_snapshot_last = n; + wake_up(&usx2y->us428ctls_wait_queue_head); } } - - - if (usX2Y->US04) { - if (0 == usX2Y->US04->submitted) + + if (usx2y->us04) { + if (!usx2y->us04->submitted) { do { - err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); - } while (!err && usX2Y->US04->submitted < usX2Y->US04->len); - } else - if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { - if (us428ctls->p4outLast != us428ctls->p4outSent) { - int j, send = us428ctls->p4outSent + 1; - if (send >= N_us428_p4out_BUFS) + err = usb_submit_urb(usx2y->us04->urb[usx2y->us04->submitted++], GFP_ATOMIC); + } while (!err && usx2y->us04->submitted < usx2y->us04->len); + } + } else { + if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) { + if (us428ctls->p4out_last != us428ctls->p4out_sent) { + send = us428ctls->p4out_sent + 1; + if (send >= N_US428_P4OUT_BUFS) send = 0; - for (j = 0; j < URBS_AsyncSeq && !err; ++j) - if (0 == usX2Y->AS04.urb[j]->status) { - struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. - usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol, - p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, - i_usX2Y_Out04Int, usX2Y); - err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC); - us428ctls->p4outSent = send; + for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) { + if (!usx2y->as04.urb[j]->status) { + p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. + usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol, + p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5, + i_usx2y_out04_int, usx2y); + err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); + us428ctls->p4out_sent = send; break; } + } } } + } if (err) - snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); + snd_printk(KERN_ERR "in04_int() usb_submit_urb err=%i\n", err); - urb->dev = usX2Y->dev; + urb->dev = usx2y->dev; usb_submit_urb(urb, GFP_ATOMIC); } /* * Prepare some urbs */ -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y) +int usx2y_async_seq04_init(struct usx2ydev *usx2y) { - int err = 0, - i; + int err = 0, i; + + if (WARN_ON(usx2y->as04.buffer)) + return -EBUSY; - usX2Y->AS04.buffer = kmalloc_array(URBS_AsyncSeq, - URB_DataLen_AsyncSeq, GFP_KERNEL); - if (NULL == usX2Y->AS04.buffer) { + usx2y->as04.buffer = kmalloc_array(URBS_ASYNC_SEQ, + URB_DATA_LEN_ASYNC_SEQ, GFP_KERNEL); + if (!usx2y->as04.buffer) { err = -ENOMEM; - } else - for (i = 0; i < URBS_AsyncSeq; ++i) { - if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { + } else { + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + usx2y->as04.urb[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!usx2y->as04.urb[i]) { err = -ENOMEM; break; } - usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), - usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0, - i_usX2Y_Out04Int, usX2Y - ); - err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]); + usb_fill_bulk_urb(usx2y->as04.urb[i], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), + usx2y->as04.buffer + URB_DATA_LEN_ASYNC_SEQ * i, 0, + i_usx2y_out04_int, usx2y); + err = usb_urb_ep_type_check(usx2y->as04.urb[i]); if (err < 0) break; } + } + if (err) + usx2y_unlinkseq(&usx2y->as04); return err; } -int usX2Y_In04_init(struct usX2Ydev *usX2Y) +int usx2y_in04_init(struct usx2ydev *usx2y) { - if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) - return -ENOMEM; - - if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) - return -ENOMEM; - - init_waitqueue_head(&usX2Y->In04WaitQueue); - usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), - usX2Y->In04Buf, 21, - i_usX2Y_In04Int, usX2Y, + int err; + + if (WARN_ON(usx2y->in04_urb)) + return -EBUSY; + + usx2y->in04_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!usx2y->in04_urb) { + err = -ENOMEM; + goto error; + } + + usx2y->in04_buf = kmalloc(21, GFP_KERNEL); + if (!usx2y->in04_buf) { + err = -ENOMEM; + goto error; + } + + init_waitqueue_head(&usx2y->in04_wait_queue); + usb_fill_int_urb(usx2y->in04_urb, usx2y->dev, usb_rcvintpipe(usx2y->dev, 0x4), + usx2y->in04_buf, 21, + i_usx2y_in04_int, usx2y, 10); - if (usb_urb_ep_type_check(usX2Y->In04urb)) - return -EINVAL; - return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); + if (usb_urb_ep_type_check(usx2y->in04_urb)) { + err = -EINVAL; + goto error; + } + return usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); + + error: + kfree(usx2y->in04_buf); + usb_free_urb(usx2y->in04_urb); + usx2y->in04_buf = NULL; + usx2y->in04_urb = NULL; + return err; } -static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S) +static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s) { int i; - for (i = 0; i < URBS_AsyncSeq; ++i) { - usb_kill_urb(S->urb[i]); - usb_free_urb(S->urb[i]); - S->urb[i] = NULL; + + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + if (!s->urb[i]) + continue; + usb_kill_urb(s->urb[i]); + usb_free_urb(s->urb[i]); + s->urb[i] = NULL; } - kfree(S->buffer); + kfree(s->buffer); + s->buffer = NULL; } - -static const struct usb_device_id snd_usX2Y_usb_id_table[] = { +static const struct usb_device_id snd_usx2y_usb_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x1604, - .idProduct = USB_ID_US428 + .idProduct = USB_ID_US428 }, { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x1604, - .idProduct = USB_ID_US122 + .idProduct = USB_ID_US122 }, - { + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x1604, .idProduct = USB_ID_US224 }, { /* terminator */ } }; +MODULE_DEVICE_TABLE(usb, snd_usx2y_usb_id_table); -static int usX2Y_create_card(struct usb_device *device, +static int usx2y_create_card(struct usb_device *device, struct usb_interface *intf, struct snd_card **cardp) { int dev; - struct snd_card * card; + struct snd_card *card; int err; for (dev = 0; dev < SNDRV_CARDS; ++dev) - if (enable[dev] && !snd_usX2Y_card_used[dev]) + if (enable[dev] && !snd_usx2y_card_used[dev]) break; if (dev >= SNDRV_CARDS) return -ENODEV; err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); + sizeof(struct usx2ydev), &card); if (err < 0) return err; - snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; - card->private_free = snd_usX2Y_card_private_free; - usX2Y(card)->dev = device; - init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->pcm_mutex); - INIT_LIST_HEAD(&usX2Y(card)->midi_list); + snd_usx2y_card_used[usx2y(card)->card_index = dev] = 1; + card->private_free = snd_usx2y_card_private_free; + usx2y(card)->dev = device; + init_waitqueue_head(&usx2y(card)->prepare_wait_queue); + init_waitqueue_head(&usx2y(card)->us428ctls_wait_queue_head); + mutex_init(&usx2y(card)->pcm_mutex); + INIT_LIST_HEAD(&usx2y(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", - card->shortname, + card->shortname, le16_to_cpu(device->descriptor.idVendor), le16_to_cpu(device->descriptor.idProduct), 0,//us428(card)->usbmidi.ifnum, - usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum - ); + usx2y(card)->dev->bus->busnum, usx2y(card)->dev->devnum); *cardp = card; return 0; } - -static int usX2Y_usb_probe(struct usb_device *device, - struct usb_interface *intf, - const struct usb_device_id *device_id, - struct snd_card **cardp) +static void snd_usx2y_card_private_free(struct snd_card *card) { - int err; - struct snd_card * card; + struct usx2ydev *usx2y = usx2y(card); + + kfree(usx2y->in04_buf); + usb_free_urb(usx2y->in04_urb); + if (usx2y->us428ctls_sharedmem) + free_pages_exact(usx2y->us428ctls_sharedmem, + US428_SHAREDMEM_PAGES); + if (usx2y->card_index >= 0 && usx2y->card_index < SNDRV_CARDS) + snd_usx2y_card_used[usx2y->card_index] = 0; +} - *cardp = NULL; - if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || - (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && - le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) - return -EINVAL; +static void snd_usx2y_disconnect(struct usb_interface *intf) +{ + struct snd_card *card; + struct usx2ydev *usx2y; + struct list_head *p; - err = usX2Y_create_card(device, intf, &card); - if (err < 0) - return err; - if ((err = usX2Y_hwdep_new(card, device)) < 0 || - (err = snd_card_register(card)) < 0) { - snd_card_free(card); - return err; + card = usb_get_intfdata(intf); + if (!card) + return; + usx2y = usx2y(card); + usx2y->chip_status = USX2Y_STAT_CHIP_HUP; + usx2y_unlinkseq(&usx2y->as04); + usb_kill_urb(usx2y->in04_urb); + snd_card_disconnect(card); + + /* release the midi resources */ + list_for_each(p, &usx2y->midi_list) { + snd_usbmidi_disconnect(p); } - *cardp = card; - return 0; + if (usx2y->us428ctls_sharedmem) + wake_up(&usx2y->us428ctls_wait_queue_head); + snd_card_free(card); } -/* - * new 2.5 USB kernel API - */ -static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int snd_usx2y_probe(struct usb_interface *intf, + const struct usb_device_id *id) { + struct usb_device *device = interface_to_usbdev(intf); struct snd_card *card; int err; - err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); + if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || + (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && + le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && + le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) + return -EINVAL; + + err = usx2y_create_card(device, intf, &card); if (err < 0) return err; + err = usx2y_hwdep_new(card, device); + if (err < 0) + goto error; + err = snd_card_register(card); + if (err < 0) + goto error; + dev_set_drvdata(&intf->dev, card); return 0; -} -static void snd_usX2Y_disconnect(struct usb_interface *intf) -{ - usX2Y_usb_disconnect(interface_to_usbdev(intf), - usb_get_intfdata(intf)); + error: + snd_card_free(card); + return err; } -MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table); -static struct usb_driver snd_usX2Y_usb_driver = { +static struct usb_driver snd_usx2y_usb_driver = { .name = "snd-usb-usx2y", - .probe = snd_usX2Y_probe, - .disconnect = snd_usX2Y_disconnect, - .id_table = snd_usX2Y_usb_id_table, + .probe = snd_usx2y_probe, + .disconnect = snd_usx2y_disconnect, + .id_table = snd_usx2y_usb_id_table, }; - -static void snd_usX2Y_card_private_free(struct snd_card *card) -{ - kfree(usX2Y(card)->In04Buf); - usb_free_urb(usX2Y(card)->In04urb); - if (usX2Y(card)->us428ctls_sharedmem) - free_pages_exact(usX2Y(card)->us428ctls_sharedmem, - sizeof(*usX2Y(card)->us428ctls_sharedmem)); - if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) - snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; -} - -/* - * Frees the device. - */ -static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr) -{ - if (ptr) { - struct snd_card *card = ptr; - struct usX2Ydev *usX2Y = usX2Y(card); - struct list_head *p; - usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; - usX2Y_unlinkSeq(&usX2Y->AS04); - usb_kill_urb(usX2Y->In04urb); - snd_card_disconnect(card); - /* release the midi resources */ - list_for_each(p, &usX2Y->midi_list) { - snd_usbmidi_disconnect(p); - } - if (usX2Y->us428ctls_sharedmem) - wake_up(&usX2Y->us428ctls_wait_queue_head); - snd_card_free(card); - } -} - -module_usb_driver(snd_usX2Y_usb_driver); +module_usb_driver(snd_usx2y_usb_driver); diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index 144b85f57bd2..8d82f5cc2fe1 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -3,19 +3,19 @@ #define USBUSX2Y_H #include "../usbaudio.h" #include "../midi.h" -#include "usbus428ctldefs.h" +#include "usbus428ctldefs.h" -#define NRURBS 2 +#define NRURBS 2 -#define URBS_AsyncSeq 10 -#define URB_DataLen_AsyncSeq 32 -struct snd_usX2Y_AsyncSeq { - struct urb *urb[URBS_AsyncSeq]; +#define URBS_ASYNC_SEQ 10 +#define URB_DATA_LEN_ASYNC_SEQ 32 +struct snd_usx2y_async_seq { + struct urb *urb[URBS_ASYNC_SEQ]; char *buffer; }; -struct snd_usX2Y_urbSeq { +struct snd_usx2y_urb_seq { int submitted; int len; struct urb *urb[]; @@ -23,17 +23,17 @@ struct snd_usX2Y_urbSeq { #include "usx2yhwdeppcm.h" -struct usX2Ydev { +struct usx2ydev { struct usb_device *dev; int card_index; int stride; - struct urb *In04urb; - void *In04Buf; - char In04Last[24]; - unsigned In04IntCalls; - struct snd_usX2Y_urbSeq *US04; - wait_queue_head_t In04WaitQueue; - struct snd_usX2Y_AsyncSeq AS04; + struct urb *in04_urb; + void *in04_buf; + char in04_last[24]; + unsigned int in04_int_calls; + struct snd_usx2y_urb_seq *us04; + wait_queue_head_t in04_wait_queue; + struct snd_usx2y_async_seq as04; unsigned int rate, format; int chip_status; @@ -41,31 +41,30 @@ struct usX2Ydev { struct us428ctls_sharedmem *us428ctls_sharedmem; int wait_iso_frame; wait_queue_head_t us428ctls_wait_queue_head; - struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm; - struct snd_usX2Y_substream *subs[4]; - struct snd_usX2Y_substream * volatile prepare_subs; + struct snd_usx2y_hwdep_pcm_shm *hwdep_pcm_shm; + struct snd_usx2y_substream *subs[4]; + struct snd_usx2y_substream * volatile prepare_subs; wait_queue_head_t prepare_wait_queue; struct list_head midi_list; - struct list_head pcm_list; int pcm_devs; }; -struct snd_usX2Y_substream { - struct usX2Ydev *usX2Y; +struct snd_usx2y_substream { + struct usx2ydev *usx2y; struct snd_pcm_substream *pcm_substream; - int endpoint; + int endpoint; unsigned int maxpacksize; /* max packet size in bytes */ atomic_t state; -#define state_STOPPED 0 -#define state_STARTING1 1 -#define state_STARTING2 2 -#define state_STARTING3 3 -#define state_PREPARED 4 -#define state_PRERUNNING 6 -#define state_RUNNING 8 +#define STATE_STOPPED 0 +#define STATE_STARTING1 1 +#define STATE_STARTING2 2 +#define STATE_STARTING3 3 +#define STATE_PREPARED 4 +#define STATE_PRERUNNING 6 +#define STATE_RUNNING 8 int hwptr; /* free frame position in the buffer (only for playback) */ int hwptr_done; /* processed frame position in the buffer */ @@ -77,12 +76,12 @@ struct snd_usX2Y_substream { }; -#define usX2Y(c) ((struct usX2Ydev *)(c)->private_data) +#define usx2y(c) ((struct usx2ydev *)(c)->private_data) -int usX2Y_audio_create(struct snd_card *card); +int usx2y_audio_create(struct snd_card *card); -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y); -int usX2Y_In04_init(struct usX2Ydev *usX2Y); +int usx2y_async_seq04_init(struct usx2ydev *usx2y); +int usx2y_in04_init(struct usx2ydev *usx2y); #define NAME_ALLCAPS "US-X2Y" diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index ecaf41265dcd..c39cc6851e2d 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -11,7 +11,7 @@ * * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> * - * Many codes borrowed from audio.c by + * Many codes borrowed from audio.c by * Alan Cox (alan@lxorguk.ukuu.org.uk) * Thomas Sailer (sailer@ife.ee.ethz.ch) */ @@ -28,66 +28,69 @@ #include "usx2y.h" #include "usbusx2y.h" -#define USX2Y_NRPACKS 4 /* Default value used for nr of packs per urb. - 1 to 4 have been tested ok on uhci. - To use 3 on ohci, you'd need a patch: - look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on - "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425" - . - 1, 2 and 4 work out of the box on ohci, if I recall correctly. - Bigger is safer operation, - smaller gives lower latencies. - */ -#define USX2Y_NRPACKS_VARIABLE y /* If your system works ok with this module's parameter - nrpacks set to 1, you might as well comment - this #define out, and thereby produce smaller, faster code. - You'd also set USX2Y_NRPACKS to 1 then. - */ +/* Default value used for nr of packs per urb. + * 1 to 4 have been tested ok on uhci. + * To use 3 on ohci, you'd need a patch: + * look for "0000425-linux-2.6.9-rc4-mm1_ohci-hcd.patch.gz" on + * "https://bugtrack.alsa-project.org/alsa-bug/bug_view_page.php?bug_id=0000425" + * + * 1, 2 and 4 work out of the box on ohci, if I recall correctly. + * Bigger is safer operation, smaller gives lower latencies. + */ +#define USX2Y_NRPACKS 4 + +/* If your system works ok with this module's parameter + * nrpacks set to 1, you might as well comment + * this define out, and thereby produce smaller, faster code. + * You'd also set USX2Y_NRPACKS to 1 then. + */ +#define USX2Y_NRPACKS_VARIABLE 1 #ifdef USX2Y_NRPACKS_VARIABLE - static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */ - #define nr_of_packs() nrpacks - module_param(nrpacks, int, 0444); - MODULE_PARM_DESC(nrpacks, "Number of packets per URB."); +static int nrpacks = USX2Y_NRPACKS; /* number of packets per urb */ +#define nr_of_packs() nrpacks +module_param(nrpacks, int, 0444); +MODULE_PARM_DESC(nrpacks, "Number of packets per URB."); #else - #define nr_of_packs() USX2Y_NRPACKS +#define nr_of_packs() USX2Y_NRPACKS #endif - -static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; unsigned char *cp; - int i, len, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; + int i, len, lens = 0, hwptr_done = subs->hwptr_done; + int cnt, blen; + struct usx2ydev *usx2y = subs->usx2y; for (i = 0; i < nr_of_packs(); i++) { - cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; + cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR "active frame status %i. " - "Most probably some hardware problem.\n", + snd_printk(KERN_ERR + "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - len = urb->iso_frame_desc[i].actual_length / usX2Y->stride; - if (! len) { + len = urb->iso_frame_desc[i].actual_length / usx2y->stride; + if (!len) { snd_printd("0 == len ERROR!\n"); continue; } /* copy a data chunk */ if ((hwptr_done + len) > runtime->buffer_size) { - int cnt = runtime->buffer_size - hwptr_done; - int blen = cnt * usX2Y->stride; - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen); - memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen); + cnt = runtime->buffer_size - hwptr_done; + blen = cnt * usx2y->stride; + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, blen); + memcpy(runtime->dma_area, cp + blen, len * usx2y->stride - blen); } else { - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, - len * usX2Y->stride); + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, + len * usx2y->stride); } lens += len; - if ((hwptr_done += len) >= runtime->buffer_size) + hwptr_done += len; + if (hwptr_done >= runtime->buffer_size) hwptr_done -= runtime->buffer_size; } @@ -100,6 +103,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) } return 0; } + /* * prepare urb for playback data pipe * @@ -110,18 +114,18 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *cap_urb, struct urb *urb) { - int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; + int count, counts, pack, len; count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride; + counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride; count += counts; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); @@ -134,29 +138,30 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, 0; urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length; } - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) { if (subs->hwptr + count > runtime->buffer_size) { /* err, the transferred area goes over buffer boundary. * copy the data to the temp buffer. */ - int len; len = runtime->buffer_size - subs->hwptr; urb->transfer_buffer = subs->tmpbuf; memcpy(subs->tmpbuf, runtime->dma_area + - subs->hwptr * usX2Y->stride, len * usX2Y->stride); - memcpy(subs->tmpbuf + len * usX2Y->stride, - runtime->dma_area, (count - len) * usX2Y->stride); + subs->hwptr * usx2y->stride, len * usx2y->stride); + memcpy(subs->tmpbuf + len * usx2y->stride, + runtime->dma_area, (count - len) * usx2y->stride); subs->hwptr += count; subs->hwptr -= runtime->buffer_size; } else { /* set the buffer pointer */ - urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride; - if ((subs->hwptr += count) >= runtime->buffer_size) + urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride; + subs->hwptr += count; + if (subs->hwptr >= runtime->buffer_size) subs->hwptr -= runtime->buffer_size; } - else + } else { urb->transfer_buffer = subs->tmpbuf; - urb->transfer_buffer_length = count * usX2Y->stride; + } + urb->transfer_buffer_length = count * usx2y->stride; return 0; } @@ -165,10 +170,10 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, * * update the current position and call callback if a period is processed. */ -static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_urb_play_retire(struct snd_usx2y_substream *subs, struct urb *urb) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int len = urb->actual_length / subs->usX2Y->stride; + int len = urb->actual_length / subs->usx2y->stride; subs->transfer_done += len; subs->hwptr_done += len; @@ -180,181 +185,195 @@ static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb * } } -static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, int frame) +static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, int frame) { int err; + if (!urb) return -ENODEV; - urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks + urb->start_frame = frame + NRURBS * nr_of_packs(); // let hcd do rollover sanity checks urb->hcpriv = NULL; - urb->dev = subs->usX2Y->dev; /* we need to set this at each time */ - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { + urb->dev = subs->usx2y->dev; /* we need to set this at each time */ + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); return err; } return 0; } -static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *playbacksubs, - int frame) +static int usx2y_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *playbacksubs, + int frame) { int err, state; struct urb *urb = playbacksubs->completed_urb; state = atomic_read(&playbacksubs->state); - if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (urb) { + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + err = usx2y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb); + if (err) + return err; + err = usx2y_urb_submit(playbacksubs, urb, frame); + if (err) return err; - } } playbacksubs->completed_urb = NULL; state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + err = usx2y_urb_capt_retire(capsubs); + if (err) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) { atomic_inc(&capsubs->state); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + } + err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame); + if (err) return err; } capsubs->completed_urb = NULL; return 0; } - -static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) +static void usx2y_clients_stop(struct usx2ydev *usx2y) { + struct snd_usx2y_substream *subs; + struct urb *urb; int s, u; for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + subs = usx2y->subs[s]; if (subs) { snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state)); - atomic_set(&subs->state, state_STOPPED); + atomic_set(&subs->state, STATE_STOPPED); } } for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + subs = usx2y->subs[s]; if (subs) { - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) snd_pcm_stop_xrun(subs->pcm_substream); for (u = 0; u < NRURBS; u++) { - struct urb *urb = subs->urb[u]; - if (NULL != urb) + urb = subs->urb[u]; + if (urb) snd_printdd("%i status=%i start_frame=%i\n", u, urb->status, urb->start_frame); } } } - usX2Y->prepare_subs = NULL; - wake_up(&usX2Y->prepare_wait_queue); + usx2y->prepare_subs = NULL; + wake_up(&usx2y->prepare_wait_queue); } -static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_error_urb_status(struct usx2ydev *usx2y, + struct snd_usx2y_substream *subs, struct urb *urb) { snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); urb->status = 0; - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } -static void i_usX2Y_urb_complete(struct urb *urb) +static void i_usx2y_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs, *playbacksubs; - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; } subs->completed_urb = urb; - { - struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], - *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && - atomic_read(&capsubs->state) >= state_PREPARED && - (playbacksubs->completed_urb || - atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); - else { - snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); - } + capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + + if (capsubs->completed_urb && + atomic_read(&capsubs->state) >= STATE_PREPARED && + (playbacksubs->completed_urb || + atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) { + usx2y->wait_iso_frame += nr_of_packs(); + } else { + snd_printdd("\n"); + usx2y_clients_stop(usx2y); } } } -static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, +static void usx2y_urbs_set_complete(struct usx2ydev *usx2y, void (*complete)(struct urb *)) { + struct snd_usx2y_substream *subs; + struct urb *urb; int s, u; + for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; - if (NULL != subs) + subs = usx2y->subs[s]; + if (subs) { for (u = 0; u < NRURBS; u++) { - struct urb * urb = subs->urb[u]; - if (NULL != urb) + urb = subs->urb[u]; + if (urb) urb->complete = complete; } + } } } -static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_subs_startup_finish(struct usx2ydev *usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_urb_complete); + usx2y->prepare_subs = NULL; } -static void i_usX2Y_subs_startup(struct urb *urb) +static void i_usx2y_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; - if (NULL != prepare_subs) + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; + + if (prepare_subs) { if (urb->start_frame == prepare_subs->urb[0]->start_frame) { - usX2Y_subs_startup_finish(usX2Y); + usx2y_subs_startup_finish(usx2y); atomic_inc(&prepare_subs->state); - wake_up(&usX2Y->prepare_wait_queue); + wake_up(&usx2y->prepare_wait_queue); } + } - i_usX2Y_urb_complete(urb); + i_usx2y_urb_complete(urb); } -static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) +static void usx2y_subs_prepare(struct snd_usx2y_substream *subs) { - snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", + snd_printdd("usx2y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", subs, subs->endpoint, subs->urb[0], subs->urb[1]); /* reset the pointer */ subs->hwptr = 0; @@ -362,8 +381,7 @@ static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) subs->transfer_done = 0; } - -static void usX2Y_urb_release(struct urb **urb, int free_tb) +static void usx2y_urb_release(struct urb **urb, int free_tb) { if (*urb) { usb_kill_urb(*urb); @@ -373,29 +391,33 @@ static void usX2Y_urb_release(struct urb **urb, int free_tb) *urb = NULL; } } + /* * release a substreams urbs */ -static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("usX2Y_urbs_release() %i\n", subs->endpoint); + + snd_printdd("%s %i\n", __func__, subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_urb_release(subs->urb + i, - subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); + usx2y_urb_release(subs->urb + i, + subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]); kfree(subs->tmpbuf); subs->tmpbuf = NULL; } + /* * initialize a substream's urbs */ -static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev; + struct urb **purb; pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -403,21 +425,21 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) if (!subs->maxpacksize) return -EINVAL; - if (is_playback && NULL == subs->tmpbuf) { /* allocate a temporary buffer for playback */ + if (is_playback && !subs->tmpbuf) { /* allocate a temporary buffer for playback */ subs->tmpbuf = kcalloc(nr_of_packs(), subs->maxpacksize, GFP_KERNEL); if (!subs->tmpbuf) return -ENOMEM; } /* allocate and initialize data urbs */ for (i = 0; i < NRURBS; i++) { - struct urb **purb = subs->urb + i; + purb = subs->urb + i; if (*purb) { usb_kill_urb(*purb); continue; } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); - if (NULL == *purb) { - usX2Y_urbs_release(subs); + if (!*purb) { + usx2y_urbs_release(subs); return -ENOMEM; } if (!is_playback && !(*purb)->transfer_buffer) { @@ -425,8 +447,8 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) (*purb)->transfer_buffer = kmalloc_array(subs->maxpacksize, nr_of_packs(), GFP_KERNEL); - if (NULL == (*purb)->transfer_buffer) { - usX2Y_urbs_release(subs); + if (!(*purb)->transfer_buffer) { + usx2y_urbs_release(subs); return -ENOMEM; } } @@ -435,70 +457,76 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_subs_startup; + (*purb)->complete = i_usx2y_subs_startup; } return 0; } -static void usX2Y_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev *usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev *usx2y = subs->usx2y; + + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; wmb(); - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_subs_startup); + usx2y_urbs_set_complete(usx2y, i_usx2y_subs_startup); } -static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_start(struct snd_usx2y_substream *subs) { int i, err; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; + struct urb *urb; + unsigned long pack; - if ((err = usX2Y_urbs_allocate(subs)) < 0) + err = usx2y_urbs_allocate(subs); + if (err < 0) return err; subs->completed_urb = NULL; for (i = 0; i < 4; i++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[i]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[i]; + + if (subs && atomic_read(&subs->state) >= STATE_PREPARED) goto start; } start: - usX2Y_subs_startup(subs); + usx2y_subs_startup(subs); for (i = 0; i < NRURBS; i++) { - struct urb *urb = subs->urb[i]; + urb = subs->urb[i]; if (usb_pipein(urb->pipe)) { - unsigned long pack; - if (0 == i) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; + if (!i) + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; for (pack = 0; pack < nr_of_packs(); pack++) { urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack; urb->iso_frame_desc[pack].length = subs->maxpacksize; } - urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); - if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); + urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { + snd_printk(KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err); err = -EPIPE; goto cleanup; - } else - if (i == 0) - usX2Y->wait_iso_frame = urb->start_frame; + } else { + if (!i) + usx2y->wait_iso_frame = urb->start_frame; + } urb->transfer_flags = 0; } else { - atomic_set(&subs->state, state_STARTING1); + atomic_set(&subs->state, STATE_STARTING1); break; } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, !usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE; cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); + usx2y_clients_stop(usx2y); // something is completely wrong > stop everything } return err; } @@ -506,33 +534,35 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) /* * return the current pcm pointer. just return the hwptr_done value. */ -static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_usx2y_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data; + return subs->hwptr_done; } + /* * start/stop substream */ -static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("snd_usX2Y_pcm_trigger(START)\n"); - if (atomic_read(&subs->state) == state_PREPARED && - atomic_read(&subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= state_PREPARED) { - atomic_set(&subs->state, state_PRERUNNING); + snd_printdd("%s(START)\n", __func__); + if (atomic_read(&subs->state) == STATE_PREPARED && + atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) { + atomic_set(&subs->state, STATE_PRERUNNING); } else { snd_printdd("\n"); return -EPIPE; } break; case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n"); - if (atomic_read(&subs->state) >= state_PRERUNNING) - atomic_set(&subs->state, state_PREPARED); + snd_printdd("%s(STOP)\n", __func__); + if (atomic_read(&subs->state) >= STATE_PRERUNNING) + atomic_set(&subs->state, STATE_PREPARED); break; default: return -EINVAL; @@ -540,7 +570,6 @@ static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return 0; } - /* * allocate a buffer, setup samplerate * @@ -549,12 +578,11 @@ static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) * if sg buffer is supported on the later version of alsa, we'll follow * that. */ -static const struct s_c2 -{ +struct s_c2 { char c1, c2; -} - SetRate44100[] = -{ +}; + +static const struct s_c2 setrate_44100[] = { { 0x14, 0x08}, // this line sets 44100, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... { 0x18, 0x42}, @@ -589,8 +617,8 @@ static const struct s_c2 { 0x18, 0x7C}, { 0x18, 0x7E} }; -static const struct s_c2 SetRate48000[] = -{ + +static const struct s_c2 setrate_48000[] = { { 0x14, 0x09}, // this line sets 48000, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... { 0x18, 0x42}, @@ -625,62 +653,65 @@ static const struct s_c2 SetRate48000[] = { 0x18, 0x7C}, { 0x18, 0x7E} }; -#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000) -static void i_usX2Y_04Int(struct urb *urb) +#define NOOF_SETRATE_URBS ARRAY_SIZE(setrate_48000) + +static void i_usx2y_04int(struct urb *urb) { - struct usX2Ydev *usX2Y = urb->context; - + struct usx2ydev *usx2y = urb->context; + if (urb->status) - snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status); - if (0 == --usX2Y->US04->len) - wake_up(&usX2Y->In04WaitQueue); + snd_printk(KERN_ERR "snd_usx2y_04int() urb->status=%i\n", urb->status); + if (!--usx2y->us04->len) + wake_up(&usx2y->in04_wait_queue); } -static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) +static int usx2y_rate_set(struct usx2ydev *usx2y, int rate) { int err = 0, i; - struct snd_usX2Y_urbSeq *us = NULL; + struct snd_usx2y_urb_seq *us = NULL; int *usbdata = NULL; - const struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100; + const struct s_c2 *ra = rate == 48000 ? setrate_48000 : setrate_44100; + struct urb *urb; - if (usX2Y->rate != rate) { - us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL); - if (NULL == us) { + if (usx2y->rate != rate) { + us = kzalloc(sizeof(*us) + sizeof(struct urb *) * NOOF_SETRATE_URBS, GFP_KERNEL); + if (!us) { err = -ENOMEM; goto cleanup; } usbdata = kmalloc_array(NOOF_SETRATE_URBS, sizeof(int), GFP_KERNEL); - if (NULL == usbdata) { + if (!usbdata) { err = -ENOMEM; goto cleanup; } for (i = 0; i < NOOF_SETRATE_URBS; ++i) { - if (NULL == (us->urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { + us->urb[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!us->urb[i]) { err = -ENOMEM; goto cleanup; } - ((char*)(usbdata + i))[0] = ra[i].c1; - ((char*)(usbdata + i))[1] = ra[i].c2; - usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), - usbdata + i, 2, i_usX2Y_04Int, usX2Y); + ((char *)(usbdata + i))[0] = ra[i].c1; + ((char *)(usbdata + i))[1] = ra[i].c2; + usb_fill_bulk_urb(us->urb[i], usx2y->dev, usb_sndbulkpipe(usx2y->dev, 4), + usbdata + i, 2, i_usx2y_04int, usx2y); } err = usb_urb_ep_type_check(us->urb[0]); if (err < 0) goto cleanup; us->submitted = 0; us->len = NOOF_SETRATE_URBS; - usX2Y->US04 = us; - wait_event_timeout(usX2Y->In04WaitQueue, 0 == us->len, HZ); - usX2Y->US04 = NULL; + usx2y->us04 = us; + wait_event_timeout(usx2y->in04_wait_queue, !us->len, HZ); + usx2y->us04 = NULL; if (us->len) err = -ENODEV; cleanup: if (us) { us->submitted = 2*NOOF_SETRATE_URBS; for (i = 0; i < NOOF_SETRATE_URBS; ++i) { - struct urb *urb = us->urb[i]; + urb = us->urb[i]; if (!urb) continue; if (urb->status) { @@ -690,67 +721,68 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } usb_free_urb(urb); } - usX2Y->US04 = NULL; + usx2y->us04 = NULL; kfree(usbdata); kfree(us); if (!err) - usX2Y->rate = rate; + usx2y->rate = rate; } } return err; } - -static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format) +static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format) { int alternate, err; - struct list_head* p; + struct list_head *p; + if (format == SNDRV_PCM_FORMAT_S24_3LE) { alternate = 2; - usX2Y->stride = 6; + usx2y->stride = 6; } else { alternate = 1; - usX2Y->stride = 4; + usx2y->stride = 4; } - list_for_each(p, &usX2Y->midi_list) { + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_stop(p); } - usb_kill_urb(usX2Y->In04urb); - if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) { - snd_printk(KERN_ERR "usb_set_interface error \n"); + usb_kill_urb(usx2y->in04_urb); + err = usb_set_interface(usx2y->dev, 0, alternate); + if (err) { + snd_printk(KERN_ERR "usb_set_interface error\n"); return err; } - usX2Y->In04urb->dev = usX2Y->dev; - err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); - list_for_each(p, &usX2Y->midi_list) { + usx2y->in04_urb->dev = usx2y->dev; + err = usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_start(p); } - usX2Y->format = format; - usX2Y->rate = 0; + usx2y->format = format; + usx2y->rate = 0; return err; } -static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, +static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int err = 0; unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); + struct snd_usx2y_substream *subs; + struct snd_pcm_substream *test_substream; int i; - mutex_lock(&usX2Y(card)->pcm_mutex); - snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - /* all pcm substreams off one usX2Y have to operate at the same + mutex_lock(&usx2y(card)->pcm_mutex); + snd_printdd("snd_usx2y_hw_params(%p, %p)\n", substream, hw_params); + /* all pcm substreams off one usx2y have to operate at the same * rate & format */ for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; - struct snd_pcm_substream *test_substream; - + subs = dev->subs[i]; if (!subs) continue; test_substream = subs->pcm_substream; @@ -767,81 +799,89 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, } error: - mutex_unlock(&usX2Y(card)->pcm_mutex); + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } /* * free the buffer */ -static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); - - if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + struct snd_usx2y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *cap_subs, *playback_subs; + + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("snd_usx2y_hw_free(%p)\n", substream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - usX2Y_urbs_release(cap_subs); + atomic_set(&cap_subs->state, STATE_STOPPED); + usx2y_urbs_release(cap_subs); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } + /* * prepare callback * * set format and initialize urbs */ -static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - - mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); -// Start hardware streams -// SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + + snd_printdd("%s(%p)\n", __func__, substream); + + mutex_lock(&usx2y->pcm_mutex); + usx2y_subs_prepare(subs); + // Start hardware streams + // SyncStream first.... + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) { + err = usx2y_format_set(usx2y, runtime->format); + if (err < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + } + if (usx2y->rate != runtime->rate) { + err = usx2y_rate_set(usx2y, runtime->rate); + if (err < 0) goto up_prepare_mutex; + } snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_urbs_start(capsubs))) + err = usx2y_urbs_start(capsubs); + if (err < 0) goto up_prepare_mutex; } - if (subs != capsubs && atomic_read(&subs->state) < state_PREPARED) - err = usX2Y_urbs_start(subs); + if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED) + err = usx2y_urbs_start(subs); up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; } -static const struct snd_pcm_hardware snd_usX2Y_2c = -{ +static const struct snd_pcm_hardware snd_usx2y_2c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | @@ -860,106 +900,101 @@ static const struct snd_pcm_hardware snd_usX2Y_2c = .fifo_size = 0 }; - - -static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) - snd_pcm_substream_chip(substream))[substream->stream]; + struct snd_usx2y_substream *subs = + ((struct snd_usx2y_substream **) + snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime; - if (subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) + if (subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) return -EBUSY; - runtime->hw = snd_usX2Y_2c; + runtime->hw = snd_usx2y_2c; runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); return 0; } - - -static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data; subs->pcm_substream = NULL; return 0; } - -static const struct snd_pcm_ops snd_usX2Y_pcm_ops = -{ - .open = snd_usX2Y_pcm_open, - .close = snd_usX2Y_pcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_pcm_hw_free, - .prepare = snd_usX2Y_pcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, +static const struct snd_pcm_ops snd_usx2y_pcm_ops = { + .open = snd_usx2y_pcm_open, + .close = snd_usx2y_pcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_pcm_hw_free, + .prepare = snd_usx2y_pcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, }; - /* * free a usb stream instance */ -static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) +static void usx2y_audio_stream_free(struct snd_usx2y_substream **usx2y_substream) { int stream; for_each_pcm_streams(stream) { - kfree(usX2Y_substream[stream]); - usX2Y_substream[stream] = NULL; + kfree(usx2y_substream[stream]); + usx2y_substream[stream] = NULL; } } -static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) +static void snd_usx2y_pcm_private_free(struct snd_pcm *pcm) { - struct snd_usX2Y_substream **usX2Y_stream = pcm->private_data; - if (usX2Y_stream) - usX2Y_audio_stream_free(usX2Y_stream); + struct snd_usx2y_substream **usx2y_stream = pcm->private_data; + + if (usx2y_stream) + usx2y_audio_stream_free(usx2y_stream); } -static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) +static int usx2y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) { struct snd_pcm *pcm; int err, i; - struct snd_usX2Y_substream **usX2Y_substream = - usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs; + struct snd_usx2y_substream **usx2y_substream = + usx2y(card)->subs + 2 * usx2y(card)->pcm_devs; for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; i <= SNDRV_PCM_STREAM_CAPTURE; ++i) { - usX2Y_substream[i] = kzalloc(sizeof(struct snd_usX2Y_substream), GFP_KERNEL); - if (!usX2Y_substream[i]) + usx2y_substream[i] = kzalloc(sizeof(struct snd_usx2y_substream), GFP_KERNEL); + if (!usx2y_substream[i]) return -ENOMEM; - usX2Y_substream[i]->usX2Y = usX2Y(card); + usx2y_substream[i]->usx2y = usx2y(card); } if (playback_endpoint) - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; - err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs, + err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usx2y(card)->pcm_devs, playback_endpoint ? 1 : 0, 1, &pcm); if (err < 0) { - usX2Y_audio_stream_free(usX2Y_substream); + usx2y_audio_stream_free(usx2y_substream); return err; } if (playback_endpoint) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_pcm_ops); - pcm->private_data = usX2Y_substream; - pcm->private_free = snd_usX2Y_pcm_private_free; + pcm->private_data = usx2y_substream; + pcm->private_free = snd_usx2y_pcm_private_free; pcm->info_flags = 0; - sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs); + sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usx2y(card)->pcm_devs); if (playback_endpoint) { snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, @@ -972,7 +1007,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, SNDRV_DMA_TYPE_CONTINUOUS, NULL, 64*1024, 128*1024); - usX2Y(card)->pcm_devs++; + usx2y(card)->pcm_devs++; return 0; } @@ -980,18 +1015,19 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, /* * create a chip instance and set its names. */ -int usX2Y_audio_create(struct snd_card *card) +int usx2y_audio_create(struct snd_card *card) { - int err = 0; - - INIT_LIST_HEAD(&usX2Y(card)->pcm_list); + int err; - if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8))) + err = usx2y_audio_stream_new(card, 0xA, 0x8); + if (err < 0) return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428) - if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA))) - return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122) - err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) == USB_ID_US428) { + err = usx2y_audio_stream_new(card, 0, 0xA); + if (err < 0) + return err; + } + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) != USB_ID_US122) + err = usx2y_rate_set(usx2y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 8253669c6a7d..db83522c1b49 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -6,7 +6,7 @@ Its usb's unableness to atomically handle power of 2 period sized data chuncs at standard samplerates, - what led to this part of the usx2y module: + what led to this part of the usx2y module: It provides the alsa kernel half of the usx2y-alsa-jack driver pair. The pair uses a hardware dependent alsa-device for mmaped pcm transport. Advantage achieved: @@ -35,7 +35,7 @@ Kernel: - rawusb dma pcm buffer transport should go to snd-usb-lib, so also snd-usb-audio devices can use it. - Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. + Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. */ #include <linux/delay.h> @@ -46,28 +46,32 @@ #include <sound/hwdep.h> - -static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int i, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; - if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME - int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1; - if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso)) + int i, lens = 0, hwptr_done = subs->hwptr_done; + struct usx2ydev *usx2y = subs->usx2y; + int head; + + if (usx2y->hwdep_pcm_shm->capture_iso_start < 0) { //FIXME + head = usx2y->hwdep_pcm_shm->captured_iso_head + 1; + if (head >= ARRAY_SIZE(usx2y->hwdep_pcm_shm->captured_iso)) head = 0; - usX2Y->hwdep_pcm_shm->capture_iso_start = head; + usx2y->hwdep_pcm_shm->capture_iso_start = head; snd_printdd("cap start %i\n", head); } for (i = 0; i < nr_of_packs(); i++) { if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); + snd_printk(KERN_ERR + "active frame status %i. Most probably some hardware problem.\n", + urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; + lens += urb->iso_frame_desc[i].actual_length / usx2y->stride; } - if ((hwptr_done += lens) >= runtime->buffer_size) + hwptr_done += lens; + if (hwptr_done >= runtime->buffer_size) hwptr_done -= runtime->buffer_size; subs->hwptr_done = hwptr_done; subs->transfer_done += lens; @@ -79,10 +83,10 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) return 0; } -static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, - struct usX2Ydev * usX2Y) +static int usx2y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, + struct usx2ydev *usx2y) { - return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ? + return (runtime->buffer_size * 1000) / usx2y->rate + 1; //FIXME: so far only correct period_size == 2^x ? } /* @@ -95,18 +99,18 @@ static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_hwdep_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *urb) { int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_hwdep_pcm_shm *shm = usx2y->hwdep_pcm_shm; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - if (0 > shm->playback_iso_start) { + if (shm->playback_iso_start < 0) { shm->playback_iso_start = shm->captured_iso_head - - usX2Y_iso_frames_per_buffer(runtime, usX2Y); - if (0 > shm->playback_iso_start) + usx2y_iso_frames_per_buffer(runtime, usx2y); + if (shm->playback_iso_start < 0) shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso); shm->playback_iso_head = shm->playback_iso_start; } @@ -114,7 +118,7 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride; + counts = shm->captured_iso[shm->playback_iso_head].length / usx2y->stride; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); return -EPIPE; @@ -122,27 +126,29 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, /* set up descriptor */ urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset; urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length; - if (atomic_read(&subs->state) != state_RUNNING) + if (atomic_read(&subs->state) != STATE_RUNNING) memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0, urb->iso_frame_desc[pack].length); if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso)) shm->playback_iso_head = 0; count += counts; } - urb->transfer_buffer_length = count * usX2Y->stride; + urb->transfer_buffer_length = count * usx2y->stride; return 0; } - -static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs, - struct urb *urb) +static void usx2y_usbpcm_urb_capt_iso_advance(struct snd_usx2y_substream *subs, + struct urb *urb) { - int pack; + struct usb_iso_packet_descriptor *desc; + struct snd_usx2y_hwdep_pcm_shm *shm; + int pack, head; + for (pack = 0; pack < nr_of_packs(); ++pack) { - struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack; - if (NULL != subs) { - struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm; - int head = shm->captured_iso_head + 1; + desc = urb->iso_frame_desc + pack; + if (subs) { + shm = subs->usx2y->hwdep_pcm_shm; + head = shm->captured_iso_head + 1; if (head >= ARRAY_SIZE(shm->captured_iso)) head = 0; shm->captured_iso[head].frame = urb->start_frame + pack; @@ -151,106 +157,111 @@ static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream shm->captured_iso_head = head; shm->captured_iso_frames++; } - if ((desc->offset += desc->length * NRURBS*nr_of_packs()) + - desc->length >= SSS) + desc->offset += desc->length * NRURBS * nr_of_packs(); + if (desc->offset + desc->length >= SSS) desc->offset -= (SSS - desc->length); } } -static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *capsubs2, - struct snd_usX2Y_substream *playbacksubs, - int frame) +static int usx2y_usbpcm_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *capsubs2, + struct snd_usx2y_substream *playbacksubs, + int frame) { int err, state; struct urb *urb = playbacksubs->completed_urb; state = atomic_read(&playbacksubs->state); - if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (urb) { + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_hwdep_urb_play_prepare(playbacksubs, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb); + if (err) + return err; + err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb); + if (err) return err; - } } - + playbacksubs->completed_urb = NULL; state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + err = usx2y_usbpcm_urb_capt_retire(capsubs); + if (err) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) { atomic_inc(&capsubs->state); - usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); - if (NULL != capsubs2) - usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + } + usx2y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); + if (capsubs2) + usx2y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); + err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame); + if (err) return err; - if (NULL != capsubs2) - if ((err = usX2Y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) + if (capsubs2) { + err = usx2y_urb_submit(capsubs2, capsubs2->completed_urb, frame); + if (err) return err; + } } capsubs->completed_urb = NULL; - if (NULL != capsubs2) + if (capsubs2) capsubs2->completed_urb = NULL; return 0; } - -static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) +static void i_usx2y_usbpcm_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs, *capsubs2, *playbacksubs; - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; } subs->completed_urb = urb; - capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && - (NULL == capsubs2 || capsubs2->completed_urb) && - (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); - else { + capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + capsubs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (capsubs->completed_urb && atomic_read(&capsubs->state) >= STATE_PREPARED && + (!capsubs2 || capsubs2->completed_urb) && + (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) { + usx2y->wait_iso_frame += nr_of_packs(); + } else { snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } } } - -static void usX2Y_hwdep_urb_release(struct urb **urb) +static void usx2y_hwdep_urb_release(struct urb **urb) { usb_kill_urb(*urb); usb_free_urb(*urb); @@ -260,49 +271,53 @@ static void usX2Y_hwdep_urb_release(struct urb **urb) /* * release a substream */ -static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint); + + snd_printdd("snd_usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_hwdep_urb_release(subs->urb + i); + usx2y_hwdep_urb_release(subs->urb + i); } -static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_usbpcm_subs_startup_finish(struct usx2ydev *usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_urb_complete); + usx2y->prepare_subs = NULL; } -static void i_usX2Y_usbpcm_subs_startup(struct urb *urb) +static void i_usx2y_usbpcm_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; - if (NULL != prepare_subs && + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; + struct snd_usx2y_substream *cap_subs2; + + if (prepare_subs && urb->start_frame == prepare_subs->urb[0]->start_frame) { atomic_inc(&prepare_subs->state); - if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) { - struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - if (cap_subs2 != NULL) + if (prepare_subs == usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]) { + cap_subs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + if (cap_subs2) atomic_inc(&cap_subs2->state); } - usX2Y_usbpcm_subs_startup_finish(usX2Y); - wake_up(&usX2Y->prepare_wait_queue); + usx2y_usbpcm_subs_startup_finish(usx2y); + wake_up(&usx2y->prepare_wait_queue); } - i_usX2Y_usbpcm_urb_complete(urb); + i_usx2y_usbpcm_urb_complete(urb); } /* * initialize a substream's urbs */ -static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev; + struct urb **purb; pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -312,28 +327,28 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) /* allocate and initialize data urbs */ for (i = 0; i < NRURBS; i++) { - struct urb **purb = subs->urb + i; + purb = subs->urb + i; if (*purb) { usb_kill_urb(*purb); continue; } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); - if (NULL == *purb) { - usX2Y_usbpcm_urbs_release(subs); + if (!*purb) { + usx2y_usbpcm_urbs_release(subs); return -ENOMEM; } (*purb)->transfer_buffer = is_playback ? - subs->usX2Y->hwdep_pcm_shm->playback : ( + subs->usx2y->hwdep_pcm_shm->playback : ( subs->endpoint == 0x8 ? - subs->usX2Y->hwdep_pcm_shm->capture0x8 : - subs->usX2Y->hwdep_pcm_shm->capture0xA); + subs->usx2y->hwdep_pcm_shm->capture0x8 : + subs->usx2y->hwdep_pcm_shm->capture0xA); (*purb)->dev = dev; (*purb)->pipe = pipe; (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_usbpcm_subs_startup; + (*purb)->complete = i_usx2y_usbpcm_subs_startup; } return 0; } @@ -341,195 +356,216 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) /* * free the buffer */ -static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data, - *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); - - if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); + struct snd_usx2y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *cap_subs; + struct snd_usx2y_substream *playback_subs; + struct snd_usx2y_substream *cap_subs2; + + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("%s(%p)\n", __func__, substream); + + cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(cap_subs); - if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + atomic_set(&cap_subs->state, STATE_STOPPED); + if (cap_subs2) + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(cap_subs); + if (cap_subs2) + usx2y_usbpcm_urbs_release(cap_subs2); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); - if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); + if (cap_subs2) + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); + if (cap_subs2) + usx2y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } -static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev * usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev *usx2y = subs->usx2y; + + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; - smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); + smp_wmb(); // Make sure above modifications are seen by i_usx2y_subs_startup() + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_subs_startup); } -static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs) { - int p, u, err, - stream = subs->pcm_substream->stream; - struct usX2Ydev *usX2Y = subs->usX2Y; - - if (SNDRV_PCM_STREAM_CAPTURE == stream) { - usX2Y->hwdep_pcm_shm->captured_iso_head = -1; - usX2Y->hwdep_pcm_shm->captured_iso_frames = 0; + int p, u, err, stream = subs->pcm_substream->stream; + struct usx2ydev *usx2y = subs->usx2y; + struct urb *urb; + unsigned long pack; + + if (stream == SNDRV_PCM_STREAM_CAPTURE) { + usx2y->hwdep_pcm_shm->captured_iso_head = -1; + usx2y->hwdep_pcm_shm->captured_iso_frames = 0; } for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; - if (subs != NULL) { - if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0) + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; + if (subs) { + err = usx2y_usbpcm_urbs_allocate(subs); + if (err < 0) return err; subs->completed_urb = NULL; } } for (p = 0; p < 4; p++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[p]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[p]; + + if (subs && atomic_read(&subs->state) >= STATE_PREPARED) goto start; } start: - usX2Y_usbpcm_subs_startup(subs); + usx2y_usbpcm_subs_startup(subs); for (u = 0; u < NRURBS; u++) { for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; - if (subs != NULL) { - struct urb *urb = subs->urb[u]; - if (usb_pipein(urb->pipe)) { - unsigned long pack; - if (0 == u) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; - for (pack = 0; pack < nr_of_packs(); pack++) { - urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); - urb->iso_frame_desc[pack].length = subs->maxpacksize; - } - urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); - if ((err = usb_submit_urb(urb, GFP_KERNEL)) < 0) { - snd_printk (KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err); - err = -EPIPE; - goto cleanup; - } else { - snd_printdd("%i\n", urb->start_frame); - if (u == 0) - usX2Y->wait_iso_frame = urb->start_frame; - } - urb->transfer_flags = 0; - } else { - atomic_set(&subs->state, state_STARTING1); - break; - } + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; + + if (!subs) + continue; + urb = subs->urb[u]; + if (usb_pipein(urb->pipe)) { + if (!u) + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; + for (pack = 0; pack < nr_of_packs(); pack++) { + urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); + urb->iso_frame_desc[pack].length = subs->maxpacksize; + } + urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err < 0) { + snd_printk(KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err); + err = -EPIPE; + goto cleanup; + } else { + snd_printdd("%i\n", urb->start_frame); + if (!u) + usx2y->wait_iso_frame = urb->start_frame; + } + urb->transfer_flags = 0; + } else { + atomic_set(&subs->state, STATE_STARTING1); + break; } } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, !usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE; - + cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); // Call it now - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); // Call it now + usx2y_clients_stop(usx2y); // something is completely wrong > stop everything } return err; } +#define USX2Y_HWDEP_PCM_PAGES \ + PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm)) + /* * prepare callback * * set format and initialize urbs */ -static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); - if (NULL == usX2Y->hwdep_pcm_shm) { - usX2Y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usX2Y_hwdep_pcm_shm), + snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream); + + mutex_lock(&usx2y->pcm_mutex); + + if (!usx2y->hwdep_pcm_shm) { + usx2y->hwdep_pcm_shm = alloc_pages_exact(USX2Y_HWDEP_PCM_PAGES, GFP_KERNEL); - if (!usX2Y->hwdep_pcm_shm) - return -ENOMEM; - memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + if (!usx2y->hwdep_pcm_shm) { + err = -ENOMEM; + goto up_prepare_mutex; + } + memset(usx2y->hwdep_pcm_shm, 0, USX2Y_HWDEP_PCM_PAGES); } - mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); -// Start hardware streams -// SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + usx2y_subs_prepare(subs); + // Start hardware streams + // SyncStream first.... + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) { + err = usx2y_format_set(usx2y, runtime->format); + if (err < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + } + if (usx2y->rate != runtime->rate) { + err = usx2y_rate_set(usx2y, runtime->rate); + if (err < 0) goto up_prepare_mutex; + } snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs))) + err = usx2y_usbpcm_urbs_start(capsubs); + if (err < 0) goto up_prepare_mutex; } if (subs != capsubs) { - usX2Y->hwdep_pcm_shm->playback_iso_start = -1; - if (atomic_read(&subs->state) < state_PREPARED) { - while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > - usX2Y->hwdep_pcm_shm->captured_iso_frames) { - snd_printdd("Wait: iso_frames_per_buffer=%i," - "captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); + usx2y->hwdep_pcm_shm->playback_iso_start = -1; + if (atomic_read(&subs->state) < STATE_PREPARED) { + while (usx2y_iso_frames_per_buffer(runtime, usx2y) > + usx2y->hwdep_pcm_shm->captured_iso_frames) { + snd_printdd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); if (msleep_interruptible(10)) { err = -ERESTARTSYS; goto up_prepare_mutex; } - } - if (0 > (err = usX2Y_usbpcm_urbs_start(subs))) + } + err = usx2y_usbpcm_urbs_start(subs); + if (err < 0) goto up_prepare_mutex; } snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); - } else - usX2Y->hwdep_pcm_shm->capture_iso_start = -1; + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); + } else { + usx2y->hwdep_pcm_shm->capture_iso_start = -1; + } up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; } -static const struct snd_pcm_hardware snd_usX2Y_4c = -{ +static const struct snd_pcm_hardware snd_usx2y_4c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), @@ -547,55 +583,53 @@ static const struct snd_pcm_hardware snd_usX2Y_4c = .fifo_size = 0 }; - - -static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) - snd_pcm_substream_chip(substream))[substream->stream]; + struct snd_usx2y_substream *subs = + ((struct snd_usx2y_substream **) + snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime; - if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) + if (!(subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) return -EBUSY; - runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c : - (subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = snd_usx2y_2c; + else + runtime->hw = (subs->usx2y->subs[3] ? snd_usx2y_4c : snd_usx2y_2c); runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); return 0; } - -static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data; subs->pcm_substream = NULL; return 0; } - -static const struct snd_pcm_ops snd_usX2Y_usbpcm_ops = -{ - .open = snd_usX2Y_usbpcm_open, - .close = snd_usX2Y_usbpcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_usbpcm_hw_free, - .prepare = snd_usX2Y_usbpcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, +static const struct snd_pcm_ops snd_usx2y_usbpcm_ops = { + .open = snd_usx2y_usbpcm_open, + .close = snd_usx2y_usbpcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_usbpcm_hw_free, + .prepare = snd_usx2y_usbpcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, }; - -static int usX2Y_pcms_busy_check(struct snd_card *card) +static int usx2y_pcms_busy_check(struct snd_card *card) { - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); + struct snd_usx2y_substream *subs; int i; for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; + subs = dev->subs[i]; if (subs && subs->pcm_substream && SUBSTREAM_BUSY(subs->pcm_substream)) return -EBUSY; @@ -603,125 +637,120 @@ static int usX2Y_pcms_busy_check(struct snd_card *card) return 0; } -static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err; - mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } - -static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err; - mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } - -static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_open(struct vm_area_struct *area) { } - -static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_close(struct vm_area_struct *area) { } - -static vm_fault_t snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf) +static vm_fault_t snd_usx2y_hwdep_pcm_vm_fault(struct vm_fault *vmf) { unsigned long offset; void *vaddr; offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; vmf->page = virt_to_page(vaddr); get_page(vmf->page); return 0; } - -static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { - .open = snd_usX2Y_hwdep_pcm_vm_open, - .close = snd_usX2Y_hwdep_pcm_vm_close, - .fault = snd_usX2Y_hwdep_pcm_vm_fault, +static const struct vm_operations_struct snd_usx2y_hwdep_pcm_vm_ops = { + .open = snd_usx2y_hwdep_pcm_vm_open, + .close = snd_usx2y_hwdep_pcm_vm_close, + .fault = snd_usx2y_hwdep_pcm_vm_fault, }; - -static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) +static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep *hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *usX2Y = hw->private_data; + struct usx2ydev *usx2y = hw->private_data; - if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT)) + if (!(usx2y->chip_status & USX2Y_STAT_CHIP_INIT)) return -EBUSY; - /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) { - snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + /* if userspace tries to mmap beyond end of our buffer, fail */ + if (size > USX2Y_HWDEP_PCM_PAGES) { + snd_printd("%lu > %lu\n", size, (unsigned long)USX2Y_HWDEP_PCM_PAGES); return -EINVAL; } - if (!usX2Y->hwdep_pcm_shm) { + if (!usx2y->hwdep_pcm_shm) return -ENODEV; - } - area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; + + area->vm_ops = &snd_usx2y_hwdep_pcm_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; area->vm_private_data = hw->private_data; return 0; } - -static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) +static void snd_usx2y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) { - struct usX2Ydev *usX2Y = hwdep->private_data; - if (NULL != usX2Y->hwdep_pcm_shm) - free_pages_exact(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); -} + struct usx2ydev *usx2y = hwdep->private_data; + if (usx2y->hwdep_pcm_shm) + free_pages_exact(usx2y->hwdep_pcm_shm, USX2Y_HWDEP_PCM_PAGES); +} -int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { int err; struct snd_hwdep *hw; struct snd_pcm *pcm; - struct usb_device *dev = usX2Y(card)->dev; - if (1 != nr_of_packs()) + struct usb_device *dev = usx2y(card)->dev; + + if (nr_of_packs() != 1) return 0; - if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0) + err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw); + if (err < 0) return err; hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM; - hw->private_data = usX2Y(card); - hw->private_free = snd_usX2Y_hwdep_pcm_private_free; - hw->ops.open = snd_usX2Y_hwdep_pcm_open; - hw->ops.release = snd_usX2Y_hwdep_pcm_release; - hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap; + hw->private_data = usx2y(card); + hw->private_free = snd_usx2y_hwdep_pcm_private_free; + hw->ops.open = snd_usx2y_hwdep_pcm_open; + hw->ops.release = snd_usx2y_hwdep_pcm_release; + hw->ops.mmap = snd_usx2y_hwdep_pcm_mmap; hw->exclusive = 1; sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum); err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm); - if (err < 0) { + if (err < 0) return err; - } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops); - pcm->private_data = usX2Y(card)->subs; + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_usbpcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_usbpcm_ops); + + pcm->private_data = usx2y(card)->subs; pcm->info_flags = 0; sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio"); @@ -739,7 +768,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) #else -int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { return 0; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h index eb5a46466f0e..731b1c5a3474 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.h +++ b/sound/usb/usx2y/usx2yhwdeppcm.h @@ -4,7 +4,7 @@ #define MAXSTRIDE 3 #define SSS (((MAXPACK*MAXBUFFERMS*MAXSTRIDE + 4096) / 4096) * 4096) -struct snd_usX2Y_hwdep_pcm_shm { +struct snd_usx2y_hwdep_pcm_shm { char playback[SSS]; char capture0x8[SSS]; char capture0xA[SSS]; @@ -20,4 +20,4 @@ struct snd_usX2Y_hwdep_pcm_shm { int capture_iso_start; }; -int usX2Y_hwdep_pcm_new(struct snd_card *card); +int usx2y_hwdep_pcm_new(struct snd_card *card); diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 33b12aa67cf5..a34d7d9c2a57 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -236,7 +236,7 @@ static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val) * updating AUD_CONFIG register. * This is because: * Bit6 of AUD_CONFIG register is writeonly due to a silicon bug on VLV2 - * HDMI IP. As a result a read-modify of AUD_CONFIG regiter will always + * HDMI IP. As a result a read-modify of AUD_CONFIG register will always * clear bit6. AUD_CONFIG[6:4] represents the "channels" field of the * register. This field should be 1xy binary for configuration with 6 or * more channels. Read-modify of AUD_CONFIG (Eg. for enabling audio) @@ -342,7 +342,7 @@ static int had_prog_status_reg(struct snd_pcm_substream *substream, /* * function to initialize audio - * registers and buffer confgiuration registers + * registers and buffer configuration registers * This function is called in the prepare callback */ static int had_init_audio_ctrl(struct snd_pcm_substream *substream, @@ -1790,7 +1790,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) pcm->private_data = ctx; pcm->info_flags = 0; strscpy(pcm->name, card->shortname, strlen(card->shortname)); - /* setup the ops for playabck */ + /* setup the ops for playback */ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); /* allocate dma pages; diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h index 0d91bb5dbab7..bb3853195922 100644 --- a/sound/x86/intel_hdmi_audio.h +++ b/sound/x86/intel_hdmi_audio.h @@ -96,7 +96,7 @@ struct pcm_stream_info { * @had_spinlock: driver lock * @aes_bits: IEC958 status bits * @buff_done: id of current buffer done intr - * @dev: platoform device handle + * @dev: platform device handle * @chmap: holds channel map info */ struct snd_intelhad { |