35 #include <linux/module.h>
36 #include <linux/slab.h>
43 #include "../soundbus/soundbus.h"
46 #define PFX "snd-aoa-codec-onyx: "
65 #define codec_to_onyx(c) container_of(c, struct onyx, codec)
102 .dev_register = onyx_dev_register,
107 #define VOLUME_RANGE_SHIFT 128
109 static int onyx_snd_vol_info(
struct snd_kcontrol *kcontrol,
119 static int onyx_snd_vol_get(
struct snd_kcontrol *kcontrol,
136 static int onyx_snd_vol_put(
struct snd_kcontrol *kcontrol,
160 ucontrol->
value.integer.value[0]
163 ucontrol->
value.integer.value[1]
172 .name =
"Master Playback Volume",
174 .info = onyx_snd_vol_info,
175 .get = onyx_snd_vol_get,
176 .put = onyx_snd_vol_put,
183 #define INPUTGAIN_RANGE_SHIFT (-3)
185 static int onyx_snd_inputgain_info(
struct snd_kcontrol *kcontrol,
195 static int onyx_snd_inputgain_get(
struct snd_kcontrol *kcontrol,
205 ucontrol->
value.integer.value[0] =
211 static int onyx_snd_inputgain_put(
struct snd_kcontrol *kcontrol,
234 .name =
"Master Capture Volume",
236 .info = onyx_snd_inputgain_info,
237 .get = onyx_snd_inputgain_get,
238 .put = onyx_snd_inputgain_put,
241 static int onyx_snd_capture_source_info(
struct snd_kcontrol *kcontrol,
244 static char *texts[] = {
"Line-In",
"Microphone" };
255 static int onyx_snd_capture_source_get(
struct snd_kcontrol *kcontrol,
270 static void onyx_set_capture_source(
struct onyx *onyx,
int mic)
283 static int onyx_snd_capture_source_put(
struct snd_kcontrol *kcontrol,
286 if (ucontrol->
value.enumerated.item[0] > 1)
289 ucontrol->
value.enumerated.item[0]);
306 .name =
"Capture Source",
308 .info = onyx_snd_capture_source_info,
309 .get = onyx_snd_capture_source_get,
310 .put = onyx_snd_capture_source_put,
313 #define onyx_snd_mute_info snd_ctl_boolean_stereo_info
315 static int onyx_snd_mute_get(
struct snd_kcontrol *kcontrol,
331 static int onyx_snd_mute_put(
struct snd_kcontrol *kcontrol,
345 if (!ucontrol->
value.integer.value[0])
347 if (!ucontrol->
value.integer.value[1])
354 return !err ? (v !=
c) : err;
359 .name =
"Master Playback Switch",
362 .get = onyx_snd_mute_get,
363 .put = onyx_snd_mute_put,
367 #define onyx_snd_single_bit_info snd_ctl_boolean_mono_info
369 #define FLAG_POLARITY_INVERT 1
370 #define FLAG_SPDIFLOCK 2
372 static int onyx_snd_single_bit_get(
struct snd_kcontrol *kcontrol,
383 onyx_read_register(onyx, address, &c);
386 ucontrol->
value.integer.value[0] = !!(c &
mask) ^ polarity;
391 static int onyx_snd_single_bit_put(
struct snd_kcontrol *kcontrol,
409 onyx_read_register(onyx, address, &v);
412 if (!!ucontrol->
value.integer.value[0] ^ polarity)
414 err = onyx_write_register(onyx, address,
c);
419 return !err ? (v !=
c) : err;
422 #define SINGLE_BIT(n, type, description, address, mask, flags) \
423 static struct snd_kcontrol_new n##_control = { \
424 .iface = SNDRV_CTL_ELEM_IFACE_##type, \
425 .name = description, \
426 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
427 .info = onyx_snd_single_bit_info, \
428 .get = onyx_snd_single_bit_get, \
429 .put = onyx_snd_single_bit_put, \
430 .private_value = (flags << 16) | (address << 8) | mask \
447 "Fast Digital Filter Rolloff",
459 "Digital De-Emphasis",
464 static int onyx_spdif_info(
struct snd_kcontrol *kcontrol,
472 static int onyx_spdif_mask_get(
struct snd_kcontrol *kcontrol,
476 ucontrol->
value.iec958.status[0] = 0x3e;
477 ucontrol->
value.iec958.status[1] = 0xff;
479 ucontrol->
value.iec958.status[3] = 0x3f;
480 ucontrol->
value.iec958.status[4] = 0x0f;
489 .info = onyx_spdif_info,
490 .get = onyx_spdif_mask_get,
493 static int onyx_spdif_get(
struct snd_kcontrol *kcontrol,
501 ucontrol->
value.iec958.status[0] = v & 0x3e;
504 ucontrol->
value.iec958.status[1] =
v;
507 ucontrol->
value.iec958.status[3] = v & 0x3f;
510 ucontrol->
value.iec958.status[4] = v & 0x0f;
516 static int onyx_spdif_put(
struct snd_kcontrol *kcontrol,
524 v = (v & ~0x3e) | (ucontrol->
value.iec958.status[0] & 0x3e);
527 v = ucontrol->
value.iec958.status[1];
531 v = (v & ~0x3f) | (ucontrol->
value.iec958.status[3] & 0x3f);
535 v = (v & ~0x0f) | (ucontrol->
value.iec958.status[4] & 0x0f);
546 .info = onyx_spdif_info,
547 .get = onyx_spdif_get,
548 .put = onyx_spdif_put,
585 static int onyx_register_init(
struct onyx *onyx)
589 u8 regs[
sizeof(initial_values)];
592 memcpy(
regs, initial_values,
sizeof(initial_values));
593 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
596 val |= initial_values[3];
599 for (i=0; i<
sizeof(register_map); i++)
603 for (i=0; i<
sizeof(register_map); i++) {
604 if (onyx_write_register(onyx, register_map[i],
regs[i]))
622 .must_be_clock_source = 0,
631 #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
632 | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
645 .must_be_clock_source = 0,
657 .must_be_clock_source = 0,
660 #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
664 .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
680 int spdif_enabled, analog_enabled;
693 case 1:
return analog_enabled;
694 case 2:
return spdif_enabled;
709 #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
710 if (substream->
runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
713 if (onyx_write_register(onyx,
722 switch (substream->
runtime->rate) {
735 if (onyx_write_register(onyx,
785 onyx->
codec.gpio->methods->all_amps_off(onyx->
codec.gpio);
788 onyx->
codec.gpio->methods->all_amps_restore(onyx->
codec.gpio);
807 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
827 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 0);
829 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 1);
831 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 0);
835 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
841 onyx_register_init(onyx);
852 .transfers = onyx_transfers,
853 .sysclock_factor = 256,
856 .usable = onyx_usable,
857 .prepare = onyx_prepare,
860 .switch_clock = onyx_switch_clock,
862 .suspend = onyx_suspend,
863 .resume = onyx_resume,
875 if (!onyx->
codec.gpio || !onyx->
codec.gpio->methods) {
880 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 0);
882 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 1);
884 onyx->
codec.gpio->methods->set_hw_reset(onyx->
codec.gpio, 0);
887 if (onyx_register_init(onyx)) {
898 if ((onyx->
codec.connected & 0xF) == 0)
902 if ((onyx->
codec.connected & 0xC) == 0) {
908 *ci = onyx_codec_info;
913 if ((onyx->
codec.connected & 3) == 0) {
921 *ci = onyx_codec_info;
925 if (onyx->
codec.soundbus_dev->attach_codec(onyx->
codec.soundbus_dev,
933 ctl = snd_ctl_new1(&n, onyx); \
936 onyx->codec.soundbus_dev->pcm->device; \
937 err = aoa_snd_ctl_add(ctl); \
943 if (onyx->
codec.soundbus_dev->pcm) {
946 if ((onyx->
codec.connected & 0xC) == 0xC)
947 ADDCTL(capture_source_control);
948 else if (onyx->
codec.connected & 4)
949 onyx_set_capture_source(onyx, 0);
951 onyx_set_capture_source(onyx, 1);
952 if (onyx->
codec.connected & 0xC)
953 ADDCTL(inputgain_control);
957 if (onyx->
codec.connected & 1) {
966 if (onyx->
codec.connected & 2) {
970 if ((onyx->
codec.connected & 3) == 3)
973 if ((onyx->
codec.connected & 3) == 2) {
984 onyx->
codec.soundbus_dev->detach_codec(onyx->
codec.soundbus_dev, onyx);
989 static void onyx_exit_codec(
struct aoa_codec *codec)
993 if (!onyx->
codec.soundbus_dev) {
997 onyx->
codec.soundbus_dev->detach_codec(onyx->
codec.soundbus_dev, onyx);
1007 onyx = kzalloc(
sizeof(
struct onyx),
GFP_KERNEL);
1014 i2c_set_clientdata(client, onyx);
1018 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
1025 onyx->
codec.init = onyx_init_codec;
1026 onyx->
codec.exit = onyx_exit_codec;
1027 onyx->
codec.node = of_node_get(node);
1039 static int onyx_i2c_remove(
struct i2c_client *client)
1041 struct onyx *onyx = i2c_get_clientdata(client);
1044 of_node_put(onyx->
codec.node);
1051 {
"MAC,pcm3052", 0 },
1058 .name =
"aoa_codec_onyx",
1061 .probe = onyx_i2c_probe,
1062 .remove = onyx_i2c_remove,
1063 .id_table = onyx_i2c_id,