brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · cad33a2 Raw
171 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   ALSA driver for ICEnsemble ICE1712 (Envy24)4 *5 *   AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface6 *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 20MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");21MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");22MODULE_LICENSE("GPL");23 24static 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 31static 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 register40 */41static 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		else84			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 template111 */112int 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 139void 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 controls153 */154int 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 168EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);169EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);170EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);171