cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aw2-alsa.c (18375B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*****************************************************************************
      3 *
      4 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
      5 * Jean-Christian Hassler <jhassler@free.fr>
      6 *
      7 * This file is part of the Audiowerk2 ALSA driver
      8 *
      9 *****************************************************************************/
     10#include <linux/init.h>
     11#include <linux/pci.h>
     12#include <linux/dma-mapping.h>
     13#include <linux/slab.h>
     14#include <linux/interrupt.h>
     15#include <linux/delay.h>
     16#include <linux/io.h>
     17#include <linux/module.h>
     18#include <sound/core.h>
     19#include <sound/initval.h>
     20#include <sound/pcm.h>
     21#include <sound/pcm_params.h>
     22#include <sound/control.h>
     23
     24#include "saa7146.h"
     25#include "aw2-saa7146.h"
     26
     27MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis@free.fr>, "
     28	      "Jean-Christian Hassler <jhassler@free.fr>");
     29MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
     30MODULE_LICENSE("GPL");
     31
     32/*********************************
     33 * DEFINES
     34 ********************************/
     35#define CTL_ROUTE_ANALOG 0
     36#define CTL_ROUTE_DIGITAL 1
     37
     38/*********************************
     39 * TYPEDEFS
     40 ********************************/
     41  /* hardware definition */
     42static const struct snd_pcm_hardware snd_aw2_playback_hw = {
     43	.info = (SNDRV_PCM_INFO_MMAP |
     44		 SNDRV_PCM_INFO_INTERLEAVED |
     45		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
     46	.formats = SNDRV_PCM_FMTBIT_S16_LE,
     47	.rates = SNDRV_PCM_RATE_44100,
     48	.rate_min = 44100,
     49	.rate_max = 44100,
     50	.channels_min = 2,
     51	.channels_max = 4,
     52	.buffer_bytes_max = 32768,
     53	.period_bytes_min = 4096,
     54	.period_bytes_max = 32768,
     55	.periods_min = 1,
     56	.periods_max = 1024,
     57};
     58
     59static const struct snd_pcm_hardware snd_aw2_capture_hw = {
     60	.info = (SNDRV_PCM_INFO_MMAP |
     61		 SNDRV_PCM_INFO_INTERLEAVED |
     62		 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
     63	.formats = SNDRV_PCM_FMTBIT_S16_LE,
     64	.rates = SNDRV_PCM_RATE_44100,
     65	.rate_min = 44100,
     66	.rate_max = 44100,
     67	.channels_min = 2,
     68	.channels_max = 2,
     69	.buffer_bytes_max = 32768,
     70	.period_bytes_min = 4096,
     71	.period_bytes_max = 32768,
     72	.periods_min = 1,
     73	.periods_max = 1024,
     74};
     75
     76struct aw2_pcm_device {
     77	struct snd_pcm *pcm;
     78	unsigned int stream_number;
     79	struct aw2 *chip;
     80};
     81
     82struct aw2 {
     83	struct snd_aw2_saa7146 saa7146;
     84
     85	struct pci_dev *pci;
     86	int irq;
     87	spinlock_t reg_lock;
     88	struct mutex mtx;
     89
     90	unsigned long iobase_phys;
     91	void __iomem *iobase_virt;
     92
     93	struct snd_card *card;
     94
     95	struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
     96	struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
     97};
     98
     99/*********************************
    100 * FUNCTION DECLARATIONS
    101 ********************************/
    102static int snd_aw2_create(struct snd_card *card, struct pci_dev *pci);
    103static int snd_aw2_probe(struct pci_dev *pci,
    104			 const struct pci_device_id *pci_id);
    105static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
    106static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
    107static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
    108static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
    109static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
    110static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
    111static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
    112					int cmd);
    113static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
    114				       int cmd);
    115static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
    116						      *substream);
    117static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
    118						     *substream);
    119static int snd_aw2_new_pcm(struct aw2 *chip);
    120
    121static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
    122					       struct snd_ctl_elem_info *uinfo);
    123static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
    124					      struct snd_ctl_elem_value
    125					      *ucontrol);
    126static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
    127					      struct snd_ctl_elem_value
    128					      *ucontrol);
    129
    130/*********************************
    131 * VARIABLES
    132 ********************************/
    133static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
    134static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
    135static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
    136
    137module_param_array(index, int, NULL, 0444);
    138MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
    139module_param_array(id, charp, NULL, 0444);
    140MODULE_PARM_DESC(id, "ID string for the Audiowerk2 soundcard.");
    141module_param_array(enable, bool, NULL, 0444);
    142MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
    143
    144static const struct pci_device_id snd_aw2_ids[] = {
    145	{PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0,
    146	 0, 0, 0},
    147	{0}
    148};
    149
    150MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
    151
    152/* pci_driver definition */
    153static struct pci_driver aw2_driver = {
    154	.name = KBUILD_MODNAME,
    155	.id_table = snd_aw2_ids,
    156	.probe = snd_aw2_probe,
    157};
    158
    159module_pci_driver(aw2_driver);
    160
    161/* operators for playback PCM alsa interface */
    162static const struct snd_pcm_ops snd_aw2_playback_ops = {
    163	.open = snd_aw2_pcm_playback_open,
    164	.close = snd_aw2_pcm_playback_close,
    165	.prepare = snd_aw2_pcm_prepare_playback,
    166	.trigger = snd_aw2_pcm_trigger_playback,
    167	.pointer = snd_aw2_pcm_pointer_playback,
    168};
    169
    170/* operators for capture PCM alsa interface */
    171static const struct snd_pcm_ops snd_aw2_capture_ops = {
    172	.open = snd_aw2_pcm_capture_open,
    173	.close = snd_aw2_pcm_capture_close,
    174	.prepare = snd_aw2_pcm_prepare_capture,
    175	.trigger = snd_aw2_pcm_trigger_capture,
    176	.pointer = snd_aw2_pcm_pointer_capture,
    177};
    178
    179static const struct snd_kcontrol_new aw2_control = {
    180	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    181	.name = "PCM Capture Route",
    182	.index = 0,
    183	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    184	.private_value = 0xffff,
    185	.info = snd_aw2_control_switch_capture_info,
    186	.get = snd_aw2_control_switch_capture_get,
    187	.put = snd_aw2_control_switch_capture_put
    188};
    189
    190/*********************************
    191 * FUNCTION IMPLEMENTATIONS
    192 ********************************/
    193
    194/* component-destructor */
    195static void snd_aw2_free(struct snd_card *card)
    196{
    197	struct aw2 *chip = card->private_data;
    198
    199	/* Free hardware */
    200	snd_aw2_saa7146_free(&chip->saa7146);
    201}
    202
    203/* chip-specific constructor */
    204static int snd_aw2_create(struct snd_card *card,
    205			  struct pci_dev *pci)
    206{
    207	struct aw2 *chip = card->private_data;
    208	int err;
    209
    210	/* initialize the PCI entry */
    211	err = pcim_enable_device(pci);
    212	if (err < 0)
    213		return err;
    214	pci_set_master(pci);
    215
    216	/* check PCI availability (32bit DMA) */
    217	if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
    218		dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
    219		return -ENXIO;
    220	}
    221
    222	/* initialize the stuff */
    223	chip->card = card;
    224	chip->pci = pci;
    225	chip->irq = -1;
    226
    227	/* (1) PCI resource allocation */
    228	err = pcim_iomap_regions(pci, 1 << 0, "Audiowerk2");
    229	if (err < 0)
    230		return err;
    231	chip->iobase_phys = pci_resource_start(pci, 0);
    232	chip->iobase_virt = pcim_iomap_table(pci)[0];
    233
    234	/* (2) initialization of the chip hardware */
    235	snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
    236
    237	if (devm_request_irq(&pci->dev, pci->irq, snd_aw2_saa7146_interrupt,
    238			     IRQF_SHARED, KBUILD_MODNAME, chip)) {
    239		dev_err(card->dev, "Cannot grab irq %d\n", pci->irq);
    240		return -EBUSY;
    241	}
    242	chip->irq = pci->irq;
    243	card->sync_irq = chip->irq;
    244	card->private_free = snd_aw2_free;
    245
    246	dev_info(card->dev,
    247		 "Audiowerk 2 sound card (saa7146 chipset) detected and managed\n");
    248	return 0;
    249}
    250
    251/* constructor */
    252static int snd_aw2_probe(struct pci_dev *pci,
    253			 const struct pci_device_id *pci_id)
    254{
    255	static int dev;
    256	struct snd_card *card;
    257	struct aw2 *chip;
    258	int err;
    259
    260	/* (1) Continue if device is not enabled, else inc dev */
    261	if (dev >= SNDRV_CARDS)
    262		return -ENODEV;
    263	if (!enable[dev]) {
    264		dev++;
    265		return -ENOENT;
    266	}
    267
    268	/* (2) Create card instance */
    269	err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
    270				sizeof(*chip), &card);
    271	if (err < 0)
    272		return err;
    273	chip = card->private_data;
    274
    275	/* (3) Create main component */
    276	err = snd_aw2_create(card, pci);
    277	if (err < 0)
    278		goto error;
    279
    280	/* initialize mutex */
    281	mutex_init(&chip->mtx);
    282	/* init spinlock */
    283	spin_lock_init(&chip->reg_lock);
    284	/* (4) Define driver ID and name string */
    285	strcpy(card->driver, "aw2");
    286	strcpy(card->shortname, "Audiowerk2");
    287
    288	sprintf(card->longname, "%s with SAA7146 irq %i",
    289		card->shortname, chip->irq);
    290
    291	/* (5) Create other components */
    292	snd_aw2_new_pcm(chip);
    293
    294	/* (6) Register card instance */
    295	err = snd_card_register(card);
    296	if (err < 0)
    297		goto error;
    298
    299	/* (7) Set PCI driver data */
    300	pci_set_drvdata(pci, card);
    301
    302	dev++;
    303	return 0;
    304
    305 error:
    306	snd_card_free(card);
    307	return err;
    308}
    309
    310/* open callback */
    311static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
    312{
    313	struct snd_pcm_runtime *runtime = substream->runtime;
    314
    315	dev_dbg(substream->pcm->card->dev, "Playback_open\n");
    316	runtime->hw = snd_aw2_playback_hw;
    317	return 0;
    318}
    319
    320/* close callback */
    321static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
    322{
    323	return 0;
    324
    325}
    326
    327static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
    328{
    329	struct snd_pcm_runtime *runtime = substream->runtime;
    330
    331	dev_dbg(substream->pcm->card->dev, "Capture_open\n");
    332	runtime->hw = snd_aw2_capture_hw;
    333	return 0;
    334}
    335
    336/* close callback */
    337static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
    338{
    339	/* TODO: something to do ? */
    340	return 0;
    341}
    342
    343/* prepare callback for playback */
    344static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
    345{
    346	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    347	struct aw2 *chip = pcm_device->chip;
    348	struct snd_pcm_runtime *runtime = substream->runtime;
    349	unsigned long period_size, buffer_size;
    350
    351	mutex_lock(&chip->mtx);
    352
    353	period_size = snd_pcm_lib_period_bytes(substream);
    354	buffer_size = snd_pcm_lib_buffer_bytes(substream);
    355
    356	snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
    357					  pcm_device->stream_number,
    358					  runtime->dma_addr, period_size,
    359					  buffer_size);
    360
    361	/* Define Interrupt callback */
    362	snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
    363						    (snd_aw2_saa7146_it_cb)
    364						    snd_pcm_period_elapsed,
    365						    (void *)substream);
    366
    367	mutex_unlock(&chip->mtx);
    368
    369	return 0;
    370}
    371
    372/* prepare callback for capture */
    373static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
    374{
    375	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    376	struct aw2 *chip = pcm_device->chip;
    377	struct snd_pcm_runtime *runtime = substream->runtime;
    378	unsigned long period_size, buffer_size;
    379
    380	mutex_lock(&chip->mtx);
    381
    382	period_size = snd_pcm_lib_period_bytes(substream);
    383	buffer_size = snd_pcm_lib_buffer_bytes(substream);
    384
    385	snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
    386					 pcm_device->stream_number,
    387					 runtime->dma_addr, period_size,
    388					 buffer_size);
    389
    390	/* Define Interrupt callback */
    391	snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
    392						   (snd_aw2_saa7146_it_cb)
    393						   snd_pcm_period_elapsed,
    394						   (void *)substream);
    395
    396	mutex_unlock(&chip->mtx);
    397
    398	return 0;
    399}
    400
    401/* playback trigger callback */
    402static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
    403					int cmd)
    404{
    405	int status = 0;
    406	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    407	struct aw2 *chip = pcm_device->chip;
    408	spin_lock(&chip->reg_lock);
    409	switch (cmd) {
    410	case SNDRV_PCM_TRIGGER_START:
    411		snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
    412							   pcm_device->
    413							   stream_number);
    414		break;
    415	case SNDRV_PCM_TRIGGER_STOP:
    416		snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
    417							  pcm_device->
    418							  stream_number);
    419		break;
    420	default:
    421		status = -EINVAL;
    422	}
    423	spin_unlock(&chip->reg_lock);
    424	return status;
    425}
    426
    427/* capture trigger callback */
    428static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
    429				       int cmd)
    430{
    431	int status = 0;
    432	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    433	struct aw2 *chip = pcm_device->chip;
    434	spin_lock(&chip->reg_lock);
    435	switch (cmd) {
    436	case SNDRV_PCM_TRIGGER_START:
    437		snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
    438							  pcm_device->
    439							  stream_number);
    440		break;
    441	case SNDRV_PCM_TRIGGER_STOP:
    442		snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
    443							 pcm_device->
    444							 stream_number);
    445		break;
    446	default:
    447		status = -EINVAL;
    448	}
    449	spin_unlock(&chip->reg_lock);
    450	return status;
    451}
    452
    453/* playback pointer callback */
    454static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
    455						      *substream)
    456{
    457	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    458	struct aw2 *chip = pcm_device->chip;
    459	unsigned int current_ptr;
    460
    461	/* get the current hardware pointer */
    462	struct snd_pcm_runtime *runtime = substream->runtime;
    463	current_ptr =
    464		snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
    465						    pcm_device->stream_number,
    466						    runtime->dma_area,
    467						    runtime->buffer_size);
    468
    469	return bytes_to_frames(substream->runtime, current_ptr);
    470}
    471
    472/* capture pointer callback */
    473static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
    474						     *substream)
    475{
    476	struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
    477	struct aw2 *chip = pcm_device->chip;
    478	unsigned int current_ptr;
    479
    480	/* get the current hardware pointer */
    481	struct snd_pcm_runtime *runtime = substream->runtime;
    482	current_ptr =
    483		snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
    484						   pcm_device->stream_number,
    485						   runtime->dma_area,
    486						   runtime->buffer_size);
    487
    488	return bytes_to_frames(substream->runtime, current_ptr);
    489}
    490
    491/* create a pcm device */
    492static int snd_aw2_new_pcm(struct aw2 *chip)
    493{
    494	struct snd_pcm *pcm_playback_ana;
    495	struct snd_pcm *pcm_playback_num;
    496	struct snd_pcm *pcm_capture;
    497	struct aw2_pcm_device *pcm_device;
    498	int err = 0;
    499
    500	/* Create new Alsa PCM device */
    501
    502	err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
    503			  &pcm_playback_ana);
    504	if (err < 0) {
    505		dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err);
    506		return err;
    507	}
    508
    509	/* Creation ok */
    510	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
    511
    512	/* Set PCM device name */
    513	strcpy(pcm_playback_ana->name, "Analog playback");
    514	/* Associate private data to PCM device */
    515	pcm_playback_ana->private_data = pcm_device;
    516	/* set operators of PCM device */
    517	snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
    518			&snd_aw2_playback_ops);
    519	/* store PCM device */
    520	pcm_device->pcm = pcm_playback_ana;
    521	/* give base chip pointer to our internal pcm device
    522	   structure */
    523	pcm_device->chip = chip;
    524	/* Give stream number to PCM device */
    525	pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
    526
    527	/* pre-allocation of buffers */
    528	/* Preallocate continuous pages. */
    529	snd_pcm_set_managed_buffer_all(pcm_playback_ana,
    530				       SNDRV_DMA_TYPE_DEV,
    531				       &chip->pci->dev,
    532				       64 * 1024, 64 * 1024);
    533
    534	err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
    535			  &pcm_playback_num);
    536
    537	if (err < 0) {
    538		dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err);
    539		return err;
    540	}
    541	/* Creation ok */
    542	pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
    543
    544	/* Set PCM device name */
    545	strcpy(pcm_playback_num->name, "Digital playback");
    546	/* Associate private data to PCM device */
    547	pcm_playback_num->private_data = pcm_device;
    548	/* set operators of PCM device */
    549	snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
    550			&snd_aw2_playback_ops);
    551	/* store PCM device */
    552	pcm_device->pcm = pcm_playback_num;
    553	/* give base chip pointer to our internal pcm device
    554	   structure */
    555	pcm_device->chip = chip;
    556	/* Give stream number to PCM device */
    557	pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
    558
    559	/* pre-allocation of buffers */
    560	/* Preallocate continuous pages. */
    561	snd_pcm_set_managed_buffer_all(pcm_playback_num,
    562				       SNDRV_DMA_TYPE_DEV,
    563				       &chip->pci->dev,
    564				       64 * 1024, 64 * 1024);
    565
    566	err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
    567			  &pcm_capture);
    568
    569	if (err < 0) {
    570		dev_err(chip->card->dev, "snd_pcm_new error (0x%X)\n", err);
    571		return err;
    572	}
    573
    574	/* Creation ok */
    575	pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
    576
    577	/* Set PCM device name */
    578	strcpy(pcm_capture->name, "Capture");
    579	/* Associate private data to PCM device */
    580	pcm_capture->private_data = pcm_device;
    581	/* set operators of PCM device */
    582	snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
    583			&snd_aw2_capture_ops);
    584	/* store PCM device */
    585	pcm_device->pcm = pcm_capture;
    586	/* give base chip pointer to our internal pcm device
    587	   structure */
    588	pcm_device->chip = chip;
    589	/* Give stream number to PCM device */
    590	pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
    591
    592	/* pre-allocation of buffers */
    593	/* Preallocate continuous pages. */
    594	snd_pcm_set_managed_buffer_all(pcm_capture,
    595				       SNDRV_DMA_TYPE_DEV,
    596				       &chip->pci->dev,
    597				       64 * 1024, 64 * 1024);
    598
    599	/* Create control */
    600	err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
    601	if (err < 0) {
    602		dev_err(chip->card->dev, "snd_ctl_add error (0x%X)\n", err);
    603		return err;
    604	}
    605
    606	return 0;
    607}
    608
    609static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
    610					       struct snd_ctl_elem_info *uinfo)
    611{
    612	static const char * const texts[2] = {
    613		"Analog", "Digital"
    614	};
    615	return snd_ctl_enum_info(uinfo, 1, 2, texts);
    616}
    617
    618static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
    619					      struct snd_ctl_elem_value
    620					      *ucontrol)
    621{
    622	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
    623	if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
    624		ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
    625	else
    626		ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
    627	return 0;
    628}
    629
    630static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
    631					      struct snd_ctl_elem_value
    632					      *ucontrol)
    633{
    634	struct aw2 *chip = snd_kcontrol_chip(kcontrol);
    635	int changed = 0;
    636	int is_disgital =
    637	    snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
    638
    639	if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
    640	     && !is_disgital)
    641	    || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
    642		&& is_disgital)) {
    643		snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
    644		changed = 1;
    645	}
    646	return changed;
    647}