Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
0004  *
0005  *   AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface
0006  *
0007  *  Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
0008  */      
0009 
0010 #include <linux/io.h>
0011 #include <linux/delay.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/slab.h>
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016 #include <sound/core.h>
0017 #include <sound/initval.h>
0018 #include "ice1712.h"
0019 
0020 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0021 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
0022 MODULE_LICENSE("GPL");
0023 
0024 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip)
0025 {
0026     struct snd_ice1712 *ice = ak->private_data[0];
0027 
0028     snd_ice1712_save_gpio_status(ice);
0029 }
0030 
0031 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip)
0032 {
0033     struct snd_ice1712 *ice = ak->private_data[0];
0034 
0035     snd_ice1712_restore_gpio_status(ice);
0036 }
0037 
0038 /*
0039  * write AK4xxx register
0040  */
0041 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip,
0042                       unsigned char addr, unsigned char data)
0043 {
0044     unsigned int tmp;
0045     int idx;
0046     unsigned int addrdata;
0047     struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
0048     struct snd_ice1712 *ice = ak->private_data[0];
0049 
0050     if (snd_BUG_ON(chip < 0 || chip >= 4))
0051         return;
0052 
0053     tmp = snd_ice1712_gpio_read(ice);
0054     tmp |= priv->add_flags;
0055     tmp &= ~priv->mask_flags;
0056     if (priv->cs_mask == priv->cs_addr) {
0057         if (priv->cif) {
0058             tmp |= priv->cs_mask; /* start without chip select */
0059         }  else {
0060             tmp &= ~priv->cs_mask; /* chip select low */
0061             snd_ice1712_gpio_write(ice, tmp);
0062             udelay(1);
0063         }
0064     } else {
0065         /* doesn't handle cf=1 yet */
0066         tmp &= ~priv->cs_mask;
0067         tmp |= priv->cs_addr;
0068         snd_ice1712_gpio_write(ice, tmp);
0069         udelay(1);
0070     }
0071 
0072     /* build I2C address + data byte */
0073     addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f);
0074     addrdata = (addrdata << 8) | data;
0075     for (idx = 15; idx >= 0; idx--) {
0076         /* drop clock */
0077         tmp &= ~priv->clk_mask;
0078         snd_ice1712_gpio_write(ice, tmp);
0079         udelay(1);
0080         /* set data */
0081         if (addrdata & (1 << idx))
0082             tmp |= priv->data_mask;
0083         else
0084             tmp &= ~priv->data_mask;
0085         snd_ice1712_gpio_write(ice, tmp);
0086         udelay(1);
0087         /* raise clock */
0088         tmp |= priv->clk_mask;
0089         snd_ice1712_gpio_write(ice, tmp);
0090         udelay(1);
0091     }
0092 
0093     if (priv->cs_mask == priv->cs_addr) {
0094         if (priv->cif) {
0095             /* assert a cs pulse to trigger */
0096             tmp &= ~priv->cs_mask;
0097             snd_ice1712_gpio_write(ice, tmp);
0098             udelay(1);
0099         }
0100         tmp |= priv->cs_mask; /* chip select high to trigger */
0101     } else {
0102         tmp &= ~priv->cs_mask;
0103         tmp |= priv->cs_none; /* deselect address */
0104     }
0105     snd_ice1712_gpio_write(ice, tmp);
0106     udelay(1);
0107 }
0108 
0109 /*
0110  * initialize the struct snd_akm4xxx record with the template
0111  */
0112 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp,
0113                  const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice)
0114 {
0115     struct snd_ak4xxx_private *priv;
0116 
0117     if (_priv != NULL) {
0118         priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0119         if (priv == NULL)
0120             return -ENOMEM;
0121         *priv = *_priv;
0122     } else {
0123         priv = NULL;
0124     }
0125     *ak = *temp;
0126     ak->card = ice->card;
0127         ak->private_value[0] = (unsigned long)priv;
0128     ak->private_data[0] = ice;
0129     if (ak->ops.lock == NULL)
0130         ak->ops.lock = snd_ice1712_akm4xxx_lock;
0131     if (ak->ops.unlock == NULL)
0132         ak->ops.unlock = snd_ice1712_akm4xxx_unlock;
0133     if (ak->ops.write == NULL)
0134         ak->ops.write = snd_ice1712_akm4xxx_write;
0135     snd_akm4xxx_init(ak);
0136     return 0;
0137 }
0138 
0139 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice)
0140 {
0141     unsigned int akidx;
0142     if (ice->akm == NULL)
0143         return;
0144     for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
0145         struct snd_akm4xxx *ak = &ice->akm[akidx];
0146         kfree((void*)ak->private_value[0]);
0147     }
0148     kfree(ice->akm);
0149 }
0150 
0151 /*
0152  * build AK4xxx controls
0153  */
0154 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice)
0155 {
0156     unsigned int akidx;
0157     int err;
0158 
0159     for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
0160         struct snd_akm4xxx *ak = &ice->akm[akidx];
0161         err = snd_akm4xxx_build_controls(ak);
0162         if (err < 0)
0163             return err;
0164     }
0165     return 0;
0166 }
0167 
0168 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);
0169 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);
0170 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);