18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * i2sbus driver -- interface register definitions
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#ifndef __I2SBUS_INTERFACE_H
88c2ecf20Sopenharmony_ci#define __I2SBUS_INTERFACE_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/* i2s bus control registers, at least what we know about them */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#define __PAD(m,n) u8 __pad##m[n]
138c2ecf20Sopenharmony_ci#define _PAD(line, n) __PAD(line, n)
148c2ecf20Sopenharmony_ci#define PAD(n) _PAD(__LINE__, (n))
158c2ecf20Sopenharmony_cistruct i2s_interface_regs {
168c2ecf20Sopenharmony_ci	__le32 intr_ctl;	/* 0x00 */
178c2ecf20Sopenharmony_ci	PAD(12);
188c2ecf20Sopenharmony_ci	__le32 serial_format;	/* 0x10 */
198c2ecf20Sopenharmony_ci	PAD(12);
208c2ecf20Sopenharmony_ci	__le32 codec_msg_out;	/* 0x20 */
218c2ecf20Sopenharmony_ci	PAD(12);
228c2ecf20Sopenharmony_ci	__le32 codec_msg_in;	/* 0x30 */
238c2ecf20Sopenharmony_ci	PAD(12);
248c2ecf20Sopenharmony_ci	__le32 frame_count;	/* 0x40 */
258c2ecf20Sopenharmony_ci	PAD(12);
268c2ecf20Sopenharmony_ci	__le32 frame_match;	/* 0x50 */
278c2ecf20Sopenharmony_ci	PAD(12);
288c2ecf20Sopenharmony_ci	__le32 data_word_sizes;	/* 0x60 */
298c2ecf20Sopenharmony_ci	PAD(12);
308c2ecf20Sopenharmony_ci	__le32 peak_level_sel;	/* 0x70 */
318c2ecf20Sopenharmony_ci	PAD(12);
328c2ecf20Sopenharmony_ci	__le32 peak_level_in0;	/* 0x80 */
338c2ecf20Sopenharmony_ci	PAD(12);
348c2ecf20Sopenharmony_ci	__le32 peak_level_in1;	/* 0x90 */
358c2ecf20Sopenharmony_ci	PAD(12);
368c2ecf20Sopenharmony_ci	/* total size: 0x100 bytes */
378c2ecf20Sopenharmony_ci}  __attribute__((__packed__));
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* interrupt register is just a bitfield with
408c2ecf20Sopenharmony_ci * interrupt enable and pending bits */
418c2ecf20Sopenharmony_ci#define I2S_REG_INTR_CTL		0x00
428c2ecf20Sopenharmony_ci#	define I2S_INT_FRAME_COUNT		(1<<31)
438c2ecf20Sopenharmony_ci#	define I2S_PENDING_FRAME_COUNT		(1<<30)
448c2ecf20Sopenharmony_ci#	define I2S_INT_MESSAGE_FLAG		(1<<29)
458c2ecf20Sopenharmony_ci#	define I2S_PENDING_MESSAGE_FLAG		(1<<28)
468c2ecf20Sopenharmony_ci#	define I2S_INT_NEW_PEAK			(1<<27)
478c2ecf20Sopenharmony_ci#	define I2S_PENDING_NEW_PEAK		(1<<26)
488c2ecf20Sopenharmony_ci#	define I2S_INT_CLOCKS_STOPPED		(1<<25)
498c2ecf20Sopenharmony_ci#	define I2S_PENDING_CLOCKS_STOPPED	(1<<24)
508c2ecf20Sopenharmony_ci#	define I2S_INT_EXTERNAL_SYNC_ERROR	(1<<23)
518c2ecf20Sopenharmony_ci#	define I2S_PENDING_EXTERNAL_SYNC_ERROR	(1<<22)
528c2ecf20Sopenharmony_ci#	define I2S_INT_EXTERNAL_SYNC_OK		(1<<21)
538c2ecf20Sopenharmony_ci#	define I2S_PENDING_EXTERNAL_SYNC_OK	(1<<20)
548c2ecf20Sopenharmony_ci#	define I2S_INT_NEW_SAMPLE_RATE		(1<<19)
558c2ecf20Sopenharmony_ci#	define I2S_PENDING_NEW_SAMPLE_RATE	(1<<18)
568c2ecf20Sopenharmony_ci#	define I2S_INT_STATUS_FLAG		(1<<17)
578c2ecf20Sopenharmony_ci#	define I2S_PENDING_STATUS_FLAG		(1<<16)
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/* serial format register is more interesting :)
608c2ecf20Sopenharmony_ci * It contains:
618c2ecf20Sopenharmony_ci *  - clock source
628c2ecf20Sopenharmony_ci *  - MClk divisor
638c2ecf20Sopenharmony_ci *  - SClk divisor
648c2ecf20Sopenharmony_ci *  - SClk master flag
658c2ecf20Sopenharmony_ci *  - serial format (sony, i2s 64x, i2s 32x, dav, silabs)
668c2ecf20Sopenharmony_ci *  - external sample frequency interrupt (don't understand)
678c2ecf20Sopenharmony_ci *  - external sample frequency
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_ci#define I2S_REG_SERIAL_FORMAT		0x10
708c2ecf20Sopenharmony_ci/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */
718c2ecf20Sopenharmony_ci#	define I2S_SF_CLOCK_SOURCE_SHIFT	30
728c2ecf20Sopenharmony_ci#	define I2S_SF_CLOCK_SOURCE_MASK		(3<<I2S_SF_CLOCK_SOURCE_SHIFT)
738c2ecf20Sopenharmony_ci#	define I2S_SF_CLOCK_SOURCE_18MHz	(0<<I2S_SF_CLOCK_SOURCE_SHIFT)
748c2ecf20Sopenharmony_ci#	define I2S_SF_CLOCK_SOURCE_45MHz	(1<<I2S_SF_CLOCK_SOURCE_SHIFT)
758c2ecf20Sopenharmony_ci#	define I2S_SF_CLOCK_SOURCE_49MHz	(2<<I2S_SF_CLOCK_SOURCE_SHIFT)
768c2ecf20Sopenharmony_ci/* also, let's define the exact clock speeds here, in Hz */
778c2ecf20Sopenharmony_ci#define I2S_CLOCK_SPEED_18MHz	18432000
788c2ecf20Sopenharmony_ci#define I2S_CLOCK_SPEED_45MHz	45158400
798c2ecf20Sopenharmony_ci#define I2S_CLOCK_SPEED_49MHz	49152000
808c2ecf20Sopenharmony_ci/* MClk is the clock that drives the codec, usually called its 'system clock'.
818c2ecf20Sopenharmony_ci * It is derived by taking only every 'divisor' tick of the clock.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_SHIFT		24
848c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_MASK		(0x1F<<I2S_SF_MCLKDIV_SHIFT)
858c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_1			(0x14<<I2S_SF_MCLKDIV_SHIFT)
868c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_3			(0x13<<I2S_SF_MCLKDIV_SHIFT)
878c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_5			(0x12<<I2S_SF_MCLKDIV_SHIFT)
888c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_14		(0x0E<<I2S_SF_MCLKDIV_SHIFT)
898c2ecf20Sopenharmony_ci#	define I2S_SF_MCLKDIV_OTHER(div)	(((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK)
908c2ecf20Sopenharmony_cistatic inline int i2s_sf_mclkdiv(int div, int *out)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	int d;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	switch(div) {
958c2ecf20Sopenharmony_ci	case 1: *out |= I2S_SF_MCLKDIV_1; return 0;
968c2ecf20Sopenharmony_ci	case 3: *out |= I2S_SF_MCLKDIV_3; return 0;
978c2ecf20Sopenharmony_ci	case 5: *out |= I2S_SF_MCLKDIV_5; return 0;
988c2ecf20Sopenharmony_ci	case 14: *out |= I2S_SF_MCLKDIV_14; return 0;
998c2ecf20Sopenharmony_ci	default:
1008c2ecf20Sopenharmony_ci		if (div%2) return -1;
1018c2ecf20Sopenharmony_ci		d = div/2-1;
1028c2ecf20Sopenharmony_ci		if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E)
1038c2ecf20Sopenharmony_ci			return -1;
1048c2ecf20Sopenharmony_ci		*out |= I2S_SF_MCLKDIV_OTHER(div);
1058c2ecf20Sopenharmony_ci		return 0;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci/* SClk is the clock that drives the i2s wire bus. Note that it is
1098c2ecf20Sopenharmony_ci * derived from the MClk above by taking only every 'divisor' tick
1108c2ecf20Sopenharmony_ci * of MClk.
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_ci#	define I2S_SF_SCLKDIV_SHIFT		20
1138c2ecf20Sopenharmony_ci#	define I2S_SF_SCLKDIV_MASK		(0xF<<I2S_SF_SCLKDIV_SHIFT)
1148c2ecf20Sopenharmony_ci#	define I2S_SF_SCLKDIV_1			(8<<I2S_SF_SCLKDIV_SHIFT)
1158c2ecf20Sopenharmony_ci#	define I2S_SF_SCLKDIV_3			(9<<I2S_SF_SCLKDIV_SHIFT)
1168c2ecf20Sopenharmony_ci#	define I2S_SF_SCLKDIV_OTHER(div)	(((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK)
1178c2ecf20Sopenharmony_cistatic inline int i2s_sf_sclkdiv(int div, int *out)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	int d;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	switch(div) {
1228c2ecf20Sopenharmony_ci	case 1: *out |= I2S_SF_SCLKDIV_1; return 0;
1238c2ecf20Sopenharmony_ci	case 3: *out |= I2S_SF_SCLKDIV_3; return 0;
1248c2ecf20Sopenharmony_ci	default:
1258c2ecf20Sopenharmony_ci		if (div%2) return -1;
1268c2ecf20Sopenharmony_ci		d = div/2-1;
1278c2ecf20Sopenharmony_ci		if (d == 8 || d == 9) return -1;
1288c2ecf20Sopenharmony_ci		*out |= I2S_SF_SCLKDIV_OTHER(div);
1298c2ecf20Sopenharmony_ci		return 0;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci#	define I2S_SF_SCLK_MASTER		(1<<19)
1338c2ecf20Sopenharmony_ci/* serial format is the way the data is put to the i2s wire bus */
1348c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_SHIFT	16
1358c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_MASK	(7<<I2S_SF_SERIAL_FORMAT_SHIFT)
1368c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_SONY	(0<<I2S_SF_SERIAL_FORMAT_SHIFT)
1378c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_I2S_64X	(1<<I2S_SF_SERIAL_FORMAT_SHIFT)
1388c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_I2S_32X	(2<<I2S_SF_SERIAL_FORMAT_SHIFT)
1398c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_I2S_DAV	(4<<I2S_SF_SERIAL_FORMAT_SHIFT)
1408c2ecf20Sopenharmony_ci#	define I2S_SF_SERIAL_FORMAT_I2S_SILABS	(5<<I2S_SF_SERIAL_FORMAT_SHIFT)
1418c2ecf20Sopenharmony_ci/* unknown */
1428c2ecf20Sopenharmony_ci#	define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT	12
1438c2ecf20Sopenharmony_ci#	define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK	(0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT)
1448c2ecf20Sopenharmony_ci/* probably gives external frequency? */
1458c2ecf20Sopenharmony_ci#	define I2S_SF_EXT_SAMPLE_FREQ_MASK	0xFFF
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci/* used to send codec messages, but how isn't clear */
1488c2ecf20Sopenharmony_ci#define I2S_REG_CODEC_MSG_OUT		0x20
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/* used to receive codec messages, but how isn't clear */
1518c2ecf20Sopenharmony_ci#define I2S_REG_CODEC_MSG_IN		0x30
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/* frame count reg isn't clear to me yet, but probably useful */
1548c2ecf20Sopenharmony_ci#define I2S_REG_FRAME_COUNT		0x40
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci/* program to some value, and get interrupt if frame count reaches it */
1578c2ecf20Sopenharmony_ci#define I2S_REG_FRAME_MATCH		0x50
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* this register describes how the bus transfers data */
1608c2ecf20Sopenharmony_ci#define I2S_REG_DATA_WORD_SIZES		0x60
1618c2ecf20Sopenharmony_ci/* number of interleaved input channels */
1628c2ecf20Sopenharmony_ci#	define I2S_DWS_NUM_CHANNELS_IN_SHIFT	24
1638c2ecf20Sopenharmony_ci#	define I2S_DWS_NUM_CHANNELS_IN_MASK	(0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT)
1648c2ecf20Sopenharmony_ci/* word size of input data */
1658c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_IN_SIZE_SHIFT	16
1668c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_IN_16BIT		(0<<I2S_DWS_DATA_IN_SIZE_SHIFT)
1678c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_IN_24BIT		(3<<I2S_DWS_DATA_IN_SIZE_SHIFT)
1688c2ecf20Sopenharmony_ci/* number of interleaved output channels */
1698c2ecf20Sopenharmony_ci#	define I2S_DWS_NUM_CHANNELS_OUT_SHIFT	8
1708c2ecf20Sopenharmony_ci#	define I2S_DWS_NUM_CHANNELS_OUT_MASK	(0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT)
1718c2ecf20Sopenharmony_ci/* word size of output data */
1728c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_OUT_SIZE_SHIFT	0
1738c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_OUT_16BIT		(0<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
1748c2ecf20Sopenharmony_ci#	define I2S_DWS_DATA_OUT_24BIT		(3<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/* unknown */
1788c2ecf20Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_SEL		0x70
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/* unknown */
1818c2ecf20Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_IN0		0x80
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci/* unknown */
1848c2ecf20Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_IN1		0x90
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci#endif /* __I2SBUS_INTERFACE_H */
187