cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

onyx.c (27870B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Apple Onboard Audio driver for Onyx codec
      4 *
      5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
      6 *
      7 * This is a driver for the pcm3052 codec chip (codenamed Onyx)
      8 * that is present in newer Apple hardware (with digital output).
      9 *
     10 * The Onyx codec has the following connections (listed by the bit
     11 * to be used in aoa_codec.connected):
     12 *  0: analog output
     13 *  1: digital output
     14 *  2: line input
     15 *  3: microphone input
     16 * Note that even though I know of no machine that has for example
     17 * the digital output connected but not the analog, I have handled
     18 * all the different cases in the code so that this driver may serve
     19 * as a good example of what to do.
     20 *
     21 * NOTE: This driver assumes that there's at most one chip to be
     22 * 	 used with one alsa card, in form of creating all kinds
     23 *	 of mixer elements without regard for their existence.
     24 *	 But snd-aoa assumes that there's at most one card, so
     25 *	 this means you can only have one onyx on a system. This
     26 *	 should probably be fixed by changing the assumption of
     27 *	 having just a single card on a system, and making the
     28 *	 'card' pointer accessible to anyone who needs it instead
     29 *	 of hiding it in the aoa_snd_* functions...
     30 */
     31#include <linux/delay.h>
     32#include <linux/module.h>
     33#include <linux/slab.h>
     34MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
     35MODULE_LICENSE("GPL");
     36MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
     37
     38#include "onyx.h"
     39#include "../aoa.h"
     40#include "../soundbus/soundbus.h"
     41
     42
     43#define PFX "snd-aoa-codec-onyx: "
     44
     45struct onyx {
     46	/* cache registers 65 to 80, they are write-only! */
     47	u8			cache[16];
     48	struct i2c_client	*i2c;
     49	struct aoa_codec	codec;
     50	u32			initialised:1,
     51				spdif_locked:1,
     52				analog_locked:1,
     53				original_mute:2;
     54	int			open_count;
     55	struct codec_info	*codec_info;
     56
     57	/* mutex serializes concurrent access to the device
     58	 * and this structure.
     59	 */
     60	struct mutex mutex;
     61};
     62#define codec_to_onyx(c) container_of(c, struct onyx, codec)
     63
     64/* both return 0 if all ok, else on error */
     65static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
     66{
     67	s32 v;
     68
     69	if (reg != ONYX_REG_CONTROL) {
     70		*value = onyx->cache[reg-FIRSTREGISTER];
     71		return 0;
     72	}
     73	v = i2c_smbus_read_byte_data(onyx->i2c, reg);
     74	if (v < 0) {
     75		*value = 0;
     76		return -1;
     77	}
     78	*value = (u8)v;
     79	onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
     80	return 0;
     81}
     82
     83static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
     84{
     85	int result;
     86
     87	result = i2c_smbus_write_byte_data(onyx->i2c, reg, value);
     88	if (!result)
     89		onyx->cache[reg-FIRSTREGISTER] = value;
     90	return result;
     91}
     92
     93/* alsa stuff */
     94
     95static int onyx_dev_register(struct snd_device *dev)
     96{
     97	return 0;
     98}
     99
    100static const struct snd_device_ops ops = {
    101	.dev_register = onyx_dev_register,
    102};
    103
    104/* this is necessary because most alsa mixer programs
    105 * can't properly handle the negative range */
    106#define VOLUME_RANGE_SHIFT	128
    107
    108static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
    109	struct snd_ctl_elem_info *uinfo)
    110{
    111	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    112	uinfo->count = 2;
    113	uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
    114	uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
    115	return 0;
    116}
    117
    118static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
    119	struct snd_ctl_elem_value *ucontrol)
    120{
    121	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    122	s8 l, r;
    123
    124	mutex_lock(&onyx->mutex);
    125	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
    126	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
    127	mutex_unlock(&onyx->mutex);
    128
    129	ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
    130	ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
    131
    132	return 0;
    133}
    134
    135static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
    136	struct snd_ctl_elem_value *ucontrol)
    137{
    138	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    139	s8 l, r;
    140
    141	if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT ||
    142	    ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT)
    143		return -EINVAL;
    144	if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT ||
    145	    ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT)
    146		return -EINVAL;
    147
    148	mutex_lock(&onyx->mutex);
    149	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
    150	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
    151
    152	if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
    153	    r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
    154		mutex_unlock(&onyx->mutex);
    155		return 0;
    156	}
    157
    158	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
    159			    ucontrol->value.integer.value[0]
    160			     - VOLUME_RANGE_SHIFT);
    161	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
    162			    ucontrol->value.integer.value[1]
    163			     - VOLUME_RANGE_SHIFT);
    164	mutex_unlock(&onyx->mutex);
    165
    166	return 1;
    167}
    168
    169static const struct snd_kcontrol_new volume_control = {
    170	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    171	.name = "Master Playback Volume",
    172	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    173	.info = onyx_snd_vol_info,
    174	.get = onyx_snd_vol_get,
    175	.put = onyx_snd_vol_put,
    176};
    177
    178/* like above, this is necessary because a lot
    179 * of alsa mixer programs don't handle ranges
    180 * that don't start at 0 properly.
    181 * even alsamixer is one of them... */
    182#define INPUTGAIN_RANGE_SHIFT	(-3)
    183
    184static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol,
    185	struct snd_ctl_elem_info *uinfo)
    186{
    187	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    188	uinfo->count = 1;
    189	uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT;
    190	uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
    191	return 0;
    192}
    193
    194static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
    195	struct snd_ctl_elem_value *ucontrol)
    196{
    197	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    198	u8 ig;
    199
    200	mutex_lock(&onyx->mutex);
    201	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
    202	mutex_unlock(&onyx->mutex);
    203
    204	ucontrol->value.integer.value[0] =
    205		(ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
    206
    207	return 0;
    208}
    209
    210static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
    211	struct snd_ctl_elem_value *ucontrol)
    212{
    213	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    214	u8 v, n;
    215
    216	if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT ||
    217	    ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT)
    218		return -EINVAL;
    219	mutex_lock(&onyx->mutex);
    220	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
    221	n = v;
    222	n &= ~ONYX_ADC_PGA_GAIN_MASK;
    223	n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
    224		& ONYX_ADC_PGA_GAIN_MASK;
    225	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
    226	mutex_unlock(&onyx->mutex);
    227
    228	return n != v;
    229}
    230
    231static const struct snd_kcontrol_new inputgain_control = {
    232	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    233	.name = "Master Capture Volume",
    234	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    235	.info = onyx_snd_inputgain_info,
    236	.get = onyx_snd_inputgain_get,
    237	.put = onyx_snd_inputgain_put,
    238};
    239
    240static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
    241	struct snd_ctl_elem_info *uinfo)
    242{
    243	static const char * const texts[] = { "Line-In", "Microphone" };
    244
    245	return snd_ctl_enum_info(uinfo, 1, 2, texts);
    246}
    247
    248static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
    249	struct snd_ctl_elem_value *ucontrol)
    250{
    251	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    252	s8 v;
    253
    254	mutex_lock(&onyx->mutex);
    255	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
    256	mutex_unlock(&onyx->mutex);
    257
    258	ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
    259
    260	return 0;
    261}
    262
    263static void onyx_set_capture_source(struct onyx *onyx, int mic)
    264{
    265	s8 v;
    266
    267	mutex_lock(&onyx->mutex);
    268	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
    269	v &= ~ONYX_ADC_INPUT_MIC;
    270	if (mic)
    271		v |= ONYX_ADC_INPUT_MIC;
    272	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
    273	mutex_unlock(&onyx->mutex);
    274}
    275
    276static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
    277	struct snd_ctl_elem_value *ucontrol)
    278{
    279	if (ucontrol->value.enumerated.item[0] > 1)
    280		return -EINVAL;
    281	onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
    282				ucontrol->value.enumerated.item[0]);
    283	return 1;
    284}
    285
    286static const struct snd_kcontrol_new capture_source_control = {
    287	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    288	/* If we name this 'Input Source', it properly shows up in
    289	 * alsamixer as a selection, * but it's shown under the
    290	 * 'Playback' category.
    291	 * If I name it 'Capture Source', it shows up in strange
    292	 * ways (two bools of which one can be selected at a
    293	 * time) but at least it's shown in the 'Capture'
    294	 * category.
    295	 * I was told that this was due to backward compatibility,
    296	 * but I don't understand then why the mangling is *not*
    297	 * done when I name it "Input Source".....
    298	 */
    299	.name = "Capture Source",
    300	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    301	.info = onyx_snd_capture_source_info,
    302	.get = onyx_snd_capture_source_get,
    303	.put = onyx_snd_capture_source_put,
    304};
    305
    306#define onyx_snd_mute_info	snd_ctl_boolean_stereo_info
    307
    308static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
    309	struct snd_ctl_elem_value *ucontrol)
    310{
    311	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    312	u8 c;
    313
    314	mutex_lock(&onyx->mutex);
    315	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
    316	mutex_unlock(&onyx->mutex);
    317
    318	ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
    319	ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
    320
    321	return 0;
    322}
    323
    324static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
    325	struct snd_ctl_elem_value *ucontrol)
    326{
    327	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    328	u8 v = 0, c = 0;
    329	int err = -EBUSY;
    330
    331	mutex_lock(&onyx->mutex);
    332	if (onyx->analog_locked)
    333		goto out_unlock;
    334
    335	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
    336	c = v;
    337	c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
    338	if (!ucontrol->value.integer.value[0])
    339		c |= ONYX_MUTE_LEFT;
    340	if (!ucontrol->value.integer.value[1])
    341		c |= ONYX_MUTE_RIGHT;
    342	err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
    343
    344 out_unlock:
    345	mutex_unlock(&onyx->mutex);
    346
    347	return !err ? (v != c) : err;
    348}
    349
    350static const struct snd_kcontrol_new mute_control = {
    351	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
    352	.name = "Master Playback Switch",
    353	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
    354	.info = onyx_snd_mute_info,
    355	.get = onyx_snd_mute_get,
    356	.put = onyx_snd_mute_put,
    357};
    358
    359
    360#define onyx_snd_single_bit_info	snd_ctl_boolean_mono_info
    361
    362#define FLAG_POLARITY_INVERT	1
    363#define FLAG_SPDIFLOCK		2
    364
    365static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
    366	struct snd_ctl_elem_value *ucontrol)
    367{
    368	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    369	u8 c;
    370	long int pv = kcontrol->private_value;
    371	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
    372	u8 address = (pv >> 8) & 0xff;
    373	u8 mask = pv & 0xff;
    374
    375	mutex_lock(&onyx->mutex);
    376	onyx_read_register(onyx, address, &c);
    377	mutex_unlock(&onyx->mutex);
    378
    379	ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
    380
    381	return 0;
    382}
    383
    384static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
    385	struct snd_ctl_elem_value *ucontrol)
    386{
    387	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    388	u8 v = 0, c = 0;
    389	int err;
    390	long int pv = kcontrol->private_value;
    391	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
    392	u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
    393	u8 address = (pv >> 8) & 0xff;
    394	u8 mask = pv & 0xff;
    395
    396	mutex_lock(&onyx->mutex);
    397	if (spdiflock && onyx->spdif_locked) {
    398		/* even if alsamixer doesn't care.. */
    399		err = -EBUSY;
    400		goto out_unlock;
    401	}
    402	onyx_read_register(onyx, address, &v);
    403	c = v;
    404	c &= ~(mask);
    405	if (!!ucontrol->value.integer.value[0] ^ polarity)
    406		c |= mask;
    407	err = onyx_write_register(onyx, address, c);
    408
    409 out_unlock:
    410	mutex_unlock(&onyx->mutex);
    411
    412	return !err ? (v != c) : err;
    413}
    414
    415#define SINGLE_BIT(n, type, description, address, mask, flags)	 	\
    416static const struct snd_kcontrol_new n##_control = {			\
    417	.iface = SNDRV_CTL_ELEM_IFACE_##type,				\
    418	.name = description,						\
    419	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,			\
    420	.info = onyx_snd_single_bit_info,				\
    421	.get = onyx_snd_single_bit_get,					\
    422	.put = onyx_snd_single_bit_put,					\
    423	.private_value = (flags << 16) | (address << 8) | mask		\
    424}
    425
    426SINGLE_BIT(spdif,
    427	   MIXER,
    428	   SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
    429	   ONYX_REG_DIG_INFO4,
    430	   ONYX_SPDIF_ENABLE,
    431	   FLAG_SPDIFLOCK);
    432SINGLE_BIT(ovr1,
    433	   MIXER,
    434	   "Oversampling Rate",
    435	   ONYX_REG_DAC_CONTROL,
    436	   ONYX_OVR1,
    437	   0);
    438SINGLE_BIT(flt0,
    439	   MIXER,
    440	   "Fast Digital Filter Rolloff",
    441	   ONYX_REG_DAC_FILTER,
    442	   ONYX_ROLLOFF_FAST,
    443	   FLAG_POLARITY_INVERT);
    444SINGLE_BIT(hpf,
    445	   MIXER,
    446	   "Highpass Filter",
    447	   ONYX_REG_ADC_HPF_BYPASS,
    448	   ONYX_HPF_DISABLE,
    449	   FLAG_POLARITY_INVERT);
    450SINGLE_BIT(dm12,
    451	   MIXER,
    452	   "Digital De-Emphasis",
    453	   ONYX_REG_DAC_DEEMPH,
    454	   ONYX_DIGDEEMPH_CTRL,
    455	   0);
    456
    457static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
    458			   struct snd_ctl_elem_info *uinfo)
    459{
    460	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
    461	uinfo->count = 1;
    462	return 0;
    463}
    464
    465static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
    466			       struct snd_ctl_elem_value *ucontrol)
    467{
    468	/* datasheet page 30, all others are 0 */
    469	ucontrol->value.iec958.status[0] = 0x3e;
    470	ucontrol->value.iec958.status[1] = 0xff;
    471
    472	ucontrol->value.iec958.status[3] = 0x3f;
    473	ucontrol->value.iec958.status[4] = 0x0f;
    474
    475	return 0;
    476}
    477
    478static const struct snd_kcontrol_new onyx_spdif_mask = {
    479	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
    480	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
    481	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
    482	.info =		onyx_spdif_info,
    483	.get =		onyx_spdif_mask_get,
    484};
    485
    486static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
    487			  struct snd_ctl_elem_value *ucontrol)
    488{
    489	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    490	u8 v;
    491
    492	mutex_lock(&onyx->mutex);
    493	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
    494	ucontrol->value.iec958.status[0] = v & 0x3e;
    495
    496	onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
    497	ucontrol->value.iec958.status[1] = v;
    498
    499	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
    500	ucontrol->value.iec958.status[3] = v & 0x3f;
    501
    502	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
    503	ucontrol->value.iec958.status[4] = v & 0x0f;
    504	mutex_unlock(&onyx->mutex);
    505
    506	return 0;
    507}
    508
    509static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
    510			  struct snd_ctl_elem_value *ucontrol)
    511{
    512	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
    513	u8 v;
    514
    515	mutex_lock(&onyx->mutex);
    516	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
    517	v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
    518	onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
    519
    520	v = ucontrol->value.iec958.status[1];
    521	onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
    522
    523	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
    524	v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
    525	onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
    526
    527	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
    528	v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
    529	onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
    530	mutex_unlock(&onyx->mutex);
    531
    532	return 1;
    533}
    534
    535static const struct snd_kcontrol_new onyx_spdif_ctrl = {
    536	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
    537	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
    538	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
    539	.info =		onyx_spdif_info,
    540	.get =		onyx_spdif_get,
    541	.put =		onyx_spdif_put,
    542};
    543
    544/* our registers */
    545
    546static const u8 register_map[] = {
    547	ONYX_REG_DAC_ATTEN_LEFT,
    548	ONYX_REG_DAC_ATTEN_RIGHT,
    549	ONYX_REG_CONTROL,
    550	ONYX_REG_DAC_CONTROL,
    551	ONYX_REG_DAC_DEEMPH,
    552	ONYX_REG_DAC_FILTER,
    553	ONYX_REG_DAC_OUTPHASE,
    554	ONYX_REG_ADC_CONTROL,
    555	ONYX_REG_ADC_HPF_BYPASS,
    556	ONYX_REG_DIG_INFO1,
    557	ONYX_REG_DIG_INFO2,
    558	ONYX_REG_DIG_INFO3,
    559	ONYX_REG_DIG_INFO4
    560};
    561
    562static const u8 initial_values[ARRAY_SIZE(register_map)] = {
    563	0x80, 0x80, /* muted */
    564	ONYX_MRST | ONYX_SRST, /* but handled specially! */
    565	ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
    566	0, /* no deemphasis */
    567	ONYX_DAC_FILTER_ALWAYS,
    568	ONYX_OUTPHASE_INVERTED,
    569	(-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
    570	ONYX_ADC_HPF_ALWAYS,
    571	(1<<2),	/* pcm audio */
    572	2,	/* category: pcm coder */
    573	0,	/* sampling frequency 44.1 kHz, clock accuracy level II */
    574	1	/* 24 bit depth */
    575};
    576
    577/* reset registers of chip, either to initial or to previous values */
    578static int onyx_register_init(struct onyx *onyx)
    579{
    580	int i;
    581	u8 val;
    582	u8 regs[sizeof(initial_values)];
    583
    584	if (!onyx->initialised) {
    585		memcpy(regs, initial_values, sizeof(initial_values));
    586		if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
    587			return -1;
    588		val &= ~ONYX_SILICONVERSION;
    589		val |= initial_values[3];
    590		regs[3] = val;
    591	} else {
    592		for (i=0; i<sizeof(register_map); i++)
    593			regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
    594	}
    595
    596	for (i=0; i<sizeof(register_map); i++) {
    597		if (onyx_write_register(onyx, register_map[i], regs[i]))
    598			return -1;
    599	}
    600	onyx->initialised = 1;
    601	return 0;
    602}
    603
    604static struct transfer_info onyx_transfers[] = {
    605	/* this is first so we can skip it if no input is present...
    606	 * No hardware exists with that, but it's here as an example
    607	 * of what to do :) */
    608	{
    609		/* analog input */
    610		.formats = SNDRV_PCM_FMTBIT_S8 |
    611			   SNDRV_PCM_FMTBIT_S16_BE |
    612			   SNDRV_PCM_FMTBIT_S24_BE,
    613		.rates = SNDRV_PCM_RATE_8000_96000,
    614		.transfer_in = 1,
    615		.must_be_clock_source = 0,
    616		.tag = 0,
    617	},
    618	{
    619		/* if analog and digital are currently off, anything should go,
    620		 * so this entry describes everything we can do... */
    621		.formats = SNDRV_PCM_FMTBIT_S8 |
    622			   SNDRV_PCM_FMTBIT_S16_BE |
    623			   SNDRV_PCM_FMTBIT_S24_BE
    624#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
    625			   | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
    626#endif
    627		,
    628		.rates = SNDRV_PCM_RATE_8000_96000,
    629		.tag = 0,
    630	},
    631	{
    632		/* analog output */
    633		.formats = SNDRV_PCM_FMTBIT_S8 |
    634			   SNDRV_PCM_FMTBIT_S16_BE |
    635			   SNDRV_PCM_FMTBIT_S24_BE,
    636		.rates = SNDRV_PCM_RATE_8000_96000,
    637		.transfer_in = 0,
    638		.must_be_clock_source = 0,
    639		.tag = 1,
    640	},
    641	{
    642		/* digital pcm output, also possible for analog out */
    643		.formats = SNDRV_PCM_FMTBIT_S8 |
    644			   SNDRV_PCM_FMTBIT_S16_BE |
    645			   SNDRV_PCM_FMTBIT_S24_BE,
    646		.rates = SNDRV_PCM_RATE_32000 |
    647			 SNDRV_PCM_RATE_44100 |
    648			 SNDRV_PCM_RATE_48000,
    649		.transfer_in = 0,
    650		.must_be_clock_source = 0,
    651		.tag = 2,
    652	},
    653#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
    654	/* Once alsa gets supports for this kind of thing we can add it... */
    655	{
    656		/* digital compressed output */
    657		.formats =  SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
    658		.rates = SNDRV_PCM_RATE_32000 |
    659			 SNDRV_PCM_RATE_44100 |
    660			 SNDRV_PCM_RATE_48000,
    661		.tag = 2,
    662	},
    663#endif
    664	{}
    665};
    666
    667static int onyx_usable(struct codec_info_item *cii,
    668		       struct transfer_info *ti,
    669		       struct transfer_info *out)
    670{
    671	u8 v;
    672	struct onyx *onyx = cii->codec_data;
    673	int spdif_enabled, analog_enabled;
    674
    675	mutex_lock(&onyx->mutex);
    676	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
    677	spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
    678	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
    679	analog_enabled =
    680		(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
    681		 != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
    682	mutex_unlock(&onyx->mutex);
    683
    684	switch (ti->tag) {
    685	case 0: return 1;
    686	case 1:	return analog_enabled;
    687	case 2: return spdif_enabled;
    688	}
    689	return 1;
    690}
    691
    692static int onyx_prepare(struct codec_info_item *cii,
    693			struct bus_info *bi,
    694			struct snd_pcm_substream *substream)
    695{
    696	u8 v;
    697	struct onyx *onyx = cii->codec_data;
    698	int err = -EBUSY;
    699
    700	mutex_lock(&onyx->mutex);
    701
    702#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
    703	if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
    704		/* mute and lock analog output */
    705		onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
    706		if (onyx_write_register(onyx,
    707					ONYX_REG_DAC_CONTROL,
    708					v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
    709			goto out_unlock;
    710		onyx->analog_locked = 1;
    711		err = 0;
    712		goto out_unlock;
    713	}
    714#endif
    715	switch (substream->runtime->rate) {
    716	case 32000:
    717	case 44100:
    718	case 48000:
    719		/* these rates are ok for all outputs */
    720		/* FIXME: program spdif channel control bits here so that
    721		 *	  userspace doesn't have to if it only plays pcm! */
    722		err = 0;
    723		goto out_unlock;
    724	default:
    725		/* got some rate that the digital output can't do,
    726		 * so disable and lock it */
    727		onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
    728		if (onyx_write_register(onyx,
    729					ONYX_REG_DIG_INFO4,
    730					v & ~ONYX_SPDIF_ENABLE))
    731			goto out_unlock;
    732		onyx->spdif_locked = 1;
    733		err = 0;
    734		goto out_unlock;
    735	}
    736
    737 out_unlock:
    738	mutex_unlock(&onyx->mutex);
    739
    740	return err;
    741}
    742
    743static int onyx_open(struct codec_info_item *cii,
    744		     struct snd_pcm_substream *substream)
    745{
    746	struct onyx *onyx = cii->codec_data;
    747
    748	mutex_lock(&onyx->mutex);
    749	onyx->open_count++;
    750	mutex_unlock(&onyx->mutex);
    751
    752	return 0;
    753}
    754
    755static int onyx_close(struct codec_info_item *cii,
    756		      struct snd_pcm_substream *substream)
    757{
    758	struct onyx *onyx = cii->codec_data;
    759
    760	mutex_lock(&onyx->mutex);
    761	onyx->open_count--;
    762	if (!onyx->open_count)
    763		onyx->spdif_locked = onyx->analog_locked = 0;
    764	mutex_unlock(&onyx->mutex);
    765
    766	return 0;
    767}
    768
    769static int onyx_switch_clock(struct codec_info_item *cii,
    770			     enum clock_switch what)
    771{
    772	struct onyx *onyx = cii->codec_data;
    773
    774	mutex_lock(&onyx->mutex);
    775	/* this *MUST* be more elaborate later... */
    776	switch (what) {
    777	case CLOCK_SWITCH_PREPARE_SLAVE:
    778		onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
    779		break;
    780	case CLOCK_SWITCH_SLAVE:
    781		onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
    782		break;
    783	default: /* silence warning */
    784		break;
    785	}
    786	mutex_unlock(&onyx->mutex);
    787
    788	return 0;
    789}
    790
    791#ifdef CONFIG_PM
    792
    793static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
    794{
    795	struct onyx *onyx = cii->codec_data;
    796	u8 v;
    797	int err = -ENXIO;
    798
    799	mutex_lock(&onyx->mutex);
    800	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
    801		goto out_unlock;
    802	onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
    803	/* Apple does a sleep here but the datasheet says to do it on resume */
    804	err = 0;
    805 out_unlock:
    806	mutex_unlock(&onyx->mutex);
    807
    808	return err;
    809}
    810
    811static int onyx_resume(struct codec_info_item *cii)
    812{
    813	struct onyx *onyx = cii->codec_data;
    814	u8 v;
    815	int err = -ENXIO;
    816
    817	mutex_lock(&onyx->mutex);
    818
    819	/* reset codec */
    820	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
    821	msleep(1);
    822	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
    823	msleep(1);
    824	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
    825	msleep(1);
    826
    827	/* take codec out of suspend (if it still is after reset) */
    828	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
    829		goto out_unlock;
    830	onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
    831	/* FIXME: should divide by sample rate, but 8k is the lowest we go */
    832	msleep(2205000/8000);
    833	/* reset all values */
    834	onyx_register_init(onyx);
    835	err = 0;
    836 out_unlock:
    837	mutex_unlock(&onyx->mutex);
    838
    839	return err;
    840}
    841
    842#endif /* CONFIG_PM */
    843
    844static struct codec_info onyx_codec_info = {
    845	.transfers = onyx_transfers,
    846	.sysclock_factor = 256,
    847	.bus_factor = 64,
    848	.owner = THIS_MODULE,
    849	.usable = onyx_usable,
    850	.prepare = onyx_prepare,
    851	.open = onyx_open,
    852	.close = onyx_close,
    853	.switch_clock = onyx_switch_clock,
    854#ifdef CONFIG_PM
    855	.suspend = onyx_suspend,
    856	.resume = onyx_resume,
    857#endif
    858};
    859
    860static int onyx_init_codec(struct aoa_codec *codec)
    861{
    862	struct onyx *onyx = codec_to_onyx(codec);
    863	struct snd_kcontrol *ctl;
    864	struct codec_info *ci = &onyx_codec_info;
    865	u8 v;
    866	int err;
    867
    868	if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
    869		printk(KERN_ERR PFX "gpios not assigned!!\n");
    870		return -EINVAL;
    871	}
    872
    873	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
    874	msleep(1);
    875	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
    876	msleep(1);
    877	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
    878	msleep(1);
    879
    880	if (onyx_register_init(onyx)) {
    881		printk(KERN_ERR PFX "failed to initialise onyx registers\n");
    882		return -ENODEV;
    883	}
    884
    885	if (aoa_snd_device_new(SNDRV_DEV_CODEC, onyx, &ops)) {
    886		printk(KERN_ERR PFX "failed to create onyx snd device!\n");
    887		return -ENODEV;
    888	}
    889
    890	/* nothing connected? what a joke! */
    891	if ((onyx->codec.connected & 0xF) == 0)
    892		return -ENOTCONN;
    893
    894	/* if no inputs are present... */
    895	if ((onyx->codec.connected & 0xC) == 0) {
    896		if (!onyx->codec_info)
    897			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
    898		if (!onyx->codec_info)
    899			return -ENOMEM;
    900		ci = onyx->codec_info;
    901		*ci = onyx_codec_info;
    902		ci->transfers++;
    903	}
    904
    905	/* if no outputs are present... */
    906	if ((onyx->codec.connected & 3) == 0) {
    907		if (!onyx->codec_info)
    908			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
    909		if (!onyx->codec_info)
    910			return -ENOMEM;
    911		ci = onyx->codec_info;
    912		/* this is fine as there have to be inputs
    913		 * if we end up in this part of the code */
    914		*ci = onyx_codec_info;
    915		ci->transfers[1].formats = 0;
    916	}
    917
    918	if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
    919						   aoa_get_card(),
    920						   ci, onyx)) {
    921		printk(KERN_ERR PFX "error creating onyx pcm\n");
    922		return -ENODEV;
    923	}
    924#define ADDCTL(n)							\
    925	do {								\
    926		ctl = snd_ctl_new1(&n, onyx);				\
    927		if (ctl) {						\
    928			ctl->id.device =				\
    929				onyx->codec.soundbus_dev->pcm->device;	\
    930			err = aoa_snd_ctl_add(ctl);			\
    931			if (err)					\
    932				goto error;				\
    933		}							\
    934	} while (0)
    935
    936	if (onyx->codec.soundbus_dev->pcm) {
    937		/* give the user appropriate controls
    938		 * depending on what inputs are connected */
    939		if ((onyx->codec.connected & 0xC) == 0xC)
    940			ADDCTL(capture_source_control);
    941		else if (onyx->codec.connected & 4)
    942			onyx_set_capture_source(onyx, 0);
    943		else
    944			onyx_set_capture_source(onyx, 1);
    945		if (onyx->codec.connected & 0xC)
    946			ADDCTL(inputgain_control);
    947
    948		/* depending on what output is connected,
    949		 * give the user appropriate controls */
    950		if (onyx->codec.connected & 1) {
    951			ADDCTL(volume_control);
    952			ADDCTL(mute_control);
    953			ADDCTL(ovr1_control);
    954			ADDCTL(flt0_control);
    955			ADDCTL(hpf_control);
    956			ADDCTL(dm12_control);
    957			/* spdif control defaults to off */
    958		}
    959		if (onyx->codec.connected & 2) {
    960			ADDCTL(onyx_spdif_mask);
    961			ADDCTL(onyx_spdif_ctrl);
    962		}
    963		if ((onyx->codec.connected & 3) == 3)
    964			ADDCTL(spdif_control);
    965		/* if only S/PDIF is connected, enable it unconditionally */
    966		if ((onyx->codec.connected & 3) == 2) {
    967			onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
    968			v |= ONYX_SPDIF_ENABLE;
    969			onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
    970		}
    971	}
    972#undef ADDCTL
    973	printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
    974
    975	return 0;
    976 error:
    977	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
    978	snd_device_free(aoa_get_card(), onyx);
    979	return err;
    980}
    981
    982static void onyx_exit_codec(struct aoa_codec *codec)
    983{
    984	struct onyx *onyx = codec_to_onyx(codec);
    985
    986	if (!onyx->codec.soundbus_dev) {
    987		printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
    988		return;
    989	}
    990	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
    991}
    992
    993static int onyx_i2c_probe(struct i2c_client *client,
    994			  const struct i2c_device_id *id)
    995{
    996	struct device_node *node = client->dev.of_node;
    997	struct onyx *onyx;
    998	u8 dummy;
    999
   1000	onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
   1001
   1002	if (!onyx)
   1003		return -ENOMEM;
   1004
   1005	mutex_init(&onyx->mutex);
   1006	onyx->i2c = client;
   1007	i2c_set_clientdata(client, onyx);
   1008
   1009	/* we try to read from register ONYX_REG_CONTROL
   1010	 * to check if the codec is present */
   1011	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
   1012		printk(KERN_ERR PFX "failed to read control register\n");
   1013		goto fail;
   1014	}
   1015
   1016	strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
   1017	onyx->codec.owner = THIS_MODULE;
   1018	onyx->codec.init = onyx_init_codec;
   1019	onyx->codec.exit = onyx_exit_codec;
   1020	onyx->codec.node = of_node_get(node);
   1021
   1022	if (aoa_codec_register(&onyx->codec)) {
   1023		goto fail;
   1024	}
   1025	printk(KERN_DEBUG PFX "created and attached onyx instance\n");
   1026	return 0;
   1027 fail:
   1028	kfree(onyx);
   1029	return -ENODEV;
   1030}
   1031
   1032static int onyx_i2c_remove(struct i2c_client *client)
   1033{
   1034	struct onyx *onyx = i2c_get_clientdata(client);
   1035
   1036	aoa_codec_unregister(&onyx->codec);
   1037	of_node_put(onyx->codec.node);
   1038	kfree(onyx->codec_info);
   1039	kfree(onyx);
   1040	return 0;
   1041}
   1042
   1043static const struct i2c_device_id onyx_i2c_id[] = {
   1044	{ "MAC,pcm3052", 0 },
   1045	{ }
   1046};
   1047MODULE_DEVICE_TABLE(i2c,onyx_i2c_id);
   1048
   1049static struct i2c_driver onyx_driver = {
   1050	.driver = {
   1051		.name = "aoa_codec_onyx",
   1052	},
   1053	.probe = onyx_i2c_probe,
   1054	.remove = onyx_i2c_remove,
   1055	.id_table = onyx_i2c_id,
   1056};
   1057
   1058module_i2c_driver(onyx_driver);