diff options
Diffstat (limited to 'sound')
89 files changed, 1277 insertions, 820 deletions
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 8f71f7e..a0c4a5d 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -112,6 +112,7 @@ MODULE_ALIAS("sound-layout-100"); MODULE_ALIAS("aoa-device-id-14"); MODULE_ALIAS("aoa-device-id-22"); +MODULE_ALIAS("aoa-device-id-31"); MODULE_ALIAS("aoa-device-id-35"); MODULE_ALIAS("aoa-device-id-44"); @@ -362,6 +363,13 @@ static struct layout layouts[] = { .connections = tas_connections_nolineout, }, }, + /* PowerBook6,1 */ + { .device_id = 31, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, /* PowerBook6,5 */ { .device_id = 44, .codecs[0] = { @@ -1161,12 +1169,7 @@ static struct soundbus_driver aoa_soundbus_driver = { static int __init aoa_fabric_layout_init(void) { - int err; - - err = soundbus_register_driver(&aoa_soundbus_driver); - if (err) - return err; - return 0; + return soundbus_register_driver(&aoa_soundbus_driver); } static void __exit aoa_fabric_layout_exit(void) diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 1cbf210..000b585 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -197,7 +197,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, * so restrict to those we do handle for now. */ if (id && (*id == 22 || *id == 14 || *id == 35 || - *id == 44)) { + *id == 31 || *id == 44)) { snprintf(dev->sound.modalias, 32, "aoa-device-id-%d", *id); ok = 1; diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 2c49848..fec1dfd 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -553,13 +553,9 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) * we should allow parameter change only when stream has been * opened not in other cases */ - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - if (copy_from_user(params, (void __user *)arg, sizeof(*params))) { - retval = -EFAULT; - goto out; - } + params = memdup_user((void __user *)arg, sizeof(*params)); + if (IS_ERR(params)) + return PTR_ERR(params); retval = snd_compress_check_input(params); if (retval) @@ -784,7 +780,7 @@ static int snd_compress_wait_for_drain(struct snd_compr_stream *stream) ret = wait_event_interruptible(stream->runtime->sleep, (stream->runtime->state != SNDRV_PCM_STATE_DRAINING)); if (ret == -ERESTARTSYS) - pr_debug("wait aborted by a signal"); + pr_debug("wait aborted by a signal\n"); else if (ret) pr_debug("wait for drain failed with %d\n", ret); @@ -966,7 +962,7 @@ static int snd_compress_dev_register(struct snd_device *device) compr->card, compr->device, &snd_compr_file_ops, compr, &compr->dev); if (ret < 0) { - pr_err("snd_register_device failed\n %d", ret); + pr_err("snd_register_device failed %d\n", ret); return ret; } return ret; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index c61fd50..9d33c1e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2637,9 +2637,11 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream) break; /* Fall through */ case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_SUSPENDED: err = 0; break; + case SNDRV_PCM_STATE_SUSPENDED: + err = -ESTRPIPE; + break; case SNDRV_PCM_STATE_XRUN: err = -EPIPE; break; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index d6d9419..4c93520 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -87,21 +87,6 @@ static int snd_seq_deliver_single_event(struct snd_seq_client *client, /* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* - */ static inline unsigned short snd_seq_file_flags(struct file *file) { switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { @@ -1128,59 +1113,69 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) /*-----------------------------------------------------*/ +static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg) +{ + int *pversion = arg; + + *pversion = SNDRV_SEQ_VERSION; + return 0; +} + +static int snd_seq_ioctl_client_id(struct snd_seq_client *client, void *arg) +{ + int *client_id = arg; + + *client_id = client->number; + return 0; +} /* SYSTEM_INFO ioctl() */ -static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg) { - struct snd_seq_system_info info; + struct snd_seq_system_info *info = arg; - memset(&info, 0, sizeof(info)); + memset(info, 0, sizeof(*info)); /* fill the info fields */ - info.queues = SNDRV_SEQ_MAX_QUEUES; - info.clients = SNDRV_SEQ_MAX_CLIENTS; - info.ports = SNDRV_SEQ_MAX_PORTS; - info.channels = 256; /* fixed limit */ - info.cur_clients = client_usage.cur; - info.cur_queues = snd_seq_queue_get_cur_queues(); - - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; + info->queues = SNDRV_SEQ_MAX_QUEUES; + info->clients = SNDRV_SEQ_MAX_CLIENTS; + info->ports = SNDRV_SEQ_MAX_PORTS; + info->channels = 256; /* fixed limit */ + info->cur_clients = client_usage.cur; + info->cur_queues = snd_seq_queue_get_cur_queues(); + return 0; } /* RUNNING_MODE ioctl() */ -static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg) { - struct snd_seq_running_info info; + struct snd_seq_running_info *info = arg; struct snd_seq_client *cptr; int err = 0; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* requested client number */ - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */ #ifdef SNDRV_BIG_ENDIAN - if (! info.big_endian) { + if (!info->big_endian) { err = -EINVAL; goto __err; } #else - if (info.big_endian) { + if (info->big_endian) { err = -EINVAL; goto __err; } #endif - if (info.cpu_mode > sizeof(long)) { + if (info->cpu_mode > sizeof(long)) { err = -EINVAL; goto __err; } - cptr->convert32 = (info.cpu_mode < sizeof(long)); + cptr->convert32 = (info->cpu_mode < sizeof(long)); __err: snd_seq_client_unlock(cptr); return err; @@ -1214,51 +1209,43 @@ static void get_client_info(struct snd_seq_client *cptr, } static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *client_info = arg; struct snd_seq_client *cptr; - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; /* requested client number */ - cptr = snd_seq_client_use_ptr(client_info.client); + cptr = snd_seq_client_use_ptr(client_info->client); if (cptr == NULL) return -ENOENT; /* don't change !!! */ - get_client_info(cptr, &client_info); + get_client_info(cptr, client_info); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &client_info, sizeof(client_info))) - return -EFAULT; return 0; } /* CLIENT_INFO ioctl() */ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_info client_info; - - if (copy_from_user(&client_info, arg, sizeof(client_info))) - return -EFAULT; + struct snd_seq_client_info *client_info = arg; /* it is not allowed to set the info fields for an another client */ - if (client->number != client_info.client) + if (client->number != client_info->client) return -EPERM; /* also client type must be set now */ - if (client->type != client_info.type) + if (client->type != client_info->type) return -EINVAL; /* fill the info fields */ - if (client_info.name[0]) - strlcpy(client->name, client_info.name, sizeof(client->name)); + if (client_info->name[0]) + strlcpy(client->name, client_info->name, sizeof(client->name)); - client->filter = client_info.filter; - client->event_lost = client_info.event_lost; - memcpy(client->event_filter, client_info.event_filter, 32); + client->filter = client_info->filter; + client->event_lost = client_info->event_lost; + memcpy(client->event_filter, client_info->event_filter, 32); return 0; } @@ -1267,30 +1254,26 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, /* * CREATE PORT ioctl() */ -static int snd_seq_ioctl_create_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; struct snd_seq_port_callback *callback; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to create the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM; - port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1); + port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1); if (port == NULL) return -ENOMEM; - if (client->type == USER_CLIENT && info.kernel) { + if (client->type == USER_CLIENT && info->kernel) { snd_seq_delete_port(client, port->addr.port); return -EINVAL; } if (client->type == KERNEL_CLIENT) { - if ((callback = info.kernel) != NULL) { + if ((callback = info->kernel) != NULL) { if (callback->owner) port->owner = callback->owner; port->private_data = callback->private_data; @@ -1303,37 +1286,29 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, } } - info.addr = port->addr; + info->addr = port->addr; - snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* * DELETE PORT ioctl() */ -static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg) { - struct snd_seq_port_info info; + struct snd_seq_port_info *info = arg; int err; - /* set passed parameters */ - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - /* it is not allowed to remove the port for an another client */ - if (info.addr.client != client->number) + if (info->addr.client != client->number) return -EPERM; - err = snd_seq_delete_port(client, info.addr.port); + err = snd_seq_delete_port(client, info->addr.port); if (err >= 0) - snd_seq_system_client_ev_port_exit(client->number, info.addr.port); + snd_seq_system_client_ev_port_exit(client->number, info->addr.port); return err; } @@ -1341,32 +1316,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, /* * GET_PORT_INFO ioctl() (on any client) */ -static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port; - struct snd_seq_port_info info; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO; - port = snd_seq_port_use_ptr(cptr, info.addr.port); + port = snd_seq_port_use_ptr(cptr, info->addr.port); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; /* don't change */ } /* get port info */ - snd_seq_get_port_info(port, &info); + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -1374,20 +1344,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, /* * SET_PORT_INFO ioctl() (only ports on this/own client) */ -static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client_port *port; - struct snd_seq_port_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (info.addr.client != client->number) /* only set our own ports ! */ + if (info->addr.client != client->number) /* only set our own ports ! */ return -EPERM; - port = snd_seq_port_use_ptr(client, info.addr.port); + port = snd_seq_port_use_ptr(client, info->addr.port); if (port) { - snd_seq_set_port_info(port, &info); + snd_seq_set_port_info(port, info); snd_seq_port_unlock(port); } return 0; @@ -1453,34 +1419,31 @@ int snd_seq_client_notify_subscription(int client, int port, * add to port's subscription list IOCTL interface */ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -EINVAL; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) goto __end; - result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end; /* connect them */ - result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs); + result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); + subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport); @@ -1498,33 +1461,30 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, * remove from port's subscription list */ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result = -ENXIO; struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL; - struct snd_seq_port_subscribe subs; - - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) + if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL) goto __end; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) + if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL) goto __end; - result = check_subscription_permission(client, sport, dport, &subs); + result = check_subscription_permission(client, sport, dport, subs); if (result < 0) goto __end; - result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs); + result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs); if (! result) /* broadcast announce */ snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, - &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); + subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); __end: if (sport) snd_seq_port_unlock(sport); @@ -1539,17 +1499,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, /* CREATE_QUEUE ioctl() */ -static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; int result; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - result = snd_seq_queue_alloc(client->number, info.locked, info.flags); + result = snd_seq_queue_alloc(client->number, info->locked, info->flags); if (result < 0) return result; @@ -1557,181 +1513,150 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, if (q == NULL) return -EINVAL; - info.queue = q->queue; - info.locked = q->locked; - info.owner = q->owner; + info->queue = q->queue; + info->locked = q->locked; + info->owner = q->owner; /* set queue name */ - if (! info.name[0]) - snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); - strlcpy(q->name, info.name, sizeof(q->name)); + if (!info->name[0]) + snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* DELETE_QUEUE ioctl() */ -static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg) { - struct snd_seq_queue_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; + struct snd_seq_queue_info *info = arg; - return snd_seq_queue_delete(client->number, info.queue); + return snd_seq_queue_delete(client->number, info->queue); } /* GET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = queueptr(info.queue); + q = queueptr(info->queue); if (q == NULL) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; - strlcpy(info.name, q->name, sizeof(info.name)); + memset(info, 0, sizeof(*info)); + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; + strlcpy(info->name, q->name, sizeof(info->name)); queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* SET_QUEUE_INFO ioctl() */ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (info.owner != client->number) + if (info->owner != client->number) return -EINVAL; /* change owner/locked permission */ - if (snd_seq_queue_check_access(info.queue, client->number)) { - if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) + if (snd_seq_queue_check_access(info->queue, client->number)) { + if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0) return -EPERM; - if (info.locked) - snd_seq_queue_use(info.queue, client->number, 1); + if (info->locked) + snd_seq_queue_use(info->queue, client->number, 1); } else { return -EPERM; } - q = queueptr(info.queue); + q = queueptr(info->queue); if (! q) return -EINVAL; if (q->owner != client->number) { queuefree(q); return -EPERM; } - strlcpy(q->name, info.name, sizeof(q->name)); + strlcpy(q->name, info->name, sizeof(q->name)); queuefree(q); return 0; } /* GET_NAMED_QUEUE ioctl() */ -static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg) +static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, + void *arg) { - struct snd_seq_queue_info info; + struct snd_seq_queue_info *info = arg; struct snd_seq_queue *q; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - q = snd_seq_queue_find_name(info.name); + q = snd_seq_queue_find_name(info->name); if (q == NULL) return -EINVAL; - info.queue = q->queue; - info.owner = q->owner; - info.locked = q->locked; + info->queue = q->queue; + info->owner = q->owner; + info->locked = q->locked; queuefree(q); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; - return 0; } /* GET_QUEUE_STATUS ioctl() */ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_status status; + struct snd_seq_queue_status *status = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&status, arg, sizeof(status))) - return -EFAULT; - - queue = queueptr(status.queue); + queue = queueptr(status->queue); if (queue == NULL) return -EINVAL; - memset(&status, 0, sizeof(status)); - status.queue = queue->queue; + memset(status, 0, sizeof(*status)); + status->queue = queue->queue; tmr = queue->timer; - status.events = queue->tickq->cells + queue->timeq->cells; + status->events = queue->tickq->cells + queue->timeq->cells; - status.time = snd_seq_timer_get_cur_time(tmr); - status.tick = snd_seq_timer_get_cur_tick(tmr); + status->time = snd_seq_timer_get_cur_time(tmr); + status->tick = snd_seq_timer_get_cur_tick(tmr); - status.running = tmr->running; + status->running = tmr->running; - status.flags = queue->flags; + status->flags = queue->flags; queuefree(queue); - if (copy_to_user(arg, &status, sizeof(status))) - return -EFAULT; return 0; } /* GET_QUEUE_TEMPO ioctl() */ static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_tempo *tempo = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - - queue = queueptr(tempo.queue); + queue = queueptr(tempo->queue); if (queue == NULL) return -EINVAL; - memset(&tempo, 0, sizeof(tempo)); - tempo.queue = queue->queue; + memset(tempo, 0, sizeof(*tempo)); + tempo->queue = queue->queue; tmr = queue->timer; - tempo.tempo = tmr->tempo; - tempo.ppq = tmr->ppq; - tempo.skew_value = tmr->skew; - tempo.skew_base = tmr->skew_base; + tempo->tempo = tmr->tempo; + tempo->ppq = tmr->ppq; + tempo->skew_value = tmr->skew; + tempo->skew_base = tmr->skew_base; queuefree(queue); - if (copy_to_user(arg, &tempo, sizeof(tempo))) - return -EFAULT; return 0; } @@ -1747,31 +1672,25 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) EXPORT_SYMBOL(snd_seq_set_queue_tempo); static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_tempo *tempo = arg; int result; - struct snd_seq_queue_tempo tempo; - - if (copy_from_user(&tempo, arg, sizeof(tempo))) - return -EFAULT; - result = snd_seq_set_queue_tempo(client->number, &tempo); + result = snd_seq_set_queue_tempo(client->number, tempo); return result < 0 ? result : 0; } /* GET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_timer timer; + struct snd_seq_queue_timer *timer = arg; struct snd_seq_queue *queue; struct snd_seq_timer *tmr; - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - - queue = queueptr(timer.queue); + queue = queueptr(timer->queue); if (queue == NULL) return -EINVAL; @@ -1780,41 +1699,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = queue->timer; - memset(&timer, 0, sizeof(timer)); - timer.queue = queue->queue; + memset(timer, 0, sizeof(*timer)); + timer->queue = queue->queue; - timer.type = tmr->type; + timer->type = tmr->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - timer.u.alsa.id = tmr->alsa_id; - timer.u.alsa.resolution = tmr->preferred_resolution; + timer->u.alsa.id = tmr->alsa_id; + timer->u.alsa.resolution = tmr->preferred_resolution; } mutex_unlock(&queue->timer_mutex); queuefree(queue); - if (copy_to_user(arg, &timer, sizeof(timer))) - return -EFAULT; return 0; } /* SET_QUEUE_TIMER ioctl() */ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_timer *timer = arg; int result = 0; - struct snd_seq_queue_timer timer; - - if (copy_from_user(&timer, arg, sizeof(timer))) - return -EFAULT; - if (timer.type != SNDRV_SEQ_TIMER_ALSA) + if (timer->type != SNDRV_SEQ_TIMER_ALSA) return -EINVAL; - if (snd_seq_queue_check_access(timer.queue, client->number)) { + if (snd_seq_queue_check_access(timer->queue, client->number)) { struct snd_seq_queue *q; struct snd_seq_timer *tmr; - q = queueptr(timer.queue); + q = queueptr(timer->queue); if (q == NULL) return -ENXIO; if (mutex_lock_interruptible(&q->timer_mutex)) { @@ -1822,13 +1736,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, return -ERESTARTSYS; } tmr = q->timer; - snd_seq_queue_timer_close(timer.queue); - tmr->type = timer.type; + snd_seq_queue_timer_close(timer->queue); + tmr->type = timer->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { - tmr->alsa_id = timer.u.alsa.id; - tmr->preferred_resolution = timer.u.alsa.resolution; + tmr->alsa_id = timer->u.alsa.id; + tmr->preferred_resolution = timer->u.alsa.resolution; } - result = snd_seq_queue_timer_open(timer.queue); + result = snd_seq_queue_timer_open(timer->queue); mutex_unlock(&q->timer_mutex); queuefree(q); } else { @@ -1841,38 +1755,30 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, /* GET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_queue_client info; + struct snd_seq_queue_client *info = arg; int used; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - used = snd_seq_queue_is_used(info.queue, client->number); + used = snd_seq_queue_is_used(info->queue, client->number); if (used < 0) return -EINVAL; - info.used = used; - info.client = client->number; + info->used = used; + info->client = client->number; - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } /* SET_QUEUE_CLIENT ioctl() */ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_queue_client *info = arg; int err; - struct snd_seq_queue_client info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - if (info.used >= 0) { - err = snd_seq_queue_use(info.queue, client->number, info.used); + if (info->used >= 0) { + err = snd_seq_queue_use(info->queue, client->number, info->used); if (err < 0) return err; } @@ -1883,78 +1789,70 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, /* GET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; struct snd_seq_client *cptr; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - cptr = snd_seq_client_use_ptr(info.client); + cptr = snd_seq_client_use_ptr(info->client); if (cptr == NULL) return -ENOENT; - memset(&info, 0, sizeof(info)); - info.client = cptr->number; - info.output_pool = cptr->pool->size; - info.output_room = cptr->pool->room; - info.output_free = info.output_pool; - info.output_free = snd_seq_unused_cells(cptr->pool); + memset(info, 0, sizeof(*info)); + info->client = cptr->number; + info->output_pool = cptr->pool->size; + info->output_room = cptr->pool->room; + info->output_free = info->output_pool; + info->output_free = snd_seq_unused_cells(cptr->pool); if (cptr->type == USER_CLIENT) { - info.input_pool = cptr->data.user.fifo_pool_size; - info.input_free = info.input_pool; + info->input_pool = cptr->data.user.fifo_pool_size; + info->input_free = info->input_pool; if (cptr->data.user.fifo) - info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); + info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); } else { - info.input_pool = 0; - info.input_free = 0; + info->input_pool = 0; + info->input_free = 0; } snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } /* SET_CLIENT_POOL ioctl() */ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_client_pool info; + struct snd_seq_client_pool *info = arg; int rc; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - - if (client->number != info.client) + if (client->number != info->client) return -EINVAL; /* can't change other clients */ - if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && + if (info->output_pool >= 1 && info->output_pool <= SNDRV_SEQ_MAX_EVENTS && (! snd_seq_write_pool_allocated(client) || - info.output_pool != client->pool->size)) { + info->output_pool != client->pool->size)) { if (snd_seq_write_pool_allocated(client)) { /* remove all existing cells */ snd_seq_queue_client_leave_cells(client->number); snd_seq_pool_done(client->pool); } - client->pool->size = info.output_pool; + client->pool->size = info->output_pool; rc = snd_seq_pool_init(client->pool); if (rc < 0) return rc; } if (client->type == USER_CLIENT && client->data.user.fifo != NULL && - info.input_pool >= 1 && - info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && - info.input_pool != client->data.user.fifo_pool_size) { + info->input_pool >= 1 && + info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && + info->input_pool != client->data.user.fifo_pool_size) { /* change pool size */ - rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); + rc = snd_seq_fifo_resize(client->data.user.fifo, info->input_pool); if (rc < 0) return rc; - client->data.user.fifo_pool_size = info.input_pool; + client->data.user.fifo_pool_size = info->input_pool; } - if (info.output_room >= 1 && - info.output_room <= client->pool->size) { - client->pool->room = info.output_room; + if (info->output_room >= 1 && + info->output_room <= client->pool->size) { + client->pool->room = info->output_room; } return snd_seq_ioctl_get_client_pool(client, arg); @@ -1963,17 +1861,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, /* REMOVE_EVENTS ioctl() */ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, - void __user *arg) + void *arg) { - struct snd_seq_remove_events info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; + struct snd_seq_remove_events *info = arg; /* * Input mostly not implemented XXX. */ - if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) { /* * No restrictions so for a user client we can clear * the whole fifo @@ -1982,8 +1877,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, snd_seq_fifo_clear(client->data.user.fifo); } - if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) - snd_seq_queue_remove_cells(client->number, &info); + if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) + snd_seq_queue_remove_cells(client->number, info); return 0; } @@ -1993,26 +1888,23 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, * get subscription info */ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_subscribe *subs = arg; int result; struct snd_seq_client *sender = NULL; struct snd_seq_client_port *sport = NULL; - struct snd_seq_port_subscribe subs; struct snd_seq_subscribers *p; - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - result = -EINVAL; - if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) + if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; - if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) + if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); + p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest); if (p) { result = 0; - subs = p->info; + *subs = p->info; } else result = -ENOENT; @@ -2021,10 +1913,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, snd_seq_port_unlock(sport); if (sender) snd_seq_client_unlock(sender); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; } @@ -2032,26 +1921,22 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, /* * get subscription info - check only its presence */ -static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, - void __user *arg) +static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg) { + struct snd_seq_query_subs *subs = arg; int result = -ENXIO; struct snd_seq_client *cptr = NULL; struct snd_seq_client_port *port = NULL; - struct snd_seq_query_subs subs; struct snd_seq_port_subs_info *group; struct list_head *p; int i; - if (copy_from_user(&subs, arg, sizeof(subs))) - return -EFAULT; - - if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) + if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL) goto __end; - if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) + if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL) goto __end; - switch (subs.type) { + switch (subs->type) { case SNDRV_SEQ_QUERY_SUBS_READ: group = &port->c_src; break; @@ -2064,22 +1949,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, down_read(&group->list_mutex); /* search for the subscriber */ - subs.num_subs = group->count; + subs->num_subs = group->count; i = 0; result = -ENOENT; list_for_each(p, &group->list_head) { - if (i++ == subs.index) { + if (i++ == subs->index) { /* found! */ struct snd_seq_subscribers *s; - if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { + if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) { s = list_entry(p, struct snd_seq_subscribers, src_list); - subs.addr = s->info.dest; + subs->addr = s->info.dest; } else { s = list_entry(p, struct snd_seq_subscribers, dest_list); - subs.addr = s->info.sender; + subs->addr = s->info.sender; } - subs.flags = s->info.flags; - subs.queue = s->info.queue; + subs->flags = s->info.flags; + subs->queue = s->info.queue; result = 0; break; } @@ -2091,10 +1976,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, snd_seq_port_unlock(port); if (cptr) snd_seq_client_unlock(cptr); - if (result >= 0) { - if (copy_to_user(arg, &subs, sizeof(subs))) - return -EFAULT; - } + return result; } @@ -2103,31 +1985,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, * query next client */ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_client_info *info = arg; struct snd_seq_client *cptr = NULL; - struct snd_seq_client_info info; - - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; /* search for next client */ - info.client++; - if (info.client < 0) - info.client = 0; - for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) { - cptr = snd_seq_client_use_ptr(info.client); + info->client++; + if (info->client < 0) + info->client = 0; + for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) { + cptr = snd_seq_client_use_ptr(info->client); if (cptr) break; /* found */ } if (cptr == NULL) return -ENOENT; - get_client_info(cptr, &info); + get_client_info(cptr, info); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -2135,43 +2012,41 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, * query next port */ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, - void __user *arg) + void *arg) { + struct snd_seq_port_info *info = arg; struct snd_seq_client *cptr; struct snd_seq_client_port *port = NULL; - struct snd_seq_port_info info; - if (copy_from_user(&info, arg, sizeof(info))) - return -EFAULT; - cptr = snd_seq_client_use_ptr(info.addr.client); + cptr = snd_seq_client_use_ptr(info->addr.client); if (cptr == NULL) return -ENXIO; /* search for next port */ - info.addr.port++; - port = snd_seq_port_query_nearest(cptr, &info); + info->addr.port++; + port = snd_seq_port_query_nearest(cptr, info); if (port == NULL) { snd_seq_client_unlock(cptr); return -ENOENT; } /* get port info */ - info.addr = port->addr; - snd_seq_get_port_info(port, &info); + info->addr = port->addr; + snd_seq_get_port_info(port, info); snd_seq_port_unlock(port); snd_seq_client_unlock(cptr); - if (copy_to_user(arg, &info, sizeof(info))) - return -EFAULT; return 0; } /* -------------------------------------------------------- */ -static struct seq_ioctl_table { +static const struct ioctl_handler { unsigned int cmd; - int (*func)(struct snd_seq_client *client, void __user * arg); -} ioctl_tables[] = { + int (*func)(struct snd_seq_client *client, void *arg); +} ioctl_handlers[] = { + { SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion }, + { SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id }, { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info }, @@ -2204,40 +2079,65 @@ static struct seq_ioctl_table { { 0, NULL }, }; -static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, - void __user *arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { - struct seq_ioctl_table *p; + struct snd_seq_client *client = file->private_data; + /* To use kernel stack for ioctl data. */ + union { + int pversion; + int client_id; + struct snd_seq_system_info system_info; + struct snd_seq_running_info running_info; + struct snd_seq_client_info client_info; + struct snd_seq_port_info port_info; + struct snd_seq_port_subscribe port_subscribe; + struct snd_seq_queue_info queue_info; + struct snd_seq_queue_status queue_status; + struct snd_seq_queue_tempo tempo; + struct snd_seq_queue_timer queue_timer; + struct snd_seq_queue_client queue_client; + struct snd_seq_client_pool client_pool; + struct snd_seq_remove_events remove_events; + struct snd_seq_query_subs query_subs; + } buf; + const struct ioctl_handler *handler; + unsigned long size; + int err; - switch (cmd) { - case SNDRV_SEQ_IOCTL_PVERSION: - /* return sequencer version number */ - return put_user(SNDRV_SEQ_VERSION, (int __user *)arg) ? -EFAULT : 0; - case SNDRV_SEQ_IOCTL_CLIENT_ID: - /* return the id of this client */ - return put_user(client->number, (int __user *)arg) ? -EFAULT : 0; - } + if (snd_BUG_ON(!client)) + return -ENXIO; - if (! arg) - return -EFAULT; - for (p = ioctl_tables; p->cmd; p++) { - if (p->cmd == cmd) - return p->func(client, arg); + for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { + if (handler->cmd == cmd) + break; } - pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", - cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); - return -ENOTTY; -} + if (handler->cmd == 0) + return -ENOTTY; + memset(&buf, 0, sizeof(buf)); -static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct snd_seq_client *client = file->private_data; + /* + * All of ioctl commands for ALSA sequencer get an argument of size + * within 13 bits. We can safely pick up the size from the command. + */ + size = _IOC_SIZE(handler->cmd); + if (handler->cmd & IOC_IN) { + if (copy_from_user(&buf, (const void __user *)arg, size)) + return -EFAULT; + } - if (snd_BUG_ON(!client)) - return -ENXIO; - - return snd_seq_do_ioctl(client, cmd, (void __user *) arg); + err = handler->func(client, &buf); + if (err >= 0) { + /* Some commands includes a bug in 'dir' field. */ + if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT || + handler->cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_POOL || + (handler->cmd & IOC_OUT)) + if (copy_to_user((void __user *)arg, &buf, size)) + return -EFAULT; + } + + return err; } #ifdef CONFIG_COMPAT @@ -2423,23 +2323,35 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); -/* - * exported, called by kernel clients to perform same functions as with - * userland ioctl() +/** + * snd_seq_kernel_client_ctl - operate a command for a client with data in + * kernel space. + * @clientid: A numerical ID for a client. + * @cmd: An ioctl(2) command for ALSA sequencer operation. + * @arg: A pointer to data in kernel space. + * + * Against its name, both kernel/application client can be handled by this + * kernel API. A pointer of 'arg' argument should be in kernel space. + * + * Return: 0 at success. Negative error code at failure. */ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) { + const struct ioctl_handler *handler; struct snd_seq_client *client; - mm_segment_t fs; - int result; client = clientptr(clientid); if (client == NULL) return -ENXIO; - fs = snd_enter_user(); - result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); - snd_leave_user(fs); - return result; + + for (handler = ioctl_handlers; handler->cmd > 0; ++handler) { + if (handler->cmd == cmd) + return handler->func(client, arg); + } + + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); + return -ENOTTY; } EXPORT_SYMBOL(snd_seq_kernel_client_ctl); diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index 6517590..fce5697 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -47,7 +47,6 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned { int err = -EFAULT; struct snd_seq_port_info *data; - mm_segment_t fs; data = kmalloc(sizeof(*data), GFP_KERNEL); if (!data) @@ -59,9 +58,7 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned goto error; data->kernel = NULL; - fs = snd_enter_user(); - err = snd_seq_do_ioctl(client, cmd, data); - snd_leave_user(fs); + err = snd_seq_kernel_client_ctl(client->number, cmd, &data); if (err < 0) goto error; @@ -123,7 +120,7 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: case SNDRV_SEQ_IOCTL_RUNNING_MODE: - return snd_seq_do_ioctl(client, cmd, argp); + return snd_seq_ioctl(file, cmd, arg); case SNDRV_SEQ_IOCTL_CREATE_PORT32: return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); case SNDRV_SEQ_IOCTL_DELETE_PORT32: diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile index af7ed66..dd45486 100644 --- a/sound/firewire/bebob/Makefile +++ b/sound/firewire/bebob/Makefile @@ -1,4 +1,5 @@ snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_midi.o \ - bebob_pcm.o bebob_hwdep.o bebob_terratec.o bebob_yamaha.o \ - bebob_focusrite.o bebob_maudio.o bebob.o + bebob_pcm.o bebob_hwdep.o bebob_terratec.o \ + bebob_yamaha_terratec.o bebob_focusrite.o bebob_maudio.o \ + bebob.o obj-$(CONFIG_SND_BEBOB) += snd-bebob.o diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index f7e2cbd..3469ac14 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -458,17 +458,17 @@ static const struct ieee1394_device_id bebob_id_table[] = { /* TerraTec Electronic GmbH, PHASE 88 Rack FW */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000003, &phase88_rack_spec), /* TerraTec Electronic GmbH, PHASE 24 FW */ - SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &phase24_series_spec), + SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000004, &yamaha_terratec_spec), /* TerraTec Electronic GmbH, Phase X24 FW */ - SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000007, &phase24_series_spec), + 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 */ SND_BEBOB_DEV_ENTRY(VEN_TERRATEC, 0x00000002, &spec_normal), /* Yamaha, GO44 */ - SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_go_spec), + SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000b, &yamaha_terratec_spec), /* YAMAHA, GO46 */ - SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_go_spec), + SND_BEBOB_DEV_ENTRY(VEN_YAMAHA, 0x0010000c, &yamaha_terratec_spec), /* Focusrite, SaffirePro 26 I/O */ SND_BEBOB_DEV_ENTRY(VEN_FOCUSRITE, 0x00000003, &saffirepro_26_spec), /* Focusrite, SaffirePro 10 I/O */ diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h index e7f1bb9..175da87 100644 --- a/sound/firewire/bebob/bebob.h +++ b/sound/firewire/bebob/bebob.h @@ -235,8 +235,7 @@ int snd_bebob_create_hwdep_device(struct snd_bebob *bebob); /* model specific operations */ extern const struct snd_bebob_spec phase88_rack_spec; -extern const struct snd_bebob_spec phase24_series_spec; -extern const struct snd_bebob_spec yamaha_go_spec; +extern const struct snd_bebob_spec yamaha_terratec_spec; extern const struct snd_bebob_spec saffirepro_26_spec; extern const struct snd_bebob_spec saffirepro_10_spec; extern const struct snd_bebob_spec saffire_le_spec; diff --git a/sound/firewire/bebob/bebob_terratec.c b/sound/firewire/bebob/bebob_terratec.c index c38358b..2fdaf93 100644 --- a/sound/firewire/bebob/bebob_terratec.c +++ b/sound/firewire/bebob/bebob_terratec.c @@ -36,25 +36,6 @@ end: return err; } -static enum snd_bebob_clock_type phase24_series_clk_src_types[] = { - SND_BEBOB_CLOCK_TYPE_INTERNAL, - SND_BEBOB_CLOCK_TYPE_EXTERNAL, /* S/PDIF */ -}; -static int -phase24_series_clk_src_get(struct snd_bebob *bebob, unsigned int *id) -{ - int err; - - err = avc_audio_get_selector(bebob->unit, 0, 4, id); - if (err < 0) - return err; - - if (*id >= ARRAY_SIZE(phase24_series_clk_src_types)) - return -EIO; - - return 0; -} - static const struct snd_bebob_rate_spec phase_series_rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, @@ -71,15 +52,3 @@ const struct snd_bebob_spec phase88_rack_spec = { .rate = &phase_series_rate_spec, .meter = NULL }; - -/* 'PHASE 24 FW' and 'PHASE X24 FW' */ -static const struct snd_bebob_clock_spec phase24_series_clk = { - .num = ARRAY_SIZE(phase24_series_clk_src_types), - .types = phase24_series_clk_src_types, - .get = &phase24_series_clk_src_get, -}; -const struct snd_bebob_spec phase24_series_spec = { - .clock = &phase24_series_clk, - .rate = &phase_series_rate_spec, - .meter = NULL -}; diff --git a/sound/firewire/bebob/bebob_yamaha.c b/sound/firewire/bebob/bebob_yamaha_terratec.c index 90d4404..a6be3e7 100644 --- a/sound/firewire/bebob/bebob_yamaha.c +++ b/sound/firewire/bebob/bebob_yamaha_terratec.c @@ -14,7 +14,7 @@ * must be accompanied. If changing the state, a LED on the device starts to * blink and its sync status is false. In this state, the device sounds nothing * even if streaming. To start streaming at the current sampling rate is only - * way to revocer this state. GO46 is better for stand-alone mixer. + * way to recover this state. GO46 is better for stand-alone mixer. * * Both of them have a capability to change its sampling rate up to 192.0kHz. * At 192.0kHz, the device reports 4 PCM-in, 1 MIDI-in, 6 PCM-out, 1 MIDI-out. @@ -25,7 +25,10 @@ * streaming with many asynchronous transactions brings sounds with noises. * Unfortunately current 'ffado-mixer' generated many asynchronous transaction * to observe device's state, mainly check cmp connection and signal format. I - * reccomend users to close ffado-mixer at 192.0kHz if mixer is needless. + * recommend users to close ffado-mixer at 192.0kHz if mixer is needless. + * + * Terratec PHASE 24 FW and PHASE X24 FW are internally the same as + * Yamaha GO 44 and GO 46. Yamaha and Terratec had cooperated for these models. */ static enum snd_bebob_clock_type clk_src_types[] = { @@ -55,7 +58,7 @@ static const struct snd_bebob_rate_spec rate_spec = { .get = &snd_bebob_stream_get_rate, .set = &snd_bebob_stream_set_rate, }; -const struct snd_bebob_spec yamaha_go_spec = { +const struct snd_bebob_spec yamaha_terratec_spec = { .clock = &clock_spec, .rate = &rate_spec, .meter = NULL diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 4aa0249..6074fe1 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -302,7 +302,7 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) int snd_dice_create_pcm(struct snd_dice *dice) { - static struct snd_pcm_ops capture_ops = { + static const struct snd_pcm_ops capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -314,7 +314,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; - static struct snd_pcm_ops playback_ops = { + static const struct snd_pcm_ops playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index cac28f7..613f058 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -329,7 +329,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&dg00x->rx_stream); } -static struct snd_pcm_ops pcm_capture_ops = { +static const struct snd_pcm_ops pcm_capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -341,7 +341,7 @@ static struct snd_pcm_ops pcm_capture_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; -static struct snd_pcm_ops pcm_playback_ops = { +static const struct snd_pcm_ops pcm_playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 8d23341..f3530f8 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -388,7 +388,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) { - static struct snd_pcm_ops capture_ops = { + static const struct snd_pcm_ops capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -400,7 +400,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; - static struct snd_pcm_ops playback_ops = { + static const struct snd_pcm_ops playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 380d3db..79db1b6 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -268,7 +268,7 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&tscm->rx_stream); } -static struct snd_pcm_ops pcm_capture_ops = { +static const struct snd_pcm_ops pcm_capture_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -280,7 +280,7 @@ static struct snd_pcm_ops pcm_capture_ops = { .page = snd_pcm_lib_get_vmalloc_page, }; -static struct snd_pcm_ops pcm_playback_ops = { +static const struct snd_pcm_ops pcm_playback_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 2441273..3be051ab5 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -424,7 +424,7 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return; } @@ -453,7 +453,7 @@ int snd_hdac_ext_stream_set_spib(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return -EINVAL; } @@ -476,7 +476,7 @@ int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->spbcap) { - dev_err(bus->dev, "Address of SPB capability is NULL"); + dev_err(bus->dev, "Address of SPB capability is NULL\n"); return -EINVAL; } @@ -516,7 +516,7 @@ void snd_hdac_ext_stream_drsm_enable(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { - dev_err(bus->dev, "Address of DRSM capability is NULL"); + dev_err(bus->dev, "Address of DRSM capability is NULL\n"); return; } @@ -545,7 +545,7 @@ int snd_hdac_ext_stream_set_dpibr(struct hdac_ext_bus *ebus, struct hdac_bus *bus = &ebus->bus; if (!bus->drsmcap) { - dev_err(bus->dev, "Address of DRSM capability is NULL"); + dev_err(bus->dev, "Address of DRSM capability is NULL\n"); return -EINVAL; } diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 1fc6d8b..8c36990 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -571,7 +571,7 @@ snd_ad1889_capture_pointer(struct snd_pcm_substream *ss) return bytes_to_frames(ss->runtime, ptr); } -static struct snd_pcm_ops snd_ad1889_playback_ops = { +static const struct snd_pcm_ops snd_ad1889_playback_ops = { .open = snd_ad1889_playback_open, .close = snd_ad1889_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -582,7 +582,7 @@ static struct snd_pcm_ops snd_ad1889_playback_ops = { .pointer = snd_ad1889_playback_pointer, }; -static struct snd_pcm_ops snd_ad1889_capture_ops = { +static const struct snd_pcm_ops snd_ad1889_capture_ops = { .open = snd_ad1889_capture_open, .close = snd_ad1889_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 36470af..92b819e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1408,6 +1408,7 @@ snd_ali_playback_pointer(struct snd_pcm_substream *substream) spin_unlock(&codec->reg_lock); dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso); + cso %= runtime->buffer_size; return cso; } @@ -1428,6 +1429,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)); spin_unlock(&codec->reg_lock); + cso %= runtime->buffer_size; return cso; } diff --git a/sound/pci/als300.c b/sound/pci/als300.c index add3176..ab75601 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -563,7 +563,7 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(substream->runtime, current_ptr); } -static struct snd_pcm_ops snd_als300_playback_ops = { +static const struct snd_pcm_ops snd_als300_playback_ops = { .open = snd_als300_playback_open, .close = snd_als300_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -574,7 +574,7 @@ static struct snd_pcm_ops snd_als300_playback_ops = { .pointer = snd_als300_pointer, }; -static struct snd_pcm_ops snd_als300_capture_ops = { +static const struct snd_pcm_ops snd_als300_capture_ops = { .open = snd_als300_capture_open, .close = snd_als300_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index ff39a0c..edabe13 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -672,7 +672,7 @@ static int snd_als4000_capture_close(struct snd_pcm_substream *substream) /******************************************************************/ -static struct snd_pcm_ops snd_als4000_playback_ops = { +static const struct snd_pcm_ops snd_als4000_playback_ops = { .open = snd_als4000_playback_open, .close = snd_als4000_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -683,7 +683,7 @@ static struct snd_pcm_ops snd_als4000_playback_ops = { .pointer = snd_als4000_playback_pointer }; -static struct snd_pcm_ops snd_als4000_capture_ops = { +static const struct snd_pcm_ops snd_als4000_capture_ops = { .open = snd_als4000_capture_open, .close = snd_als4000_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 1039ecc..976a3d2 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -1138,7 +1138,7 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { +static const struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = { .open = snd_card_asihpi_playback_open, .close = snd_card_asihpi_playback_close, .ioctl = snd_card_asihpi_playback_ioctl, @@ -1305,7 +1305,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { +static const struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = { .open = snd_card_asihpi_capture_open, .close = snd_card_asihpi_capture_close, .ioctl = snd_card_asihpi_capture_ioctl, diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 510e56c..f9b5764 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c @@ -2323,11 +2323,8 @@ u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index) u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, u32 *prate) { - u16 err; - err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, - index, 0, prate); - - return err; + return hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, + index, 0, prate); } u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 2ce0022..a40c918 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1148,7 +1148,7 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream) } /* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { +static const struct snd_pcm_ops snd_atiixp_playback_ops = { .open = snd_atiixp_playback_open, .close = snd_atiixp_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1160,7 +1160,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = { }; /* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { +static const struct snd_pcm_ops snd_atiixp_capture_ops = { .open = snd_atiixp_capture_open, .close = snd_atiixp_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1172,7 +1172,7 @@ static struct snd_pcm_ops snd_atiixp_capture_ops = { }; /* SPDIF playback */ -static struct snd_pcm_ops snd_atiixp_spdif_ops = { +static const struct snd_pcm_ops snd_atiixp_spdif_ops = { .open = snd_atiixp_spdif_open, .close = snd_atiixp_spdif_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c534552..40152fe 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -947,7 +947,7 @@ static int snd_atiixp_capture_close(struct snd_pcm_substream *substream) /* AC97 playback */ -static struct snd_pcm_ops snd_atiixp_playback_ops = { +static const struct snd_pcm_ops snd_atiixp_playback_ops = { .open = snd_atiixp_playback_open, .close = snd_atiixp_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -959,7 +959,7 @@ static struct snd_pcm_ops snd_atiixp_playback_ops = { }; /* AC97 capture */ -static struct snd_pcm_ops snd_atiixp_capture_ops = { +static const struct snd_pcm_ops snd_atiixp_capture_ops = { .open = snd_atiixp_capture_open, .close = snd_atiixp_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c index d3125c1..e1af24f 100644 --- a/sound/pci/au88x0/au88x0_core.c +++ b/sound/pci/au88x0/au88x0_core.c @@ -1043,7 +1043,7 @@ static void vortex_fifo_init(vortex_t * vortex) for (x = NR_ADB - 1; x >= 0; x--) { hwwrite(vortex->mmio, addr, (FIFO_U0 | FIFO_U1)); if (hwread(vortex->mmio, addr) != (FIFO_U0 | FIFO_U1)) - dev_err(vortex->card->dev, "bad adb fifo reset!"); + dev_err(vortex->card->dev, "bad adb fifo reset!\n"); vortex_fifo_clearadbdata(vortex, x, FIFO_SIZE); addr -= 4; } diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 1677143..57bbb87 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -179,7 +179,7 @@ static struct pci_driver aw2_driver = { module_pci_driver(aw2_driver); /* operators for playback PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_playback_ops = { +static const struct snd_pcm_ops snd_aw2_playback_ops = { .open = snd_aw2_pcm_playback_open, .close = snd_aw2_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -191,7 +191,7 @@ static struct snd_pcm_ops snd_aw2_playback_ops = { }; /* operators for capture PCM alsa interface */ -static struct snd_pcm_ops snd_aw2_capture_ops = { +static const struct snd_pcm_ops snd_aw2_capture_ops = { .open = snd_aw2_pcm_capture_open, .close = snd_aw2_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 5e2ef0b..80c4a44 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2090,7 +2090,7 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream /******************************************************************/ -static struct snd_pcm_ops snd_azf3328_playback_ops = { +static const struct snd_pcm_ops snd_azf3328_playback_ops = { .open = snd_azf3328_pcm_playback_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -2101,7 +2101,7 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = { .pointer = snd_azf3328_pcm_pointer }; -static struct snd_pcm_ops snd_azf3328_capture_ops = { +static const struct snd_pcm_ops snd_azf3328_capture_ops = { .open = snd_azf3328_pcm_capture_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -2112,7 +2112,7 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = { .pointer = snd_azf3328_pcm_pointer }; -static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { +static const struct snd_pcm_ops snd_azf3328_i2s_out_ops = { .open = snd_azf3328_pcm_i2s_out_open, .close = snd_azf3328_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 5925b71..f2c0709 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -550,7 +550,7 @@ static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream) return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); } -static struct snd_pcm_ops snd_bt87x_pcm_ops = { +static const struct snd_pcm_ops snd_bt87x_pcm_ops = { .open = snd_bt87x_pcm_open, .close = snd_bt87x_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index d3cd956..6165a57 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1109,7 +1109,7 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_ca0106_playback_front_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_front_ops = { .open = snd_ca0106_pcm_open_playback_front, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1120,7 +1120,7 @@ static struct snd_pcm_ops snd_ca0106_playback_front_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_capture_0_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_0_ops = { .open = snd_ca0106_pcm_open_0_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1131,7 +1131,7 @@ static struct snd_pcm_ops snd_ca0106_capture_0_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_1_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_1_ops = { .open = snd_ca0106_pcm_open_1_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1142,7 +1142,7 @@ static struct snd_pcm_ops snd_ca0106_capture_1_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_2_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_2_ops = { .open = snd_ca0106_pcm_open_2_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1153,7 +1153,7 @@ static struct snd_pcm_ops snd_ca0106_capture_2_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_capture_3_ops = { +static const struct snd_pcm_ops snd_ca0106_capture_3_ops = { .open = snd_ca0106_pcm_open_3_capture, .close = snd_ca0106_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, @@ -1164,7 +1164,7 @@ static struct snd_pcm_ops snd_ca0106_capture_3_ops = { .pointer = snd_ca0106_pcm_pointer_capture, }; -static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { .open = snd_ca0106_pcm_open_playback_center_lfe, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1175,7 +1175,7 @@ static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { .open = snd_ca0106_pcm_open_playback_unknown, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -1186,7 +1186,7 @@ static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = { .pointer = snd_ca0106_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_ca0106_playback_rear_ops = { +static const struct snd_pcm_ops snd_ca0106_playback_rear_ops = { .open = snd_ca0106_pcm_open_playback_rear, .close = snd_ca0106_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 24cdcba..73f5935 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -1838,7 +1838,7 @@ static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream) /* */ -static struct snd_pcm_ops snd_cmipci_playback_ops = { +static const struct snd_pcm_ops snd_cmipci_playback_ops = { .open = snd_cmipci_playback_open, .close = snd_cmipci_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1849,7 +1849,7 @@ static struct snd_pcm_ops snd_cmipci_playback_ops = { .pointer = snd_cmipci_playback_pointer, }; -static struct snd_pcm_ops snd_cmipci_capture_ops = { +static const struct snd_pcm_ops snd_cmipci_capture_ops = { .open = snd_cmipci_capture_open, .close = snd_cmipci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1860,7 +1860,7 @@ static struct snd_pcm_ops snd_cmipci_capture_ops = { .pointer = snd_cmipci_capture_pointer, }; -static struct snd_pcm_ops snd_cmipci_playback2_ops = { +static const struct snd_pcm_ops snd_cmipci_playback2_ops = { .open = snd_cmipci_playback2_open, .close = snd_cmipci_playback2_close, .ioctl = snd_pcm_lib_ioctl, @@ -1871,7 +1871,7 @@ static struct snd_pcm_ops snd_cmipci_playback2_ops = { .pointer = snd_cmipci_capture_pointer, /* channel B */ }; -static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { +static const struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { .open = snd_cmipci_playback_spdif_open, .close = snd_cmipci_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1882,7 +1882,7 @@ static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { .pointer = snd_cmipci_playback_pointer, }; -static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { +static const struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { .open = snd_cmipci_capture_spdif_open, .close = snd_cmipci_capture_spdif_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index c296fd0..615d8a9 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -951,7 +951,7 @@ static int snd_cs4281_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_cs4281_playback_ops = { +static const struct snd_pcm_ops snd_cs4281_playback_ops = { .open = snd_cs4281_playback_open, .close = snd_cs4281_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -962,7 +962,7 @@ static struct snd_pcm_ops snd_cs4281_playback_ops = { .pointer = snd_cs4281_pointer, }; -static struct snd_pcm_ops snd_cs4281_capture_ops = { +static const struct snd_pcm_ops snd_cs4281_capture_ops = { .open = snd_cs4281_capture_open, .close = snd_cs4281_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 2706f27..528102c 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2460,7 +2460,7 @@ static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec) udelay(10); if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) { dev_dbg(chip->card->dev, - "seconadry codec not present\n"); + "secondary codec not present\n"); return -ENXIO; } } @@ -2503,7 +2503,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device) chip->nr_ac97_codecs = 1; #ifdef CONFIG_SND_CS46XX_NEW_DSP - dev_dbg(chip->card->dev, "detecting seconadry codec\n"); + dev_dbg(chip->card->dev, "detecting secondary codec\n"); /* try detect a secondary codec */ if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX)) chip->nr_ac97_codecs = 2; diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index d2951ed..4a0cbd2 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -1441,7 +1441,7 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) if (chip->nr_ac97_codecs == 2) { /* create CODEC tasklet for rear Center/LFE output - slot 6 and 9 on seconadry CODEC */ + slot 6 and 9 on secondary CODEC */ clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, CLFE_MIXER_SCB_ADDR, CLFE_CODEC_SCB_ADDR, diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 27fa57d..c208c1d 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -380,7 +380,7 @@ static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream) substream->runtime->rate); } -static struct snd_pcm_ops snd_cs5535audio_playback_ops = { +static const struct snd_pcm_ops snd_cs5535audio_playback_ops = { .open = snd_cs5535audio_playback_open, .close = snd_cs5535audio_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -391,7 +391,7 @@ static struct snd_pcm_ops snd_cs5535audio_playback_ops = { .pointer = snd_cs5535audio_pcm_pointer, }; -static struct snd_pcm_ops snd_cs5535audio_capture_ops = { +static const struct snd_pcm_ops snd_cs5535audio_capture_ops = { .open = snd_cs5535audio_capture_open, .close = snd_cs5535audio_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 977a598..908658a 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1623,7 +1623,7 @@ static int atc_resume(struct ct_atc *atc) } #endif -static struct ct_atc atc_preset = { +static const struct ct_atc atc_preset = { .map_audio_buffer = ct_map_audio_buffer, .unmap_audio_buffer = ct_unmap_audio_buffer, .pcm_playback_prepare = atc_pcm_playback_prepare, diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index d86c474..9749780 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -372,7 +372,7 @@ ct_pcm_capture_pointer(struct snd_pcm_substream *substream) } /* PCM operators for playback */ -static struct snd_pcm_ops ct_pcm_playback_ops = { +static const struct snd_pcm_ops ct_pcm_playback_ops = { .open = ct_pcm_playback_open, .close = ct_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -385,7 +385,7 @@ static struct snd_pcm_ops ct_pcm_playback_ops = { }; /* PCM operators for capture */ -static struct snd_pcm_ops ct_pcm_capture_ops = { +static const struct snd_pcm_ops ct_pcm_capture_ops = { .open = ct_pcm_capture_open, .close = ct_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 419306e..520e19b 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c @@ -166,11 +166,7 @@ static void ct_vm_unmap(struct ct_vm *vm, struct ct_vm_block *block) static dma_addr_t ct_get_ptp_phys(struct ct_vm *vm, int index) { - dma_addr_t addr; - - addr = (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; - - return addr; + return (index >= CT_PTP_NUM) ? ~0UL : vm->ptp[index].addr; } int ct_vm_create(struct ct_vm **rvm, struct pci_dev *pci) diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 6d1b98d..921037e 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -548,7 +548,7 @@ snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_emu10k1x_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1x_playback_ops = { .open = snd_emu10k1x_playback_open, .close = snd_emu10k1x_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -694,7 +694,7 @@ snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream) return ptr; } -static struct snd_pcm_ops snd_emu10k1x_capture_ops = { +static const struct snd_pcm_ops snd_emu10k1x_capture_ops = { .open = snd_emu10k1x_pcm_open_capture, .close = snd_emu10k1x_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 14a305b..37be1e1 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -1364,7 +1364,7 @@ static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_emu10k1_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_playback_ops = { .open = snd_emu10k1_playback_open, .close = snd_emu10k1_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1376,7 +1376,7 @@ static struct snd_pcm_ops snd_emu10k1_playback_ops = { .page = snd_pcm_sgbuf_ops_page, }; -static struct snd_pcm_ops snd_emu10k1_capture_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_ops = { .open = snd_emu10k1_capture_open, .close = snd_emu10k1_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1388,7 +1388,7 @@ static struct snd_pcm_ops snd_emu10k1_capture_ops = { }; /* EFX playback */ -static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = { .open = snd_emu10k1_efx_playback_open, .close = snd_emu10k1_efx_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1455,7 +1455,7 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device) } -static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_mic_ops = { .open = snd_emu10k1_capture_mic_open, .close = snd_emu10k1_capture_mic_close, .ioctl = snd_pcm_lib_ioctl, @@ -1550,7 +1550,7 @@ static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = { .put = snd_emu10k1_pcm_efx_voices_mask_put }; -static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { +static const struct snd_pcm_ops snd_emu10k1_capture_efx_ops = { .open = snd_emu10k1_capture_efx_open, .close = snd_emu10k1_capture_efx_close, .ioctl = snd_pcm_lib_ioctl, @@ -1791,7 +1791,7 @@ static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream return 0; } -static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { +static const struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = { .open = snd_emu10k1_fx8010_playback_open, .close = snd_emu10k1_fx8010_playback_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 3c60b43..c11f1a2 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c @@ -300,37 +300,29 @@ static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream) static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int result; - result = snd_pcm_lib_malloc_pages(substream, + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - return result; } /* hw_params callback */ static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { - int result; - result = snd_pcm_lib_malloc_pages(substream, + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); - return result; } /* hw_free callback */ static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream) { - int result; - result = snd_pcm_lib_free_pages(substream); - return result; + return snd_pcm_lib_free_pages(substream); } /* hw_free callback */ static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream) { - int result; - result = snd_pcm_lib_free_pages(substream); - return result; + return snd_pcm_lib_free_pages(substream); } @@ -601,7 +593,7 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream) } /* operators */ -static struct snd_pcm_ops snd_p16v_playback_front_ops = { +static const struct snd_pcm_ops snd_p16v_playback_front_ops = { .open = snd_p16v_pcm_open_playback_front, .close = snd_p16v_pcm_close_playback, .ioctl = snd_pcm_lib_ioctl, @@ -612,7 +604,7 @@ static struct snd_pcm_ops snd_p16v_playback_front_ops = { .pointer = snd_p16v_pcm_pointer_playback, }; -static struct snd_pcm_ops snd_p16v_capture_ops = { +static const struct snd_pcm_ops snd_p16v_capture_ops = { .open = snd_p16v_pcm_open_capture, .close = snd_p16v_pcm_close_capture, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 626cd21..7e760fe 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -1227,7 +1227,7 @@ static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ensoniq_playback1_ops = { +static const struct snd_pcm_ops snd_ensoniq_playback1_ops = { .open = snd_ensoniq_playback1_open, .close = snd_ensoniq_playback1_close, .ioctl = snd_pcm_lib_ioctl, @@ -1238,7 +1238,7 @@ static struct snd_pcm_ops snd_ensoniq_playback1_ops = { .pointer = snd_ensoniq_playback1_pointer, }; -static struct snd_pcm_ops snd_ensoniq_playback2_ops = { +static const struct snd_pcm_ops snd_ensoniq_playback2_ops = { .open = snd_ensoniq_playback2_open, .close = snd_ensoniq_playback2_close, .ioctl = snd_pcm_lib_ioctl, @@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_ensoniq_playback2_ops = { .pointer = snd_ensoniq_playback2_pointer, }; -static struct snd_pcm_ops snd_ensoniq_capture_ops = { +static const struct snd_pcm_ops snd_ensoniq_capture_ops = { .open = snd_ensoniq_capture_open, .close = snd_ensoniq_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 8963d76..6813558 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -992,7 +992,7 @@ static int snd_es1938_playback_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_es1938_playback_ops = { +static const struct snd_pcm_ops snd_es1938_playback_ops = { .open = snd_es1938_playback_open, .close = snd_es1938_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1003,7 +1003,7 @@ static struct snd_pcm_ops snd_es1938_playback_ops = { .pointer = snd_es1938_playback_pointer, }; -static struct snd_pcm_ops snd_es1938_capture_ops = { +static const struct snd_pcm_ops snd_es1938_capture_ops = { .open = snd_es1938_capture_open, .close = snd_es1938_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 514f260..8146fb7 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -1677,7 +1677,7 @@ static int snd_es1968_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_es1968_playback_ops = { +static const struct snd_pcm_ops snd_es1968_playback_ops = { .open = snd_es1968_playback_open, .close = snd_es1968_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1688,7 +1688,7 @@ static struct snd_pcm_ops snd_es1968_playback_ops = { .pointer = snd_es1968_pcm_pointer, }; -static struct snd_pcm_ops snd_es1968_capture_ops = { +static const struct snd_pcm_ops snd_es1968_capture_ops = { .open = snd_es1968_capture_open, .close = snd_es1968_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index bade9b9..c47287d 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -691,7 +691,7 @@ static int snd_fm801_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_fm801_playback_ops = { +static const struct snd_pcm_ops snd_fm801_playback_ops = { .open = snd_fm801_playback_open, .close = snd_fm801_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -702,7 +702,7 @@ static struct snd_pcm_ops snd_fm801_playback_ops = { .pointer = snd_fm801_playback_pointer, }; -static struct snd_pcm_ops snd_fm801_capture_ops = { +static const struct snd_pcm_ops snd_fm801_capture_ops = { .open = snd_fm801_capture_open, .close = snd_fm801_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 2ad3b44..5008785 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -696,7 +696,7 @@ static int azx_pcm_mmap(struct snd_pcm_substream *substream, return snd_pcm_lib_default_mmap(substream, area); } -static struct snd_pcm_ops azx_pcm_ops = { +static const struct snd_pcm_ops azx_pcm_ops = { .open = azx_pcm_open, .close = azx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 9ceb2bc..ad06866 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -4018,7 +4018,7 @@ static int ca0132_build_controls(struct hda_codec *codec) /* * PCM */ -static struct hda_pcm_stream ca0132_pcm_analog_playback = { +static const struct hda_pcm_stream ca0132_pcm_analog_playback = { .substreams = 1, .channels_min = 2, .channels_max = 6, @@ -4029,7 +4029,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = { }, }; -static struct hda_pcm_stream ca0132_pcm_analog_capture = { +static const struct hda_pcm_stream ca0132_pcm_analog_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4040,7 +4040,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = { }, }; -static struct hda_pcm_stream ca0132_pcm_digital_playback = { +static const struct hda_pcm_stream ca0132_pcm_digital_playback = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4052,7 +4052,7 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = { }, }; -static struct hda_pcm_stream ca0132_pcm_digital_capture = { +static const struct hda_pcm_stream ca0132_pcm_digital_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, @@ -4614,7 +4614,7 @@ static void ca0132_free(struct hda_codec *codec) kfree(codec->spec); } -static struct hda_codec_ops ca0132_patch_ops = { +static const struct hda_codec_ops ca0132_patch_ops = { .build_controls = ca0132_build_controls, .build_pcms = ca0132_build_pcms, .init = ca0132_init, diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 56fefbd..ed62748 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -261,6 +261,7 @@ enum { CXT_FIXUP_HP_530, CXT_FIXUP_CAP_MIX_AMP_5047, CXT_FIXUP_MUTE_LED_EAPD, + CXT_FIXUP_HP_SPECTRE, }; /* for hda_fixup_thinkpad_acpi() */ @@ -765,6 +766,14 @@ static const struct hda_fixup cxt_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = cxt_fixup_mute_led_eapd, }, + [CXT_FIXUP_HP_SPECTRE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* enable NID 0x1d for the speaker on top */ + { 0x1d, 0x91170111 }, + { } + } + }, }; static const struct snd_pci_quirk cxt5045_fixups[] = { @@ -814,6 +823,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC), + SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 575cefd..b58e8c7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5264,6 +5264,8 @@ static const struct hda_fixup alc269_fixups[] = { [ALC269_FIXUP_THINKPAD_ACPI] = { .type = HDA_FIXUP_FUNC, .v.func = hda_fixup_thinkpad_acpi, + .chained = true, + .chain_id = ALC269_FIXUP_SKU_IGNORE, }, [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = { .type = HDA_FIXUP_FUNC, @@ -5806,6 +5808,13 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {0x14, 0x90170110}, \ {0x15, 0x0221401f} +#define ALC295_STANDARD_PINS \ + {0x12, 0xb7a60130}, \ + {0x14, 0x90170110}, \ + {0x17, 0x21014020}, \ + {0x18, 0x21a19030}, \ + {0x21, 0x04211020} + #define ALC298_STANDARD_PINS \ {0x12, 0x90a60130}, \ {0x21, 0x03211020} @@ -5846,6 +5855,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x14, 0x90170120}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x14, 0x90170110}, + {0x1b, 0x02011020}, + {0x21, 0x0221101f}), + SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x14, 0x90170130}, {0x1b, 0x01014020}, {0x21, 0x0221103f}), @@ -5911,6 +5924,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x14, 0x90170120}, {0x21, 0x02211030}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x12, 0xb7a60130}, + {0x14, 0x90170110}, + {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, ALC256_STANDARD_PINS), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, {0x12, 0x90a60130}, @@ -6021,6 +6038,8 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x13, 0x90a60140}), + SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC295_STANDARD_PINS), SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE, ALC298_STANDARD_PINS, {0x17, 0x90170110}), diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 8ae3bb7..b4aa4c1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -847,7 +847,7 @@ static int snd_ice1712_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ice1712_playback_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_ops = { .open = snd_ice1712_playback_open, .close = snd_ice1712_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -858,7 +858,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ops = { .pointer = snd_ice1712_playback_pointer, }; -static struct snd_pcm_ops snd_ice1712_playback_ds_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_ds_ops = { .open = snd_ice1712_playback_ds_open, .close = snd_ice1712_playback_ds_close, .ioctl = snd_pcm_lib_ioctl, @@ -869,7 +869,7 @@ static struct snd_pcm_ops snd_ice1712_playback_ds_ops = { .pointer = snd_ice1712_playback_ds_pointer, }; -static struct snd_pcm_ops snd_ice1712_capture_ops = { +static const struct snd_pcm_ops snd_ice1712_capture_ops = { .open = snd_ice1712_capture_open, .close = snd_ice1712_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1228,7 +1228,7 @@ static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ice1712_playback_pro_ops = { +static const struct snd_pcm_ops snd_ice1712_playback_pro_ops = { .open = snd_ice1712_playback_pro_open, .close = snd_ice1712_playback_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1239,7 +1239,7 @@ static struct snd_pcm_ops snd_ice1712_playback_pro_ops = { .pointer = snd_ice1712_playback_pro_pointer, }; -static struct snd_pcm_ops snd_ice1712_capture_pro_ops = { +static const struct snd_pcm_ops snd_ice1712_capture_pro_ops = { .open = snd_ice1712_capture_pro_open, .close = snd_ice1712_capture_pro_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 0b22c00..e5c52ed 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -620,9 +620,7 @@ static const unsigned int stdclock_rate_list[16] = { static unsigned int stdclock_get_rate(struct snd_ice1712 *ice) { - unsigned int rate; - rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15]; - return rate; + return stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15]; } static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate) @@ -1113,7 +1111,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_pro_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_pro_ops = { .open = snd_vt1724_playback_pro_open, .close = snd_vt1724_playback_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1124,7 +1122,7 @@ static struct snd_pcm_ops snd_vt1724_playback_pro_ops = { .pointer = snd_vt1724_playback_pro_pointer, }; -static struct snd_pcm_ops snd_vt1724_capture_pro_ops = { +static const struct snd_pcm_ops snd_vt1724_capture_pro_ops = { .open = snd_vt1724_capture_pro_open, .close = snd_vt1724_capture_pro_close, .ioctl = snd_pcm_lib_ioctl, @@ -1292,7 +1290,7 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { .open = snd_vt1724_playback_spdif_open, .close = snd_vt1724_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1303,7 +1301,7 @@ static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = { .pointer = snd_vt1724_pcm_pointer, }; -static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = { +static const struct snd_pcm_ops snd_vt1724_capture_spdif_ops = { .open = snd_vt1724_capture_spdif_open, .close = snd_vt1724_capture_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1437,7 +1435,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_vt1724_playback_indep_ops = { +static const struct snd_pcm_ops snd_vt1724_playback_indep_ops = { .open = snd_vt1724_playback_indep_open, .close = snd_vt1724_playback_indep_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 9e1ad11..565f7f5 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1681,7 +1681,7 @@ static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); } -static struct snd_pcm_ops snd_korg1212_playback_ops = { +static const struct snd_pcm_ops snd_korg1212_playback_ops = { .open = snd_korg1212_playback_open, .close = snd_korg1212_playback_close, .ioctl = snd_korg1212_ioctl, @@ -1693,7 +1693,7 @@ static struct snd_pcm_ops snd_korg1212_playback_ops = { .silence = snd_korg1212_playback_silence, }; -static struct snd_pcm_ops snd_korg1212_capture_ops = { +static const struct snd_pcm_ops snd_korg1212_capture_ops = { .open = snd_korg1212_capture_open, .close = snd_korg1212_capture_close, .ioctl = snd_korg1212_ioctl, diff --git a/sound/pci/lola/lola_pcm.c b/sound/pci/lola/lola_pcm.c index 3bd6985..1268ba3 100644 --- a/sound/pci/lola/lola_pcm.c +++ b/sound/pci/lola/lola_pcm.c @@ -586,7 +586,7 @@ void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits) } } -static struct snd_pcm_ops lola_pcm_ops = { +static const struct snd_pcm_ops lola_pcm_ops = { .open = lola_pcm_open, .close = lola_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 8b8e2e5..c0f0c34 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -804,7 +804,7 @@ mac_ready: return err; } -static struct snd_pcm_ops lx_ops_playback = { +static const struct snd_pcm_ops lx_ops_playback = { .open = lx_pcm_open, .close = lx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -815,7 +815,7 @@ static struct snd_pcm_ops lx_ops_playback = { .pointer = lx_pcm_stream_pointer, }; -static struct snd_pcm_ops lx_ops_capture = { +static const struct snd_pcm_ops lx_ops_capture = { .open = lx_pcm_open, .close = lx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 17ae926..cafea6d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -1834,7 +1834,7 @@ snd_m3_capture_close(struct snd_pcm_substream *subs) * create pcm instance */ -static struct snd_pcm_ops snd_m3_playback_ops = { +static const struct snd_pcm_ops snd_m3_playback_ops = { .open = snd_m3_playback_open, .close = snd_m3_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1845,7 +1845,7 @@ static struct snd_pcm_ops snd_m3_playback_ops = { .pointer = snd_m3_pcm_pointer, }; -static struct snd_pcm_ops snd_m3_capture_ops = { +static const struct snd_pcm_ops snd_m3_capture_ops = { .open = snd_m3_capture_open, .close = snd_m3_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 25c0ddd..80d4399 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -922,7 +922,7 @@ static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *sub -static struct snd_pcm_ops snd_mixart_playback_ops = { +static const struct snd_pcm_ops snd_mixart_playback_ops = { .open = snd_mixart_playback_open, .close = snd_mixart_close, .ioctl = snd_pcm_lib_ioctl, @@ -933,7 +933,7 @@ static struct snd_pcm_ops snd_mixart_playback_ops = { .pointer = snd_mixart_stream_pointer, }; -static struct snd_pcm_ops snd_mixart_capture_ops = { +static const struct snd_pcm_ops snd_mixart_capture_ops = { .open = snd_mixart_capture_open, .close = snd_mixart_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 4735e27..103fe31 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -902,7 +902,7 @@ snd_nm256_capture_close(struct snd_pcm_substream *substream) /* * create a pcm instance */ -static struct snd_pcm_ops snd_nm256_playback_ops = { +static const struct snd_pcm_ops snd_nm256_playback_ops = { .open = snd_nm256_playback_open, .close = snd_nm256_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -917,7 +917,7 @@ static struct snd_pcm_ops snd_nm256_playback_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_nm256_capture_ops = { +static const struct snd_pcm_ops snd_nm256_capture_ops = { .open = snd_nm256_capture_open, .close = snd_nm256_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c index aa2ebd1..042a243 100644 --- a/sound/pci/oxygen/oxygen_pcm.c +++ b/sound/pci/oxygen/oxygen_pcm.c @@ -631,7 +631,7 @@ static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream) return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr); } -static struct snd_pcm_ops oxygen_rec_a_ops = { +static const struct snd_pcm_ops oxygen_rec_a_ops = { .open = oxygen_rec_a_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -642,7 +642,7 @@ static struct snd_pcm_ops oxygen_rec_a_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_rec_b_ops = { +static const struct snd_pcm_ops oxygen_rec_b_ops = { .open = oxygen_rec_b_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -653,7 +653,7 @@ static struct snd_pcm_ops oxygen_rec_b_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_rec_c_ops = { +static const struct snd_pcm_ops oxygen_rec_c_ops = { .open = oxygen_rec_c_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -664,7 +664,7 @@ static struct snd_pcm_ops oxygen_rec_c_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_spdif_ops = { +static const struct snd_pcm_ops oxygen_spdif_ops = { .open = oxygen_spdif_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -675,7 +675,7 @@ static struct snd_pcm_ops oxygen_spdif_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_multich_ops = { +static const struct snd_pcm_ops oxygen_multich_ops = { .open = oxygen_multich_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, @@ -686,7 +686,7 @@ static struct snd_pcm_ops oxygen_multich_ops = { .pointer = oxygen_pointer, }; -static struct snd_pcm_ops oxygen_ac97_ops = { +static const struct snd_pcm_ops oxygen_ac97_ops = { .open = oxygen_ac97_open, .close = oxygen_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 9293235..bb7eee9 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1146,7 +1146,7 @@ static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs) } -static struct snd_pcm_ops pcxhr_ops = { +static const struct snd_pcm_ops pcxhr_ops = { .open = pcxhr_open, .close = pcxhr_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 067a912..ada5f01 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -644,7 +644,7 @@ static struct lbuspath lbus_play_paths[] = { .mono = lbus_play_mono3, }, }; -static struct lbuspath lbus_rec_path = { +static const struct lbuspath lbus_rec_path = { .noconv = lbus_rec_noconv1, .stereo = lbus_rec_stereo1, .mono = lbus_rec_mono1, @@ -1669,7 +1669,7 @@ static int snd_riptide_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_riptide_playback_ops = { +static const struct snd_pcm_ops snd_riptide_playback_ops = { .open = snd_riptide_playback_open, .close = snd_riptide_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1680,7 +1680,7 @@ static struct snd_pcm_ops snd_riptide_playback_ops = { .trigger = snd_riptide_trigger, .pointer = snd_riptide_pointer, }; -static struct snd_pcm_ops snd_riptide_capture_ops = { +static const struct snd_pcm_ops snd_riptide_capture_ops = { .open = snd_riptide_capture_open, .close = snd_riptide_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index cd94ac5..96d15db 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1196,7 +1196,7 @@ snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream) } /* for halfduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { +static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .open = snd_rme32_playback_spdif_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1210,7 +1210,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { +static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .open = snd_rme32_capture_spdif_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1223,7 +1223,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_playback_adat_ops = { +static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { .open = snd_rme32_playback_adat_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1236,7 +1236,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme32_capture_adat_ops = { +static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { .open = snd_rme32_capture_adat_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1249,7 +1249,7 @@ static struct snd_pcm_ops snd_rme32_capture_adat_ops = { }; /* for fullduplex mode */ -static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { +static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { .open = snd_rme32_playback_spdif_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1261,7 +1261,7 @@ static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { .ack = snd_rme32_playback_fd_ack, }; -static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { +static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { .open = snd_rme32_capture_spdif_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1273,7 +1273,7 @@ static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { .ack = snd_rme32_capture_fd_ack, }; -static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { +static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { .open = snd_rme32_playback_adat_open, .close = snd_rme32_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1284,7 +1284,7 @@ static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { .ack = snd_rme32_playback_fd_ack, }; -static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { +static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { .open = snd_rme32_capture_adat_open, .close = snd_rme32_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 41c31db..05b9da3 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1505,7 +1505,7 @@ snd_rme96_capture_pointer(struct snd_pcm_substream *substream) return snd_rme96_capture_ptr(rme96); } -static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { +static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .open = snd_rme96_playback_spdif_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1518,7 +1518,7 @@ static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { +static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .open = snd_rme96_capture_spdif_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1530,7 +1530,7 @@ static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_playback_adat_ops = { +static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { .open = snd_rme96_playback_adat_open, .close = snd_rme96_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1543,7 +1543,7 @@ static struct snd_pcm_ops snd_rme96_playback_adat_ops = { .mmap = snd_pcm_lib_mmap_iomem, }; -static struct snd_pcm_ops snd_rme96_capture_adat_ops = { +static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { .open = snd_rme96_capture_adat_open, .close = snd_rme96_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 7c8941b..b94fc63 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4861,7 +4861,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne return 0; } -static struct snd_pcm_ops snd_hdsp_playback_ops = { +static const struct snd_pcm_ops snd_hdsp_playback_ops = { .open = snd_hdsp_playback_open, .close = snd_hdsp_playback_release, .ioctl = snd_hdsp_ioctl, @@ -4873,7 +4873,7 @@ static struct snd_pcm_ops snd_hdsp_playback_ops = { .silence = snd_hdsp_hw_silence, }; -static struct snd_pcm_ops snd_hdsp_capture_ops = { +static const struct snd_pcm_ops snd_hdsp_capture_ops = { .open = snd_hdsp_capture_open, .close = snd_hdsp_capture_release, .ioctl = snd_hdsp_ioctl, diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index a4a999a..14bbf55 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1666,7 +1666,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) HDSPM_AUTOSYNC_FROM_NONE) { dev_warn(hdspm->card->dev, - "Detected no Externel Sync\n"); + "Detected no External Sync\n"); not_set = 1; } else if (rate != external_freq) { @@ -6361,7 +6361,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, return 0; } -static struct snd_pcm_ops snd_hdspm_ops = { +static const struct snd_pcm_ops snd_hdspm_ops = { .open = snd_hdspm_open, .close = snd_hdspm_release, .ioctl = snd_hdspm_ioctl, diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index fdbc0aa..55172c6 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -2368,7 +2368,7 @@ static int snd_rme9652_capture_release(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_rme9652_playback_ops = { +static const struct snd_pcm_ops snd_rme9652_playback_ops = { .open = snd_rme9652_playback_open, .close = snd_rme9652_playback_release, .ioctl = snd_rme9652_ioctl, @@ -2380,7 +2380,7 @@ static struct snd_pcm_ops snd_rme9652_playback_ops = { .silence = snd_rme9652_hw_silence, }; -static struct snd_pcm_ops snd_rme9652_capture_ops = { +static const struct snd_pcm_ops snd_rme9652_capture_ops = { .open = snd_rme9652_capture_open, .close = snd_rme9652_capture_release, .ioctl = snd_rme9652_ioctl, diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 1b6fad7..e1a1387 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -857,7 +857,7 @@ static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_sonicvibes_playback_ops = { +static const struct snd_pcm_ops snd_sonicvibes_playback_ops = { .open = snd_sonicvibes_playback_open, .close = snd_sonicvibes_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -868,7 +868,7 @@ static struct snd_pcm_ops snd_sonicvibes_playback_ops = { .pointer = snd_sonicvibes_playback_pointer, }; -static struct snd_pcm_ops snd_sonicvibes_capture_ops = { +static const struct snd_pcm_ops snd_sonicvibes_capture_ops = { .open = snd_sonicvibes_capture_open, .close = snd_sonicvibes_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 599d2b7..27f0ed8 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -2070,7 +2070,7 @@ static int snd_trident_foldback_close(struct snd_pcm_substream *substream) PCM operations ---------------------------------------------------------------------------*/ -static struct snd_pcm_ops snd_trident_playback_ops = { +static const struct snd_pcm_ops snd_trident_playback_ops = { .open = snd_trident_playback_open, .close = snd_trident_playback_close, .ioctl = snd_trident_ioctl, @@ -2081,7 +2081,7 @@ static struct snd_pcm_ops snd_trident_playback_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_nx_playback_ops = { +static const struct snd_pcm_ops snd_trident_nx_playback_ops = { .open = snd_trident_playback_open, .close = snd_trident_playback_close, .ioctl = snd_trident_ioctl, @@ -2115,7 +2115,7 @@ static struct snd_pcm_ops snd_trident_si7018_capture_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_foldback_ops = { +static const struct snd_pcm_ops snd_trident_foldback_ops = { .open = snd_trident_foldback_open, .close = snd_trident_foldback_close, .ioctl = snd_trident_ioctl, @@ -2126,7 +2126,7 @@ static struct snd_pcm_ops snd_trident_foldback_ops = { .pointer = snd_trident_playback_pointer, }; -static struct snd_pcm_ops snd_trident_nx_foldback_ops = { +static const struct snd_pcm_ops snd_trident_nx_foldback_ops = { .open = snd_trident_foldback_open, .close = snd_trident_foldback_close, .ioctl = snd_trident_ioctl, @@ -2138,7 +2138,7 @@ static struct snd_pcm_ops snd_trident_nx_foldback_ops = { .page = snd_pcm_sgbuf_ops_page, }; -static struct snd_pcm_ops snd_trident_spdif_ops = { +static const struct snd_pcm_ops snd_trident_spdif_ops = { .open = snd_trident_spdif_open, .close = snd_trident_spdif_close, .ioctl = snd_trident_ioctl, @@ -2149,7 +2149,7 @@ static struct snd_pcm_ops snd_trident_spdif_ops = { .pointer = snd_trident_spdif_pointer, }; -static struct snd_pcm_ops snd_trident_spdif_7018_ops = { +static const struct snd_pcm_ops snd_trident_spdif_7018_ops = { .open = snd_trident_spdif_open, .close = snd_trident_spdif_close, .ioctl = snd_trident_ioctl, diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 3dd038b..38a17b4 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1366,7 +1366,7 @@ static int snd_via8233_playback_close(struct snd_pcm_substream *substream) /* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { +static const struct snd_pcm_ops snd_via686_playback_ops = { .open = snd_via686_playback_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1379,7 +1379,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = { }; /* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { +static const struct snd_pcm_ops snd_via686_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1392,7 +1392,7 @@ static struct snd_pcm_ops snd_via686_capture_ops = { }; /* via823x DSX playback callbacks */ -static struct snd_pcm_ops snd_via8233_playback_ops = { +static const struct snd_pcm_ops snd_via8233_playback_ops = { .open = snd_via8233_playback_open, .close = snd_via8233_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1405,7 +1405,7 @@ static struct snd_pcm_ops snd_via8233_playback_ops = { }; /* via823x multi-channel playback callbacks */ -static struct snd_pcm_ops snd_via8233_multi_ops = { +static const struct snd_pcm_ops snd_via8233_multi_ops = { .open = snd_via8233_multi_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -1418,7 +1418,7 @@ static struct snd_pcm_ops snd_via8233_multi_ops = { }; /* via823x capture callbacks */ -static struct snd_pcm_ops snd_via8233_capture_ops = { +static const struct snd_pcm_ops snd_via8233_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 99b9137..2f6d40f 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -804,7 +804,7 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) /* via686 playback callbacks */ -static struct snd_pcm_ops snd_via686_playback_ops = { +static const struct snd_pcm_ops snd_via686_playback_ops = { .open = snd_via82xx_playback_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, @@ -817,7 +817,7 @@ static struct snd_pcm_ops snd_via686_playback_ops = { }; /* via686 capture callbacks */ -static struct snd_pcm_ops snd_via686_capture_ops = { +static const struct snd_pcm_ops snd_via686_capture_ops = { .open = snd_via82xx_capture_open, .close = snd_via82xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 4c26076..ffee284 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1123,7 +1123,7 @@ static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_ops = { .open = snd_ymfpci_playback_open, .close = snd_ymfpci_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1134,7 +1134,7 @@ static struct snd_pcm_ops snd_ymfpci_playback_ops = { .pointer = snd_ymfpci_playback_pointer, }; -static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { +static const struct snd_pcm_ops snd_ymfpci_capture_rec_ops = { .open = snd_ymfpci_capture_rec_open, .close = snd_ymfpci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1169,7 +1169,7 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device) snd_pcm_std_chmaps, 2, 0, NULL); } -static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { +static const struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = { .open = snd_ymfpci_capture_ac97_open, .close = snd_ymfpci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1203,7 +1203,7 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = { .open = snd_ymfpci_playback_spdif_open, .close = snd_ymfpci_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1236,7 +1236,7 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device) return 0; } -static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { +static const struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { .open = snd_ymfpci_playback_4ch_open, .close = snd_ymfpci_playback_4ch_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 3682425..b84d7d3 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -564,9 +564,7 @@ static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream) { - int ret; - ret = snd_pcm_lib_free_pages(substream); - return ret; + return snd_pcm_lib_free_pages(substream); }; static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 5bbaa66..c8455b4 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -184,15 +184,9 @@ struct sst_byt { static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id) { - u64 header; - - header = IPC_HEADER_MSG_ID(msg_id) | - IPC_HEADER_STR_ID(str_id) | - IPC_HEADER_LARGE(large) | - IPC_HEADER_DATA(data) | - SST_BYT_IPCX_BUSY; - - return header; + return IPC_HEADER_MSG_ID(msg_id) | IPC_HEADER_STR_ID(str_id) | + IPC_HEADER_LARGE(large) | IPC_HEADER_DATA(data) | + SST_BYT_IPCX_BUSY; } static inline u16 sst_byt_header_msg_id(u64 header) diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 327f864..8f66ba7 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -739,7 +739,6 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret) for (i = 0; i < N_URBS; i++) { urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL); if (!urbs[i]) { - dev_err(dev, "unable to usb_alloc_urb(), OOM!?\n"); *ret = -ENOMEM; return urbs; } diff --git a/sound/usb/card.h b/sound/usb/card.h index 71778ca..111b0f0 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -92,7 +92,7 @@ struct snd_usb_endpoint { unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int syncmaxsize; /* sync endpoint packet size */ unsigned int fill_max:1; /* fill max packet size always */ - unsigned int udh01_fb_quirk:1; /* corrupted feedback data */ + unsigned int tenor_fb_quirk:1; /* corrupted feedback data */ unsigned int datainterval; /* log_2 of data packet interval */ unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ unsigned char silence_value; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index c07a7ed..c470251 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -502,10 +502,6 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, ep->syncinterval = 3; ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize); - - if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ && - ep->syncmaxsize == 4) - ep->udh01_fb_quirk = 1; } list_add_tail(&ep->list, &chip->ep_list); @@ -1171,15 +1167,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, if (f == 0) return; - if (unlikely(sender->udh01_fb_quirk)) { + if (unlikely(sender->tenor_fb_quirk)) { /* - * The TEAC UD-H01 firmware sometimes changes the feedback value + * Devices based on Tenor 8802 chipsets (TEAC UD-H01 + * and others) sometimes change the feedback value * by +/- 0x1.0000. */ if (f < ep->freqn - 0x8000) - f += 0x10000; + f += 0xf000; else if (f > ep->freqn + 0x8000) - f -= 0x10000; + f -= 0xf000; } else if (unlikely(ep->freqshift == INT_MIN)) { /* * The first time we see a feedback value, determine its format diff --git a/sound/usb/format.c b/sound/usb/format.c index 789d19e..2c44386 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -176,10 +176,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof int r, idx; fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL); - if (fp->rate_table == NULL) { - usb_audio_err(chip, "cannot malloc\n"); + if (fp->rate_table == NULL) return -ENOMEM; - } fp->nr_rates = 0; fp->rate_min = fp->rate_max = 0; diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig index f4585d37..39b4003 100644 --- a/sound/usb/line6/Kconfig +++ b/sound/usb/line6/Kconfig @@ -2,6 +2,7 @@ config SND_USB_LINE6 tristate select SND_RAWMIDI select SND_PCM + select SND_HWDEP config SND_USB_POD tristate "Line 6 POD USB support" @@ -21,10 +22,10 @@ config SND_USB_POD re-amping) config SND_USB_PODHD - tristate "Line 6 POD HD300/400/500 USB support" + tristate "Line 6 POD X3/HD300/400/500 USB support" select SND_USB_LINE6 help - This is a driver for POD HD300, 400 and 500 devices. + This is a driver for POD X3, HD300, 400 and 500 devices. config SND_USB_TONEPORT tristate "TonePort GX, UX1 and UX2 USB support" diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index f518fbb..7c81256 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -29,10 +29,10 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) int ret; struct urb *urb_in; - index = - find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->in.active_urbs, + line6pcm->line6->iso_buffers); - if (index < 0 || index >= LINE6_ISO_BUFFERS) { + if (index < 0 || index >= line6pcm->line6->iso_buffers) { dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); return -EINVAL; } @@ -44,13 +44,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) struct usb_iso_packet_descriptor *fin = &urb_in->iso_frame_desc[i]; fin->offset = urb_size; - fin->length = line6pcm->max_packet_size; - urb_size += line6pcm->max_packet_size; + fin->length = line6pcm->max_packet_size_in; + urb_size += line6pcm->max_packet_size_in; } urb_in->transfer_buffer = line6pcm->in.buffer + - index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in; urb_in->transfer_buffer_length = urb_size; urb_in->context = line6pcm; @@ -73,7 +73,7 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) { int ret = 0, i; - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { ret = submit_audio_in_urb(line6pcm); if (ret < 0) break; @@ -90,7 +90,9 @@ void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) struct snd_pcm_substream *substream = get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); struct snd_pcm_runtime *runtime = substream->runtime; - const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->capture_hw.channels_max; int frames = fsize / bytes_per_frame; if (runtime == NULL) @@ -154,7 +156,7 @@ static void audio_in_callback(struct urb *urb) line6pcm->in.last_frame = urb->start_frame; /* find index of URB */ - for (index = 0; index < LINE6_ISO_BUFFERS; ++index) + for (index = 0; index < line6pcm->line6->iso_buffers; ++index) if (urb == line6pcm->in.urbs[index]) break; @@ -173,17 +175,27 @@ static void audio_in_callback(struct urb *urb) fbuf = urb->transfer_buffer + fin->offset; fsize = fin->actual_length; - if (fsize > line6pcm->max_packet_size) { + if (fsize > line6pcm->max_packet_size_in) { dev_err(line6pcm->line6->ifcdev, "driver and/or device bug: packet too large (%d > %d)\n", - fsize, line6pcm->max_packet_size); + fsize, line6pcm->max_packet_size_in); } length += fsize; - /* the following assumes LINE6_ISO_PACKETS == 1: */ + BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1, + "The following code assumes LINE6_ISO_PACKETS == 1"); + /* TODO: + * Also, if iso_buffers != 2, the prev frame is almost random at + * playback side. + * This needs to be redesigned. It should be "stable", but we may + * experience sync problems on such high-speed configs. + */ + line6pcm->prev_fbuf = fbuf; - line6pcm->prev_fsize = fsize; + line6pcm->prev_fsize = fsize / + (line6pcm->properties->bytes_per_channel * + line6pcm->properties->capture_hw.channels_max); if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) && @@ -220,6 +232,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) if (err < 0) return err; + line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false); + runtime->hw = line6pcm->properties->capture_hw; return 0; } @@ -227,6 +241,9 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) /* close capture callback */ static int snd_line6_capture_close(struct snd_pcm_substream *substream) { + struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); + + line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER); return 0; } @@ -247,8 +264,13 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; + line6pcm->in.urbs = kzalloc( + sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + if (line6pcm->in.urbs == NULL) + return -ENOMEM; + /* create audio URBs and fill in constant values: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio in: */ diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 81b7da8..14e587e 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -17,6 +17,7 @@ #include <sound/core.h> #include <sound/initval.h> +#include <sound/hwdep.h> #include "capture.h" #include "driver.h" @@ -29,7 +30,7 @@ /* This is Line 6's MIDI manufacturer ID. */ -const unsigned char line6_midi_id[] = { +const unsigned char line6_midi_id[3] = { 0x00, 0x01, 0x0c }; EXPORT_SYMBOL_GPL(line6_midi_id); @@ -66,10 +67,17 @@ static int line6_start_listen(struct usb_line6 *line6) { int err; - usb_fill_int_urb(line6->urb_listen, line6->usbdev, - usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), - line6->buffer_listen, LINE6_BUFSIZE_LISTEN, - line6_data_received, line6, line6->interval); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + usb_fill_int_urb(line6->urb_listen, line6->usbdev, + usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r), + line6->buffer_listen, LINE6_BUFSIZE_LISTEN, + line6_data_received, line6, line6->interval); + } else { + usb_fill_bulk_urb(line6->urb_listen, line6->usbdev, + usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r), + line6->buffer_listen, LINE6_BUFSIZE_LISTEN, + line6_data_received, line6); + } line6->urb_listen->actual_length = 0; err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC); return err; @@ -90,6 +98,7 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int size) { int i, done = 0; + const struct line6_properties *properties = line6->properties; for (i = 0; i < size; i += line6->max_packet_size) { int partial; @@ -97,15 +106,21 @@ static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, int frag_size = min(line6->max_packet_size, size - i); int retval; - retval = usb_interrupt_msg(line6->usbdev, - usb_sndintpipe(line6->usbdev, - line6->properties->ep_ctrl_w), - (char *)frag_buf, frag_size, - &partial, LINE6_TIMEOUT * HZ); + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + retval = usb_interrupt_msg(line6->usbdev, + usb_sndintpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, + &partial, LINE6_TIMEOUT * HZ); + } else { + retval = usb_bulk_msg(line6->usbdev, + usb_sndbulkpipe(line6->usbdev, properties->ep_ctrl_w), + (char *)frag_buf, frag_size, + &partial, LINE6_TIMEOUT * HZ); + } if (retval) { dev_err(line6->ifcdev, - "usb_interrupt_msg failed (%d)\n", retval); + "usb_bulk_msg failed (%d)\n", retval); break; } @@ -140,10 +155,17 @@ static int line6_send_raw_message_async_part(struct message *msg, int done = msg->done; int bytes = min(msg->size - done, line6->max_packet_size); - usb_fill_int_urb(urb, line6->usbdev, - usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), - (char *)msg->buffer + done, bytes, - line6_async_request_sent, msg, line6->interval); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + usb_fill_int_urb(urb, line6->usbdev, + usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w), + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg, line6->interval); + } else { + usb_fill_bulk_urb(urb, line6->usbdev, + usb_sndbulkpipe(line6->usbdev, line6->properties->ep_ctrl_w), + (char *)msg->buffer + done, bytes, + line6_async_request_sent, msg); + } msg->done += bytes; retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -269,28 +291,36 @@ static void line6_data_received(struct urb *urb) if (urb->status == -ESHUTDOWN) return; - done = - line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + done = + line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); - if (done < urb->actual_length) { - line6_midibuf_ignore(mb, done); - dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", - done, urb->actual_length); - } + if (done < urb->actual_length) { + line6_midibuf_ignore(mb, done); + dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", + done, urb->actual_length); + } - for (;;) { - done = - line6_midibuf_read(mb, line6->buffer_message, - LINE6_MESSAGE_MAXLEN); + for (;;) { + done = + line6_midibuf_read(mb, line6->buffer_message, + LINE6_MIDI_MESSAGE_MAXLEN); - if (done == 0) - break; + if (done == 0) + break; - line6->message_length = done; - line6_midi_receive(line6, line6->buffer_message, done); + line6->message_length = done; + line6_midi_receive(line6, line6->buffer_message, done); + if (line6->process_message) + line6->process_message(line6); + } + } else { + line6->buffer_message = urb->transfer_buffer; + line6->message_length = urb->actual_length; if (line6->process_message) line6->process_message(line6); + line6->buffer_message = NULL; } line6_start_listen(line6); @@ -447,12 +477,16 @@ static void line6_destruct(struct snd_card *card) struct usb_line6 *line6 = card->private_data; struct usb_device *usbdev = line6->usbdev; - /* free buffer memory first: */ + /* Free buffer memory first. We cannot depend on the existence of private + * data from the (podhd) module, it may be gone already during this call + */ kfree(line6->buffer_message); + kfree(line6->buffer_listen); /* then free URBs: */ usb_free_urb(line6->urb_listen); + line6->urb_listen = NULL; /* decrement reference counters: */ usb_put_dev(usbdev); @@ -462,13 +496,29 @@ static void line6_destruct(struct snd_card *card) static void line6_get_interval(struct usb_line6 *line6) { struct usb_device *usbdev = line6->usbdev; + const struct line6_properties *properties = line6->properties; + int pipe; struct usb_host_endpoint *ep; - unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r); - unsigned epnum = usb_pipeendpoint(pipe); - ep = usbdev->ep_in[epnum]; + if (properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + pipe = + usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r); + } else { + pipe = + usb_rcvbulkpipe(line6->usbdev, line6->properties->ep_ctrl_r); + } + ep = usbdev->ep_in[usb_pipeendpoint(pipe)]; + if (ep) { line6->interval = ep->desc.bInterval; + if (usbdev->speed == USB_SPEED_LOW) { + line6->intervals_per_second = USB_LOW_INTERVALS_PER_SECOND; + line6->iso_buffers = USB_LOW_ISO_BUFFERS; + } else { + line6->intervals_per_second = USB_HIGH_INTERVALS_PER_SECOND; + line6->iso_buffers = USB_HIGH_ISO_BUFFERS; + } + line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); } else { dev_err(line6->ifcdev, @@ -478,6 +528,138 @@ static void line6_get_interval(struct usb_line6 *line6) } } + +/* Enable buffering of incoming messages, flush the buffer */ +static int line6_hwdep_open(struct snd_hwdep *hw, struct file *file) +{ + struct usb_line6 *line6 = hw->private_data; + + /* NOTE: hwdep layer provides atomicity here */ + + line6->messages.active = 1; + + return 0; +} + +/* Stop buffering */ +static int line6_hwdep_release(struct snd_hwdep *hw, struct file *file) +{ + struct usb_line6 *line6 = hw->private_data; + + line6->messages.active = 0; + + return 0; +} + +/* Read from circular buffer, return to user */ +static long +line6_hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count, + loff_t *offset) +{ + struct usb_line6 *line6 = hwdep->private_data; + long rv = 0; + unsigned int out_count; + + if (mutex_lock_interruptible(&line6->messages.read_lock)) + return -ERESTARTSYS; + + while (kfifo_len(&line6->messages.fifo) == 0) { + mutex_unlock(&line6->messages.read_lock); + + rv = wait_event_interruptible( + line6->messages.wait_queue, + kfifo_len(&line6->messages.fifo) != 0); + if (rv < 0) + return rv; + + if (mutex_lock_interruptible(&line6->messages.read_lock)) + return -ERESTARTSYS; + } + + if (kfifo_peek_len(&line6->messages.fifo) > count) { + /* Buffer too small; allow re-read of the current item... */ + rv = -EINVAL; + } else { + rv = kfifo_to_user(&line6->messages.fifo, buf, count, &out_count); + if (rv == 0) + rv = out_count; + } + + mutex_unlock(&line6->messages.read_lock); + return rv; +} + +/* Write directly (no buffering) to device by user*/ +static long +line6_hwdep_write(struct snd_hwdep *hwdep, const char __user *data, long count, + loff_t *offset) +{ + struct usb_line6 *line6 = hwdep->private_data; + int rv; + char *data_copy; + + if (count > line6->max_packet_size * LINE6_RAW_MESSAGES_MAXCOUNT) { + /* This is an arbitrary limit - still better than nothing... */ + return -EINVAL; + } + + data_copy = memdup_user(data, count); + if (IS_ERR(ERR_PTR)) + return -ENOMEM; + + rv = line6_send_raw_message(line6, data_copy, count); + + kfree(data_copy); + return rv; +} + +static const struct snd_hwdep_ops hwdep_ops = { + .open = line6_hwdep_open, + .release = line6_hwdep_release, + .read = line6_hwdep_read, + .write = line6_hwdep_write, +}; + +/* Insert into circular buffer */ +static void line6_hwdep_push_message(struct usb_line6 *line6) +{ + if (!line6->messages.active) + return; + + if (kfifo_avail(&line6->messages.fifo) >= line6->message_length) { + /* No race condition here, there's only one writer */ + kfifo_in(&line6->messages.fifo, + line6->buffer_message, line6->message_length); + } /* else TODO: signal overflow */ + + wake_up_interruptible(&line6->messages.wait_queue); +} + +static int line6_hwdep_init(struct usb_line6 *line6) +{ + int err; + struct snd_hwdep *hwdep; + + /* TODO: usb_driver_claim_interface(); */ + line6->process_message = line6_hwdep_push_message; + line6->messages.active = 0; + init_waitqueue_head(&line6->messages.wait_queue); + mutex_init(&line6->messages.read_lock); + INIT_KFIFO(line6->messages.fifo); + + err = snd_hwdep_new(line6->card, "config", 0, &hwdep); + if (err < 0) + goto end; + strcpy(hwdep->name, "config"); + hwdep->iface = SNDRV_HWDEP_IFACE_LINE6; + hwdep->ops = hwdep_ops; + hwdep->private_data = line6; + hwdep->exclusive = true; + +end: + return err; +} + static int line6_init_cap_control(struct usb_line6 *line6) { int ret; @@ -487,14 +669,20 @@ static int line6_init_cap_control(struct usb_line6 *line6) if (!line6->buffer_listen) return -ENOMEM; - line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); - if (!line6->buffer_message) - return -ENOMEM; - line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); if (!line6->urb_listen) return -ENOMEM; + if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL); + if (!line6->buffer_message) + return -ENOMEM; + } else { + ret = line6_hwdep_init(line6); + if (ret < 0) + return ret; + } + ret = line6_start_listen(line6); if (ret < 0) { dev_err(line6->ifcdev, "cannot start listening: %d\n", ret); @@ -558,6 +746,7 @@ int line6_probe(struct usb_interface *interface, /* query interface number */ interface_number = interface->cur_altsetting->desc.bInterfaceNumber; + /* TODO reserves the bus bandwidth even without actual transfer */ ret = usb_set_interface(usbdev, interface_number, properties->altsetting); if (ret < 0) { @@ -565,9 +754,8 @@ int line6_probe(struct usb_interface *interface, goto error; } - line6_get_interval(line6); - if (properties->capabilities & LINE6_CAP_CONTROL) { + line6_get_interval(line6); ret = line6_init_cap_control(line6); if (ret < 0) goto error; @@ -670,3 +858,4 @@ EXPORT_SYMBOL_GPL(line6_resume); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index 7da643e..7e3a3aa 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -12,21 +12,37 @@ #ifndef DRIVER_H #define DRIVER_H -#include <linux/spinlock.h> #include <linux/usb.h> +#include <linux/mutex.h> +#include <linux/kfifo.h> #include <sound/core.h> #include "midi.h" -#define USB_INTERVALS_PER_SECOND 1000 +/* USB 1.1 speed configuration */ +#define USB_LOW_INTERVALS_PER_SECOND 1000 +#define USB_LOW_ISO_BUFFERS 2 + +/* USB 2.0+ speed configuration */ +#define USB_HIGH_INTERVALS_PER_SECOND 8000 +#define USB_HIGH_ISO_BUFFERS 16 /* Fallback USB interval and max packet size values */ #define LINE6_FALLBACK_INTERVAL 10 #define LINE6_FALLBACK_MAXPACKETSIZE 16 #define LINE6_TIMEOUT 1 -#define LINE6_BUFSIZE_LISTEN 32 -#define LINE6_MESSAGE_MAXLEN 256 +#define LINE6_BUFSIZE_LISTEN 64 +#define LINE6_MIDI_MESSAGE_MAXLEN 256 + +#define LINE6_RAW_MESSAGES_MAXCOUNT_ORDER 7 +/* 4k packets are common, BUFSIZE * MAXCOUNT should be bigger... */ +#define LINE6_RAW_MESSAGES_MAXCOUNT (1 << LINE6_RAW_MESSAGES_MAXCOUNT_ORDER) + + +#if LINE6_BUFSIZE_LISTEN > 65535 +#error "Use dynamic fifo instead" +#endif /* Line 6 MIDI control commands @@ -94,8 +110,12 @@ enum { LINE6_CAP_CONTROL = 1 << 0, /* device supports PCM input/output via USB */ LINE6_CAP_PCM = 1 << 1, - /* device support hardware monitoring */ + /* device supports hardware monitoring */ LINE6_CAP_HWMON = 1 << 2, + /* device requires output data when input is read */ + LINE6_CAP_IN_NEEDS_OUT = 1 << 3, + /* device uses raw MIDI via USB (data endpoints) */ + LINE6_CAP_CONTROL_MIDI = 1 << 4, }; /* @@ -109,10 +129,15 @@ struct usb_line6 { /* Properties */ const struct line6_properties *properties; - /* Interval (ms) */ + /* Interval for data USB packets */ int interval; + /* ...for isochronous transfers framing */ + int intervals_per_second; + + /* Number of isochronous URBs used for frame transfers */ + int iso_buffers; - /* Maximum size of USB packet */ + /* Maximum size of data USB packet */ int max_packet_size; /* Device representing the USB interface */ @@ -129,18 +154,30 @@ struct usb_line6 { /* Line 6 MIDI device data structure */ struct snd_line6_midi *line6midi; - /* URB for listening to PODxt Pro control endpoint */ + /* URB for listening to POD data endpoint */ struct urb *urb_listen; - /* Buffer for listening to PODxt Pro control endpoint */ + /* Buffer for incoming data from POD data endpoint */ unsigned char *buffer_listen; - /* Buffer for message to be processed */ + /* Buffer for message to be processed, generated from MIDI layer */ unsigned char *buffer_message; - /* Length of message to be processed */ + /* Length of message to be processed, generated from MIDI layer */ int message_length; + /* Circular buffer for non-MIDI control messages */ + struct { + struct mutex read_lock; + wait_queue_head_t wait_queue; + unsigned int active:1; + STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT) + fifo; + } messages; + + /* If MIDI is supported, buffer_message contains the pre-processed data; + * otherwise the data is only in urb_listen (buffer_incoming). + */ void (*process_message)(struct usb_line6 *); void (*disconnect)(struct usb_line6 *line6); }; diff --git a/sound/usb/line6/midi.c b/sound/usb/line6/midi.c index cebea9b..d0fb2f2 100644 --- a/sound/usb/line6/midi.c +++ b/sound/usb/line6/midi.c @@ -258,7 +258,7 @@ int line6_init_midi(struct usb_line6 *line6) struct snd_rawmidi *rmidi; struct snd_line6_midi *line6midi; - if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) { + if (!(line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI)) { /* skip MIDI initialization and report success */ return 0; } diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 41aa335..fab53f5 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -52,7 +52,7 @@ static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol, line6pcm->impulse_volume = value; if (value > 0) { - err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE); + err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE, true); if (err < 0) { line6pcm->impulse_volume = 0; return err; @@ -104,7 +104,7 @@ static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, { int i; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) { if (!test_and_set_bit(i, &pcms->unlink_urbs)) usb_unlink_urb(pcms->urbs[i]); @@ -124,7 +124,7 @@ static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, do { alive = 0; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + for (i = 0; i < line6pcm->line6->iso_buffers; i++) { if (test_bit(i, &pcms->active_urbs)) alive++; } @@ -146,15 +146,20 @@ get_stream(struct snd_line6_pcm *line6pcm, int direction) } /* allocate a buffer if not opened yet; - * call this in line6pcm.state_change mutex + * call this in line6pcm.state_mutex */ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, - struct line6_pcm_stream *pstr, int type) + struct line6_pcm_stream *pstr, int direction, int type) { + const int pkt_size = + (direction == SNDRV_PCM_STREAM_PLAYBACK) ? + line6pcm->max_packet_size_out : + line6pcm->max_packet_size_in; + /* Invoked multiple times in a row so allocate once only */ if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) { - pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * - line6pcm->max_packet_size, GFP_KERNEL); + pstr->buffer = kmalloc(line6pcm->line6->iso_buffers * + LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL); if (!pstr->buffer) return -ENOMEM; } @@ -162,12 +167,11 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm, } /* free a buffer if all streams are closed; - * call this in line6pcm.state_change mutex + * call this in line6pcm.state_mutex */ static void line6_buffer_release(struct snd_line6_pcm *line6pcm, struct line6_pcm_stream *pstr, int type) { - clear_bit(type, &pstr->opened); if (!pstr->opened) { line6_wait_clear_audio_urbs(line6pcm, pstr); @@ -194,6 +198,7 @@ static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction, else ret = line6_submit_audio_in_all_urbs(line6pcm); } + if (ret < 0) clear_bit(type, &pstr->running); spin_unlock_irqrestore(&pstr->lock, flags); @@ -237,6 +242,14 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: + if (s->stream == SNDRV_PCM_STREAM_CAPTURE && + (line6pcm->line6->properties->capabilities & + LINE6_CAP_IN_NEEDS_OUT)) { + err = line6_stream_start(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, + LINE6_STREAM_CAPTURE_HELPER); + if (err < 0) + return err; + } err = line6_stream_start(line6pcm, s->stream, LINE6_STREAM_PCM); if (err < 0) @@ -245,6 +258,12 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: + if (s->stream == SNDRV_PCM_STREAM_CAPTURE && + (line6pcm->line6->properties->capabilities & + LINE6_CAP_IN_NEEDS_OUT)) { + line6_stream_stop(line6pcm, SNDRV_PCM_STREAM_PLAYBACK, + LINE6_STREAM_CAPTURE_HELPER); + } line6_stream_stop(line6pcm, s->stream, LINE6_STREAM_PCM); break; @@ -278,27 +297,30 @@ snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream) return pstr->pos_done; } -/* Acquire and start duplex streams: +/* Acquire and optionally start duplex streams: * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR */ -int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type) +int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, bool start) { struct line6_pcm_stream *pstr; int ret = 0, dir; + /* TODO: We should assert SNDRV_PCM_STREAM_PLAYBACK/CAPTURE == 0/1 */ mutex_lock(&line6pcm->state_mutex); for (dir = 0; dir < 2; dir++) { pstr = get_stream(line6pcm, dir); - ret = line6_buffer_acquire(line6pcm, pstr, type); + ret = line6_buffer_acquire(line6pcm, pstr, dir, type); if (ret < 0) goto error; if (!pstr->running) line6_wait_clear_audio_urbs(line6pcm, pstr); } - for (dir = 0; dir < 2; dir++) { - ret = line6_stream_start(line6pcm, dir, type); - if (ret < 0) - goto error; + if (start) { + for (dir = 0; dir < 2; dir++) { + ret = line6_stream_start(line6pcm, dir, type); + if (ret < 0) + goto error; + } } error: mutex_unlock(&line6pcm->state_mutex); @@ -334,7 +356,8 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream, struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream); mutex_lock(&line6pcm->state_mutex); - ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM); + ret = line6_buffer_acquire(line6pcm, pstr, substream->stream, + LINE6_STREAM_PCM); if (ret < 0) goto error; @@ -434,24 +457,30 @@ static struct snd_kcontrol_new line6_controls[] = { /* Cleanup the PCM device. */ -static void cleanup_urbs(struct line6_pcm_stream *pcms) +static void cleanup_urbs(struct line6_pcm_stream *pcms, int iso_buffers) { int i; - for (i = 0; i < LINE6_ISO_BUFFERS; i++) { + /* Most likely impossible in current code... */ + if (pcms->urbs == NULL) + return; + + for (i = 0; i < iso_buffers; i++) { if (pcms->urbs[i]) { usb_kill_urb(pcms->urbs[i]); usb_free_urb(pcms->urbs[i]); } } + kfree(pcms->urbs); + pcms->urbs = NULL; } static void line6_cleanup_pcm(struct snd_pcm *pcm) { struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); - cleanup_urbs(&line6pcm->out); - cleanup_urbs(&line6pcm->in); + cleanup_urbs(&line6pcm->out, line6pcm->line6->iso_buffers); + cleanup_urbs(&line6pcm->in, line6pcm->line6->iso_buffers); kfree(line6pcm); } @@ -523,12 +552,12 @@ int line6_init_pcm(struct usb_line6 *line6, line6pcm->volume_monitor = 255; line6pcm->line6 = line6; - /* Read and write buffers are sized identically, so choose minimum */ - line6pcm->max_packet_size = min( - usb_maxpacket(line6->usbdev, - usb_rcvisocpipe(line6->usbdev, ep_read), 0), - usb_maxpacket(line6->usbdev, - usb_sndisocpipe(line6->usbdev, ep_write), 1)); + line6pcm->max_packet_size_in = + usb_maxpacket(line6->usbdev, + usb_rcvisocpipe(line6->usbdev, ep_read), 0); + line6pcm->max_packet_size_out = + usb_maxpacket(line6->usbdev, + usb_sndisocpipe(line6->usbdev, ep_write), 1); spin_lock_init(&line6pcm->out.lock); spin_lock_init(&line6pcm->in.lock); diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h index 508410a..bb0c9cb 100644 --- a/sound/usb/line6/pcm.h +++ b/sound/usb/line6/pcm.h @@ -20,9 +20,6 @@ #include "driver.h" -/* number of URBs */ -#define LINE6_ISO_BUFFERS 2 - /* number of USB frames per URB The Line 6 Windows driver always transmits two frames per packet, but @@ -31,7 +28,9 @@ */ #define LINE6_ISO_PACKETS 1 -/* in a "full speed" device (such as the PODxt Pro) this means 1ms */ +/* in a "full speed" device (such as the PODxt Pro) this means 1ms, + * for "high speed" it's 1/8ms + */ #define LINE6_ISO_INTERVAL 1 #define LINE6_IMPULSE_DEFAULT_PERIOD 100 @@ -74,6 +73,7 @@ enum { LINE6_STREAM_PCM, LINE6_STREAM_MONITOR, LINE6_STREAM_IMPULSE, + LINE6_STREAM_CAPTURE_HELPER, }; /* misc bit flags for PCM operation */ @@ -85,12 +85,12 @@ enum { struct line6_pcm_properties { struct snd_pcm_hardware playback_hw, capture_hw; struct snd_pcm_hw_constraint_ratdens rates; - int bytes_per_frame; + int bytes_per_channel; }; struct line6_pcm_stream { /* allocated URBs */ - struct urb *urbs[LINE6_ISO_BUFFERS]; + struct urb **urbs; /* Temporary buffer; * Since the packet size is not known in advance, this buffer is @@ -157,11 +157,12 @@ struct snd_line6_pcm { /* Previously captured frame (for software monitoring) */ unsigned char *prev_fbuf; - /* Size of previously captured frame (for software monitoring) */ + /* Size of previously captured frame (for software monitoring/sync) */ int prev_fsize; /* Maximum size of USB packet */ - int max_packet_size; + int max_packet_size_in; + int max_packet_size_out; /* PCM playback volume (left and right) */ int volume_playback[2]; @@ -191,7 +192,8 @@ extern int snd_line6_hw_params(struct snd_pcm_substream *substream, extern int snd_line6_hw_free(struct snd_pcm_substream *substream); extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream); extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); -extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type); +extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type, + bool start); extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type); #endif diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 97ed593..812d181 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -146,18 +146,20 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) int index; int i, urb_size, urb_frames; int ret; - const int bytes_per_frame = line6pcm->properties->bytes_per_frame; + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->playback_hw.channels_max; const int frame_increment = line6pcm->properties->rates.rats[0].num_min; const int frame_factor = line6pcm->properties->rates.rats[0].den * - (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL); + (line6pcm->line6->intervals_per_second / LINE6_ISO_INTERVAL); struct urb *urb_out; - index = - find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS); + index = find_first_zero_bit(&line6pcm->out.active_urbs, + line6pcm->line6->iso_buffers); - if (index < 0 || index >= LINE6_ISO_BUFFERS) { + if (index < 0 || index >= line6pcm->line6->iso_buffers) { dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); return -EINVAL; } @@ -165,6 +167,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) urb_out = line6pcm->out.urbs[index]; urb_size = 0; + /* TODO: this may not work for LINE6_ISO_PACKETS != 1 */ for (i = 0; i < LINE6_ISO_PACKETS; ++i) { /* compute frame size for given sampling rate */ int fsize = 0; @@ -178,9 +181,11 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) line6pcm->out.count += frame_increment; n = line6pcm->out.count / frame_factor; line6pcm->out.count -= n * frame_factor; - fsize = n * bytes_per_frame; + fsize = n; } + fsize *= bytes_per_frame; + fout->offset = urb_size; fout->length = fsize; urb_size += fsize; @@ -195,7 +200,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) urb_frames = urb_size / bytes_per_frame; urb_out->transfer_buffer = line6pcm->out.buffer + - index * LINE6_ISO_PACKETS * line6pcm->max_packet_size; + index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_out; urb_out->transfer_buffer_length = urb_size; urb_out->context = line6pcm; @@ -286,7 +291,7 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) { int ret = 0, i; - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { ret = submit_audio_out_urb(line6pcm); if (ret < 0) break; @@ -305,6 +310,9 @@ static void audio_out_callback(struct urb *urb) struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; struct snd_pcm_substream *substream = get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); + const int bytes_per_frame = + line6pcm->properties->bytes_per_channel * + line6pcm->properties->playback_hw.channels_max; #if USE_CLEAR_BUFFER_WORKAROUND memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); @@ -313,11 +321,11 @@ static void audio_out_callback(struct urb *urb) line6pcm->out.last_frame = urb->start_frame; /* find index of URB */ - for (index = 0; index < LINE6_ISO_BUFFERS; index++) + for (index = 0; index < line6pcm->line6->iso_buffers; index++) if (urb == line6pcm->out.urbs[index]) break; - if (index >= LINE6_ISO_BUFFERS) + if (index >= line6pcm->line6->iso_buffers) return; /* URB has been unlinked asynchronously */ for (i = 0; i < LINE6_ISO_PACKETS; i++) @@ -329,7 +337,7 @@ static void audio_out_callback(struct urb *urb) struct snd_pcm_runtime *runtime = substream->runtime; line6pcm->out.pos_done += - length / line6pcm->properties->bytes_per_frame; + length / bytes_per_frame; if (line6pcm->out.pos_done >= runtime->buffer_size) line6pcm->out.pos_done -= runtime->buffer_size; @@ -401,8 +409,13 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) struct usb_line6 *line6 = line6pcm->line6; int i; + line6pcm->out.urbs = kzalloc( + sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL); + if (line6pcm->out.urbs == NULL) + return -ENOMEM; + /* create audio URBs and fill in constant values: */ - for (i = 0; i < LINE6_ISO_BUFFERS; ++i) { + for (i = 0; i < line6->iso_buffers; ++i) { struct urb *urb; /* URB for audio out: */ diff --git a/sound/usb/line6/pod.c b/sound/usb/line6/pod.c index 45dd348..17aa616 100644 --- a/sound/usb/line6/pod.c +++ b/sound/usb/line6/pod.c @@ -83,7 +83,6 @@ struct usb_line6_pod { }; #define POD_SYSEX_CODE 3 -#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ /* *INDENT-OFF* */ @@ -167,7 +166,7 @@ static struct line6_pcm_properties pod_pcm_properties = { .rates = { .nrats = 1, .rats = &pod_ratden}, - .bytes_per_frame = POD_BYTES_PER_FRAME + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ }; static const char pod_version_header[] = { @@ -476,6 +475,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxt", .name = "BassPODxt", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -488,6 +488,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxtLive", .name = "BassPODxt Live", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, @@ -500,6 +501,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "BassPODxtPro", .name = "BassPODxt Pro", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -511,7 +513,8 @@ static const struct line6_properties pod_properties_table[] = { [LINE6_POCKETPOD] = { .id = "PocketPOD", .name = "Pocket POD", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 0, .ep_ctrl_r = 0x82, .ep_ctrl_w = 0x02, @@ -521,6 +524,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxt", .name = "PODxt", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, @@ -533,6 +537,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxtLive", .name = "PODxt Live", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, @@ -545,6 +550,7 @@ static const struct line6_properties pod_properties_table[] = { .id = "PODxtPro", .name = "PODxt Pro", .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI | LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 63dcaef..9352a44 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -2,6 +2,7 @@ * Line 6 Pod HD * * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> + * Copyright (C) 2015 Andrej Krutak <dev@andree.sk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,14 +19,46 @@ #include "driver.h" #include "pcm.h" +#define PODHD_STARTUP_DELAY 500 + +/* + * Stages of POD startup procedure + */ +enum { + PODHD_STARTUP_INIT = 1, + PODHD_STARTUP_SCHEDULE_WORKQUEUE, + PODHD_STARTUP_SETUP, + PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1 +}; + enum { LINE6_PODHD300, LINE6_PODHD400, LINE6_PODHD500_0, LINE6_PODHD500_1, + LINE6_PODX3, + LINE6_PODX3LIVE }; -#define PODHD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ +struct usb_line6_podhd { + /* Generic Line 6 USB data */ + struct usb_line6 line6; + + /* Timer for device initialization */ + struct timer_list startup_timer; + + /* Work handler for device initialization */ + struct work_struct startup_work; + + /* Current progress in startup procedure */ + int startup_progress; + + /* Serial number of device */ + u32 serial_number; + + /* Firmware version */ + int firmware_version; +}; static struct snd_ratden podhd_ratden = { .num_min = 48000, @@ -73,29 +106,233 @@ static struct line6_pcm_properties podhd_pcm_properties = { .rates = { .nrats = 1, .rats = &podhd_ratden}, - .bytes_per_frame = PODHD_BYTES_PER_FRAME + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ +}; + +static struct line6_pcm_properties podx3_pcm_properties = { + .playback_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .capture_hw = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START), + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + /* 1+2: Main signal (out), 3+4: Tone 1, + * 5+6: Tone 2, 7+8: raw + */ + .channels_min = 8, + .channels_max = 8, + .buffer_bytes_max = 60000, + .period_bytes_min = 64, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 1024}, + .rates = { + .nrats = 1, + .rats = &podhd_ratden}, + .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */ +}; + +static void podhd_startup_start_workqueue(unsigned long data); +static void podhd_startup_workqueue(struct work_struct *work); +static int podhd_startup_finalize(struct usb_line6_podhd *pod); + +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct snd_card *card = dev_to_snd_card(dev); + struct usb_line6_podhd *pod = card->private_data; + + return sprintf(buf, "%u\n", pod->serial_number); +} + +static ssize_t firmware_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct snd_card *card = dev_to_snd_card(dev); + struct usb_line6_podhd *pod = card->private_data; + + return sprintf(buf, "%06x\n", pod->firmware_version); +} + +static DEVICE_ATTR_RO(firmware_version); +static DEVICE_ATTR_RO(serial_number); + +static struct attribute *podhd_dev_attrs[] = { + &dev_attr_firmware_version.attr, + &dev_attr_serial_number.attr, + NULL +}; + +static const struct attribute_group podhd_dev_attr_group = { + .name = "podhd", + .attrs = podhd_dev_attrs, }; /* + * POD X3 startup procedure. + * + * May be compatible with other POD HD's, since it's also similar to the + * previous POD setup. In any case, it doesn't seem to be required for the + * audio nor bulk interfaces to work. + */ + +static void podhd_startup(struct usb_line6_podhd *pod) +{ + CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT); + + /* delay startup procedure: */ + line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY, + podhd_startup_start_workqueue, (unsigned long)pod); +} + +static void podhd_startup_start_workqueue(unsigned long data) +{ + struct usb_line6_podhd *pod = (struct usb_line6_podhd *)data; + + CHECK_STARTUP_PROGRESS(pod->startup_progress, + PODHD_STARTUP_SCHEDULE_WORKQUEUE); + + /* schedule work for global work queue: */ + schedule_work(&pod->startup_work); +} + +static int podhd_dev_start(struct usb_line6_podhd *pod) +{ + int ret; + u8 init_bytes[8]; + int i; + struct usb_device *usbdev = pod->line6.usbdev; + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x11, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); + return ret; + } + + /* NOTE: looks like some kind of ping message */ + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x11, 0x0, + &init_bytes, 3, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, + "receive length failed (error %d)\n", ret); + return ret; + } + + pod->firmware_version = + (init_bytes[0] << 16) | (init_bytes[1] << 8) | (init_bytes[2] << 0); + + for (i = 0; i <= 16; i++) { + ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); + if (ret < 0) + return ret; + } + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + USB_REQ_SET_FEATURE, + USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, + 1, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) + return ret; + + return 0; +} + +static void podhd_startup_workqueue(struct work_struct *work) +{ + struct usb_line6_podhd *pod = + container_of(work, struct usb_line6_podhd, startup_work); + + CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP); + + podhd_dev_start(pod); + line6_read_serial_number(&pod->line6, &pod->serial_number); + + podhd_startup_finalize(pod); +} + +static int podhd_startup_finalize(struct usb_line6_podhd *pod) +{ + struct usb_line6 *line6 = &pod->line6; + + /* ALSA audio interface: */ + return snd_card_register(line6->card); +} + +static void podhd_disconnect(struct usb_line6 *line6) +{ + struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; + + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + del_timer_sync(&pod->startup_timer); + cancel_work_sync(&pod->startup_work); + } +} + +/* Try to init POD HD device. */ static int podhd_init(struct usb_line6 *line6, const struct usb_device_id *id) { int err; + struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6; - /* initialize MIDI subsystem: */ - err = line6_init_midi(line6); - if (err < 0) - return err; + line6->disconnect = podhd_disconnect; - /* initialize PCM subsystem: */ - err = line6_init_pcm(line6, &podhd_pcm_properties); - if (err < 0) - return err; + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + /* create sysfs entries: */ + err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); + if (err < 0) + return err; + } - /* register USB audio system: */ - return snd_card_register(line6->card); + if (pod->line6.properties->capabilities & LINE6_CAP_PCM) { + /* initialize PCM subsystem: */ + err = line6_init_pcm(line6, + (id->driver_info == LINE6_PODX3) ? &podx3_pcm_properties : + &podhd_pcm_properties); + if (err < 0) + return err; + } + + if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { + /* register USB audio system directly */ + return podhd_startup_finalize(pod); + } + + /* init device and delay registering */ + init_timer(&pod->startup_timer); + INIT_WORK(&pod->startup_work, podhd_startup_workqueue); + podhd_startup(pod); + return 0; } #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod) @@ -103,10 +340,13 @@ static int podhd_init(struct usb_line6 *line6, /* table of devices that work with this driver */ static const struct usb_device_id podhd_id_table[] = { + /* TODO: no need to alloc data interfaces when only audio is used */ { LINE6_DEVICE(0x5057), .driver_info = LINE6_PODHD300 }, { LINE6_DEVICE(0x5058), .driver_info = LINE6_PODHD400 }, { LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 }, { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, + { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, + { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, {} }; @@ -116,8 +356,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD300] = { .id = "PODHD300", .name = "POD HD300", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, .ep_ctrl_r = 0x84, @@ -128,8 +367,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD400] = { .id = "PODHD400", .name = "POD HD400", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 5, .ep_ctrl_r = 0x84, @@ -140,8 +378,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD500_0] = { .id = "PODHD500", .name = "POD HD500", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -152,8 +389,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODHD500_1] = { .id = "PODHD500", .name = "POD HD500", - .capabilities = LINE6_CAP_CONTROL - | LINE6_CAP_PCM + .capabilities = LINE6_CAP_PCM | LINE6_CAP_HWMON, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -161,6 +397,28 @@ static const struct line6_properties podhd_properties_table[] = { .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, + [LINE6_PODX3] = { + .id = "PODX3", + .name = "POD X3", + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, + .altsetting = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, + [LINE6_PODX3LIVE] = { + .id = "PODX3LIVE", + .name = "POD X3 LIVE", + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, + .altsetting = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, }; /* @@ -171,7 +429,7 @@ static int podhd_probe(struct usb_interface *interface, { return line6_probe(interface, id, "Line6-PODHD", &podhd_properties_table[id->driver_info], - podhd_init, sizeof(struct usb_line6)); + podhd_init, sizeof(struct usb_line6_podhd)); } static struct usb_driver podhd_driver = { diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 6d4c50c..8e22f43 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -114,7 +114,7 @@ static struct line6_pcm_properties toneport_pcm_properties = { .rates = { .nrats = 1, .rats = &toneport_ratden}, - .bytes_per_frame = 4 + .bytes_per_channel = 2 }; static const struct { @@ -177,7 +177,7 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, line6pcm->volume_monitor = ucontrol->value.integer.value[0]; if (line6pcm->volume_monitor > 0) { - err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR); + err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR, true); if (err < 0) { line6pcm->volume_monitor = 0; line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR); @@ -246,7 +246,7 @@ static void toneport_start_pcm(unsigned long arg) struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg; struct usb_line6 *line6 = &toneport->line6; - line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR); + line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true); } /* control definition */ diff --git a/sound/usb/line6/variax.c b/sound/usb/line6/variax.c index ddc23dd..0c4512d 100644 --- a/sound/usb/line6/variax.c +++ b/sound/usb/line6/variax.c @@ -259,7 +259,8 @@ static const struct line6_properties variax_properties_table[] = { [LINE6_PODXTLIVE_VARIAX] = { .id = "PODxtLive", .name = "PODxt Live", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 1, .ep_ctrl_r = 0x86, .ep_ctrl_w = 0x05, @@ -269,7 +270,8 @@ static const struct line6_properties variax_properties_table[] = { [LINE6_VARIAX] = { .id = "Variax", .name = "Variax Workbench", - .capabilities = LINE6_CAP_CONTROL, + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_CONTROL_MIDI, .altsetting = 1, .ep_ctrl_r = 0x82, .ep_ctrl_w = 0x01, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f6c3bf7..04991b0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1831,6 +1831,7 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, } static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer, + struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { /* Approximation using 10 ranges based on output measurement on hw v1.2. @@ -1848,10 +1849,19 @@ static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer, 41, 50, TLV_DB_MINMAX_ITEM(-441, 0), ); - usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n"); - kctl->tlv.p = scale; - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + if (cval->min == 0 && cval->max == 50) { + usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk (0-50 variant)\n"); + kctl->tlv.p = scale; + kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; + kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + + } else if (cval->min == 0 && cval->max <= 1000) { + /* Some other clearly broken DragonFly variant. + * At least a 0..53 variant (hw v1.0) exists. + */ + usb_audio_info(mixer->chip, "ignoring too narrow dB range on a DragonFly device"); + kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + } } void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, @@ -1860,8 +1870,8 @@ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer, { switch (mixer->chip->usb_id) { case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ - if (unitid == 7 && cval->min == 0 && cval->max == 50) - snd_dragonfly_quirk_db_scale(mixer, kctl); + if (unitid == 7 && cval->control == UAC_FU_VOLUME) + snd_dragonfly_quirk_db_scale(mixer, cval, kctl); break; } } diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 152292e..2782155 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1217,6 +1217,12 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ep->chip->usb_id == USB_ID(0x0763, 0x2031)) && ep->type == SND_USB_ENDPOINT_TYPE_DATA) ep->skip_packets = 16; + + /* Work around devices that report unreasonable feedback data */ + if ((ep->chip->usb_id == USB_ID(0x0644, 0x8038) || /* TEAC UD-H01 */ + ep->chip->usb_id == USB_ID(0x1852, 0x5034)) && /* T+A Dac8 */ + ep->syncmaxsize == 4) + ep->tenor_fb_quirk = 1; } void snd_usb_set_interface_quirk(struct usb_device *dev) |