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-saa7146.c (12088B)


      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
     11#define AW2_SAA7146_M
     12
     13#include <linux/init.h>
     14#include <linux/pci.h>
     15#include <linux/interrupt.h>
     16#include <linux/delay.h>
     17#include <linux/io.h>
     18#include <sound/core.h>
     19#include <sound/initval.h>
     20#include <sound/pcm.h>
     21#include <sound/pcm_params.h>
     22
     23#include "saa7146.h"
     24#include "aw2-saa7146.h"
     25
     26#include "aw2-tsl.c"
     27
     28#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
     29#define READREG(addr) readl(chip->base_addr + (addr))
     30
     31static struct snd_aw2_saa7146_cb_param
     32 arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
     33static struct snd_aw2_saa7146_cb_param
     34 arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
     35
     36static int snd_aw2_saa7146_get_limit(int size);
     37
     38/* chip-specific destructor */
     39int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
     40{
     41	/* disable all irqs */
     42	WRITEREG(0, IER);
     43
     44	/* reset saa7146 */
     45	WRITEREG((MRST_N << 16), MC1);
     46
     47	/* Unset base addr */
     48	chip->base_addr = NULL;
     49
     50	return 0;
     51}
     52
     53void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
     54			   void __iomem *pci_base_addr)
     55{
     56	/* set PCI burst/threshold
     57
     58	   Burst length definition
     59	   VALUE    BURST LENGTH
     60	   000      1 Dword
     61	   001      2 Dwords
     62	   010      4 Dwords
     63	   011      8 Dwords
     64	   100      16 Dwords
     65	   101      32 Dwords
     66	   110      64 Dwords
     67	   111      128 Dwords
     68
     69	   Threshold definition
     70	   VALUE    WRITE MODE              READ MODE
     71	   00       1 Dword of valid data   1 empty Dword
     72	   01       4 Dwords of valid data  4 empty Dwords
     73	   10       8 Dwords of valid data  8 empty Dwords
     74	   11       16 Dwords of valid data 16 empty Dwords */
     75
     76	unsigned int acon2;
     77	unsigned int acon1 = 0;
     78	int i;
     79
     80	/* Set base addr */
     81	chip->base_addr = pci_base_addr;
     82
     83	/* disable all irqs */
     84	WRITEREG(0, IER);
     85
     86	/* reset saa7146 */
     87	WRITEREG((MRST_N << 16), MC1);
     88
     89	/* enable audio interface */
     90#ifdef __BIG_ENDIAN
     91	acon1 |= A1_SWAP;
     92	acon1 |= A2_SWAP;
     93#endif
     94	/* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
     95
     96	/* At initialization WS1 and WS2 are disabled (configured as input) */
     97	acon1 |= 0 * WS1_CTRL;
     98	acon1 |= 0 * WS2_CTRL;
     99
    100	/* WS4 is not used. So it must not restart A2.
    101	   This is why it is configured as output (force to low) */
    102	acon1 |= 3 * WS4_CTRL;
    103
    104	/* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
    105	acon1 |= 2 * WS3_CTRL;
    106
    107	/* A1 and A2 are active and asynchronous */
    108	acon1 |= 3 * AUDIO_MODE;
    109	WRITEREG(acon1, ACON1);
    110
    111	/* The following comes from original windows driver.
    112	   It is needed to have a correct behavior of input and output
    113	   simultenously, but I don't know why ! */
    114	WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
    115		 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
    116		 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
    117
    118	/* enable audio port pins */
    119	WRITEREG((EAP << 16) | EAP, MC1);
    120
    121	/* enable I2C */
    122	WRITEREG((EI2C << 16) | EI2C, MC1);
    123	/* enable interrupts */
    124	WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
    125
    126	/* audio configuration */
    127	acon2 = A2_CLKSRC | BCLK1_OEN;
    128	WRITEREG(acon2, ACON2);
    129
    130	/* By default use analog input */
    131	snd_aw2_saa7146_use_digital_input(chip, 0);
    132
    133	/* TSL setup */
    134	for (i = 0; i < 8; ++i) {
    135		WRITEREG(tsl1[i], TSL1 + (i * 4));
    136		WRITEREG(tsl2[i], TSL2 + (i * 4));
    137	}
    138
    139}
    140
    141void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
    142				       int stream_number,
    143				       unsigned long dma_addr,
    144				       unsigned long period_size,
    145				       unsigned long buffer_size)
    146{
    147	unsigned long dw_page, dw_limit;
    148
    149	/* Configure DMA for substream
    150	   Configuration informations: ALSA has allocated continuous memory
    151	   pages. So we don't need to use MMU of saa7146.
    152	 */
    153
    154	/* No MMU -> nothing to do with PageA1, we only configure the limit of
    155	   PageAx_out register */
    156	/* Disable MMU */
    157	dw_page = (0L << 11);
    158
    159	/* Configure Limit for DMA access.
    160	   The limit register defines an address limit, which generates
    161	   an interrupt if passed by the actual PCI address pointer.
    162	   '0001' means an interrupt will be generated if the lower
    163	   6 bits (64 bytes) of the PCI address are zero. '0010'
    164	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
    165	   so on up to 1 Mbyte defined by '1111'. This interrupt range
    166	   can be calculated as follows:
    167	   Range = 2^(5 + Limit) bytes.
    168	 */
    169	dw_limit = snd_aw2_saa7146_get_limit(period_size);
    170	dw_page |= (dw_limit << 4);
    171
    172	if (stream_number == 0) {
    173		WRITEREG(dw_page, PageA2_out);
    174
    175		/* Base address for DMA transfert. */
    176		/* This address has been reserved by ALSA. */
    177		/* This is a physical address */
    178		WRITEREG(dma_addr, BaseA2_out);
    179
    180		/* Define upper limit for DMA access */
    181		WRITEREG(dma_addr + buffer_size, ProtA2_out);
    182
    183	} else if (stream_number == 1) {
    184		WRITEREG(dw_page, PageA1_out);
    185
    186		/* Base address for DMA transfert. */
    187		/* This address has been reserved by ALSA. */
    188		/* This is a physical address */
    189		WRITEREG(dma_addr, BaseA1_out);
    190
    191		/* Define upper limit for DMA access */
    192		WRITEREG(dma_addr + buffer_size, ProtA1_out);
    193	} else {
    194		pr_err("aw2: snd_aw2_saa7146_pcm_init_playback: "
    195		       "Substream number is not 0 or 1 -> not managed\n");
    196	}
    197}
    198
    199void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
    200				      int stream_number, unsigned long dma_addr,
    201				      unsigned long period_size,
    202				      unsigned long buffer_size)
    203{
    204	unsigned long dw_page, dw_limit;
    205
    206	/* Configure DMA for substream
    207	   Configuration informations: ALSA has allocated continuous memory
    208	   pages. So we don't need to use MMU of saa7146.
    209	 */
    210
    211	/* No MMU -> nothing to do with PageA1, we only configure the limit of
    212	   PageAx_out register */
    213	/* Disable MMU */
    214	dw_page = (0L << 11);
    215
    216	/* Configure Limit for DMA access.
    217	   The limit register defines an address limit, which generates
    218	   an interrupt if passed by the actual PCI address pointer.
    219	   '0001' means an interrupt will be generated if the lower
    220	   6 bits (64 bytes) of the PCI address are zero. '0010'
    221	   defines a limit of 128 bytes, '0011' one of 256 bytes, and
    222	   so on up to 1 Mbyte defined by '1111'. This interrupt range
    223	   can be calculated as follows:
    224	   Range = 2^(5 + Limit) bytes.
    225	 */
    226	dw_limit = snd_aw2_saa7146_get_limit(period_size);
    227	dw_page |= (dw_limit << 4);
    228
    229	if (stream_number == 0) {
    230		WRITEREG(dw_page, PageA1_in);
    231
    232		/* Base address for DMA transfert. */
    233		/* This address has been reserved by ALSA. */
    234		/* This is a physical address */
    235		WRITEREG(dma_addr, BaseA1_in);
    236
    237		/* Define upper limit for DMA access  */
    238		WRITEREG(dma_addr + buffer_size, ProtA1_in);
    239	} else {
    240		pr_err("aw2: snd_aw2_saa7146_pcm_init_capture: "
    241		       "Substream number is not 0 -> not managed\n");
    242	}
    243}
    244
    245void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
    246						 snd_aw2_saa7146_it_cb
    247						 p_it_callback,
    248						 void *p_callback_param)
    249{
    250	if (stream_number < NB_STREAM_PLAYBACK) {
    251		arr_substream_it_playback_cb[stream_number].p_it_callback =
    252		    (snd_aw2_saa7146_it_cb) p_it_callback;
    253		arr_substream_it_playback_cb[stream_number].p_callback_param =
    254		    (void *)p_callback_param;
    255	}
    256}
    257
    258void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
    259						snd_aw2_saa7146_it_cb
    260						p_it_callback,
    261						void *p_callback_param)
    262{
    263	if (stream_number < NB_STREAM_CAPTURE) {
    264		arr_substream_it_capture_cb[stream_number].p_it_callback =
    265		    (snd_aw2_saa7146_it_cb) p_it_callback;
    266		arr_substream_it_capture_cb[stream_number].p_callback_param =
    267		    (void *)p_callback_param;
    268	}
    269}
    270
    271void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
    272						int stream_number)
    273{
    274	unsigned int acon1 = 0;
    275	/* In aw8 driver, dma transfert is always active. It is
    276	   started and stopped in a larger "space" */
    277	acon1 = READREG(ACON1);
    278	if (stream_number == 0) {
    279		WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
    280
    281		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
    282		acon1 |= 2 * WS2_CTRL;
    283		WRITEREG(acon1, ACON1);
    284
    285	} else if (stream_number == 1) {
    286		WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
    287
    288		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
    289		acon1 |= 1 * WS1_CTRL;
    290		WRITEREG(acon1, ACON1);
    291	}
    292}
    293
    294void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
    295					       int stream_number)
    296{
    297	unsigned int acon1 = 0;
    298	acon1 = READREG(ACON1);
    299	if (stream_number == 0) {
    300		/* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
    301		acon1 &= ~(3 * WS2_CTRL);
    302		WRITEREG(acon1, ACON1);
    303
    304		WRITEREG((TR_E_A2_OUT << 16), MC1);
    305	} else if (stream_number == 1) {
    306		/* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
    307		acon1 &= ~(3 * WS1_CTRL);
    308		WRITEREG(acon1, ACON1);
    309
    310		WRITEREG((TR_E_A1_OUT << 16), MC1);
    311	}
    312}
    313
    314void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
    315					       int stream_number)
    316{
    317	/* In aw8 driver, dma transfert is always active. It is
    318	   started and stopped in a larger "space" */
    319	if (stream_number == 0)
    320		WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
    321}
    322
    323void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
    324					      int stream_number)
    325{
    326	if (stream_number == 0)
    327		WRITEREG((TR_E_A1_IN << 16), MC1);
    328}
    329
    330irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
    331{
    332	unsigned int isr;
    333	__always_unused unsigned int iicsta;
    334	struct snd_aw2_saa7146 *chip = dev_id;
    335
    336	isr = READREG(ISR);
    337	if (!isr)
    338		return IRQ_NONE;
    339
    340	WRITEREG(isr, ISR);
    341
    342	if (isr & (IIC_S | IIC_E)) {
    343		iicsta = READREG(IICSTA);
    344		WRITEREG(0x100, IICSTA);
    345	}
    346
    347	if (isr & A1_out) {
    348		if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
    349			arr_substream_it_playback_cb[1].
    350			    p_it_callback(arr_substream_it_playback_cb[1].
    351					  p_callback_param);
    352		}
    353	}
    354	if (isr & A2_out) {
    355		if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
    356			arr_substream_it_playback_cb[0].
    357			    p_it_callback(arr_substream_it_playback_cb[0].
    358					  p_callback_param);
    359		}
    360
    361	}
    362	if (isr & A1_in) {
    363		if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
    364			arr_substream_it_capture_cb[0].
    365			    p_it_callback(arr_substream_it_capture_cb[0].
    366					  p_callback_param);
    367		}
    368	}
    369	return IRQ_HANDLED;
    370}
    371
    372unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
    373						 int stream_number,
    374						 unsigned char *start_addr,
    375						 unsigned int buffer_size)
    376{
    377	long pci_adp = 0;
    378	size_t ptr = 0;
    379
    380	if (stream_number == 0) {
    381		pci_adp = READREG(PCI_ADP3);
    382		ptr = pci_adp - (long)start_addr;
    383
    384		if (ptr == buffer_size)
    385			ptr = 0;
    386	}
    387	if (stream_number == 1) {
    388		pci_adp = READREG(PCI_ADP1);
    389		ptr = pci_adp - (size_t) start_addr;
    390
    391		if (ptr == buffer_size)
    392			ptr = 0;
    393	}
    394	return ptr;
    395}
    396
    397unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
    398						int stream_number,
    399						unsigned char *start_addr,
    400						unsigned int buffer_size)
    401{
    402	size_t pci_adp = 0;
    403	size_t ptr = 0;
    404	if (stream_number == 0) {
    405		pci_adp = READREG(PCI_ADP2);
    406		ptr = pci_adp - (size_t) start_addr;
    407
    408		if (ptr == buffer_size)
    409			ptr = 0;
    410	}
    411	return ptr;
    412}
    413
    414void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
    415				       int use_digital)
    416{
    417	/* FIXME: switch between analog and digital input does not always work.
    418	   It can produce a kind of white noise. It seams that received data
    419	   are inverted sometime (endian inversion). Why ? I don't know, maybe
    420	   a problem of synchronization... However for the time being I have
    421	   not found the problem. Workaround: switch again (and again) between
    422	   digital and analog input until it works. */
    423	if (use_digital)
    424		WRITEREG(0x40, GPIO_CTRL);
    425	else
    426		WRITEREG(0x50, GPIO_CTRL);
    427}
    428
    429int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
    430{
    431	unsigned int reg_val = READREG(GPIO_CTRL);
    432	if ((reg_val & 0xFF) == 0x40)
    433		return 1;
    434	else
    435		return 0;
    436}
    437
    438
    439static int snd_aw2_saa7146_get_limit(int size)
    440{
    441	int limitsize = 32;
    442	int limit = 0;
    443	while (limitsize < size) {
    444		limitsize *= 2;
    445		limit++;
    446	}
    447	return limit;
    448}