Lines Matching +full:no +full:- +full:1 +full:- +full:8 +full:- +full:v
1 // SPDX-License-Identifier: GPL-2.0-only
13 * 1: digital output
16 * Note that even though I know of no machine that has for example
24 * But snd-aoa assumes that there's at most one card, so
37 MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
44 #define PFX "snd-aoa-codec-onyx: "
47 /* cache registers 65 to 80, they are write-only! */
51 u32 initialised:1,
52 spdif_locked:1,
53 analog_locked:1,
68 s32 v; in onyx_read_register() local
71 *value = onyx->cache[reg-FIRSTREGISTER]; in onyx_read_register()
74 v = i2c_smbus_read_byte_data(onyx->i2c, reg); in onyx_read_register()
75 if (v < 0) { in onyx_read_register()
77 return -1; in onyx_read_register()
79 *value = (u8)v; in onyx_read_register()
80 onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; in onyx_read_register()
88 result = i2c_smbus_write_byte_data(onyx->i2c, reg, value); in onyx_write_register()
90 onyx->cache[reg-FIRSTREGISTER] = value; in onyx_write_register()
112 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in onyx_snd_vol_info()
113 uinfo->count = 2; in onyx_snd_vol_info()
114 uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT; in onyx_snd_vol_info()
115 uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT; in onyx_snd_vol_info()
125 mutex_lock(&onyx->mutex); in onyx_snd_vol_get()
128 mutex_unlock(&onyx->mutex); in onyx_snd_vol_get()
130 ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; in onyx_snd_vol_get()
131 ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; in onyx_snd_vol_get()
142 if (ucontrol->value.integer.value[0] < -128 + VOLUME_RANGE_SHIFT || in onyx_snd_vol_put()
143 ucontrol->value.integer.value[0] > -1 + VOLUME_RANGE_SHIFT) in onyx_snd_vol_put()
144 return -EINVAL; in onyx_snd_vol_put()
145 if (ucontrol->value.integer.value[1] < -128 + VOLUME_RANGE_SHIFT || in onyx_snd_vol_put()
146 ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT) in onyx_snd_vol_put()
147 return -EINVAL; in onyx_snd_vol_put()
149 mutex_lock(&onyx->mutex); in onyx_snd_vol_put()
153 if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && in onyx_snd_vol_put()
154 r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { in onyx_snd_vol_put()
155 mutex_unlock(&onyx->mutex); in onyx_snd_vol_put()
160 ucontrol->value.integer.value[0] in onyx_snd_vol_put()
161 - VOLUME_RANGE_SHIFT); in onyx_snd_vol_put()
163 ucontrol->value.integer.value[1] in onyx_snd_vol_put()
164 - VOLUME_RANGE_SHIFT); in onyx_snd_vol_put()
165 mutex_unlock(&onyx->mutex); in onyx_snd_vol_put()
167 return 1; in onyx_snd_vol_put()
183 #define INPUTGAIN_RANGE_SHIFT (-3)
188 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in onyx_snd_inputgain_info()
189 uinfo->count = 1; in onyx_snd_inputgain_info()
190 uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT; in onyx_snd_inputgain_info()
191 uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT; in onyx_snd_inputgain_info()
201 mutex_lock(&onyx->mutex); in onyx_snd_inputgain_get()
203 mutex_unlock(&onyx->mutex); in onyx_snd_inputgain_get()
205 ucontrol->value.integer.value[0] = in onyx_snd_inputgain_get()
215 u8 v, n; in onyx_snd_inputgain_put() local
217 if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT || in onyx_snd_inputgain_put()
218 ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT) in onyx_snd_inputgain_put()
219 return -EINVAL; in onyx_snd_inputgain_put()
220 mutex_lock(&onyx->mutex); in onyx_snd_inputgain_put()
221 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); in onyx_snd_inputgain_put()
222 n = v; in onyx_snd_inputgain_put()
224 n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) in onyx_snd_inputgain_put()
227 mutex_unlock(&onyx->mutex); in onyx_snd_inputgain_put()
229 return n != v; in onyx_snd_inputgain_put()
244 static const char * const texts[] = { "Line-In", "Microphone" }; in onyx_snd_capture_source_info()
246 return snd_ctl_enum_info(uinfo, 1, 2, texts); in onyx_snd_capture_source_info()
253 s8 v; in onyx_snd_capture_source_get() local
255 mutex_lock(&onyx->mutex); in onyx_snd_capture_source_get()
256 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); in onyx_snd_capture_source_get()
257 mutex_unlock(&onyx->mutex); in onyx_snd_capture_source_get()
259 ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); in onyx_snd_capture_source_get()
266 s8 v; in onyx_set_capture_source() local
268 mutex_lock(&onyx->mutex); in onyx_set_capture_source()
269 onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); in onyx_set_capture_source()
270 v &= ~ONYX_ADC_INPUT_MIC; in onyx_set_capture_source()
272 v |= ONYX_ADC_INPUT_MIC; in onyx_set_capture_source()
273 onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); in onyx_set_capture_source()
274 mutex_unlock(&onyx->mutex); in onyx_set_capture_source()
280 if (ucontrol->value.enumerated.item[0] > 1) in onyx_snd_capture_source_put()
281 return -EINVAL; in onyx_snd_capture_source_put()
283 ucontrol->value.enumerated.item[0]); in onyx_snd_capture_source_put()
284 return 1; in onyx_snd_capture_source_put()
315 mutex_lock(&onyx->mutex); in onyx_snd_mute_get()
317 mutex_unlock(&onyx->mutex); in onyx_snd_mute_get()
319 ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); in onyx_snd_mute_get()
320 ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); in onyx_snd_mute_get()
329 u8 v = 0, c = 0; in onyx_snd_mute_put() local
330 int err = -EBUSY; in onyx_snd_mute_put()
332 mutex_lock(&onyx->mutex); in onyx_snd_mute_put()
333 if (onyx->analog_locked) in onyx_snd_mute_put()
336 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); in onyx_snd_mute_put()
337 c = v; in onyx_snd_mute_put()
339 if (!ucontrol->value.integer.value[0]) in onyx_snd_mute_put()
341 if (!ucontrol->value.integer.value[1]) in onyx_snd_mute_put()
346 mutex_unlock(&onyx->mutex); in onyx_snd_mute_put()
348 return !err ? (v != c) : err; in onyx_snd_mute_put()
363 #define FLAG_POLARITY_INVERT 1
371 long int pv = kcontrol->private_value; in onyx_snd_single_bit_get()
373 u8 address = (pv >> 8) & 0xff; in onyx_snd_single_bit_get()
376 mutex_lock(&onyx->mutex); in onyx_snd_single_bit_get()
378 mutex_unlock(&onyx->mutex); in onyx_snd_single_bit_get()
380 ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; in onyx_snd_single_bit_get()
389 u8 v = 0, c = 0; in onyx_snd_single_bit_put() local
391 long int pv = kcontrol->private_value; in onyx_snd_single_bit_put()
394 u8 address = (pv >> 8) & 0xff; in onyx_snd_single_bit_put()
397 mutex_lock(&onyx->mutex); in onyx_snd_single_bit_put()
398 if (spdiflock && onyx->spdif_locked) { in onyx_snd_single_bit_put()
400 err = -EBUSY; in onyx_snd_single_bit_put()
403 onyx_read_register(onyx, address, &v); in onyx_snd_single_bit_put()
404 c = v; in onyx_snd_single_bit_put()
406 if (!!ucontrol->value.integer.value[0] ^ polarity) in onyx_snd_single_bit_put()
411 mutex_unlock(&onyx->mutex); in onyx_snd_single_bit_put()
413 return !err ? (v != c) : err; in onyx_snd_single_bit_put()
424 .private_value = (flags << 16) | (address << 8) | mask \
453 "Digital De-Emphasis",
461 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in onyx_spdif_info()
462 uinfo->count = 1; in onyx_spdif_info()
470 ucontrol->value.iec958.status[0] = 0x3e; in onyx_spdif_mask_get()
471 ucontrol->value.iec958.status[1] = 0xff; in onyx_spdif_mask_get()
473 ucontrol->value.iec958.status[3] = 0x3f; in onyx_spdif_mask_get()
474 ucontrol->value.iec958.status[4] = 0x0f; in onyx_spdif_mask_get()
491 u8 v; in onyx_spdif_get() local
493 mutex_lock(&onyx->mutex); in onyx_spdif_get()
494 onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); in onyx_spdif_get()
495 ucontrol->value.iec958.status[0] = v & 0x3e; in onyx_spdif_get()
497 onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v); in onyx_spdif_get()
498 ucontrol->value.iec958.status[1] = v; in onyx_spdif_get()
500 onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); in onyx_spdif_get()
501 ucontrol->value.iec958.status[3] = v & 0x3f; in onyx_spdif_get()
503 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); in onyx_spdif_get()
504 ucontrol->value.iec958.status[4] = v & 0x0f; in onyx_spdif_get()
505 mutex_unlock(&onyx->mutex); in onyx_spdif_get()
514 u8 v; in onyx_spdif_put() local
516 mutex_lock(&onyx->mutex); in onyx_spdif_put()
517 onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); in onyx_spdif_put()
518 v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); in onyx_spdif_put()
519 onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); in onyx_spdif_put()
521 v = ucontrol->value.iec958.status[1]; in onyx_spdif_put()
522 onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v); in onyx_spdif_put()
524 onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); in onyx_spdif_put()
525 v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f); in onyx_spdif_put()
526 onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v); in onyx_spdif_put()
528 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); in onyx_spdif_put()
529 v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); in onyx_spdif_put()
530 onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); in onyx_spdif_put()
531 mutex_unlock(&onyx->mutex); in onyx_spdif_put()
533 return 1; in onyx_spdif_put()
567 0, /* no deemphasis */
570 (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
572 (1<<2), /* pcm audio */
575 1 /* 24 bit depth */
585 if (!onyx->initialised) { in onyx_register_init()
588 return -1; in onyx_register_init()
594 regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER]; in onyx_register_init()
599 return -1; in onyx_register_init()
601 onyx->initialised = 1; in onyx_register_init()
606 /* this is first so we can skip it if no input is present...
607 * No hardware exists with that, but it's here as an example
615 .transfer_in = 1,
640 .tag = 1,
672 u8 v; in onyx_usable() local
673 struct onyx *onyx = cii->codec_data; in onyx_usable()
676 mutex_lock(&onyx->mutex); in onyx_usable()
677 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); in onyx_usable()
678 spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); in onyx_usable()
679 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); in onyx_usable()
681 (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) in onyx_usable()
683 mutex_unlock(&onyx->mutex); in onyx_usable()
685 switch (ti->tag) { in onyx_usable()
686 case 0: return 1; in onyx_usable()
687 case 1: return analog_enabled; in onyx_usable()
690 return 1; in onyx_usable()
697 u8 v; in onyx_prepare() local
698 struct onyx *onyx = cii->codec_data; in onyx_prepare()
699 int err = -EBUSY; in onyx_prepare()
701 mutex_lock(&onyx->mutex); in onyx_prepare()
704 if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { in onyx_prepare()
706 onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); in onyx_prepare()
709 v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) in onyx_prepare()
711 onyx->analog_locked = 1; in onyx_prepare()
716 switch (substream->runtime->rate) { in onyx_prepare()
728 onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v); in onyx_prepare()
731 v & ~ONYX_SPDIF_ENABLE)) in onyx_prepare()
733 onyx->spdif_locked = 1; in onyx_prepare()
739 mutex_unlock(&onyx->mutex); in onyx_prepare()
747 struct onyx *onyx = cii->codec_data; in onyx_open()
749 mutex_lock(&onyx->mutex); in onyx_open()
750 onyx->open_count++; in onyx_open()
751 mutex_unlock(&onyx->mutex); in onyx_open()
759 struct onyx *onyx = cii->codec_data; in onyx_close()
761 mutex_lock(&onyx->mutex); in onyx_close()
762 onyx->open_count--; in onyx_close()
763 if (!onyx->open_count) in onyx_close()
764 onyx->spdif_locked = onyx->analog_locked = 0; in onyx_close()
765 mutex_unlock(&onyx->mutex); in onyx_close()
773 struct onyx *onyx = cii->codec_data; in onyx_switch_clock()
775 mutex_lock(&onyx->mutex); in onyx_switch_clock()
779 onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio); in onyx_switch_clock()
782 onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio); in onyx_switch_clock()
787 mutex_unlock(&onyx->mutex); in onyx_switch_clock()
796 struct onyx *onyx = cii->codec_data; in onyx_suspend()
797 u8 v; in onyx_suspend() local
798 int err = -ENXIO; in onyx_suspend()
800 mutex_lock(&onyx->mutex); in onyx_suspend()
801 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) in onyx_suspend()
803 onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); in onyx_suspend()
807 mutex_unlock(&onyx->mutex); in onyx_suspend()
814 struct onyx *onyx = cii->codec_data; in onyx_resume()
815 u8 v; in onyx_resume() local
816 int err = -ENXIO; in onyx_resume()
818 mutex_lock(&onyx->mutex); in onyx_resume()
821 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); in onyx_resume()
822 msleep(1); in onyx_resume()
823 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); in onyx_resume()
824 msleep(1); in onyx_resume()
825 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); in onyx_resume()
826 msleep(1); in onyx_resume()
829 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) in onyx_resume()
831 onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); in onyx_resume()
832 /* FIXME: should divide by sample rate, but 8k is the lowest we go */ in onyx_resume()
838 mutex_unlock(&onyx->mutex); in onyx_resume()
866 u8 v; in onyx_init_codec() local
869 if (!onyx->codec.gpio || !onyx->codec.gpio->methods) { in onyx_init_codec()
871 return -EINVAL; in onyx_init_codec()
874 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); in onyx_init_codec()
875 msleep(1); in onyx_init_codec()
876 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); in onyx_init_codec()
877 msleep(1); in onyx_init_codec()
878 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); in onyx_init_codec()
879 msleep(1); in onyx_init_codec()
883 return -ENODEV; in onyx_init_codec()
888 return -ENODEV; in onyx_init_codec()
892 if ((onyx->codec.connected & 0xF) == 0) in onyx_init_codec()
893 return -ENOTCONN; in onyx_init_codec()
895 /* if no inputs are present... */ in onyx_init_codec()
896 if ((onyx->codec.connected & 0xC) == 0) { in onyx_init_codec()
897 if (!onyx->codec_info) in onyx_init_codec()
898 onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); in onyx_init_codec()
899 if (!onyx->codec_info) in onyx_init_codec()
900 return -ENOMEM; in onyx_init_codec()
901 ci = onyx->codec_info; in onyx_init_codec()
903 ci->transfers++; in onyx_init_codec()
906 /* if no outputs are present... */ in onyx_init_codec()
907 if ((onyx->codec.connected & 3) == 0) { in onyx_init_codec()
908 if (!onyx->codec_info) in onyx_init_codec()
909 onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); in onyx_init_codec()
910 if (!onyx->codec_info) in onyx_init_codec()
911 return -ENOMEM; in onyx_init_codec()
912 ci = onyx->codec_info; in onyx_init_codec()
916 ci->transfers[1].formats = 0; in onyx_init_codec()
919 if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev, in onyx_init_codec()
923 return -ENODEV; in onyx_init_codec()
929 ctl->id.device = \ in onyx_init_codec()
930 onyx->codec.soundbus_dev->pcm->device; \ in onyx_init_codec()
937 if (onyx->codec.soundbus_dev->pcm) { in onyx_init_codec()
940 if ((onyx->codec.connected & 0xC) == 0xC) in onyx_init_codec()
942 else if (onyx->codec.connected & 4) in onyx_init_codec()
945 onyx_set_capture_source(onyx, 1); in onyx_init_codec()
946 if (onyx->codec.connected & 0xC) in onyx_init_codec()
951 if (onyx->codec.connected & 1) { in onyx_init_codec()
960 if (onyx->codec.connected & 2) { in onyx_init_codec()
964 if ((onyx->codec.connected & 3) == 3) in onyx_init_codec()
967 if ((onyx->codec.connected & 3) == 2) { in onyx_init_codec()
968 onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); in onyx_init_codec()
969 v |= ONYX_SPDIF_ENABLE; in onyx_init_codec()
970 onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); in onyx_init_codec()
978 onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); in onyx_init_codec()
987 if (!onyx->codec.soundbus_dev) { in onyx_exit_codec()
991 onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); in onyx_exit_codec()
996 struct device_node *node = client->dev.of_node; in onyx_i2c_probe()
1003 return -ENOMEM; in onyx_i2c_probe()
1005 mutex_init(&onyx->mutex); in onyx_i2c_probe()
1006 onyx->i2c = client; in onyx_i2c_probe()
1016 strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN); in onyx_i2c_probe()
1017 onyx->codec.owner = THIS_MODULE; in onyx_i2c_probe()
1018 onyx->codec.init = onyx_init_codec; in onyx_i2c_probe()
1019 onyx->codec.exit = onyx_exit_codec; in onyx_i2c_probe()
1020 onyx->codec.node = of_node_get(node); in onyx_i2c_probe()
1022 if (aoa_codec_register(&onyx->codec)) { in onyx_i2c_probe()
1029 return -ENODEV; in onyx_i2c_probe()
1036 aoa_codec_unregister(&onyx->codec); in onyx_i2c_remove()
1037 of_node_put(onyx->codec.node); in onyx_i2c_remove()
1038 kfree(onyx->codec_info); in onyx_i2c_remove()