// SPDX-License-Identifier: GPL-2.0 // // ak4613.c -- Asahi Kasei ALSA Soc Audio driver // // Copyright (C) 2015 Renesas Electronics Corporation // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> // // Based on ak4642.c by Kuninori Morimoto // Based on wm8731.c by Richard Purdie // Based on ak4535.c by Richard Purdie // Based on wm8753.c by Liam Girdwood
/* * +-------+ * |AK4613 | * SDTO1 <-| | * | | * SDTI1 ->| | * SDTI2 ->| | * SDTI3 ->| | * +-------+ * * +---+ * clk | |___________________________________________... * * [TDM512] * SDTO1 [L1][R1][L2][R2] * SDTI1 [L1][R1][L2][R2][L3][R3][L4][R4][L5][R5][L6][R6] * * [TDM256] * SDTO1 [L1][R1][L2][R2] * SDTI1 [L1][R1][L2][R2][L3][R3][L4][R4] * SDTI2 [L5][R5][L6][R6] * * [TDM128] * SDTO1 [L1][R1][L2][R2] * SDTI1 [L1][R1][L2][R2] * SDTI2 [L3][R3][L4][R4] * SDTI3 [L5][R5][L6][R6] * * [STEREO] * Playback 2ch : SDTI1 * Capture 2ch : SDTO1 * * [TDM512] * Playback 12ch : SDTI1 * Capture 4ch : SDTO1 * * [TDM256] * Playback 12ch : SDTI1 + SDTI2 * Playback 8ch : SDTI1 * Capture 4ch : SDTO1 * * [TDM128] * Playback 12ch : SDTI1 + SDTI2 + SDTI3 * Playback 8ch : SDTI1 + SDTI2 * Playback 4ch : SDTI1 * Capture 4ch : SDTO1 * * * !!! NOTE !!! * * Renesas is the only user of ak4613 on upstream so far, * but the chip connection is like below. * Thus, Renesas can't test all connection case. * Tested TDM is very limited. * * +-----+ +-----------+ * | SoC | | AK4613 | * | |<-----|SDTO1 IN1|<-- Mic * | | | IN2| * | | | | * | |----->|SDTI1 OUT1|--> Headphone * +-----+ |SDTI2 OUT2| * |SDTI3 OUT3| * | OUT4| * | OUT5| * | OUT6| * +-----------+ * * Renesas SoC can handle [2, 6,8] channels. * Ak4613 can handle [2,4, 8,12] channels. * * Because of above HW connection and available channels number, * Renesas could test are ... * * [STEREO] Playback 2ch : SDTI1 * Capture 2ch : SDTO1 * [TDM256] Playback 8ch : SDTI1 (*) * * (*) it used 8ch data between SoC <-> AK4613 on TDM256 mode, * but could confirm is only first 2ch because only 1 * Headphone is connected. * * see * AK4613_ENABLE_TDM_TEST
*/ #include <linux/clk.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/of.h> #include <linux/of_graph.h> #include <linux/module.h> #include <linux/regmap.h> #include <sound/soc.h> #include <sound/pcm_params.h> #include <sound/tlv.h>
#define PW_MGMT1 0x00 /* Power Management 1 */ #define PW_MGMT2 0x01 /* Power Management 2 */ #define PW_MGMT3 0x02 /* Power Management 3 */ #define CTRL1 0x03 /* Control 1 */ #define CTRL2 0x04 /* Control 2 */ #define DEMP1 0x05 /* De-emphasis1 */ #define DEMP2 0x06 /* De-emphasis2 */ #define OFD 0x07 /* Overflow Detect */ #define ZRD 0x08 /* Zero Detect */ #define ICTRL 0x09 /* Input Control */ #define OCTRL 0x0a /* Output Control */ #define LOUT1 0x0b /* LOUT1 Volume Control */ #define ROUT1 0x0c /* ROUT1 Volume Control */ #define LOUT2 0x0d /* LOUT2 Volume Control */ #define ROUT2 0x0e /* ROUT2 Volume Control */ #define LOUT3 0x0f /* LOUT3 Volume Control */ #define ROUT3 0x10 /* ROUT3 Volume Control */ #define LOUT4 0x11 /* LOUT4 Volume Control */ #define ROUT4 0x12 /* ROUT4 Volume Control */ #define LOUT5 0x13 /* LOUT5 Volume Control */ #define ROUT5 0x14 /* ROUT5 Volume Control */ #define LOUT6 0x15 /* LOUT6 Volume Control */ #define ROUT6 0x16 /* ROUT6 Volume Control */
/* * AK4613_CONFIG_SDTI_x * * It indicates how many SDTIx is connected.
*/ #define AK4613_CONFIG_SDTI_MASK (0xF << 4) #define AK4613_CONFIG_SDTI(x) (((x) & 0xF) << 4) #define AK4613_CONFIG_SDTI_set(priv, x) AK4613_CONFIG_SET(priv, SDTI(x)) #define AK4613_CONFIG_SDTI_get(priv) ((AK4613_CONFIG_GET(priv, SDTI) >> 4) & 0xF)
/* * AK4613_CONFIG_MODE_x * * Same as Ctrl1 :: TDM1/TDM0 * No shift is requested * see * AK4613_CTRL1_TO_MODE() * Table 11/12/13/14
*/ #define AK4613_CONFIG_MODE_MASK (0xF) #define AK4613_CONFIG_MODE_STEREO (0x0) #define AK4613_CONFIG_MODE_TDM512 (0x1) #define AK4613_CONFIG_MODE_TDM256 (0x2) #define AK4613_CONFIG_MODE_TDM128 (0x3)
/* * !!!! FIXME !!!! * * Because of testable HW limitation, TDM256 8ch TDM was only tested. * This driver uses AK4613_ENABLE_TDM_TEST instead of new DT property so far. * Don't hesitate to update driver, you don't need to care compatible * with Renesas. * * #define AK4613_ENABLE_TDM_TEST
*/
sdti_num = AK4613_CONFIG_SDTI_get(priv); if (WARN_ON(sdti_num >= SDTx_MAX)) return;
if (priv->cnt) { /* * If it was already working, * the constraint is same as working mode.
*/
mode = AK4613_CTRL1_TO_MODE(priv);
mask = 0; /* no default */
} else { /* * It is not yet working, * the constraint is based on board configs. * STEREO mask is default
*/
mode = AK4613_CONFIG_GET(priv, MODE);
mask = mask_list[AK4613_CONFIG_MODE_STEREO][is_play * sdti_num];
}
rate = params_rate(params); switch (rate) { case 32000: case 44100: case 48000:
ctrl2 = DFS_NORMAL_SPEED; break; case 64000: case 88200: case 96000:
ctrl2 = DFS_DOUBLE_SPEED; break; case 176400: case 192000:
ctrl2 = DFS_QUAD_SPEED; break; default: return -EINVAL;
}
priv->rate = rate;
/* * FIXME * * It doesn't have full TDM suppert yet
*/
ret = -EINVAL;
mutex_lock(&priv->lock); if (priv->cnt > 1) { /* * If it was already working, use current priv->ctrl1
*/
ret = 0;
} else { /* * It is not yet working,
*/ unsignedint channel = params_channels(params);
u8 tdm;
/* STEREO or TDM */ if (channel == 2)
tdm = AK4613_CONFIG_MODE_STEREO; else
tdm = AK4613_CONFIG_GET(priv, MODE);
for (i = ARRAY_SIZE(ak4613_iface) - 1; i >= 0; i--) { conststruct ak4613_interface *iface = ak4613_iface + i;
/* * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks * * Note * * To avoid extra delay, we want to avoid preemption here, * but we can't. Because it uses I2C access which is using IRQ * and sleep. Thus, delay might be more than 5 LR clocks * see also * ak4613_dai_trigger()
*/
udelay(5000000 / priv->rate);
/* * FIXME * * PW_MGMT1 / PW_MGMT3 needs dummy write at least after 5 LR clocks * from Power Down Release. Otherwise, Playback volume will be 0dB. * To avoid complex multiple delay/dummy_write method from * ak4613_set_bias_level() / SND_SOC_DAPM_DAC_E("DACx", ...), * call it once here. * * But, unfortunately, we can't "write" here because here is atomic * context (It uses I2C access for writing). * Thus, use schedule_work() to switching to normal context * immediately. * * Note * * Calling ak4613_dummy_write() function might be delayed. * In such case, ak4613 volume might be temporarily 0dB when * beggining of playback. * see also * ak4613_dummy_write()
*/
if ((cmd != SNDRV_PCM_TRIGGER_START) &&
(cmd != SNDRV_PCM_TRIGGER_RESUME)) return 0;
if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) return 0;
staticvoid ak4613_parse_of(struct ak4613_priv *priv, struct device *dev)
{ struct device_node *np = dev->of_node; char prop[32]; int sdti_num; int i;
/* Input 1 - 2 */ for (i = 0; i < 2; i++) {
snprintf(prop, sizeof(prop), "asahi-kasei,in%d-single-end", i + 1); if (!of_property_read_bool(np, prop))
priv->ic |= 1 << i;
}
/* Output 1 - 6 */ for (i = 0; i < 6; i++) {
snprintf(prop, sizeof(prop), "asahi-kasei,out%d-single-end", i + 1); if (!of_property_read_bool(np, prop))
priv->oc |= 1 << i;
}
/* * enable TDM256 test * * !!! FIXME !!! * * It should be configured by DT or other way * if it was full supported. * But it is using ifdef style for now for test * purpose.
*/ #ifdefined(AK4613_ENABLE_TDM_TEST)
AK4613_CONFIG_SET(priv, MODE_TDM256); #endif
/* * connected STDI * TDM support is assuming it is probed via Audio-Graph-Card style here. * Default is SDTIx1 if it was probed via Simple-Audio-Card for now.
*/
sdti_num = of_graph_get_endpoint_count(np); if ((sdti_num >= SDTx_MAX) || (sdti_num < 1))
sdti_num = 1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.