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