162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * i2sbus driver -- interface register definitions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#ifndef __I2SBUS_INTERFACE_H 862306a36Sopenharmony_ci#define __I2SBUS_INTERFACE_H 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* i2s bus control registers, at least what we know about them */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define __PAD(m,n) u8 __pad##m[n] 1362306a36Sopenharmony_ci#define _PAD(line, n) __PAD(line, n) 1462306a36Sopenharmony_ci#define PAD(n) _PAD(__LINE__, (n)) 1562306a36Sopenharmony_cistruct i2s_interface_regs { 1662306a36Sopenharmony_ci __le32 intr_ctl; /* 0x00 */ 1762306a36Sopenharmony_ci PAD(12); 1862306a36Sopenharmony_ci __le32 serial_format; /* 0x10 */ 1962306a36Sopenharmony_ci PAD(12); 2062306a36Sopenharmony_ci __le32 codec_msg_out; /* 0x20 */ 2162306a36Sopenharmony_ci PAD(12); 2262306a36Sopenharmony_ci __le32 codec_msg_in; /* 0x30 */ 2362306a36Sopenharmony_ci PAD(12); 2462306a36Sopenharmony_ci __le32 frame_count; /* 0x40 */ 2562306a36Sopenharmony_ci PAD(12); 2662306a36Sopenharmony_ci __le32 frame_match; /* 0x50 */ 2762306a36Sopenharmony_ci PAD(12); 2862306a36Sopenharmony_ci __le32 data_word_sizes; /* 0x60 */ 2962306a36Sopenharmony_ci PAD(12); 3062306a36Sopenharmony_ci __le32 peak_level_sel; /* 0x70 */ 3162306a36Sopenharmony_ci PAD(12); 3262306a36Sopenharmony_ci __le32 peak_level_in0; /* 0x80 */ 3362306a36Sopenharmony_ci PAD(12); 3462306a36Sopenharmony_ci __le32 peak_level_in1; /* 0x90 */ 3562306a36Sopenharmony_ci PAD(12); 3662306a36Sopenharmony_ci /* total size: 0x100 bytes */ 3762306a36Sopenharmony_ci} __attribute__((__packed__)); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* interrupt register is just a bitfield with 4062306a36Sopenharmony_ci * interrupt enable and pending bits */ 4162306a36Sopenharmony_ci#define I2S_REG_INTR_CTL 0x00 4262306a36Sopenharmony_ci# define I2S_INT_FRAME_COUNT (1<<31) 4362306a36Sopenharmony_ci# define I2S_PENDING_FRAME_COUNT (1<<30) 4462306a36Sopenharmony_ci# define I2S_INT_MESSAGE_FLAG (1<<29) 4562306a36Sopenharmony_ci# define I2S_PENDING_MESSAGE_FLAG (1<<28) 4662306a36Sopenharmony_ci# define I2S_INT_NEW_PEAK (1<<27) 4762306a36Sopenharmony_ci# define I2S_PENDING_NEW_PEAK (1<<26) 4862306a36Sopenharmony_ci# define I2S_INT_CLOCKS_STOPPED (1<<25) 4962306a36Sopenharmony_ci# define I2S_PENDING_CLOCKS_STOPPED (1<<24) 5062306a36Sopenharmony_ci# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23) 5162306a36Sopenharmony_ci# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22) 5262306a36Sopenharmony_ci# define I2S_INT_EXTERNAL_SYNC_OK (1<<21) 5362306a36Sopenharmony_ci# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20) 5462306a36Sopenharmony_ci# define I2S_INT_NEW_SAMPLE_RATE (1<<19) 5562306a36Sopenharmony_ci# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18) 5662306a36Sopenharmony_ci# define I2S_INT_STATUS_FLAG (1<<17) 5762306a36Sopenharmony_ci# define I2S_PENDING_STATUS_FLAG (1<<16) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* serial format register is more interesting :) 6062306a36Sopenharmony_ci * It contains: 6162306a36Sopenharmony_ci * - clock source 6262306a36Sopenharmony_ci * - MClk divisor 6362306a36Sopenharmony_ci * - SClk divisor 6462306a36Sopenharmony_ci * - SClk master flag 6562306a36Sopenharmony_ci * - serial format (sony, i2s 64x, i2s 32x, dav, silabs) 6662306a36Sopenharmony_ci * - external sample frequency interrupt (don't understand) 6762306a36Sopenharmony_ci * - external sample frequency 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci#define I2S_REG_SERIAL_FORMAT 0x10 7062306a36Sopenharmony_ci/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */ 7162306a36Sopenharmony_ci# define I2S_SF_CLOCK_SOURCE_SHIFT 30 7262306a36Sopenharmony_ci# define I2S_SF_CLOCK_SOURCE_MASK (3<<I2S_SF_CLOCK_SOURCE_SHIFT) 7362306a36Sopenharmony_ci# define I2S_SF_CLOCK_SOURCE_18MHz (0<<I2S_SF_CLOCK_SOURCE_SHIFT) 7462306a36Sopenharmony_ci# define I2S_SF_CLOCK_SOURCE_45MHz (1<<I2S_SF_CLOCK_SOURCE_SHIFT) 7562306a36Sopenharmony_ci# define I2S_SF_CLOCK_SOURCE_49MHz (2<<I2S_SF_CLOCK_SOURCE_SHIFT) 7662306a36Sopenharmony_ci/* also, let's define the exact clock speeds here, in Hz */ 7762306a36Sopenharmony_ci#define I2S_CLOCK_SPEED_18MHz 18432000 7862306a36Sopenharmony_ci#define I2S_CLOCK_SPEED_45MHz 45158400 7962306a36Sopenharmony_ci#define I2S_CLOCK_SPEED_49MHz 49152000 8062306a36Sopenharmony_ci/* MClk is the clock that drives the codec, usually called its 'system clock'. 8162306a36Sopenharmony_ci * It is derived by taking only every 'divisor' tick of the clock. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_SHIFT 24 8462306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_MASK (0x1F<<I2S_SF_MCLKDIV_SHIFT) 8562306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_1 (0x14<<I2S_SF_MCLKDIV_SHIFT) 8662306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_3 (0x13<<I2S_SF_MCLKDIV_SHIFT) 8762306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_5 (0x12<<I2S_SF_MCLKDIV_SHIFT) 8862306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_14 (0x0E<<I2S_SF_MCLKDIV_SHIFT) 8962306a36Sopenharmony_ci# define I2S_SF_MCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK) 9062306a36Sopenharmony_cistatic inline int i2s_sf_mclkdiv(int div, int *out) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci int d; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci switch(div) { 9562306a36Sopenharmony_ci case 1: *out |= I2S_SF_MCLKDIV_1; return 0; 9662306a36Sopenharmony_ci case 3: *out |= I2S_SF_MCLKDIV_3; return 0; 9762306a36Sopenharmony_ci case 5: *out |= I2S_SF_MCLKDIV_5; return 0; 9862306a36Sopenharmony_ci case 14: *out |= I2S_SF_MCLKDIV_14; return 0; 9962306a36Sopenharmony_ci default: 10062306a36Sopenharmony_ci if (div%2) return -1; 10162306a36Sopenharmony_ci d = div/2-1; 10262306a36Sopenharmony_ci if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E) 10362306a36Sopenharmony_ci return -1; 10462306a36Sopenharmony_ci *out |= I2S_SF_MCLKDIV_OTHER(div); 10562306a36Sopenharmony_ci return 0; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci/* SClk is the clock that drives the i2s wire bus. Note that it is 10962306a36Sopenharmony_ci * derived from the MClk above by taking only every 'divisor' tick 11062306a36Sopenharmony_ci * of MClk. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_ci# define I2S_SF_SCLKDIV_SHIFT 20 11362306a36Sopenharmony_ci# define I2S_SF_SCLKDIV_MASK (0xF<<I2S_SF_SCLKDIV_SHIFT) 11462306a36Sopenharmony_ci# define I2S_SF_SCLKDIV_1 (8<<I2S_SF_SCLKDIV_SHIFT) 11562306a36Sopenharmony_ci# define I2S_SF_SCLKDIV_3 (9<<I2S_SF_SCLKDIV_SHIFT) 11662306a36Sopenharmony_ci# define I2S_SF_SCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK) 11762306a36Sopenharmony_cistatic inline int i2s_sf_sclkdiv(int div, int *out) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci int d; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci switch(div) { 12262306a36Sopenharmony_ci case 1: *out |= I2S_SF_SCLKDIV_1; return 0; 12362306a36Sopenharmony_ci case 3: *out |= I2S_SF_SCLKDIV_3; return 0; 12462306a36Sopenharmony_ci default: 12562306a36Sopenharmony_ci if (div%2) return -1; 12662306a36Sopenharmony_ci d = div/2-1; 12762306a36Sopenharmony_ci if (d == 8 || d == 9) return -1; 12862306a36Sopenharmony_ci *out |= I2S_SF_SCLKDIV_OTHER(div); 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci# define I2S_SF_SCLK_MASTER (1<<19) 13362306a36Sopenharmony_ci/* serial format is the way the data is put to the i2s wire bus */ 13462306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_SHIFT 16 13562306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_MASK (7<<I2S_SF_SERIAL_FORMAT_SHIFT) 13662306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_SONY (0<<I2S_SF_SERIAL_FORMAT_SHIFT) 13762306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_I2S_64X (1<<I2S_SF_SERIAL_FORMAT_SHIFT) 13862306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_I2S_32X (2<<I2S_SF_SERIAL_FORMAT_SHIFT) 13962306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_I2S_DAV (4<<I2S_SF_SERIAL_FORMAT_SHIFT) 14062306a36Sopenharmony_ci# define I2S_SF_SERIAL_FORMAT_I2S_SILABS (5<<I2S_SF_SERIAL_FORMAT_SHIFT) 14162306a36Sopenharmony_ci/* unknown */ 14262306a36Sopenharmony_ci# define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12 14362306a36Sopenharmony_ci# define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT) 14462306a36Sopenharmony_ci/* probably gives external frequency? */ 14562306a36Sopenharmony_ci# define I2S_SF_EXT_SAMPLE_FREQ_MASK 0xFFF 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/* used to send codec messages, but how isn't clear */ 14862306a36Sopenharmony_ci#define I2S_REG_CODEC_MSG_OUT 0x20 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* used to receive codec messages, but how isn't clear */ 15162306a36Sopenharmony_ci#define I2S_REG_CODEC_MSG_IN 0x30 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* frame count reg isn't clear to me yet, but probably useful */ 15462306a36Sopenharmony_ci#define I2S_REG_FRAME_COUNT 0x40 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* program to some value, and get interrupt if frame count reaches it */ 15762306a36Sopenharmony_ci#define I2S_REG_FRAME_MATCH 0x50 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* this register describes how the bus transfers data */ 16062306a36Sopenharmony_ci#define I2S_REG_DATA_WORD_SIZES 0x60 16162306a36Sopenharmony_ci/* number of interleaved input channels */ 16262306a36Sopenharmony_ci# define I2S_DWS_NUM_CHANNELS_IN_SHIFT 24 16362306a36Sopenharmony_ci# define I2S_DWS_NUM_CHANNELS_IN_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT) 16462306a36Sopenharmony_ci/* word size of input data */ 16562306a36Sopenharmony_ci# define I2S_DWS_DATA_IN_SIZE_SHIFT 16 16662306a36Sopenharmony_ci# define I2S_DWS_DATA_IN_16BIT (0<<I2S_DWS_DATA_IN_SIZE_SHIFT) 16762306a36Sopenharmony_ci# define I2S_DWS_DATA_IN_24BIT (3<<I2S_DWS_DATA_IN_SIZE_SHIFT) 16862306a36Sopenharmony_ci/* number of interleaved output channels */ 16962306a36Sopenharmony_ci# define I2S_DWS_NUM_CHANNELS_OUT_SHIFT 8 17062306a36Sopenharmony_ci# define I2S_DWS_NUM_CHANNELS_OUT_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT) 17162306a36Sopenharmony_ci/* word size of output data */ 17262306a36Sopenharmony_ci# define I2S_DWS_DATA_OUT_SIZE_SHIFT 0 17362306a36Sopenharmony_ci# define I2S_DWS_DATA_OUT_16BIT (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT) 17462306a36Sopenharmony_ci# define I2S_DWS_DATA_OUT_24BIT (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT) 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* unknown */ 17862306a36Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_SEL 0x70 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/* unknown */ 18162306a36Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_IN0 0x80 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* unknown */ 18462306a36Sopenharmony_ci#define I2S_REG_PEAK_LEVEL_IN1 0x90 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci#endif /* __I2SBUS_INTERFACE_H */ 187