/*
 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __DRIVERS_SOUND_IPQ806X_REG_H__
#define __DRIVERS_SOUND_IPQ806X_REG_H__

#define IPQ806X_LCC_BASE                0x28000000
#define IPQ806X_LPAIF_BASE		0x28100000
#define IPQ806X_LPM_BASE		0x28400000

#define LPM_SIZE			(4 * 1024)

#define LPAIF_BANK_OFFSET		0x1000

/* LCC MI2S Configuration/Control */

#define LCC_MI2S_NS_REG                 0x48
#define LCC_MI2S_STAT_REG               0x50

#define LCC_MI2S_NS_OSR_CXC_MASK        0x20000
#define LCC_MI2S_NS_OSR_CXC_SHIFT       17
#define LCC_MI2S_NS_OSR_CXC_ENABLE      (1 << LCC_MI2S_NS_OSR_CXC_SHIFT)

#define LCC_MI2S_NS_BIT_CXC_MASK        0x8000
#define LCC_MI2S_NS_BIT_CXC_SHIFT       15
#define LCC_MI2S_NS_BIT_CXC_ENABLE      (1 << LCC_MI2S_NS_BIT_CXC_SHIFT)

#define LCC_MI2S_STAT_OSR_CLK_MASK      0x2
#define LCC_MI2S_STAT_OSR_CLK_SHIFT     1
#define LCC_MI2S_STAT_OSR_CLK_ON        (1 << LCC_MI2S_STAT_OSR_CLK_SHIFT)

#define LCC_MI2S_STAT_BIT_CLK_MASK      0x1
#define LCC_MI2S_STAT_BIT_CLK_SHIFT     0
#define LCC_MI2S_STAT_BIT_CLK_ON        (1 << LCC_MI2S_STAT_BIT_CLK_SHIFT)

/* LPAIF I2S Configuration/Control */

#define LPAIF_MI2S_CTL_OFFSET(x)	(0x0010 + 0x4 * (x))

#define LPAIF_MI2SCTL_LB_SHIFT		15
#define LPAIF_MI2SCTL_LB		(1 << LPAIF_MI2SCTL_LB_SHIFT)

#define LPAIF_MI2SCTL_SPKEN_SHIFT	14
#define LPAIF_MI2SCTL_SPKEN		(1 << LPAIF_MI2SCTL_SPKEN_SHIFT)

#define LPAIF_MI2SCTL_SPKMODE_MASK	0x3C00
#define LPAIF_MI2SCTL_SPKMODE_SHIFT	10
#define LPAIF_MI2SCTL_SPKMODE_NONE	(0 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_SD0	(1 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_SD1	(2 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_SD2	(3 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_SD3	(4 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_QUAD01	(5 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_QUAD23	(6 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_6CH	(7 << LPAIF_MI2SCTL_SPKMODE_SHIFT)
#define LPAIF_MI2SCTL_SPKMODE_8CH	(8 << LPAIF_MI2SCTL_SPKMODE_SHIFT)

#define LPAIF_MI2SCTL_SPKMONO_MASK	0x0200
#define LPAIF_MI2SCTL_SPKMONO_SHIFT	9
#define LPAIF_MI2SCTL_SPKMONO_STEREO	(0 << LPAIF_MI2SCTL_SPKMONO_SHIFT)
#define LPAIF_MI2SCTL_SPKMONO_MONO	(1 << LPAIF_MI2SCTL_SPKMONO_SHIFT)

#define LPAIF_MI2SCTL_WS_SHIFT		2
#define LPAIF_MI2SCTL_WS		(1 << LPAIF_MI2SCTL_WS_SHIFT)

#define LPAIF_MI2SCTL_BITWIDTH_MASK	0x3
#define LPAIF_MI2SCTL_BITWIDTH_SHIFT	0
#define LPAIF_MI2SCTL_BITWIDTH_16	(0 << LPAIF_MI2SCTL_BITWIDTH_SHIFT)
#define LPAIF_MI2SCTL_BITWIDTH_24	(1 << LPAIF_MI2SCTL_BITWIDTH_SHIFT)
#define LPAIF_MI2SCTL_BITWIDTH_32	(2 << LPAIF_MI2SCTL_BITWIDTH_SHIFT)

/* LPAIF DMA Configuration/Control */

#define LPAIF_DMA_BASE			0x6000
#define LPAIF_DMA_INDEX(ch)		(LPAIF_BANK_OFFSET * (ch))
#define LPAIF_DMA_ADDR(ch, addr)	(LPAIF_DMA_BASE \
						+ (LPAIF_DMA_INDEX(ch) \
						+ (addr)))

#define LPAIF_DMA_CTL(x)		LPAIF_DMA_ADDR((x), 0x00)
#define LPAIF_DMA_BASEADDR(x)		LPAIF_DMA_ADDR((x), 0x04)
#define	LPAIF_DMA_BUFFLEN(x)		LPAIF_DMA_ADDR((x), 0x08)
#define LPAIF_DMA_CURRADDR(x)		LPAIF_DMA_ADDR((x), 0x0c)
#define	LPAIF_DMA_PERLEN(x)		LPAIF_DMA_ADDR((x), 0x10)
#define	LPAIF_DMA_PERCNT(x)		LPAIF_DMA_ADDR((x), 0x14)
#define	LPAIF_DMA_FRM(x)		LPAIF_DMA_ADDR((x), 0x18)
#define LPAIF_DMA_FRMCLR(x)		LPAIF_DMA_ADDR((x), 0x1c)
#define LPAIF_DMA_SETBUFFCNT(x)		LPAIF_DMA_ADDR((x), 0x20)
#define	LPAIF_DMA_SETPERCNT(x)		LPAIF_DMA_ADDR((x), 0x24)

#define LPAIF_DMACTL_BURST_EN_SHIFT	11
#define LPAIF_DMACTL_BURST_EN		(1 << LPAIF_DMACTL_BURST_EN_SHIFT)

#define LPAIF_DMACTL_WPSCNT_MASK	0x700
#define LPAIF_DMACTL_WPSCNT_SHIFT	8
#define LPAIF_DMACTL_WPSCNT_SINGLE	(0 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_DOUBLE	(1 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_TRIPLE	(2 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_QUAD	(3 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_SIXPACK	(5 << LPAIF_DMACTL_WPSCNT_SHIFT)
#define LPAIF_DMACTL_WPSCNT_OCTAL	(7 << LPAIF_DMACTL_WPSCNT_SHIFT)

#define LPAIF_DMACTL_AUDIO_INTF_MASK	0x0F0
#define LPAIF_DMACTL_AUDIO_INTF_SHIFT	4
#define LPAIF_DMACTL_AUDIO_INTF_NONE	(0 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_CODEC	(1 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_PCM	(2 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_SEC_I2S	(3 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_MI2S	(4 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_HDMI	(5 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_MIXOUT	(6 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_LB1	(7 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)
#define LPAIF_DMACTL_AUDIO_INTF_LB2	(8 << LPAIF_DMACTL_AUDIO_INTF_SHIFT)

#define LPAIF_DMACTL_FIFO_WM_MASK	0x00E
#define LPAIF_DMACTL_FIFO_WM_SHIFT	1
#define LPAIF_DMACTL_FIFO_WM_1		(0 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_2		(1 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_3		(2 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_4		(3 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_5		(4 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_6		(5 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_7		(6 << LPAIF_DMACTL_FIFO_WM_SHIFT)
#define LPAIF_DMACTL_FIFO_WM_8		(7 << LPAIF_DMACTL_FIFO_WM_SHIFT)

#define LPAIF_DMACTL_ENABLE_SHIFT	0
#define LPAIF_DMACTL_ENABLE		(1 << LPAIF_DMACTL_ENABLE_SHIFT)

/* LPAIF DMA Interrupt Control */

#define LPAIF_DMAIRQ_BASE		0x3000
#define LPAIF_DMAIRQ_INDEX(x)		(LPAIF_BANK_OFFSET * (x))
#define LPAIF_DMAIRQ_ADDR(irq, addr)	(LPAIF_DMAIRQ_BASE  \
						+ LPAIF_DMAIRQ_INDEX(irq) \
						+ (addr))

#define LPAIF_DMAIRQ_EN(x)		LPAIF_DMAIRQ_ADDR((x), 0x00)
#define LPAIF_DMAIRQ_STAT(x)		LPAIF_DMAIRQ_ADDR((x), 0x04)
#define LPAIF_DMAIRQ_RAW_STAT(x)	LPAIF_DMAIRQ_ADDR((x), 0x08)
#define LPAIF_DMAIRQ_CLEAR(x)		LPAIF_DMAIRQ_ADDR((x), 0x0c)
#define LPAIF_DMAIRQ_FORCE(x)		LPAIF_DMAIRQ_ADDR((x), 0x10)

#define LPAIF_DMAIRQ_SHIFT		3
#define LPAIF_DMAIRQ_PER(x)		(1 << (LPAIF_DMAIRQ_SHIFT * (x)))
#define LPAIF_DMAIRQ_XRUN(x)		(2 << (LPAIF_DMAIRQ_SHIFT * (x)))
#define LPAIF_DMAIRQ_ERR(x)		(4 << (LPAIF_DMAIRQ_SHIFT * (x)))
#define LPAIF_DMAIRQ_ALL(x)		(7 << (LPAIF_DMAIRQ_SHIFT * (x)))

enum lpaif_i2s_interface_ports {
	LPAIF_I2S_PORT_CODEC_SPK = 0,
	LPAIF_I2S_PORT_CODEC_MIC = 1,
	LPAIF_I2S_PORT_SEC_SPK   = 2,
	LPAIF_I2S_PORT_SEC_MIC   = 3,
	LPAIF_I2S_PORT_MI2S      = 4,
};

enum lpaif_dma_interface_channels {
	LPAIF_DMA_RD_CH_MI2S = 0,
	LPAIF_DMA_RD_CH_PCM0 = 1,
	LPAIF_DMA_RD_CH_PCM1 = 2,
	LPAIF_DMA_WR_CH_PCM0 = 5,
	LPAIF_DMA_WR_CH_PCM1 = 6,
	LPAIF_DMA_WR_CH_MI2S = 6,
};

enum lpaif_dmairq_interface_receivers {
	LPAIF_IRQ_RECV_HOST = 0,
	LPAIF_IRQ_RECV_ADSP = 1,
	LPAIF_IRQ_RECV_UNKN = 2,
};

#endif /* __DRIVERS_SOUND_IPQ806X_REG_H__ */
