aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/asihpi/hpioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/asihpi/hpioctl.c')
-rw-r--r--sound/pci/asihpi/hpioctl.c124
1 files changed, 115 insertions, 9 deletions
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 7f0272032fbb..9454932fc9c0 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -1,7 +1,8 @@
1/******************************************************************************* 1/*******************************************************************************
2
3 AudioScience HPI driver 2 AudioScience HPI driver
4 Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> 3 Common Linux HPI ioctl and module probe/remove functions
4
5 Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>
5 6
6 This program is free software; you can redistribute it and/or modify 7 This program is free software; you can redistribute it and/or modify
7 it under the terms of version 2 of the GNU General Public License as 8 it under the terms of version 2 of the GNU General Public License as
@@ -12,11 +13,6 @@
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 14 GNU General Public License for more details.
14 15
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19Common Linux HPI ioctl and module probe/remove functions
20*******************************************************************************/ 16*******************************************************************************/
21#define SOURCEFILE_NAME "hpioctl.c" 17#define SOURCEFILE_NAME "hpioctl.c"
22 18
@@ -29,6 +25,7 @@ Common Linux HPI ioctl and module probe/remove functions
29#include "hpicmn.h" 25#include "hpicmn.h"
30 26
31#include <linux/fs.h> 27#include <linux/fs.h>
28#include <linux/interrupt.h>
32#include <linux/slab.h> 29#include <linux/slab.h>
33#include <linux/moduleparam.h> 30#include <linux/moduleparam.h>
34#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -307,10 +304,38 @@ out:
307 return err; 304 return err;
308} 305}
309 306
307static int asihpi_irq_count;
308
309static irqreturn_t asihpi_isr(int irq, void *dev_id)
310{
311 struct hpi_adapter *a = dev_id;
312 int handled;
313
314 if (!a->adapter->irq_query_and_clear) {
315 pr_err("asihpi_isr ASI%04X:%d no handler\n", a->adapter->type,
316 a->adapter->index);
317 return IRQ_NONE;
318 }
319
320 handled = a->adapter->irq_query_and_clear(a->adapter, 0);
321
322 if (!handled)
323 return IRQ_NONE;
324
325 asihpi_irq_count++;
326 /* printk(KERN_INFO "asihpi_isr %d ASI%04X:%d irq handled\n",
327 asihpi_irq_count, a->adapter->type, a->adapter->index); */
328
329 if (a->interrupt_callback)
330 a->interrupt_callback(a);
331
332 return IRQ_HANDLED;
333}
334
310int asihpi_adapter_probe(struct pci_dev *pci_dev, 335int asihpi_adapter_probe(struct pci_dev *pci_dev,
311 const struct pci_device_id *pci_id) 336 const struct pci_device_id *pci_id)
312{ 337{
313 int idx, nm; 338 int idx, nm, low_latency_mode = 0, irq_supported = 0;
314 int adapter_index; 339 int adapter_index;
315 unsigned int memlen; 340 unsigned int memlen;
316 struct hpi_message hm; 341 struct hpi_message hm;
@@ -388,8 +413,39 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
388 hm.adapter_index = adapter.adapter->index; 413 hm.adapter_index = adapter.adapter->index;
389 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); 414 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
390 415
391 if (hr.error) 416 if (hr.error) {
417 HPI_DEBUG_LOG(ERROR, "HPI_ADAPTER_OPEN failed, aborting\n");
418 goto err;
419 }
420
421 /* Check if current mode == Low Latency mode */
422 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
423 HPI_ADAPTER_GET_MODE);
424 hm.adapter_index = adapter.adapter->index;
425 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
426
427 if (hr.error) {
428 HPI_DEBUG_LOG(ERROR,
429 "HPI_ADAPTER_GET_MODE failed, aborting\n");
392 goto err; 430 goto err;
431 }
432
433 if (hr.u.ax.mode.adapter_mode == HPI_ADAPTER_MODE_LOW_LATENCY)
434 low_latency_mode = 1;
435
436 /* Check if IRQs are supported */
437 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
438 HPI_ADAPTER_GET_PROPERTY);
439 hm.adapter_index = adapter.adapter->index;
440 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ;
441 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
442 if (hr.error || !hr.u.ax.property_get.parameter1) {
443 dev_info(&pci_dev->dev,
444 "IRQs not supported by adapter at index %d\n",
445 adapter.adapter->index);
446 } else {
447 irq_supported = 1;
448 }
393 449
394 /* WARNING can't init mutex in 'adapter' 450 /* WARNING can't init mutex in 'adapter'
395 * and then copy it to adapters[] ?!?! 451 * and then copy it to adapters[] ?!?!
@@ -398,6 +454,44 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
398 mutex_init(&adapters[adapter_index].mutex); 454 mutex_init(&adapters[adapter_index].mutex);
399 pci_set_drvdata(pci_dev, &adapters[adapter_index]); 455 pci_set_drvdata(pci_dev, &adapters[adapter_index]);
400 456
457 if (low_latency_mode && irq_supported) {
458 if (!adapter.adapter->irq_query_and_clear) {
459 dev_err(&pci_dev->dev,
460 "no IRQ handler for adapter %d, aborting\n",
461 adapter.adapter->index);
462 goto err;
463 }
464
465 /* Disable IRQ generation on DSP side by setting the rate to 0 */
466 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
467 HPI_ADAPTER_SET_PROPERTY);
468 hm.adapter_index = adapter.adapter->index;
469 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE;
470 hm.u.ax.property_set.parameter1 = 0;
471 hm.u.ax.property_set.parameter2 = 0;
472 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
473 if (hr.error) {
474 HPI_DEBUG_LOG(ERROR,
475 "HPI_ADAPTER_GET_MODE failed, aborting\n");
476 goto err;
477 }
478
479 /* Note: request_irq calls asihpi_isr here */
480 if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED,
481 "asihpi", &adapters[adapter_index])) {
482 dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
483 pci_dev->irq);
484 goto err;
485 }
486
487 adapters[adapter_index].interrupt_mode = 1;
488
489 dev_info(&pci_dev->dev, "using irq %d\n", pci_dev->irq);
490 adapters[adapter_index].irq = pci_dev->irq;
491 } else {
492 dev_info(&pci_dev->dev, "using polled mode\n");
493 }
494
401 dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n", 495 dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
402 adapter.adapter->type, adapter_index); 496 adapter.adapter->type, adapter_index);
403 497
@@ -431,6 +525,15 @@ void asihpi_adapter_remove(struct pci_dev *pci_dev)
431 pa = pci_get_drvdata(pci_dev); 525 pa = pci_get_drvdata(pci_dev);
432 pci = pa->adapter->pci; 526 pci = pa->adapter->pci;
433 527
528 /* Disable IRQ generation on DSP side */
529 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
530 HPI_ADAPTER_SET_PROPERTY);
531 hm.adapter_index = pa->adapter->index;
532 hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE;
533 hm.u.ax.property_set.parameter1 = 0;
534 hm.u.ax.property_set.parameter2 = 0;
535 hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
536
434 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, 537 hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
435 HPI_ADAPTER_DELETE); 538 HPI_ADAPTER_DELETE);
436 hm.adapter_index = pa->adapter->index; 539 hm.adapter_index = pa->adapter->index;
@@ -442,6 +545,9 @@ void asihpi_adapter_remove(struct pci_dev *pci_dev)
442 iounmap(pci.ap_mem_base[idx]); 545 iounmap(pci.ap_mem_base[idx]);
443 } 546 }
444 547
548 if (pa->irq)
549 free_irq(pa->irq, pa);
550
445 if (pa->p_buffer) 551 if (pa->p_buffer)
446 vfree(pa->p_buffer); 552 vfree(pa->p_buffer);
447 553