linux/sound/pci/ice1712/ak4xxx.c
<<
>>
Prefs
   1/*
   2 *   ALSA driver for ICEnsemble ICE1712 (Envy24)
   3 *
   4 *   AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface
   5 *
   6 *      Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 */      
  23
  24#include <linux/io.h>
  25#include <linux/delay.h>
  26#include <linux/interrupt.h>
  27#include <linux/slab.h>
  28#include <linux/init.h>
  29#include <linux/module.h>
  30#include <sound/core.h>
  31#include <sound/initval.h>
  32#include "ice1712.h"
  33
  34MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  35MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
  36MODULE_LICENSE("GPL");
  37
  38static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip)
  39{
  40        struct snd_ice1712 *ice = ak->private_data[0];
  41
  42        snd_ice1712_save_gpio_status(ice);
  43}
  44
  45static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip)
  46{
  47        struct snd_ice1712 *ice = ak->private_data[0];
  48
  49        snd_ice1712_restore_gpio_status(ice);
  50}
  51
  52/*
  53 * write AK4xxx register
  54 */
  55static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip,
  56                                      unsigned char addr, unsigned char data)
  57{
  58        unsigned int tmp;
  59        int idx;
  60        unsigned int addrdata;
  61        struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
  62        struct snd_ice1712 *ice = ak->private_data[0];
  63
  64        if (snd_BUG_ON(chip < 0 || chip >= 4))
  65                return;
  66
  67        tmp = snd_ice1712_gpio_read(ice);
  68        tmp |= priv->add_flags;
  69        tmp &= ~priv->mask_flags;
  70        if (priv->cs_mask == priv->cs_addr) {
  71                if (priv->cif) {
  72                        tmp |= priv->cs_mask; /* start without chip select */
  73                }  else {
  74                        tmp &= ~priv->cs_mask; /* chip select low */
  75                        snd_ice1712_gpio_write(ice, tmp);
  76                        udelay(1);
  77                }
  78        } else {
  79                /* doesn't handle cf=1 yet */
  80                tmp &= ~priv->cs_mask;
  81                tmp |= priv->cs_addr;
  82                snd_ice1712_gpio_write(ice, tmp);
  83                udelay(1);
  84        }
  85
  86        /* build I2C address + data byte */
  87        addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f);
  88        addrdata = (addrdata << 8) | data;
  89        for (idx = 15; idx >= 0; idx--) {
  90                /* drop clock */
  91                tmp &= ~priv->clk_mask;
  92                snd_ice1712_gpio_write(ice, tmp);
  93                udelay(1);
  94                /* set data */
  95                if (addrdata & (1 << idx))
  96                        tmp |= priv->data_mask;
  97                else
  98                        tmp &= ~priv->data_mask;
  99                snd_ice1712_gpio_write(ice, tmp);
 100                udelay(1);
 101                /* raise clock */
 102                tmp |= priv->clk_mask;
 103                snd_ice1712_gpio_write(ice, tmp);
 104                udelay(1);
 105        }
 106
 107        if (priv->cs_mask == priv->cs_addr) {
 108                if (priv->cif) {
 109                        /* assert a cs pulse to trigger */
 110                        tmp &= ~priv->cs_mask;
 111                        snd_ice1712_gpio_write(ice, tmp);
 112                        udelay(1);
 113                }
 114                tmp |= priv->cs_mask; /* chip select high to trigger */
 115        } else {
 116                tmp &= ~priv->cs_mask;
 117                tmp |= priv->cs_none; /* deselect address */
 118        }
 119        snd_ice1712_gpio_write(ice, tmp);
 120        udelay(1);
 121}
 122
 123/*
 124 * initialize the struct snd_akm4xxx record with the template
 125 */
 126int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp,
 127                             const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice)
 128{
 129        struct snd_ak4xxx_private *priv;
 130
 131        if (_priv != NULL) {
 132                priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 133                if (priv == NULL)
 134                        return -ENOMEM;
 135                *priv = *_priv;
 136        } else {
 137                priv = NULL;
 138        }
 139        *ak = *temp;
 140        ak->card = ice->card;
 141        ak->private_value[0] = (unsigned long)priv;
 142        ak->private_data[0] = ice;
 143        if (ak->ops.lock == NULL)
 144                ak->ops.lock = snd_ice1712_akm4xxx_lock;
 145        if (ak->ops.unlock == NULL)
 146                ak->ops.unlock = snd_ice1712_akm4xxx_unlock;
 147        if (ak->ops.write == NULL)
 148                ak->ops.write = snd_ice1712_akm4xxx_write;
 149        snd_akm4xxx_init(ak);
 150        return 0;
 151}
 152
 153void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice)
 154{
 155        unsigned int akidx;
 156        if (ice->akm == NULL)
 157                return;
 158        for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
 159                struct snd_akm4xxx *ak = &ice->akm[akidx];
 160                kfree((void*)ak->private_value[0]);
 161        }
 162        kfree(ice->akm);
 163}
 164
 165/*
 166 * build AK4xxx controls
 167 */
 168int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice)
 169{
 170        unsigned int akidx;
 171        int err;
 172
 173        for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
 174                struct snd_akm4xxx *ak = &ice->akm[akidx];
 175                err = snd_akm4xxx_build_controls(ak);
 176                if (err < 0)
 177                        return err;
 178        }
 179        return 0;
 180}
 181
 182EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);
 183EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);
 184EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);
 185