Linux Audio Driver 5: UDA1341 Chip Operating Interface

This paper is a learning note based on Linux version number of mini2440 development board linux-2.6.32.2

I. Hardware information of uda1341

The CPU controls uda1341 chips through L3 interface, which are:
L3DATA: Data Line
L3MODE: Mode control line, 0, address mode; 1, data mode
L3CLOCK: Clock Line

  • Address mode:
    data[7:2]: Represents the device address. The device address of UDA1341TS chip is 000101.
    data[1:0]: Represents the transport type

    00: Address register, volume, bass enhancement, treble, peak detection
    Extended Register Address, AGC Control, MIC Sensitivity Control, etc.
    01: Read back the peak information
    STATUS status information, reset, clock, data input format (data bit width), etc.

STATUS control, address: 00010110 = 0x16




Data 0 control: address: 00010100 = 0x14


Data 1 control, address: 00010101 = 0x15

Writing control function of uda1341

Write control functions defined as follows:

static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value)
  • Save value in cache[reg].
uda134x_write_reg_cache(codec, reg, value);
  • Write the address based on the incoming reg value.
  • UDA134X_EA000 ~ UDA134X_EA111 belongs to extended address and data[0:0]
    The sending address is: (5 << 2) | 0). When sending the address, the L3MODE pin is pulled down and the address mode is set.
    Send extended addresses. There are up to eight extended addresses, but the maximum two-digit extended addresses are 1, so the address should be the same as the previous 0xc0.
#define UDA134X_EXTADDR_PREFIX	0xC0
addr =  (reg | UDA134X_EXTADDR_PREFIX);
ret = l3_write(&pd->l3, UDA134X_DATA0_ADDR, &addr, 1);

Send extended data, the top three of extended data are 1, so add 0xe0 to the original value.

#define UDA134X_EXTDATA_PREFIX	0xE0
data = (value | UDA134X_EXTDATA_PREFIX);
ret = l3_write(&pd->l3, addr, &data, 1);

Sending extended address and sending extended data are actually sending data. L3MODE pin should be raised to select data mode.

  • UDA134X_STATUS 0 and UDA134X_STATUS1 belong to data[1:0]
    The sending address is: (5 << 2) | 2)
    Send data:
#define UDA134X_STATUS_ADDR	((UDA134X_L3ADDR << 2) | 2)
addr = UDA134X_STATUS_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
  • UDA134X_DATA000, UDA134X_DATA001, UDA134X_DATA010 belong to data[0:0]
    The sending address is: (5 << 2) | 0)
    Send data:
#define UDA134X_L3ADDR	5
#define UDA134X_DATA0_ADDR	((UDA134X_L3ADDR << 2) | 0)
addr = UDA134X_DATA0_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
  • UDA134X_DATA1 belongs to data[0:1]
    The sending address is: (5 << 2) | 1)
    Send data:
#define UDA134X_L3ADDR	5
#define UDA134X_DATA1_ADDR	((UDA134X_L3ADDR << 2) | 1)
addr = UDA134X_DATA1_ADDR;
ret = l3_write(&pd->l3, addr, &data, 1);
IV. Reset operation of uda1341

Send Address: (5 << 2) | 2)
Send data: value | (1 6)

V. Mute operation of uda1341

Send Address: (5 << 2) | 0)
Send data: value | (1 and 2)

6. Clock settings for uda1341

1. Setting System Clock
uda1341 supports three system clocks, 512fs, 384fs, 256fs
2. The sampling rates supported by uda1341 are 8000, 11025, 16000, 22050, 32000, 44100, 48000.
3. The range of system clock is 256 * 8000 <= freq <= 512 * 48000.

2. Setting the clock call function uda134x_set_dai_sysclk

static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct uda134x_priv *uda134x = codec->private_data;

	pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
		 clk_id, freq, dir);

	/* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
	   because the codec is slave. Of course limitations of the clock
	   master (the IIS controller) apply.
	   We'll error out on set_hw_params if it's not OK */
	if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
		uda134x->sysclk = freq;
		return 0;
	}

	printk(KERN_ERR "%s unsupported sysclk\n", __func__);
	return -EINVAL;
}

Here the system clock is not really set down, but saved to uda134x - > sysclk variable, leaving behind the settings.

Setting up Support Data Format

1.uda1341 supports the following formats:

(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
  1. The function called to set the data format is uda134x_set_dai_fmt
static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct uda134x_priv *uda134x = codec->private_data;

	pr_debug("%s fmt: %08X\n", __func__, fmt);

	/* codec supports only full slave mode */
	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
		printk(KERN_ERR "%s unsupported slave mode\n", __func__);
		return -EINVAL;
	}

	/* no support for clock inversion */
	if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
		printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
		return -EINVAL;
	}

	/* We can't setup DAI format here as it depends on the word bit num */
	/* so let's just store the value for later */
	uda134x->dai_fmt = fmt;

	return 0;
}
8. uda1341 setting bias (guess power supply) level

SND_SOC_BIAS_ON Level:
Open ADC, DAC
Send Address: (5 << 2) | 2)
Send data: 0x83

SND_SOC_BIAS_PREPARE level:

pd->power(1);
for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
    codec->write(codec, i, *cache++);

SND_SOC_BIAS_STANDBY:
Send Address: (5 << 2) | 2)
Send data: value & ~ (0x03)

SND_SOC_BIAS_OFF:

pd->power(0);
9. Setting Hardware Parameters

The function to set the hardware parameters is uda134x_hw_params

  • Setting the divisor of the system clock of the chip, 512, 384, 256
switch (uda134x->sysclk / params_rate(params)) 
{
	case 512:
		break;
	case 384:
		hw_params |= (1<<4);
		break;
	case 256:
		hw_params |= (1<<5);
		break;
	default:
		printk(KERN_ERR "%s unsupported fs\n", __func__);
		return -EINVAL;
}


Send data: 384fs (vaule | (1 < < 4)) 256fs (value | 1 < < 5)

  • Setting up data mode
switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) 
{
	case SND_SOC_DAIFMT_I2S:
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		switch (params_format(params)) {
		case SNDRV_PCM_FORMAT_S16_LE:
			hw_params |= (1<<1);
			break;
		case SNDRV_PCM_FORMAT_S18_3LE:
			hw_params |= (1<<2);
			break;
		case SNDRV_PCM_FORMAT_S20_3LE:
			hw_params |= ((1<<2) | (1<<1));
			break;
		default:
			printk(KERN_ERR "%s unsupported format (right)\n",
			       __func__);
			return -EINVAL;
		}
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		hw_params |= (1<<3);
		break;
	default:
		printk(KERN_ERR "%s unsupported format\n", __func__);
		return -EINVAL;
}

SND_SOC_DAIFMT_I2S: 0
SND_SOC_DAIFMT_RIGHT_J and SND_SOC_DAIFMT_LEFT_J mode reference figure below

X. Linux UDA1341 Chip Interface Registration
static struct snd_soc_dai_ops uda134x_dai_ops = {
	.startup	= uda134x_startup,
	.shutdown	= uda134x_shutdown,
	.hw_params	= uda134x_hw_params,
	.digital_mute	= uda134x_mute,
	.set_sysclk	= uda134x_set_dai_sysclk,
	.set_fmt	= uda134x_set_dai_fmt,
};
struct snd_soc_dai uda134x_dai = {
	.name = "UDA134X",
	/* playback capabilities */
	.playback = {
		.stream_name = "Playback",
		.channels_min = 1,
		.channels_max = 2,
		.rates = UDA134X_RATES,
		.formats = UDA134X_FORMATS,
	},
	/* capture capabilities */
	.capture = {
		.stream_name = "Capture",
		.channels_min = 1,
		.channels_max = 2,
		.rates = UDA134X_RATES,
		.formats = UDA134X_FORMATS,
	},
	/* pcm operations */
	.ops = &uda134x_dai_ops,
};
  • Registration time: The uda134x_init function is called at startup. Register UDA1341 interface in uda134x_init function.
static int __init uda134x_init(void)
{
	return snd_soc_register_dai(&uda134x_dai);
}
module_init(uda134x_init);

Like the I2S interface registration, it is registered in a global list of dai_list s, where there are various Dai interfaces.

XI. SUMMARY
  • The uda134x_dai interface is registered when the kernel is up.
  • Uda134x_dai interface includes hardware settings such as clock and transmission mode for UDA1341 chip, and a hardware parameter operation set uda134x_dai_ops.

Reference Blog:
https://blog.csdn.net/gqb_driver/article/details/8551551

Keywords: codec Linux IIS

Added by bloo on Sun, 12 May 2019 10:19:52 +0300