File Index
Files and directories
Sign in
FILE

onyx.c

File preview with syntax highlighting.

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