linux/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for Sound Core PDAudioCF soundcard
   4 *
   5 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/slab.h>
  10#include <sound/core.h>
  11#include <sound/info.h>
  12#include "pdaudiocf.h"
  13#include <sound/initval.h>
  14
  15/*
  16 *
  17 */
  18static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
  19{
  20        struct snd_pdacf *chip = private_data;
  21        unsigned long timeout;
  22        unsigned long flags;
  23        unsigned char res;
  24
  25        spin_lock_irqsave(&chip->ak4117_lock, flags);
  26        timeout = 1000;
  27        while (pdacf_reg_read(chip, PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) {
  28                udelay(5);
  29                if (--timeout == 0) {
  30                        spin_unlock_irqrestore(&chip->ak4117_lock, flags);
  31                        snd_printk(KERN_ERR "AK4117 ready timeout (read)\n");
  32                        return 0;
  33                }
  34        }
  35        pdacf_reg_write(chip, PDAUDIOCF_REG_AK_IFR, (u16)reg << 8);
  36        timeout = 1000;
  37        while (pdacf_reg_read(chip, PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) {
  38                udelay(5);
  39                if (--timeout == 0) {
  40                        spin_unlock_irqrestore(&chip->ak4117_lock, flags);
  41                        snd_printk(KERN_ERR "AK4117 read timeout (read2)\n");
  42                        return 0;
  43                }
  44        }
  45        res = (unsigned char)pdacf_reg_read(chip, PDAUDIOCF_REG_AK_IFR);
  46        spin_unlock_irqrestore(&chip->ak4117_lock, flags);
  47        return res;
  48}
  49
  50static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val)
  51{
  52        struct snd_pdacf *chip = private_data;
  53        unsigned long timeout;
  54        unsigned long flags;
  55
  56        spin_lock_irqsave(&chip->ak4117_lock, flags);
  57        timeout = 1000;
  58        while (inw(chip->port + PDAUDIOCF_REG_SCR) & PDAUDIOCF_AK_SBP) {
  59                udelay(5);
  60                if (--timeout == 0) {
  61                        spin_unlock_irqrestore(&chip->ak4117_lock, flags);
  62                        snd_printk(KERN_ERR "AK4117 ready timeout (write)\n");
  63                        return;
  64                }
  65        }
  66        outw((u16)reg << 8 | val | (1<<13), chip->port + PDAUDIOCF_REG_AK_IFR);
  67        spin_unlock_irqrestore(&chip->ak4117_lock, flags);
  68}
  69
  70#if 0
  71void pdacf_dump(struct snd_pdacf *chip)
  72{
  73        printk(KERN_DEBUG "PDAUDIOCF DUMP (0x%lx):\n", chip->port);
  74        printk(KERN_DEBUG "WPD         : 0x%x\n",
  75               inw(chip->port + PDAUDIOCF_REG_WDP));
  76        printk(KERN_DEBUG "RDP         : 0x%x\n",
  77               inw(chip->port + PDAUDIOCF_REG_RDP));
  78        printk(KERN_DEBUG "TCR         : 0x%x\n",
  79               inw(chip->port + PDAUDIOCF_REG_TCR));
  80        printk(KERN_DEBUG "SCR         : 0x%x\n",
  81               inw(chip->port + PDAUDIOCF_REG_SCR));
  82        printk(KERN_DEBUG "ISR         : 0x%x\n",
  83               inw(chip->port + PDAUDIOCF_REG_ISR));
  84        printk(KERN_DEBUG "IER         : 0x%x\n",
  85               inw(chip->port + PDAUDIOCF_REG_IER));
  86        printk(KERN_DEBUG "AK_IFR      : 0x%x\n",
  87               inw(chip->port + PDAUDIOCF_REG_AK_IFR));
  88}
  89#endif
  90
  91static int pdacf_reset(struct snd_pdacf *chip, int powerdown)
  92{
  93        u16 val;
  94        
  95        val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
  96        val |= PDAUDIOCF_PDN;
  97        val &= ~PDAUDIOCF_RECORD;               /* for sure */
  98        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
  99        udelay(5);
 100        val |= PDAUDIOCF_RST;
 101        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 102        udelay(200);
 103        val &= ~PDAUDIOCF_RST;
 104        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 105        udelay(5);
 106        if (!powerdown) {
 107                val &= ~PDAUDIOCF_PDN;
 108                pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 109                udelay(200);
 110        }
 111        return 0;
 112}
 113
 114void pdacf_reinit(struct snd_pdacf *chip, int resume)
 115{
 116        pdacf_reset(chip, 0);
 117        if (resume)
 118                pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, chip->suspend_reg_scr);
 119        snd_ak4117_reinit(chip->ak4117);
 120        pdacf_reg_write(chip, PDAUDIOCF_REG_TCR, chip->regmap[PDAUDIOCF_REG_TCR>>1]);
 121        pdacf_reg_write(chip, PDAUDIOCF_REG_IER, chip->regmap[PDAUDIOCF_REG_IER>>1]);
 122}
 123
 124static void pdacf_proc_read(struct snd_info_entry * entry,
 125                            struct snd_info_buffer *buffer)
 126{
 127        struct snd_pdacf *chip = entry->private_data;
 128        u16 tmp;
 129
 130        snd_iprintf(buffer, "PDAudioCF\n\n");
 131        tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
 132        snd_iprintf(buffer, "FPGA revision      : 0x%x\n", PDAUDIOCF_FPGAREV(tmp));
 133                                           
 134}
 135
 136static void pdacf_proc_init(struct snd_pdacf *chip)
 137{
 138        snd_card_ro_proc_new(chip->card, "pdaudiocf", chip, pdacf_proc_read);
 139}
 140
 141struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
 142{
 143        struct snd_pdacf *chip;
 144
 145        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 146        if (chip == NULL)
 147                return NULL;
 148        chip->card = card;
 149        mutex_init(&chip->reg_lock);
 150        spin_lock_init(&chip->ak4117_lock);
 151        card->private_data = chip;
 152
 153        pdacf_proc_init(chip);
 154        return chip;
 155}
 156
 157static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
 158{
 159        struct snd_pdacf *chip = ak4117->change_callback_private;
 160        u16 val;
 161
 162        if (!(c0 & AK4117_UNLCK))
 163                return;
 164        mutex_lock(&chip->reg_lock);
 165        val = chip->regmap[PDAUDIOCF_REG_SCR>>1];
 166        if (ak4117->rcs0 & AK4117_UNLCK)
 167                val |= PDAUDIOCF_BLUE_LED_OFF;
 168        else
 169                val &= ~PDAUDIOCF_BLUE_LED_OFF;
 170        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 171        mutex_unlock(&chip->reg_lock);
 172}
 173
 174int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
 175{
 176        int err;
 177        u16 val;
 178        /* design note: if we unmask PLL unlock, parity, valid, audio or auto bit interrupts */
 179        /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */
 180        /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */
 181        /* high-rate sources */
 182        static const unsigned char pgm[5] = {
 183                AK4117_XTL_24_576M | AK4117_EXCT,                               /* AK4117_REG_PWRDN */
 184                AK4117_CM_PLL_XTAL | AK4117_PKCS_128fs | AK4117_XCKS_128fs,     /* AK4117_REQ_CLOCK */
 185                AK4117_EFH_1024LRCLK | AK4117_DIF_24R | AK4117_IPS,             /* AK4117_REG_IO */
 186                0xff,                                                           /* AK4117_REG_INT0_MASK */
 187                AK4117_MAUTO | AK4117_MAUD | AK4117_MULK | AK4117_MPAR | AK4117_MV, /* AK4117_REG_INT1_MASK */
 188        };
 189
 190        err = pdacf_reset(chip, 0);
 191        if (err < 0)
 192                return err;
 193        err = snd_ak4117_create(chip->card, pdacf_ak4117_read, pdacf_ak4117_write, pgm, chip, &chip->ak4117);
 194        if (err < 0)
 195                return err;
 196
 197        val = pdacf_reg_read(chip, PDAUDIOCF_REG_TCR);
 198#if 1 /* normal operation */
 199        val &= ~(PDAUDIOCF_ELIMAKMBIT|PDAUDIOCF_TESTDATASEL);
 200#else /* debug */
 201        val |= PDAUDIOCF_ELIMAKMBIT;
 202        val &= ~PDAUDIOCF_TESTDATASEL;
 203#endif
 204        pdacf_reg_write(chip, PDAUDIOCF_REG_TCR, val);
 205        
 206        /* setup the FPGA to match AK4117 setup */
 207        val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
 208        val &= ~(PDAUDIOCF_CLKDIV0 | PDAUDIOCF_CLKDIV1);                /* use 24.576Mhz clock */
 209        val &= ~(PDAUDIOCF_RED_LED_OFF|PDAUDIOCF_BLUE_LED_OFF);
 210        val |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1;                 /* 24-bit data */
 211        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 212
 213        /* setup LEDs and IRQ */
 214        val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER);
 215        val &= ~(PDAUDIOCF_IRQLVLEN0 | PDAUDIOCF_IRQLVLEN1);
 216        val &= ~(PDAUDIOCF_BLUEDUTY0 | PDAUDIOCF_REDDUTY0 | PDAUDIOCF_REDDUTY1);
 217        val |= PDAUDIOCF_BLUEDUTY1 | PDAUDIOCF_HALFRATE;
 218        val |= PDAUDIOCF_IRQOVREN | PDAUDIOCF_IRQAKMEN;
 219        pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val);
 220
 221        chip->ak4117->change_callback_private = chip;
 222        chip->ak4117->change_callback = snd_pdacf_ak4117_change;
 223
 224        /* update LED status */
 225        snd_pdacf_ak4117_change(chip->ak4117, AK4117_UNLCK, 0);
 226
 227        return 0;
 228}
 229
 230void snd_pdacf_powerdown(struct snd_pdacf *chip)
 231{
 232        u16 val;
 233
 234        val = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
 235        chip->suspend_reg_scr = val;
 236        val |= PDAUDIOCF_RED_LED_OFF | PDAUDIOCF_BLUE_LED_OFF;
 237        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
 238        /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
 239        val = inw(chip->port + PDAUDIOCF_REG_IER);
 240        val &= ~(PDAUDIOCF_IRQOVREN|PDAUDIOCF_IRQAKMEN|PDAUDIOCF_IRQLVLEN0|PDAUDIOCF_IRQLVLEN1);
 241        outw(val, chip->port + PDAUDIOCF_REG_IER);
 242        pdacf_reset(chip, 1);
 243}
 244
 245#ifdef CONFIG_PM
 246
 247int snd_pdacf_suspend(struct snd_pdacf *chip)
 248{
 249        u16 val;
 250        
 251        snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
 252        /* disable interrupts, but use direct write to preserve old register value in chip->regmap */
 253        val = inw(chip->port + PDAUDIOCF_REG_IER);
 254        val &= ~(PDAUDIOCF_IRQOVREN|PDAUDIOCF_IRQAKMEN|PDAUDIOCF_IRQLVLEN0|PDAUDIOCF_IRQLVLEN1);
 255        outw(val, chip->port + PDAUDIOCF_REG_IER);
 256        chip->chip_status |= PDAUDIOCF_STAT_IS_SUSPENDED;       /* ignore interrupts from now */
 257        snd_pdacf_powerdown(chip);
 258        return 0;
 259}
 260
 261static inline int check_signal(struct snd_pdacf *chip)
 262{
 263        return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0;
 264}
 265
 266int snd_pdacf_resume(struct snd_pdacf *chip)
 267{
 268        int timeout = 40;
 269
 270        pdacf_reinit(chip, 1);
 271        /* wait for AK4117's PLL */
 272        while (timeout-- > 0 &&
 273               (snd_ak4117_external_rate(chip->ak4117) <= 0 || !check_signal(chip)))
 274                mdelay(1);
 275        chip->chip_status &= ~PDAUDIOCF_STAT_IS_SUSPENDED;
 276        snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
 277        return 0;
 278}
 279#endif
 280