root/sound/pci/ice1712/ak4xxx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_ice1712_akm4xxx_lock
  2. snd_ice1712_akm4xxx_unlock
  3. snd_ice1712_akm4xxx_write
  4. snd_ice1712_akm4xxx_init
  5. snd_ice1712_akm4xxx_free
  6. snd_ice1712_akm4xxx_build_controls

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
   4  *
   5  *   AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface
   6  *
   7  *      Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
   8  */      
   9 
  10 #include <linux/io.h>
  11 #include <linux/delay.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/slab.h>
  14 #include <linux/init.h>
  15 #include <linux/module.h>
  16 #include <sound/core.h>
  17 #include <sound/initval.h>
  18 #include "ice1712.h"
  19 
  20 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  21 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
  22 MODULE_LICENSE("GPL");
  23 
  24 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip)
  25 {
  26         struct snd_ice1712 *ice = ak->private_data[0];
  27 
  28         snd_ice1712_save_gpio_status(ice);
  29 }
  30 
  31 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip)
  32 {
  33         struct snd_ice1712 *ice = ak->private_data[0];
  34 
  35         snd_ice1712_restore_gpio_status(ice);
  36 }
  37 
  38 /*
  39  * write AK4xxx register
  40  */
  41 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip,
  42                                       unsigned char addr, unsigned char data)
  43 {
  44         unsigned int tmp;
  45         int idx;
  46         unsigned int addrdata;
  47         struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
  48         struct snd_ice1712 *ice = ak->private_data[0];
  49 
  50         if (snd_BUG_ON(chip < 0 || chip >= 4))
  51                 return;
  52 
  53         tmp = snd_ice1712_gpio_read(ice);
  54         tmp |= priv->add_flags;
  55         tmp &= ~priv->mask_flags;
  56         if (priv->cs_mask == priv->cs_addr) {
  57                 if (priv->cif) {
  58                         tmp |= priv->cs_mask; /* start without chip select */
  59                 }  else {
  60                         tmp &= ~priv->cs_mask; /* chip select low */
  61                         snd_ice1712_gpio_write(ice, tmp);
  62                         udelay(1);
  63                 }
  64         } else {
  65                 /* doesn't handle cf=1 yet */
  66                 tmp &= ~priv->cs_mask;
  67                 tmp |= priv->cs_addr;
  68                 snd_ice1712_gpio_write(ice, tmp);
  69                 udelay(1);
  70         }
  71 
  72         /* build I2C address + data byte */
  73         addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f);
  74         addrdata = (addrdata << 8) | data;
  75         for (idx = 15; idx >= 0; idx--) {
  76                 /* drop clock */
  77                 tmp &= ~priv->clk_mask;
  78                 snd_ice1712_gpio_write(ice, tmp);
  79                 udelay(1);
  80                 /* set data */
  81                 if (addrdata & (1 << idx))
  82                         tmp |= priv->data_mask;
  83                 else
  84                         tmp &= ~priv->data_mask;
  85                 snd_ice1712_gpio_write(ice, tmp);
  86                 udelay(1);
  87                 /* raise clock */
  88                 tmp |= priv->clk_mask;
  89                 snd_ice1712_gpio_write(ice, tmp);
  90                 udelay(1);
  91         }
  92 
  93         if (priv->cs_mask == priv->cs_addr) {
  94                 if (priv->cif) {
  95                         /* assert a cs pulse to trigger */
  96                         tmp &= ~priv->cs_mask;
  97                         snd_ice1712_gpio_write(ice, tmp);
  98                         udelay(1);
  99                 }
 100                 tmp |= priv->cs_mask; /* chip select high to trigger */
 101         } else {
 102                 tmp &= ~priv->cs_mask;
 103                 tmp |= priv->cs_none; /* deselect address */
 104         }
 105         snd_ice1712_gpio_write(ice, tmp);
 106         udelay(1);
 107 }
 108 
 109 /*
 110  * initialize the struct snd_akm4xxx record with the template
 111  */
 112 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp,
 113                              const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice)
 114 {
 115         struct snd_ak4xxx_private *priv;
 116 
 117         if (_priv != NULL) {
 118                 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
 119                 if (priv == NULL)
 120                         return -ENOMEM;
 121                 *priv = *_priv;
 122         } else {
 123                 priv = NULL;
 124         }
 125         *ak = *temp;
 126         ak->card = ice->card;
 127         ak->private_value[0] = (unsigned long)priv;
 128         ak->private_data[0] = ice;
 129         if (ak->ops.lock == NULL)
 130                 ak->ops.lock = snd_ice1712_akm4xxx_lock;
 131         if (ak->ops.unlock == NULL)
 132                 ak->ops.unlock = snd_ice1712_akm4xxx_unlock;
 133         if (ak->ops.write == NULL)
 134                 ak->ops.write = snd_ice1712_akm4xxx_write;
 135         snd_akm4xxx_init(ak);
 136         return 0;
 137 }
 138 
 139 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice)
 140 {
 141         unsigned int akidx;
 142         if (ice->akm == NULL)
 143                 return;
 144         for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
 145                 struct snd_akm4xxx *ak = &ice->akm[akidx];
 146                 kfree((void*)ak->private_value[0]);
 147         }
 148         kfree(ice->akm);
 149 }
 150 
 151 /*
 152  * build AK4xxx controls
 153  */
 154 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice)
 155 {
 156         unsigned int akidx;
 157         int err;
 158 
 159         for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
 160                 struct snd_akm4xxx *ak = &ice->akm[akidx];
 161                 err = snd_akm4xxx_build_controls(ak);
 162                 if (err < 0)
 163                         return err;
 164         }
 165         return 0;
 166 }
 167 
 168 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);
 169 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);
 170 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);

/* [<][>][^][v][top][bottom][index][help] */