xref: /openbmc/u-boot/drivers/sound/wm8994.c (revision 6647c7ac8ed6ae8b5bda86df0671aea9ee3bc761)
1a2d8e0a7SRajeshwari Shinde /*
2a2d8e0a7SRajeshwari Shinde  * Copyright (C) 2012 Samsung Electronics
3a2d8e0a7SRajeshwari Shinde  * R. Chandrasekar <rcsekar@samsung.com>
4a2d8e0a7SRajeshwari Shinde  *
5a2d8e0a7SRajeshwari Shinde  * See file CREDITS for list of people who contributed to this
6a2d8e0a7SRajeshwari Shinde  * project.
7a2d8e0a7SRajeshwari Shinde  *
8a2d8e0a7SRajeshwari Shinde  * This program is free software; you can redistribute it and/or
9a2d8e0a7SRajeshwari Shinde  * modify it under the terms of the GNU General Public License as
10a2d8e0a7SRajeshwari Shinde  * published by the Free Software Foundation; either version 2 of
11a2d8e0a7SRajeshwari Shinde  * the License, or (at your option) any later version.
12a2d8e0a7SRajeshwari Shinde  *
13a2d8e0a7SRajeshwari Shinde  * This program is distributed in the hope that it will be useful,
14a2d8e0a7SRajeshwari Shinde  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15a2d8e0a7SRajeshwari Shinde  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16a2d8e0a7SRajeshwari Shinde  * GNU General Public License for more details.
17a2d8e0a7SRajeshwari Shinde  *
18a2d8e0a7SRajeshwari Shinde  * You should have received a copy of the GNU General Public License
19a2d8e0a7SRajeshwari Shinde  * along with this program; if not, write to the Free Software
20a2d8e0a7SRajeshwari Shinde  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21a2d8e0a7SRajeshwari Shinde  * MA 02111-1307 USA
22a2d8e0a7SRajeshwari Shinde  */
23a2d8e0a7SRajeshwari Shinde #include <asm/arch/clk.h>
24a2d8e0a7SRajeshwari Shinde #include <asm/arch/cpu.h>
25a2d8e0a7SRajeshwari Shinde #include <asm/gpio.h>
26a2d8e0a7SRajeshwari Shinde #include <asm/io.h>
27a2d8e0a7SRajeshwari Shinde #include <common.h>
28a2d8e0a7SRajeshwari Shinde #include <div64.h>
29*6647c7acSRajeshwari Shinde #include <fdtdec.h>
30a2d8e0a7SRajeshwari Shinde #include <i2c.h>
31a2d8e0a7SRajeshwari Shinde #include <i2s.h>
32a2d8e0a7SRajeshwari Shinde #include <sound.h>
33*6647c7acSRajeshwari Shinde #include <asm/arch/sound.h>
34a2d8e0a7SRajeshwari Shinde #include "wm8994.h"
35a2d8e0a7SRajeshwari Shinde #include "wm8994_registers.h"
36a2d8e0a7SRajeshwari Shinde 
37a2d8e0a7SRajeshwari Shinde /* defines for wm8994 system clock selection */
38a2d8e0a7SRajeshwari Shinde #define SEL_MCLK1	0x00
39a2d8e0a7SRajeshwari Shinde #define SEL_MCLK2	0x08
40a2d8e0a7SRajeshwari Shinde #define SEL_FLL1	0x10
41a2d8e0a7SRajeshwari Shinde #define SEL_FLL2	0x18
42a2d8e0a7SRajeshwari Shinde 
43a2d8e0a7SRajeshwari Shinde /* fll config to configure fll */
44a2d8e0a7SRajeshwari Shinde struct wm8994_fll_config {
45a2d8e0a7SRajeshwari Shinde 	int src;	/* Source */
46a2d8e0a7SRajeshwari Shinde 	int in;		/* Input frequency in Hz */
47a2d8e0a7SRajeshwari Shinde 	int out;	/* output frequency in Hz */
48a2d8e0a7SRajeshwari Shinde };
49a2d8e0a7SRajeshwari Shinde 
50a2d8e0a7SRajeshwari Shinde /* codec private data */
51a2d8e0a7SRajeshwari Shinde struct wm8994_priv {
52a2d8e0a7SRajeshwari Shinde 	enum wm8994_type type;		/* codec type of wolfson */
53a2d8e0a7SRajeshwari Shinde 	int revision;			/* Revision */
54a2d8e0a7SRajeshwari Shinde 	int sysclk[WM8994_MAX_AIF];	/* System clock frequency in Hz  */
55a2d8e0a7SRajeshwari Shinde 	int mclk[WM8994_MAX_AIF];	/* master clock frequency in Hz */
56a2d8e0a7SRajeshwari Shinde 	int aifclk[WM8994_MAX_AIF];	/* audio interface clock in Hz   */
57a2d8e0a7SRajeshwari Shinde 	struct wm8994_fll_config fll[2]; /* fll config to configure fll */
58a2d8e0a7SRajeshwari Shinde };
59a2d8e0a7SRajeshwari Shinde 
60a2d8e0a7SRajeshwari Shinde /* wm 8994 supported sampling rate values */
61a2d8e0a7SRajeshwari Shinde static unsigned int src_rate[] = {
62a2d8e0a7SRajeshwari Shinde 			 8000, 11025, 12000, 16000, 22050, 24000,
63a2d8e0a7SRajeshwari Shinde 			 32000, 44100, 48000, 88200, 96000
64a2d8e0a7SRajeshwari Shinde };
65a2d8e0a7SRajeshwari Shinde 
66a2d8e0a7SRajeshwari Shinde /* op clock divisions */
67a2d8e0a7SRajeshwari Shinde static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
68a2d8e0a7SRajeshwari Shinde 
69a2d8e0a7SRajeshwari Shinde /* lr clock frame size ratio */
70a2d8e0a7SRajeshwari Shinde static int fs_ratios[] = {
71a2d8e0a7SRajeshwari Shinde 	64, 128, 192, 256, 348, 512, 768, 1024, 1408, 1536
72a2d8e0a7SRajeshwari Shinde };
73a2d8e0a7SRajeshwari Shinde 
74a2d8e0a7SRajeshwari Shinde /* bit clock divisors */
75a2d8e0a7SRajeshwari Shinde static int bclk_divs[] = {
76a2d8e0a7SRajeshwari Shinde 	10, 15, 20, 30, 40, 50, 60, 80, 110, 120, 160, 220, 240, 320, 440, 480,
77a2d8e0a7SRajeshwari Shinde 	640, 880, 960, 1280, 1760, 1920
78a2d8e0a7SRajeshwari Shinde };
79a2d8e0a7SRajeshwari Shinde 
80a2d8e0a7SRajeshwari Shinde static struct wm8994_priv g_wm8994_info;
81a2d8e0a7SRajeshwari Shinde static unsigned char g_wm8994_i2c_dev_addr;
82*6647c7acSRajeshwari Shinde static struct sound_codec_info g_codec_info;
83a2d8e0a7SRajeshwari Shinde 
84a2d8e0a7SRajeshwari Shinde /*
85a2d8e0a7SRajeshwari Shinde  * Initialise I2C for wm 8994
86a2d8e0a7SRajeshwari Shinde  *
87a2d8e0a7SRajeshwari Shinde  * @param bus no	i2c bus number in which wm8994 is connected
88a2d8e0a7SRajeshwari Shinde  */
89a2d8e0a7SRajeshwari Shinde static void wm8994_i2c_init(int bus_no)
90a2d8e0a7SRajeshwari Shinde {
91a2d8e0a7SRajeshwari Shinde 	i2c_set_bus_num(bus_no);
92a2d8e0a7SRajeshwari Shinde }
93a2d8e0a7SRajeshwari Shinde 
94a2d8e0a7SRajeshwari Shinde /*
95a2d8e0a7SRajeshwari Shinde  * Writes value to a device register through i2c
96a2d8e0a7SRajeshwari Shinde  *
97a2d8e0a7SRajeshwari Shinde  * @param reg	reg number to be write
98a2d8e0a7SRajeshwari Shinde  * @param data	data to be writen to the above registor
99a2d8e0a7SRajeshwari Shinde  *
100a2d8e0a7SRajeshwari Shinde  * @return	int value 1 for change, 0 for no change or negative error code.
101a2d8e0a7SRajeshwari Shinde  */
102a2d8e0a7SRajeshwari Shinde static int wm8994_i2c_write(unsigned int reg, unsigned short data)
103a2d8e0a7SRajeshwari Shinde {
104a2d8e0a7SRajeshwari Shinde 	unsigned char val[2];
105a2d8e0a7SRajeshwari Shinde 
106a2d8e0a7SRajeshwari Shinde 	val[0] = (unsigned char)((data >> 8) & 0xff);
107a2d8e0a7SRajeshwari Shinde 	val[1] = (unsigned char)(data & 0xff);
108a2d8e0a7SRajeshwari Shinde 	debug("Write Addr : 0x%04X, Data :  0x%04X\n", reg, data);
109a2d8e0a7SRajeshwari Shinde 
110a2d8e0a7SRajeshwari Shinde 	return i2c_write(g_wm8994_i2c_dev_addr, reg, 2, val, 2);
111a2d8e0a7SRajeshwari Shinde }
112a2d8e0a7SRajeshwari Shinde 
113a2d8e0a7SRajeshwari Shinde /*
114a2d8e0a7SRajeshwari Shinde  * Read a value from a device register through i2c
115a2d8e0a7SRajeshwari Shinde  *
116a2d8e0a7SRajeshwari Shinde  * @param reg	reg number to be read
117a2d8e0a7SRajeshwari Shinde  * @param data	address of read data to be stored
118a2d8e0a7SRajeshwari Shinde  *
119a2d8e0a7SRajeshwari Shinde  * @return	int value 0 for success, -1 in case of error.
120a2d8e0a7SRajeshwari Shinde  */
121a2d8e0a7SRajeshwari Shinde static unsigned int  wm8994_i2c_read(unsigned int reg , unsigned short *data)
122a2d8e0a7SRajeshwari Shinde {
123a2d8e0a7SRajeshwari Shinde 	unsigned char val[2];
124a2d8e0a7SRajeshwari Shinde 	int ret;
125a2d8e0a7SRajeshwari Shinde 
126a2d8e0a7SRajeshwari Shinde 	ret = i2c_read(g_wm8994_i2c_dev_addr, reg, 2, val, 2);
127a2d8e0a7SRajeshwari Shinde 	if (ret != 0) {
128a2d8e0a7SRajeshwari Shinde 		debug("%s: Error while reading register %#04x\n",
129a2d8e0a7SRajeshwari Shinde 		      __func__, reg);
130a2d8e0a7SRajeshwari Shinde 		return -1;
131a2d8e0a7SRajeshwari Shinde 	}
132a2d8e0a7SRajeshwari Shinde 
133a2d8e0a7SRajeshwari Shinde 	*data = val[0];
134a2d8e0a7SRajeshwari Shinde 	*data <<= 8;
135a2d8e0a7SRajeshwari Shinde 	*data |= val[1];
136a2d8e0a7SRajeshwari Shinde 
137a2d8e0a7SRajeshwari Shinde 	return 0;
138a2d8e0a7SRajeshwari Shinde }
139a2d8e0a7SRajeshwari Shinde 
140a2d8e0a7SRajeshwari Shinde /*
141a2d8e0a7SRajeshwari Shinde  * update device register bits through i2c
142a2d8e0a7SRajeshwari Shinde  *
143a2d8e0a7SRajeshwari Shinde  * @param reg	codec register
144a2d8e0a7SRajeshwari Shinde  * @param mask	register mask
145a2d8e0a7SRajeshwari Shinde  * @param value	new value
146a2d8e0a7SRajeshwari Shinde  *
147a2d8e0a7SRajeshwari Shinde  * @return int value 1 if change in the register value,
148a2d8e0a7SRajeshwari Shinde  * 0 for no change or negative error code.
149a2d8e0a7SRajeshwari Shinde  */
150a2d8e0a7SRajeshwari Shinde static int wm8994_update_bits(unsigned int reg, unsigned short mask,
151a2d8e0a7SRajeshwari Shinde 						unsigned short value)
152a2d8e0a7SRajeshwari Shinde {
153a2d8e0a7SRajeshwari Shinde 	int change , ret = 0;
154a2d8e0a7SRajeshwari Shinde 	unsigned short old, new;
155a2d8e0a7SRajeshwari Shinde 
156a2d8e0a7SRajeshwari Shinde 	if (wm8994_i2c_read(reg, &old) != 0)
157a2d8e0a7SRajeshwari Shinde 		return -1;
158a2d8e0a7SRajeshwari Shinde 	new = (old & ~mask) | (value & mask);
159a2d8e0a7SRajeshwari Shinde 	change  = (old != new) ? 1 : 0;
160a2d8e0a7SRajeshwari Shinde 	if (change)
161a2d8e0a7SRajeshwari Shinde 		ret = wm8994_i2c_write(reg, new);
162a2d8e0a7SRajeshwari Shinde 	if (ret < 0)
163a2d8e0a7SRajeshwari Shinde 		return ret;
164a2d8e0a7SRajeshwari Shinde 
165a2d8e0a7SRajeshwari Shinde 	return change;
166a2d8e0a7SRajeshwari Shinde }
167a2d8e0a7SRajeshwari Shinde 
168a2d8e0a7SRajeshwari Shinde /*
169a2d8e0a7SRajeshwari Shinde  * Sets i2s set format
170a2d8e0a7SRajeshwari Shinde  *
171a2d8e0a7SRajeshwari Shinde  * @param aif_id	Interface ID
172a2d8e0a7SRajeshwari Shinde  * @param fmt		i2S format
173a2d8e0a7SRajeshwari Shinde  *
174a2d8e0a7SRajeshwari Shinde  * @return -1 for error and 0  Success.
175a2d8e0a7SRajeshwari Shinde  */
176a2d8e0a7SRajeshwari Shinde int wm8994_set_fmt(int aif_id, unsigned int fmt)
177a2d8e0a7SRajeshwari Shinde {
178a2d8e0a7SRajeshwari Shinde 	int ms_reg;
179a2d8e0a7SRajeshwari Shinde 	int aif_reg;
180a2d8e0a7SRajeshwari Shinde 	int ms = 0;
181a2d8e0a7SRajeshwari Shinde 	int aif = 0;
182a2d8e0a7SRajeshwari Shinde 	int aif_clk = 0;
183a2d8e0a7SRajeshwari Shinde 	int error = 0;
184a2d8e0a7SRajeshwari Shinde 
185a2d8e0a7SRajeshwari Shinde 	switch (aif_id) {
186a2d8e0a7SRajeshwari Shinde 	case 1:
187a2d8e0a7SRajeshwari Shinde 		ms_reg = WM8994_AIF1_MASTER_SLAVE;
188a2d8e0a7SRajeshwari Shinde 		aif_reg = WM8994_AIF1_CONTROL_1;
189a2d8e0a7SRajeshwari Shinde 		aif_clk = WM8994_AIF1_CLOCKING_1;
190a2d8e0a7SRajeshwari Shinde 		break;
191a2d8e0a7SRajeshwari Shinde 	case 2:
192a2d8e0a7SRajeshwari Shinde 		ms_reg = WM8994_AIF2_MASTER_SLAVE;
193a2d8e0a7SRajeshwari Shinde 		aif_reg = WM8994_AIF2_CONTROL_1;
194a2d8e0a7SRajeshwari Shinde 		aif_clk = WM8994_AIF2_CLOCKING_1;
195a2d8e0a7SRajeshwari Shinde 		break;
196a2d8e0a7SRajeshwari Shinde 	default:
197a2d8e0a7SRajeshwari Shinde 		debug("%s: Invalid audio interface selection\n", __func__);
198a2d8e0a7SRajeshwari Shinde 		return -1;
199a2d8e0a7SRajeshwari Shinde 	}
200a2d8e0a7SRajeshwari Shinde 
201a2d8e0a7SRajeshwari Shinde 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
202a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_CBS_CFS:
203a2d8e0a7SRajeshwari Shinde 		break;
204a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_CBM_CFM:
205a2d8e0a7SRajeshwari Shinde 		ms = WM8994_AIF1_MSTR;
206a2d8e0a7SRajeshwari Shinde 		break;
207a2d8e0a7SRajeshwari Shinde 	default:
208a2d8e0a7SRajeshwari Shinde 		debug("%s: Invalid i2s master selection\n", __func__);
209a2d8e0a7SRajeshwari Shinde 		return -1;
210a2d8e0a7SRajeshwari Shinde 	}
211a2d8e0a7SRajeshwari Shinde 
212a2d8e0a7SRajeshwari Shinde 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
213a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_DSP_B:
214a2d8e0a7SRajeshwari Shinde 		aif |= WM8994_AIF1_LRCLK_INV;
215a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_DSP_A:
216a2d8e0a7SRajeshwari Shinde 		aif |= 0x18;
217a2d8e0a7SRajeshwari Shinde 		break;
218a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_I2S:
219a2d8e0a7SRajeshwari Shinde 		aif |= 0x10;
220a2d8e0a7SRajeshwari Shinde 		break;
221a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_RIGHT_J:
222a2d8e0a7SRajeshwari Shinde 		break;
223a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_LEFT_J:
224a2d8e0a7SRajeshwari Shinde 		aif |= 0x8;
225a2d8e0a7SRajeshwari Shinde 		break;
226a2d8e0a7SRajeshwari Shinde 	default:
227a2d8e0a7SRajeshwari Shinde 		debug("%s: Invalid i2s format selection\n", __func__);
228a2d8e0a7SRajeshwari Shinde 		return -1;
229a2d8e0a7SRajeshwari Shinde 	}
230a2d8e0a7SRajeshwari Shinde 
231a2d8e0a7SRajeshwari Shinde 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
232a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_DSP_A:
233a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_DSP_B:
234a2d8e0a7SRajeshwari Shinde 		/* frame inversion not valid for DSP modes */
235a2d8e0a7SRajeshwari Shinde 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
236a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_NB_NF:
237a2d8e0a7SRajeshwari Shinde 			break;
238a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_IB_NF:
239a2d8e0a7SRajeshwari Shinde 			aif |= WM8994_AIF1_BCLK_INV;
240a2d8e0a7SRajeshwari Shinde 			break;
241a2d8e0a7SRajeshwari Shinde 		default:
242a2d8e0a7SRajeshwari Shinde 			debug("%s: Invalid i2s frame inverse selection\n",
243a2d8e0a7SRajeshwari Shinde 			      __func__);
244a2d8e0a7SRajeshwari Shinde 			return -1;
245a2d8e0a7SRajeshwari Shinde 		}
246a2d8e0a7SRajeshwari Shinde 		break;
247a2d8e0a7SRajeshwari Shinde 
248a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_I2S:
249a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_RIGHT_J:
250a2d8e0a7SRajeshwari Shinde 	case SND_SOC_DAIFMT_LEFT_J:
251a2d8e0a7SRajeshwari Shinde 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
252a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_NB_NF:
253a2d8e0a7SRajeshwari Shinde 			break;
254a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_IB_IF:
255a2d8e0a7SRajeshwari Shinde 			aif |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
256a2d8e0a7SRajeshwari Shinde 			break;
257a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_IB_NF:
258a2d8e0a7SRajeshwari Shinde 			aif |= WM8994_AIF1_BCLK_INV;
259a2d8e0a7SRajeshwari Shinde 			break;
260a2d8e0a7SRajeshwari Shinde 		case SND_SOC_DAIFMT_NB_IF:
261a2d8e0a7SRajeshwari Shinde 			aif |= WM8994_AIF1_LRCLK_INV;
262a2d8e0a7SRajeshwari Shinde 			break;
263a2d8e0a7SRajeshwari Shinde 		default:
264a2d8e0a7SRajeshwari Shinde 			debug("%s: Invalid i2s clock polarity selection\n",
265a2d8e0a7SRajeshwari Shinde 			      __func__);
266a2d8e0a7SRajeshwari Shinde 			return -1;
267a2d8e0a7SRajeshwari Shinde 		}
268a2d8e0a7SRajeshwari Shinde 		break;
269a2d8e0a7SRajeshwari Shinde 	default:
270a2d8e0a7SRajeshwari Shinde 		debug("%s: Invalid i2s format selection\n", __func__);
271a2d8e0a7SRajeshwari Shinde 		return -1;
272a2d8e0a7SRajeshwari Shinde 	}
273a2d8e0a7SRajeshwari Shinde 
274a2d8e0a7SRajeshwari Shinde 	error = wm8994_update_bits(aif_reg, WM8994_AIF1_BCLK_INV |
275a2d8e0a7SRajeshwari Shinde 			WM8994_AIF1_LRCLK_INV_MASK | WM8994_AIF1_FMT_MASK, aif);
276a2d8e0a7SRajeshwari Shinde 
277a2d8e0a7SRajeshwari Shinde 	error |= wm8994_update_bits(ms_reg, WM8994_AIF1_MSTR_MASK, ms);
278a2d8e0a7SRajeshwari Shinde 	error |= wm8994_update_bits(aif_clk, WM8994_AIF1CLK_ENA_MASK,
279a2d8e0a7SRajeshwari Shinde 						WM8994_AIF1CLK_ENA);
280a2d8e0a7SRajeshwari Shinde 	if (error < 0) {
281a2d8e0a7SRajeshwari Shinde 		debug("%s: codec register access error\n", __func__);
282a2d8e0a7SRajeshwari Shinde 		return -1;
283a2d8e0a7SRajeshwari Shinde 	}
284a2d8e0a7SRajeshwari Shinde 
285a2d8e0a7SRajeshwari Shinde 	return 0;
286a2d8e0a7SRajeshwari Shinde }
287a2d8e0a7SRajeshwari Shinde 
288a2d8e0a7SRajeshwari Shinde /*
289a2d8e0a7SRajeshwari Shinde  * Sets hw params FOR WM8994
290a2d8e0a7SRajeshwari Shinde  *
291a2d8e0a7SRajeshwari Shinde  * @param wm8994		wm8994 information pointer
292a2d8e0a7SRajeshwari Shinde  * @param aif_id		Audio interface ID
293a2d8e0a7SRajeshwari Shinde  * @param sampling_rate		Sampling rate
294a2d8e0a7SRajeshwari Shinde  * @param bits_per_sample	Bits per sample
295a2d8e0a7SRajeshwari Shinde  * @param Channels		Channels in the given audio input
296a2d8e0a7SRajeshwari Shinde  *
297a2d8e0a7SRajeshwari Shinde  * @return -1 for error  and 0  Success.
298a2d8e0a7SRajeshwari Shinde  */
299a2d8e0a7SRajeshwari Shinde static int wm8994_hw_params(struct wm8994_priv *wm8994, int aif_id,
300a2d8e0a7SRajeshwari Shinde 		unsigned int sampling_rate, unsigned int bits_per_sample,
301a2d8e0a7SRajeshwari Shinde 		unsigned int channels)
302a2d8e0a7SRajeshwari Shinde {
303a2d8e0a7SRajeshwari Shinde 	int aif1_reg;
304a2d8e0a7SRajeshwari Shinde 	int aif2_reg;
305a2d8e0a7SRajeshwari Shinde 	int bclk_reg;
306a2d8e0a7SRajeshwari Shinde 	int bclk = 0;
307a2d8e0a7SRajeshwari Shinde 	int rate_reg;
308a2d8e0a7SRajeshwari Shinde 	int aif1 = 0;
309a2d8e0a7SRajeshwari Shinde 	int aif2 = 0;
310a2d8e0a7SRajeshwari Shinde 	int rate_val = 0;
311a2d8e0a7SRajeshwari Shinde 	int id = aif_id - 1;
312a2d8e0a7SRajeshwari Shinde 	int i, cur_val, best_val, bclk_rate, best;
313a2d8e0a7SRajeshwari Shinde 	unsigned short reg_data;
314a2d8e0a7SRajeshwari Shinde 	int ret = 0;
315a2d8e0a7SRajeshwari Shinde 
316a2d8e0a7SRajeshwari Shinde 	switch (aif_id) {
317a2d8e0a7SRajeshwari Shinde 	case 1:
318a2d8e0a7SRajeshwari Shinde 		aif1_reg = WM8994_AIF1_CONTROL_1;
319a2d8e0a7SRajeshwari Shinde 		aif2_reg = WM8994_AIF1_CONTROL_2;
320a2d8e0a7SRajeshwari Shinde 		bclk_reg = WM8994_AIF1_BCLK;
321a2d8e0a7SRajeshwari Shinde 		rate_reg = WM8994_AIF1_RATE;
322a2d8e0a7SRajeshwari Shinde 		break;
323a2d8e0a7SRajeshwari Shinde 	case 2:
324a2d8e0a7SRajeshwari Shinde 		aif1_reg = WM8994_AIF2_CONTROL_1;
325a2d8e0a7SRajeshwari Shinde 		aif2_reg = WM8994_AIF2_CONTROL_2;
326a2d8e0a7SRajeshwari Shinde 		bclk_reg = WM8994_AIF2_BCLK;
327a2d8e0a7SRajeshwari Shinde 		rate_reg = WM8994_AIF2_RATE;
328a2d8e0a7SRajeshwari Shinde 		break;
329a2d8e0a7SRajeshwari Shinde 	default:
330a2d8e0a7SRajeshwari Shinde 		return -1;
331a2d8e0a7SRajeshwari Shinde 	}
332a2d8e0a7SRajeshwari Shinde 
333a2d8e0a7SRajeshwari Shinde 	bclk_rate = sampling_rate * 32;
334a2d8e0a7SRajeshwari Shinde 	switch (bits_per_sample) {
335a2d8e0a7SRajeshwari Shinde 	case 16:
336a2d8e0a7SRajeshwari Shinde 		bclk_rate *= 16;
337a2d8e0a7SRajeshwari Shinde 		break;
338a2d8e0a7SRajeshwari Shinde 	case 20:
339a2d8e0a7SRajeshwari Shinde 		bclk_rate *= 20;
340a2d8e0a7SRajeshwari Shinde 		aif1 |= 0x20;
341a2d8e0a7SRajeshwari Shinde 		break;
342a2d8e0a7SRajeshwari Shinde 	case 24:
343a2d8e0a7SRajeshwari Shinde 		bclk_rate *= 24;
344a2d8e0a7SRajeshwari Shinde 		aif1 |= 0x40;
345a2d8e0a7SRajeshwari Shinde 		break;
346a2d8e0a7SRajeshwari Shinde 	case 32:
347a2d8e0a7SRajeshwari Shinde 		bclk_rate *= 32;
348a2d8e0a7SRajeshwari Shinde 		aif1 |= 0x60;
349a2d8e0a7SRajeshwari Shinde 		break;
350a2d8e0a7SRajeshwari Shinde 	default:
351a2d8e0a7SRajeshwari Shinde 		return -1;
352a2d8e0a7SRajeshwari Shinde 	}
353a2d8e0a7SRajeshwari Shinde 
354a2d8e0a7SRajeshwari Shinde 	/* Try to find an appropriate sample rate; look for an exact match. */
355a2d8e0a7SRajeshwari Shinde 	for (i = 0; i < ARRAY_SIZE(src_rate); i++)
356a2d8e0a7SRajeshwari Shinde 		if (src_rate[i] == sampling_rate)
357a2d8e0a7SRajeshwari Shinde 			break;
358a2d8e0a7SRajeshwari Shinde 
359a2d8e0a7SRajeshwari Shinde 	if (i == ARRAY_SIZE(src_rate)) {
360a2d8e0a7SRajeshwari Shinde 		debug("%s: Could not get the best matching samplingrate\n",
361a2d8e0a7SRajeshwari Shinde 		      __func__);
362a2d8e0a7SRajeshwari Shinde 		return -1;
363a2d8e0a7SRajeshwari Shinde 	}
364a2d8e0a7SRajeshwari Shinde 
365a2d8e0a7SRajeshwari Shinde 	rate_val |= i << WM8994_AIF1_SR_SHIFT;
366a2d8e0a7SRajeshwari Shinde 
367a2d8e0a7SRajeshwari Shinde 	/* AIFCLK/fs ratio; look for a close match in either direction */
368a2d8e0a7SRajeshwari Shinde 	best = 0;
369a2d8e0a7SRajeshwari Shinde 	best_val = abs((fs_ratios[0] * sampling_rate)
370a2d8e0a7SRajeshwari Shinde 						- wm8994->aifclk[id]);
371a2d8e0a7SRajeshwari Shinde 
372a2d8e0a7SRajeshwari Shinde 	for (i = 1; i < ARRAY_SIZE(fs_ratios); i++) {
373a2d8e0a7SRajeshwari Shinde 		cur_val = abs((fs_ratios[i] * sampling_rate)
374a2d8e0a7SRajeshwari Shinde 					- wm8994->aifclk[id]);
375a2d8e0a7SRajeshwari Shinde 		if (cur_val >= best_val)
376a2d8e0a7SRajeshwari Shinde 			continue;
377a2d8e0a7SRajeshwari Shinde 		best = i;
378a2d8e0a7SRajeshwari Shinde 		best_val = cur_val;
379a2d8e0a7SRajeshwari Shinde 	}
380a2d8e0a7SRajeshwari Shinde 
381a2d8e0a7SRajeshwari Shinde 	rate_val |= best;
382a2d8e0a7SRajeshwari Shinde 
383a2d8e0a7SRajeshwari Shinde 	/*
384a2d8e0a7SRajeshwari Shinde 	 * We may not get quite the right frequency if using
385a2d8e0a7SRajeshwari Shinde 	 * approximate clocks so look for the closest match that is
386a2d8e0a7SRajeshwari Shinde 	 * higher than the target (we need to ensure that there enough
387a2d8e0a7SRajeshwari Shinde 	 * BCLKs to clock out the samples).
388a2d8e0a7SRajeshwari Shinde 	 */
389a2d8e0a7SRajeshwari Shinde 	best = 0;
390a2d8e0a7SRajeshwari Shinde 	for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
391a2d8e0a7SRajeshwari Shinde 		cur_val = (wm8994->aifclk[id] * 10 / bclk_divs[i]) - bclk_rate;
392a2d8e0a7SRajeshwari Shinde 		if (cur_val < 0) /* BCLK table is sorted */
393a2d8e0a7SRajeshwari Shinde 			break;
394a2d8e0a7SRajeshwari Shinde 		best = i;
395a2d8e0a7SRajeshwari Shinde 	}
396a2d8e0a7SRajeshwari Shinde 
397a2d8e0a7SRajeshwari Shinde 	if (i ==  ARRAY_SIZE(bclk_divs)) {
398a2d8e0a7SRajeshwari Shinde 		debug("%s: Could not get the best matching bclk division\n",
399a2d8e0a7SRajeshwari Shinde 		      __func__);
400a2d8e0a7SRajeshwari Shinde 		return -1;
401a2d8e0a7SRajeshwari Shinde 	}
402a2d8e0a7SRajeshwari Shinde 
403a2d8e0a7SRajeshwari Shinde 	bclk_rate = wm8994->aifclk[id] * 10 / bclk_divs[best];
404a2d8e0a7SRajeshwari Shinde 	bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
405a2d8e0a7SRajeshwari Shinde 
406a2d8e0a7SRajeshwari Shinde 	if (wm8994_i2c_read(aif1_reg, &reg_data) != 0) {
407a2d8e0a7SRajeshwari Shinde 		debug("%s: AIF1 register read Failed\n", __func__);
408a2d8e0a7SRajeshwari Shinde 		return -1;
409a2d8e0a7SRajeshwari Shinde 	}
410a2d8e0a7SRajeshwari Shinde 
411a2d8e0a7SRajeshwari Shinde 	if ((channels == 1) && ((reg_data & 0x18) == 0x18))
412a2d8e0a7SRajeshwari Shinde 		aif2 |= WM8994_AIF1_MONO;
413a2d8e0a7SRajeshwari Shinde 
414a2d8e0a7SRajeshwari Shinde 	if (wm8994->aifclk[id] == 0) {
415a2d8e0a7SRajeshwari Shinde 		debug("%s:Audio interface clock not set\n", __func__);
416a2d8e0a7SRajeshwari Shinde 		return -1;
417a2d8e0a7SRajeshwari Shinde 	}
418a2d8e0a7SRajeshwari Shinde 
419a2d8e0a7SRajeshwari Shinde 	ret = wm8994_update_bits(aif1_reg, WM8994_AIF1_WL_MASK, aif1);
420a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(aif2_reg, WM8994_AIF1_MONO, aif2);
421a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(bclk_reg, WM8994_AIF1_BCLK_DIV_MASK, bclk);
422a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(rate_reg, WM8994_AIF1_SR_MASK |
423a2d8e0a7SRajeshwari Shinde 				WM8994_AIF1CLK_RATE_MASK, rate_val);
424a2d8e0a7SRajeshwari Shinde 
425a2d8e0a7SRajeshwari Shinde 	debug("rate vale = %x , bclk val= %x\n", rate_val, bclk);
426a2d8e0a7SRajeshwari Shinde 
427a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
428a2d8e0a7SRajeshwari Shinde 		debug("%s: codec register access error\n", __func__);
429a2d8e0a7SRajeshwari Shinde 		return -1;
430a2d8e0a7SRajeshwari Shinde 	}
431a2d8e0a7SRajeshwari Shinde 
432a2d8e0a7SRajeshwari Shinde 	return 0;
433a2d8e0a7SRajeshwari Shinde }
434a2d8e0a7SRajeshwari Shinde 
435a2d8e0a7SRajeshwari Shinde /*
436a2d8e0a7SRajeshwari Shinde  * Configures Audio interface Clock
437a2d8e0a7SRajeshwari Shinde  *
438a2d8e0a7SRajeshwari Shinde  * @param wm8994	wm8994 information pointer
439a2d8e0a7SRajeshwari Shinde  * @param aif		Audio Interface ID
440a2d8e0a7SRajeshwari Shinde  *
441a2d8e0a7SRajeshwari Shinde  * @return -1 for error  and 0  Success.
442a2d8e0a7SRajeshwari Shinde  */
443a2d8e0a7SRajeshwari Shinde static int configure_aif_clock(struct wm8994_priv *wm8994, int aif)
444a2d8e0a7SRajeshwari Shinde {
445a2d8e0a7SRajeshwari Shinde 	int rate;
446a2d8e0a7SRajeshwari Shinde 	int reg1 = 0;
447a2d8e0a7SRajeshwari Shinde 	int offset;
448a2d8e0a7SRajeshwari Shinde 	int ret;
449a2d8e0a7SRajeshwari Shinde 
450a2d8e0a7SRajeshwari Shinde 	/* AIF(1/0) register adress offset calculated */
451a2d8e0a7SRajeshwari Shinde 	if (aif)
452a2d8e0a7SRajeshwari Shinde 		offset = 4;
453a2d8e0a7SRajeshwari Shinde 	else
454a2d8e0a7SRajeshwari Shinde 		offset = 0;
455a2d8e0a7SRajeshwari Shinde 
456a2d8e0a7SRajeshwari Shinde 	switch (wm8994->sysclk[aif]) {
457a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_MCLK1:
458a2d8e0a7SRajeshwari Shinde 		reg1 |= SEL_MCLK1;
459a2d8e0a7SRajeshwari Shinde 		rate = wm8994->mclk[0];
460a2d8e0a7SRajeshwari Shinde 		break;
461a2d8e0a7SRajeshwari Shinde 
462a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_MCLK2:
463a2d8e0a7SRajeshwari Shinde 		reg1 |= SEL_MCLK2;
464a2d8e0a7SRajeshwari Shinde 		rate = wm8994->mclk[1];
465a2d8e0a7SRajeshwari Shinde 		break;
466a2d8e0a7SRajeshwari Shinde 
467a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_FLL1:
468a2d8e0a7SRajeshwari Shinde 		reg1 |= SEL_FLL1;
469a2d8e0a7SRajeshwari Shinde 		rate = wm8994->fll[0].out;
470a2d8e0a7SRajeshwari Shinde 		break;
471a2d8e0a7SRajeshwari Shinde 
472a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_FLL2:
473a2d8e0a7SRajeshwari Shinde 		reg1 |= SEL_FLL2;
474a2d8e0a7SRajeshwari Shinde 		rate = wm8994->fll[1].out;
475a2d8e0a7SRajeshwari Shinde 		break;
476a2d8e0a7SRajeshwari Shinde 
477a2d8e0a7SRajeshwari Shinde 	default:
478a2d8e0a7SRajeshwari Shinde 		debug("%s: Invalid input clock selection [%d]\n",
479a2d8e0a7SRajeshwari Shinde 		      __func__, wm8994->sysclk[aif]);
480a2d8e0a7SRajeshwari Shinde 		return -1;
481a2d8e0a7SRajeshwari Shinde 	}
482a2d8e0a7SRajeshwari Shinde 
483a2d8e0a7SRajeshwari Shinde 	/* if input clock frequenct is more than 135Mhz then divide */
484a2d8e0a7SRajeshwari Shinde 	if (rate >= WM8994_MAX_INPUT_CLK_FREQ) {
485a2d8e0a7SRajeshwari Shinde 		rate /= 2;
486a2d8e0a7SRajeshwari Shinde 		reg1 |= WM8994_AIF1CLK_DIV;
487a2d8e0a7SRajeshwari Shinde 	}
488a2d8e0a7SRajeshwari Shinde 
489a2d8e0a7SRajeshwari Shinde 	wm8994->aifclk[aif] = rate;
490a2d8e0a7SRajeshwari Shinde 
491a2d8e0a7SRajeshwari Shinde 	ret = wm8994_update_bits(WM8994_AIF1_CLOCKING_1 + offset,
492a2d8e0a7SRajeshwari Shinde 				WM8994_AIF1CLK_SRC_MASK | WM8994_AIF1CLK_DIV,
493a2d8e0a7SRajeshwari Shinde 				reg1);
494a2d8e0a7SRajeshwari Shinde 
495a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_CLOCKING_1,
496a2d8e0a7SRajeshwari Shinde 			WM8994_SYSCLK_SRC | WM8994_AIF2DSPCLK_ENA_MASK |
497a2d8e0a7SRajeshwari Shinde 			WM8994_SYSDSPCLK_ENA_MASK, WM8994_SYSCLK_SRC |
498a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DSPCLK_ENA | WM8994_SYSDSPCLK_ENA);
499a2d8e0a7SRajeshwari Shinde 
500a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
501a2d8e0a7SRajeshwari Shinde 		debug("%s: codec register access error\n", __func__);
502a2d8e0a7SRajeshwari Shinde 		return -1;
503a2d8e0a7SRajeshwari Shinde 	}
504a2d8e0a7SRajeshwari Shinde 
505a2d8e0a7SRajeshwari Shinde 	return 0;
506a2d8e0a7SRajeshwari Shinde }
507a2d8e0a7SRajeshwari Shinde 
508a2d8e0a7SRajeshwari Shinde /*
509a2d8e0a7SRajeshwari Shinde  * Configures Audio interface  for the given frequency
510a2d8e0a7SRajeshwari Shinde  *
511a2d8e0a7SRajeshwari Shinde  * @param wm8994	wm8994 information
512a2d8e0a7SRajeshwari Shinde  * @param aif_id	Audio Interface
513a2d8e0a7SRajeshwari Shinde  * @param clk_id	Input Clock ID
514a2d8e0a7SRajeshwari Shinde  * @param freq		Sampling frequency in Hz
515a2d8e0a7SRajeshwari Shinde  *
516a2d8e0a7SRajeshwari Shinde  * @return -1 for error and 0 success.
517a2d8e0a7SRajeshwari Shinde  */
518a2d8e0a7SRajeshwari Shinde static int wm8994_set_sysclk(struct wm8994_priv *wm8994, int aif_id,
519a2d8e0a7SRajeshwari Shinde 				int clk_id, unsigned int freq)
520a2d8e0a7SRajeshwari Shinde {
521a2d8e0a7SRajeshwari Shinde 	int i;
522a2d8e0a7SRajeshwari Shinde 	int ret = 0;
523a2d8e0a7SRajeshwari Shinde 
524a2d8e0a7SRajeshwari Shinde 	wm8994->sysclk[aif_id - 1] = clk_id;
525a2d8e0a7SRajeshwari Shinde 
526a2d8e0a7SRajeshwari Shinde 	switch (clk_id) {
527a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_MCLK1:
528a2d8e0a7SRajeshwari Shinde 		wm8994->mclk[0] = freq;
529a2d8e0a7SRajeshwari Shinde 		if (aif_id == 2) {
530a2d8e0a7SRajeshwari Shinde 			ret = wm8994_update_bits(WM8994_AIF1_CLOCKING_2 ,
531a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_DIV_MASK , 0);
532a2d8e0a7SRajeshwari Shinde 		}
533a2d8e0a7SRajeshwari Shinde 		break;
534a2d8e0a7SRajeshwari Shinde 
535a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_MCLK2:
536a2d8e0a7SRajeshwari Shinde 		/* TODO: Set GPIO AF */
537a2d8e0a7SRajeshwari Shinde 		wm8994->mclk[1] = freq;
538a2d8e0a7SRajeshwari Shinde 		break;
539a2d8e0a7SRajeshwari Shinde 
540a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_FLL1:
541a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_FLL2:
542a2d8e0a7SRajeshwari Shinde 		break;
543a2d8e0a7SRajeshwari Shinde 
544a2d8e0a7SRajeshwari Shinde 	case WM8994_SYSCLK_OPCLK:
545a2d8e0a7SRajeshwari Shinde 		/*
546a2d8e0a7SRajeshwari Shinde 		 * Special case - a division (times 10) is given and
547a2d8e0a7SRajeshwari Shinde 		 * no effect on main clocking.
548a2d8e0a7SRajeshwari Shinde 		 */
549a2d8e0a7SRajeshwari Shinde 		if (freq) {
550a2d8e0a7SRajeshwari Shinde 			for (i = 0; i < ARRAY_SIZE(opclk_divs); i++)
551a2d8e0a7SRajeshwari Shinde 				if (opclk_divs[i] == freq)
552a2d8e0a7SRajeshwari Shinde 					break;
553a2d8e0a7SRajeshwari Shinde 			if (i == ARRAY_SIZE(opclk_divs)) {
554a2d8e0a7SRajeshwari Shinde 				debug("%s frequency divisor not found\n",
555a2d8e0a7SRajeshwari Shinde 					__func__);
556a2d8e0a7SRajeshwari Shinde 				return -1;
557a2d8e0a7SRajeshwari Shinde 			}
558a2d8e0a7SRajeshwari Shinde 			ret = wm8994_update_bits(WM8994_CLOCKING_2,
559a2d8e0a7SRajeshwari Shinde 					    WM8994_OPCLK_DIV_MASK, i);
560a2d8e0a7SRajeshwari Shinde 			ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_2,
561a2d8e0a7SRajeshwari Shinde 					    WM8994_OPCLK_ENA, WM8994_OPCLK_ENA);
562a2d8e0a7SRajeshwari Shinde 		} else {
563a2d8e0a7SRajeshwari Shinde 			ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_2,
564a2d8e0a7SRajeshwari Shinde 					    WM8994_OPCLK_ENA, 0);
565a2d8e0a7SRajeshwari Shinde 		}
566a2d8e0a7SRajeshwari Shinde 
567a2d8e0a7SRajeshwari Shinde 	default:
568a2d8e0a7SRajeshwari Shinde 		debug("%s Invalid input clock selection [%d]\n",
569a2d8e0a7SRajeshwari Shinde 		      __func__, clk_id);
570a2d8e0a7SRajeshwari Shinde 		return -1;
571a2d8e0a7SRajeshwari Shinde 	}
572a2d8e0a7SRajeshwari Shinde 
573a2d8e0a7SRajeshwari Shinde 	ret |= configure_aif_clock(wm8994, aif_id - 1);
574a2d8e0a7SRajeshwari Shinde 
575a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
576a2d8e0a7SRajeshwari Shinde 		debug("%s: codec register access error\n", __func__);
577a2d8e0a7SRajeshwari Shinde 		return -1;
578a2d8e0a7SRajeshwari Shinde 	}
579a2d8e0a7SRajeshwari Shinde 
580a2d8e0a7SRajeshwari Shinde 	return 0;
581a2d8e0a7SRajeshwari Shinde }
582a2d8e0a7SRajeshwari Shinde 
583a2d8e0a7SRajeshwari Shinde /*
584a2d8e0a7SRajeshwari Shinde  * Initializes Volume for AIF2 to HP path
585a2d8e0a7SRajeshwari Shinde  *
586a2d8e0a7SRajeshwari Shinde  * @returns -1 for error  and 0 Success.
587a2d8e0a7SRajeshwari Shinde  *
588a2d8e0a7SRajeshwari Shinde  */
589a2d8e0a7SRajeshwari Shinde static int wm8994_init_volume_aif2_dac1(void)
590a2d8e0a7SRajeshwari Shinde {
591a2d8e0a7SRajeshwari Shinde 	int ret;
592a2d8e0a7SRajeshwari Shinde 
593a2d8e0a7SRajeshwari Shinde 	/* Unmute AIF2DAC */
594a2d8e0a7SRajeshwari Shinde 	ret = wm8994_update_bits(WM8994_AIF2_DAC_FILTERS_1,
595a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_MUTE_MASK, 0);
596a2d8e0a7SRajeshwari Shinde 
597a2d8e0a7SRajeshwari Shinde 
598a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_AIF2_DAC_LEFT_VOLUME,
599a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_VU_MASK | WM8994_AIF2DACL_VOL_MASK,
600a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_VU | 0xff);
601a2d8e0a7SRajeshwari Shinde 
602a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_AIF2_DAC_RIGHT_VOLUME,
603a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_VU_MASK | WM8994_AIF2DACR_VOL_MASK,
604a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DAC_VU | 0xff);
605a2d8e0a7SRajeshwari Shinde 
606a2d8e0a7SRajeshwari Shinde 
607a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_DAC1_LEFT_VOLUME,
608a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1_VU_MASK | WM8994_DAC1L_VOL_MASK |
609a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1L_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
610a2d8e0a7SRajeshwari Shinde 
611a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_VOLUME,
612a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1_VU_MASK | WM8994_DAC1R_VOL_MASK |
613a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1R_MUTE_MASK, WM8994_DAC1_VU | 0xc0);
614a2d8e0a7SRajeshwari Shinde 	/* Head Phone Volume */
615a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_i2c_write(WM8994_LEFT_OUTPUT_VOLUME, 0x12D);
616a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_i2c_write(WM8994_RIGHT_OUTPUT_VOLUME, 0x12D);
617a2d8e0a7SRajeshwari Shinde 
618a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
619a2d8e0a7SRajeshwari Shinde 		debug("%s: codec register access error\n", __func__);
620a2d8e0a7SRajeshwari Shinde 		return -1;
621a2d8e0a7SRajeshwari Shinde 	}
622a2d8e0a7SRajeshwari Shinde 
623a2d8e0a7SRajeshwari Shinde 	return 0;
624a2d8e0a7SRajeshwari Shinde }
625a2d8e0a7SRajeshwari Shinde 
626a2d8e0a7SRajeshwari Shinde /*
627a2d8e0a7SRajeshwari Shinde  * Intialise wm8994 codec device
628a2d8e0a7SRajeshwari Shinde  *
629a2d8e0a7SRajeshwari Shinde  * @param wm8994	wm8994 information
630a2d8e0a7SRajeshwari Shinde  *
631a2d8e0a7SRajeshwari Shinde  * @returns -1 for error  and 0 Success.
632a2d8e0a7SRajeshwari Shinde  */
633a2d8e0a7SRajeshwari Shinde static int wm8994_device_init(struct wm8994_priv *wm8994)
634a2d8e0a7SRajeshwari Shinde {
635a2d8e0a7SRajeshwari Shinde 	const char *devname;
636a2d8e0a7SRajeshwari Shinde 	unsigned short reg_data;
637a2d8e0a7SRajeshwari Shinde 	int ret;
638a2d8e0a7SRajeshwari Shinde 
639a2d8e0a7SRajeshwari Shinde 	wm8994_i2c_write(WM8994_SOFTWARE_RESET, WM8994_SW_RESET);/* Reset */
640a2d8e0a7SRajeshwari Shinde 
641a2d8e0a7SRajeshwari Shinde 	ret = wm8994_i2c_read(WM8994_SOFTWARE_RESET, &reg_data);
642a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
643a2d8e0a7SRajeshwari Shinde 		debug("Failed to read ID register\n");
644a2d8e0a7SRajeshwari Shinde 		goto err;
645a2d8e0a7SRajeshwari Shinde 	}
646a2d8e0a7SRajeshwari Shinde 
647a2d8e0a7SRajeshwari Shinde 	if (reg_data == WM8994_ID) {
648a2d8e0a7SRajeshwari Shinde 		devname = "WM8994";
649a2d8e0a7SRajeshwari Shinde 		debug("Device registered as type %d\n", wm8994->type);
650a2d8e0a7SRajeshwari Shinde 		wm8994->type = WM8994;
651a2d8e0a7SRajeshwari Shinde 	} else {
652a2d8e0a7SRajeshwari Shinde 		debug("Device is not a WM8994, ID is %x\n", ret);
653a2d8e0a7SRajeshwari Shinde 		ret = -1;
654a2d8e0a7SRajeshwari Shinde 		goto err;
655a2d8e0a7SRajeshwari Shinde 	}
656a2d8e0a7SRajeshwari Shinde 
657a2d8e0a7SRajeshwari Shinde 	ret = wm8994_i2c_read(WM8994_CHIP_REVISION, &reg_data);
658a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
659a2d8e0a7SRajeshwari Shinde 		debug("Failed to read revision register: %d\n", ret);
660a2d8e0a7SRajeshwari Shinde 		goto err;
661a2d8e0a7SRajeshwari Shinde 	}
662a2d8e0a7SRajeshwari Shinde 	wm8994->revision = reg_data;
663a2d8e0a7SRajeshwari Shinde 	debug("%s revision %c\n", devname, 'A' + wm8994->revision);
664a2d8e0a7SRajeshwari Shinde 
665a2d8e0a7SRajeshwari Shinde 	/* VMID Selection */
666a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
667a2d8e0a7SRajeshwari Shinde 			WM8994_VMID_SEL_MASK | WM8994_BIAS_ENA_MASK, 0x3);
668a2d8e0a7SRajeshwari Shinde 
669a2d8e0a7SRajeshwari Shinde 	/* Charge Pump Enable */
670a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_CHARGE_PUMP_1, WM8994_CP_ENA_MASK,
671a2d8e0a7SRajeshwari Shinde 					WM8994_CP_ENA);
672a2d8e0a7SRajeshwari Shinde 
673a2d8e0a7SRajeshwari Shinde 	/* Head Phone Power Enable */
674a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
675a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1L_ENA_MASK, WM8994_HPOUT1L_ENA);
676a2d8e0a7SRajeshwari Shinde 
677a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_1,
678a2d8e0a7SRajeshwari Shinde 				WM8994_HPOUT1R_ENA_MASK, WM8994_HPOUT1R_ENA);
679a2d8e0a7SRajeshwari Shinde 
680a2d8e0a7SRajeshwari Shinde 	/* Power enable for AIF2 and DAC1 */
681a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_POWER_MANAGEMENT_5,
682a2d8e0a7SRajeshwari Shinde 		WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK |
683a2d8e0a7SRajeshwari Shinde 		WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK,
684a2d8e0a7SRajeshwari Shinde 		WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | WM8994_DAC1L_ENA |
685a2d8e0a7SRajeshwari Shinde 		WM8994_DAC1R_ENA);
686a2d8e0a7SRajeshwari Shinde 
687a2d8e0a7SRajeshwari Shinde 	/* Head Phone Initialisation */
688a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_ANALOGUE_HP_1,
689a2d8e0a7SRajeshwari Shinde 		WM8994_HPOUT1L_DLY_MASK | WM8994_HPOUT1R_DLY_MASK,
690a2d8e0a7SRajeshwari Shinde 		WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_DLY);
691a2d8e0a7SRajeshwari Shinde 
692a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_DC_SERVO_1,
693a2d8e0a7SRajeshwari Shinde 			WM8994_DCS_ENA_CHAN_0_MASK |
694a2d8e0a7SRajeshwari Shinde 			WM8994_DCS_ENA_CHAN_1_MASK , WM8994_DCS_ENA_CHAN_0 |
695a2d8e0a7SRajeshwari Shinde 			WM8994_DCS_ENA_CHAN_1);
696a2d8e0a7SRajeshwari Shinde 
697a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_ANALOGUE_HP_1,
698a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1L_DLY_MASK |
699a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1L_OUTP_MASK |
700a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_OUTP_MASK |
701a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1L_RMV_SHORT_MASK |
702a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_RMV_SHORT_MASK, WM8994_HPOUT1L_DLY |
703a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_DLY | WM8994_HPOUT1L_OUTP |
704a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_OUTP | WM8994_HPOUT1L_RMV_SHORT |
705a2d8e0a7SRajeshwari Shinde 			WM8994_HPOUT1R_RMV_SHORT);
706a2d8e0a7SRajeshwari Shinde 
707a2d8e0a7SRajeshwari Shinde 	/* MIXER Config DAC1 to HP */
708a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_OUTPUT_MIXER_1,
709a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1L_TO_HPOUT1L_MASK, WM8994_DAC1L_TO_HPOUT1L);
710a2d8e0a7SRajeshwari Shinde 
711a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_OUTPUT_MIXER_2,
712a2d8e0a7SRajeshwari Shinde 			WM8994_DAC1R_TO_HPOUT1R_MASK, WM8994_DAC1R_TO_HPOUT1R);
713a2d8e0a7SRajeshwari Shinde 
714a2d8e0a7SRajeshwari Shinde 	/* Routing AIF2 to DAC1 */
715a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_DAC1_LEFT_MIXER_ROUTING,
716a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DACL_TO_DAC1L_MASK,
717a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DACL_TO_DAC1L);
718a2d8e0a7SRajeshwari Shinde 
719a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_DAC1_RIGHT_MIXER_ROUTING,
720a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DACR_TO_DAC1R_MASK,
721a2d8e0a7SRajeshwari Shinde 			WM8994_AIF2DACR_TO_DAC1R);
722a2d8e0a7SRajeshwari Shinde 
723a2d8e0a7SRajeshwari Shinde 	 /* GPIO Settings for AIF2 */
724a2d8e0a7SRajeshwari Shinde 	 /* B CLK */
725a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_GPIO_3, WM8994_GPIO_DIR_MASK |
726a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_MASK ,
727a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_DIR_OUTPUT |
728a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_I2S_CLK);
729a2d8e0a7SRajeshwari Shinde 
730a2d8e0a7SRajeshwari Shinde 	/* LR CLK */
731a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_GPIO_4, WM8994_GPIO_DIR_MASK |
732a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_MASK,
733a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_DIR_OUTPUT |
734a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_I2S_CLK);
735a2d8e0a7SRajeshwari Shinde 
736a2d8e0a7SRajeshwari Shinde 	/* DATA */
737a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_update_bits(WM8994_GPIO_5, WM8994_GPIO_DIR_MASK |
738a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_MASK,
739a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_DIR_OUTPUT |
740a2d8e0a7SRajeshwari Shinde 				WM8994_GPIO_FUNCTION_I2S_CLK);
741a2d8e0a7SRajeshwari Shinde 
742a2d8e0a7SRajeshwari Shinde 	ret |= wm8994_init_volume_aif2_dac1();
743a2d8e0a7SRajeshwari Shinde 	if (ret < 0)
744a2d8e0a7SRajeshwari Shinde 		goto err;
745a2d8e0a7SRajeshwari Shinde 
746a2d8e0a7SRajeshwari Shinde 	debug("%s: Codec chip init ok\n", __func__);
747a2d8e0a7SRajeshwari Shinde 	return 0;
748a2d8e0a7SRajeshwari Shinde err:
749a2d8e0a7SRajeshwari Shinde 	debug("%s: Codec chip init error\n", __func__);
750a2d8e0a7SRajeshwari Shinde 	return -1;
751a2d8e0a7SRajeshwari Shinde }
752a2d8e0a7SRajeshwari Shinde 
753*6647c7acSRajeshwari Shinde /*
754*6647c7acSRajeshwari Shinde  * Gets fdt values for wm8994 config parameters
755*6647c7acSRajeshwari Shinde  *
756*6647c7acSRajeshwari Shinde  * @param pcodec_info	codec information structure
757*6647c7acSRajeshwari Shinde  * @param blob		FDT blob
758*6647c7acSRajeshwari Shinde  * @return		int value, 0 for success
759*6647c7acSRajeshwari Shinde  */
760*6647c7acSRajeshwari Shinde static int get_codec_values(struct sound_codec_info *pcodec_info,
761*6647c7acSRajeshwari Shinde 			const void *blob)
762*6647c7acSRajeshwari Shinde {
763*6647c7acSRajeshwari Shinde 	int error = 0;
764*6647c7acSRajeshwari Shinde #ifdef CONFIG_OF_CONTROL
765*6647c7acSRajeshwari Shinde 	enum fdt_compat_id compat;
766*6647c7acSRajeshwari Shinde 	int node;
767*6647c7acSRajeshwari Shinde 	int parent;
768*6647c7acSRajeshwari Shinde 
769*6647c7acSRajeshwari Shinde 	/* Get the node from FDT for codec */
770*6647c7acSRajeshwari Shinde 	node = fdtdec_next_compatible(blob, 0, COMPAT_WOLFSON_WM8994_CODEC);
771*6647c7acSRajeshwari Shinde 	if (node <= 0) {
772*6647c7acSRajeshwari Shinde 		debug("EXYNOS_SOUND: No node for codec in device tree\n");
773*6647c7acSRajeshwari Shinde 		debug("node = %d\n", node);
774*6647c7acSRajeshwari Shinde 		return -1;
775*6647c7acSRajeshwari Shinde 	}
776*6647c7acSRajeshwari Shinde 
777*6647c7acSRajeshwari Shinde 	parent = fdt_parent_offset(blob, node);
778*6647c7acSRajeshwari Shinde 	if (parent < 0) {
779*6647c7acSRajeshwari Shinde 		debug("%s: Cannot find node parent\n", __func__);
780*6647c7acSRajeshwari Shinde 		return -1;
781*6647c7acSRajeshwari Shinde 	}
782*6647c7acSRajeshwari Shinde 
783*6647c7acSRajeshwari Shinde 	compat = fdtdec_lookup(blob, parent);
784*6647c7acSRajeshwari Shinde 	switch (compat) {
785*6647c7acSRajeshwari Shinde 	case COMPAT_SAMSUNG_S3C2440_I2C:
786*6647c7acSRajeshwari Shinde 		pcodec_info->i2c_bus = i2c_get_bus_num_fdt(parent);
787*6647c7acSRajeshwari Shinde 		error |= pcodec_info->i2c_bus;
788*6647c7acSRajeshwari Shinde 		debug("i2c bus = %d\n", pcodec_info->i2c_bus);
789*6647c7acSRajeshwari Shinde 		pcodec_info->i2c_dev_addr = fdtdec_get_int(blob, node,
790*6647c7acSRajeshwari Shinde 							"reg", 0);
791*6647c7acSRajeshwari Shinde 		error |= pcodec_info->i2c_dev_addr;
792*6647c7acSRajeshwari Shinde 		debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr);
793*6647c7acSRajeshwari Shinde 		break;
794*6647c7acSRajeshwari Shinde 	default:
795*6647c7acSRajeshwari Shinde 		debug("%s: Unknown compat id %d\n", __func__, compat);
796*6647c7acSRajeshwari Shinde 		return -1;
797*6647c7acSRajeshwari Shinde 	}
798*6647c7acSRajeshwari Shinde #else
799*6647c7acSRajeshwari Shinde 	pcodec_info->i2c_bus = AUDIO_I2C_BUS;
800*6647c7acSRajeshwari Shinde 	pcodec_info->i2c_dev_addr = AUDIO_I2C_REG;
801*6647c7acSRajeshwari Shinde 	debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr);
802*6647c7acSRajeshwari Shinde #endif
803*6647c7acSRajeshwari Shinde 
804*6647c7acSRajeshwari Shinde 	pcodec_info->codec_type = CODEC_WM_8994;
805*6647c7acSRajeshwari Shinde 
806*6647c7acSRajeshwari Shinde 	if (error == -1) {
807*6647c7acSRajeshwari Shinde 		debug("fail to get wm8994 codec node properties\n");
808*6647c7acSRajeshwari Shinde 		return -1;
809*6647c7acSRajeshwari Shinde 	}
810*6647c7acSRajeshwari Shinde 
811*6647c7acSRajeshwari Shinde 	return 0;
812*6647c7acSRajeshwari Shinde }
813*6647c7acSRajeshwari Shinde 
814a2d8e0a7SRajeshwari Shinde /*wm8994 Device Initialisation */
815*6647c7acSRajeshwari Shinde int wm8994_init(const void *blob, enum en_audio_interface aif_id,
816a2d8e0a7SRajeshwari Shinde 			int sampling_rate, int mclk_freq,
817a2d8e0a7SRajeshwari Shinde 			int bits_per_sample, unsigned int channels)
818a2d8e0a7SRajeshwari Shinde {
819a2d8e0a7SRajeshwari Shinde 	int ret = 0;
820*6647c7acSRajeshwari Shinde 	struct sound_codec_info *pcodec_info = &g_codec_info;
821*6647c7acSRajeshwari Shinde 
822*6647c7acSRajeshwari Shinde 	/* Get the codec Values */
823*6647c7acSRajeshwari Shinde 	if (get_codec_values(pcodec_info, blob) < 0) {
824*6647c7acSRajeshwari Shinde 		debug("FDT Codec values failed\n");
825*6647c7acSRajeshwari Shinde 		return -1;
826*6647c7acSRajeshwari Shinde 	}
827a2d8e0a7SRajeshwari Shinde 
828a2d8e0a7SRajeshwari Shinde 	/* shift the device address by 1 for 7 bit addressing */
829a2d8e0a7SRajeshwari Shinde 	g_wm8994_i2c_dev_addr = pcodec_info->i2c_dev_addr;
830a2d8e0a7SRajeshwari Shinde 	wm8994_i2c_init(pcodec_info->i2c_bus);
831a2d8e0a7SRajeshwari Shinde 
832a2d8e0a7SRajeshwari Shinde 	if (pcodec_info->codec_type == CODEC_WM_8994)
833a2d8e0a7SRajeshwari Shinde 		g_wm8994_info.type = WM8994;
834a2d8e0a7SRajeshwari Shinde 	else {
835a2d8e0a7SRajeshwari Shinde 		debug("%s: Codec id [%d] not defined\n", __func__,
836a2d8e0a7SRajeshwari Shinde 				pcodec_info->codec_type);
837a2d8e0a7SRajeshwari Shinde 		return -1;
838a2d8e0a7SRajeshwari Shinde 	}
839a2d8e0a7SRajeshwari Shinde 
840a2d8e0a7SRajeshwari Shinde 	ret = wm8994_device_init(&g_wm8994_info);
841a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
842a2d8e0a7SRajeshwari Shinde 		debug("%s: wm8994 codec chip init failed\n", __func__);
843a2d8e0a7SRajeshwari Shinde 		return ret;
844a2d8e0a7SRajeshwari Shinde 	}
845a2d8e0a7SRajeshwari Shinde 
846a2d8e0a7SRajeshwari Shinde 	ret =  wm8994_set_sysclk(&g_wm8994_info, aif_id, WM8994_SYSCLK_MCLK1,
847a2d8e0a7SRajeshwari Shinde 							mclk_freq);
848a2d8e0a7SRajeshwari Shinde 	if (ret < 0) {
849a2d8e0a7SRajeshwari Shinde 		debug("%s: wm8994 codec set sys clock failed\n", __func__);
850a2d8e0a7SRajeshwari Shinde 		return ret;
851a2d8e0a7SRajeshwari Shinde 	}
852a2d8e0a7SRajeshwari Shinde 
853a2d8e0a7SRajeshwari Shinde 	ret = wm8994_hw_params(&g_wm8994_info, aif_id, sampling_rate,
854a2d8e0a7SRajeshwari Shinde 						bits_per_sample, channels);
855a2d8e0a7SRajeshwari Shinde 
856a2d8e0a7SRajeshwari Shinde 	if (ret == 0) {
857a2d8e0a7SRajeshwari Shinde 		ret = wm8994_set_fmt(aif_id, SND_SOC_DAIFMT_I2S |
858a2d8e0a7SRajeshwari Shinde 						SND_SOC_DAIFMT_NB_NF |
859a2d8e0a7SRajeshwari Shinde 						SND_SOC_DAIFMT_CBS_CFS);
860a2d8e0a7SRajeshwari Shinde 	}
861a2d8e0a7SRajeshwari Shinde 	return ret;
862a2d8e0a7SRajeshwari Shinde }
863