1fe1ff614SJack Yu // SPDX-License-Identifier: GPL-2.0-only
2fe1ff614SJack Yu //
3fe1ff614SJack Yu // rt1318.c -- RT1318 ALSA SoC audio amplifier driver
4fe1ff614SJack Yu // Author: Jack Yu <jack.yu@realtek.com>
5fe1ff614SJack Yu //
6fe1ff614SJack Yu // Copyright(c) 2024 Realtek Semiconductor Corp.
7fe1ff614SJack Yu //
8fe1ff614SJack Yu //
9fe1ff614SJack Yu
10fe1ff614SJack Yu #include <linux/acpi.h>
11fe1ff614SJack Yu #include <linux/fs.h>
12fe1ff614SJack Yu #include <linux/module.h>
13fe1ff614SJack Yu #include <linux/moduleparam.h>
14fe1ff614SJack Yu #include <linux/init.h>
15fe1ff614SJack Yu #include <linux/delay.h>
16fe1ff614SJack Yu #include <linux/pm.h>
17fe1ff614SJack Yu #include <linux/regmap.h>
18fe1ff614SJack Yu #include <linux/i2c.h>
19fe1ff614SJack Yu #include <linux/platform_device.h>
20fe1ff614SJack Yu #include <linux/firmware.h>
21fe1ff614SJack Yu #include <linux/gpio.h>
22fe1ff614SJack Yu #include <sound/core.h>
23fe1ff614SJack Yu #include <sound/pcm.h>
24fe1ff614SJack Yu #include <sound/pcm_params.h>
25fe1ff614SJack Yu #include <sound/soc.h>
26fe1ff614SJack Yu #include <sound/soc-dapm.h>
27fe1ff614SJack Yu #include <sound/initval.h>
28fe1ff614SJack Yu #include <sound/tlv.h>
29fe1ff614SJack Yu #include <sound/rt1318.h>
30fe1ff614SJack Yu
31fe1ff614SJack Yu #include "rt1318.h"
32fe1ff614SJack Yu
33ab73c7c0SChristophe JAILLET static const struct reg_sequence init_list[] = {
34fe1ff614SJack Yu { 0x0000C000, 0x01},
35fe1ff614SJack Yu { 0x0000F20D, 0x00},
36fe1ff614SJack Yu { 0x0000F212, 0x3E},
37fe1ff614SJack Yu { 0x0000C001, 0x02},
38fe1ff614SJack Yu { 0x0000C003, 0x22},
39fe1ff614SJack Yu { 0x0000C004, 0x44},
40fe1ff614SJack Yu { 0x0000C005, 0x44},
41fe1ff614SJack Yu { 0x0000C007, 0x64},
42fe1ff614SJack Yu { 0x0000C00E, 0xE7},
43fe1ff614SJack Yu { 0x0000F223, 0x7F},
44fe1ff614SJack Yu { 0x0000F224, 0xDB},
45fe1ff614SJack Yu { 0x0000F225, 0xEE},
46fe1ff614SJack Yu { 0x0000F226, 0x3F},
47fe1ff614SJack Yu { 0x0000F227, 0x0F},
48fe1ff614SJack Yu { 0x0000F21A, 0x78},
49fe1ff614SJack Yu { 0x0000F242, 0x3C},
50fe1ff614SJack Yu { 0x0000C120, 0x40},
51fe1ff614SJack Yu { 0x0000C125, 0x03},
52fe1ff614SJack Yu { 0x0000C321, 0x0A},
53fe1ff614SJack Yu { 0x0000C200, 0xD8},
54fe1ff614SJack Yu { 0x0000C201, 0x27},
55fe1ff614SJack Yu { 0x0000C202, 0x0F},
56fe1ff614SJack Yu { 0x0000C400, 0x0E},
57fe1ff614SJack Yu { 0x0000C401, 0x43},
58fe1ff614SJack Yu { 0x0000C402, 0xE0},
59fe1ff614SJack Yu { 0x0000C403, 0x00},
60fe1ff614SJack Yu { 0x0000C404, 0x4C},
61fe1ff614SJack Yu { 0x0000C406, 0x40},
62fe1ff614SJack Yu { 0x0000C407, 0x02},
63fe1ff614SJack Yu { 0x0000C408, 0x3F},
64fe1ff614SJack Yu { 0x0000C300, 0x01},
65fe1ff614SJack Yu { 0x0000C125, 0x03},
66fe1ff614SJack Yu { 0x0000DF00, 0x10},
67fe1ff614SJack Yu { 0x0000F20B, 0x2A},
68fe1ff614SJack Yu { 0x0000DF5F, 0x01},
69fe1ff614SJack Yu { 0x0000DF60, 0xA7},
70fe1ff614SJack Yu { 0x0000C203, 0x84},
71fe1ff614SJack Yu { 0x0000C206, 0x78},
72fe1ff614SJack Yu { 0x0000F10A, 0x09},
73fe1ff614SJack Yu { 0x0000F10B, 0x4C},
74fe1ff614SJack Yu { 0x0000F104, 0xF4},
75fe1ff614SJack Yu { 0x0000F105, 0x03},
76fe1ff614SJack Yu { 0x0000F109, 0xE0},
77fe1ff614SJack Yu { 0x0000F10B, 0x5C},
78fe1ff614SJack Yu { 0x0000F104, 0xF4},
79fe1ff614SJack Yu { 0x0000F105, 0x04},
80fe1ff614SJack Yu { 0x0000F109, 0x65},
81fe1ff614SJack Yu { 0x0000F10B, 0x5C},
82fe1ff614SJack Yu { 0x0000F104, 0xF4},
83fe1ff614SJack Yu { 0x0000F105, 0x02},
84fe1ff614SJack Yu { 0x0000F109, 0x30},
85fe1ff614SJack Yu { 0x0000F10B, 0x5C},
86fe1ff614SJack Yu { 0x0000E706, 0x0F},
87fe1ff614SJack Yu { 0x0000E707, 0x30},
88fe1ff614SJack Yu { 0x0000E806, 0x0F},
89fe1ff614SJack Yu { 0x0000E807, 0x30},
90fe1ff614SJack Yu { 0x0000CE04, 0x03},
91fe1ff614SJack Yu { 0x0000CE05, 0x5F},
92fe1ff614SJack Yu { 0x0000CE06, 0xA2},
93fe1ff614SJack Yu { 0x0000CE07, 0x6B},
94fe1ff614SJack Yu { 0x0000CF04, 0x03},
95fe1ff614SJack Yu { 0x0000CF05, 0x5F},
96fe1ff614SJack Yu { 0x0000CF06, 0xA2},
97fe1ff614SJack Yu { 0x0000CF07, 0x6B},
98fe1ff614SJack Yu { 0x0000CE60, 0xE3},
99fe1ff614SJack Yu { 0x0000C130, 0x51},
100fe1ff614SJack Yu { 0x0000E000, 0xA8},
101fe1ff614SJack Yu { 0x0000F102, 0x00},
102fe1ff614SJack Yu { 0x0000F103, 0x00},
103fe1ff614SJack Yu { 0x0000F104, 0xF5},
104fe1ff614SJack Yu { 0x0000F105, 0x23},
105fe1ff614SJack Yu { 0x0000F109, 0x04},
106fe1ff614SJack Yu { 0x0000F10A, 0x0B},
107fe1ff614SJack Yu { 0x0000F10B, 0x4C},
108fe1ff614SJack Yu { 0x0000F10B, 0x5C},
109fe1ff614SJack Yu { 0x41001888, 0x00},
110fe1ff614SJack Yu { 0x0000C121, 0x0B},
111fe1ff614SJack Yu { 0x0000F102, 0x00},
112fe1ff614SJack Yu { 0x0000F103, 0x00},
113fe1ff614SJack Yu { 0x0000F104, 0xF5},
114fe1ff614SJack Yu { 0x0000F105, 0x23},
115fe1ff614SJack Yu { 0x0000F109, 0x00},
116fe1ff614SJack Yu { 0x0000F10A, 0x0B},
117fe1ff614SJack Yu { 0x0000F10B, 0x4C},
118fe1ff614SJack Yu { 0x0000F10B, 0x5C},
119fe1ff614SJack Yu { 0x0000F800, 0x20},
120fe1ff614SJack Yu { 0x0000CA00, 0x80},
121fe1ff614SJack Yu { 0x0000CA10, 0x00},
122fe1ff614SJack Yu { 0x0000CA02, 0x78},
123fe1ff614SJack Yu { 0x0000CA12, 0x78},
124fe1ff614SJack Yu { 0x0000ED00, 0x90},
125fe1ff614SJack Yu { 0x0000E604, 0x00},
126fe1ff614SJack Yu { 0x0000DB00, 0x0C},
127fe1ff614SJack Yu { 0x0000DD00, 0x0C},
128fe1ff614SJack Yu { 0x0000DC19, 0x00},
129fe1ff614SJack Yu { 0x0000DC1A, 0x6A},
130fe1ff614SJack Yu { 0x0000DC1B, 0xAA},
131fe1ff614SJack Yu { 0x0000DC1C, 0xAB},
132fe1ff614SJack Yu { 0x0000DC1D, 0x00},
133fe1ff614SJack Yu { 0x0000DC1E, 0x16},
134fe1ff614SJack Yu { 0x0000DC1F, 0xDB},
135fe1ff614SJack Yu { 0x0000DC20, 0x6D},
136fe1ff614SJack Yu { 0x0000DE19, 0x00},
137fe1ff614SJack Yu { 0x0000DE1A, 0x6A},
138fe1ff614SJack Yu { 0x0000DE1B, 0xAA},
139fe1ff614SJack Yu { 0x0000DE1C, 0xAB},
140fe1ff614SJack Yu { 0x0000DE1D, 0x00},
141fe1ff614SJack Yu { 0x0000DE1E, 0x16},
142fe1ff614SJack Yu { 0x0000DE1F, 0xDB},
143fe1ff614SJack Yu { 0x0000DE20, 0x6D},
144fe1ff614SJack Yu { 0x0000DB32, 0x00},
145fe1ff614SJack Yu { 0x0000DD32, 0x00},
146fe1ff614SJack Yu { 0x0000DB33, 0x0A},
147fe1ff614SJack Yu { 0x0000DD33, 0x0A},
148fe1ff614SJack Yu { 0x0000DB34, 0x1A},
149fe1ff614SJack Yu { 0x0000DD34, 0x1A},
150fe1ff614SJack Yu { 0x0000DB15, 0xEF},
151fe1ff614SJack Yu { 0x0000DD15, 0xEF},
152fe1ff614SJack Yu { 0x0000DB17, 0xEF},
153fe1ff614SJack Yu { 0x0000DD17, 0xEF},
154fe1ff614SJack Yu { 0x0000DB94, 0x70},
155fe1ff614SJack Yu { 0x0000DD94, 0x70},
156fe1ff614SJack Yu { 0x0000DB19, 0x40},
157fe1ff614SJack Yu { 0x0000DD19, 0x40},
158fe1ff614SJack Yu { 0x0000DB12, 0xC0},
159fe1ff614SJack Yu { 0x0000DD12, 0xC0},
160fe1ff614SJack Yu { 0x0000DB00, 0x4C},
161fe1ff614SJack Yu { 0x0000DB04, 0x05},
162fe1ff614SJack Yu { 0x0000DB05, 0x03},
163fe1ff614SJack Yu { 0x0000DD04, 0x05},
164fe1ff614SJack Yu { 0x0000DD05, 0x03},
165fe1ff614SJack Yu { 0x0000DBBB, 0x09},
166fe1ff614SJack Yu { 0x0000DBBC, 0x30},
167fe1ff614SJack Yu { 0x0000DBBD, 0xF0},
168fe1ff614SJack Yu { 0x0000DBBE, 0xF1},
169fe1ff614SJack Yu { 0x0000DDBB, 0x09},
170fe1ff614SJack Yu { 0x0000DDBC, 0x30},
171fe1ff614SJack Yu { 0x0000DDBD, 0xF0},
172fe1ff614SJack Yu { 0x0000DDBE, 0xF1},
173fe1ff614SJack Yu { 0x0000DB01, 0x79},
174fe1ff614SJack Yu { 0x0000DD01, 0x79},
175fe1ff614SJack Yu { 0x0000DB08, 0x40},
176fe1ff614SJack Yu { 0x0000DD08, 0x40},
177fe1ff614SJack Yu { 0x0000DC52, 0xEF},
178fe1ff614SJack Yu { 0x0000DE52, 0xEF},
179fe1ff614SJack Yu { 0x0000DB00, 0xCC},
180fe1ff614SJack Yu { 0x0000CC2C, 0x00},
181fe1ff614SJack Yu { 0x0000CC2D, 0x2A},
182fe1ff614SJack Yu { 0x0000CC2E, 0x83},
183fe1ff614SJack Yu { 0x0000CC2F, 0xA8},
184fe1ff614SJack Yu { 0x0000CD2C, 0x00},
185fe1ff614SJack Yu { 0x0000CD2D, 0x2A},
186fe1ff614SJack Yu { 0x0000CD2E, 0x83},
187fe1ff614SJack Yu { 0x0000CD2F, 0xA8},
188fe1ff614SJack Yu { 0x0000CC24, 0x00},
189fe1ff614SJack Yu { 0x0000CC25, 0x51},
190fe1ff614SJack Yu { 0x0000CC26, 0xEB},
191fe1ff614SJack Yu { 0x0000CC27, 0x85},
192fe1ff614SJack Yu { 0x0000CD24, 0x00},
193fe1ff614SJack Yu { 0x0000CD25, 0x51},
194fe1ff614SJack Yu { 0x0000CD26, 0xEB},
195fe1ff614SJack Yu { 0x0000CD27, 0x85},
196fe1ff614SJack Yu { 0x0000CC20, 0x00},
197fe1ff614SJack Yu { 0x0000CC21, 0x00},
198fe1ff614SJack Yu { 0x0000CC22, 0x43},
199fe1ff614SJack Yu { 0x0000CD20, 0x00},
200fe1ff614SJack Yu { 0x0000CD21, 0x00},
201fe1ff614SJack Yu { 0x0000CD22, 0x43},
202fe1ff614SJack Yu { 0x0000CC16, 0x0F},
203fe1ff614SJack Yu { 0x0000CC17, 0x00},
204fe1ff614SJack Yu { 0x0000CD16, 0x0F},
205fe1ff614SJack Yu { 0x0000CD17, 0x00},
206fe1ff614SJack Yu { 0x0000CC29, 0x5D},
207fe1ff614SJack Yu { 0x0000CC2A, 0xC0},
208fe1ff614SJack Yu { 0x0000CD29, 0x5D},
209fe1ff614SJack Yu { 0x0000CD2A, 0xC0},
210fe1ff614SJack Yu { 0x0000CC31, 0x20},
211fe1ff614SJack Yu { 0x0000CC32, 0x00},
212fe1ff614SJack Yu { 0x0000CC33, 0x00},
213fe1ff614SJack Yu { 0x0000CC34, 0x00},
214fe1ff614SJack Yu { 0x0000CD31, 0x20},
215fe1ff614SJack Yu { 0x0000CD32, 0x00},
216fe1ff614SJack Yu { 0x0000CD33, 0x00},
217fe1ff614SJack Yu { 0x0000CD34, 0x00},
218fe1ff614SJack Yu { 0x0000CC36, 0x79},
219fe1ff614SJack Yu { 0x0000CC37, 0x99},
220fe1ff614SJack Yu { 0x0000CC38, 0x99},
221fe1ff614SJack Yu { 0x0000CC39, 0x99},
222fe1ff614SJack Yu { 0x0000CD36, 0x79},
223fe1ff614SJack Yu { 0x0000CD37, 0x99},
224fe1ff614SJack Yu { 0x0000CD38, 0x99},
225fe1ff614SJack Yu { 0x0000CD39, 0x99},
226fe1ff614SJack Yu { 0x0000CC09, 0x00},
227fe1ff614SJack Yu { 0x0000CC0A, 0x07},
228fe1ff614SJack Yu { 0x0000CC0B, 0x5F},
229fe1ff614SJack Yu { 0x0000CC0C, 0x6F},
230fe1ff614SJack Yu { 0x0000CD09, 0x00},
231fe1ff614SJack Yu { 0x0000CD0A, 0x07},
232fe1ff614SJack Yu { 0x0000CD0B, 0x5F},
233fe1ff614SJack Yu { 0x0000CD0C, 0x6F},
234fe1ff614SJack Yu { 0x0000CC0E, 0x00},
235fe1ff614SJack Yu { 0x0000CC0F, 0x03},
236fe1ff614SJack Yu { 0x0000CC10, 0xAF},
237fe1ff614SJack Yu { 0x0000CC11, 0xB7},
238fe1ff614SJack Yu { 0x0000CD0E, 0x00},
239fe1ff614SJack Yu { 0x0000CD0F, 0x03},
240fe1ff614SJack Yu { 0x0000CD10, 0xAF},
241fe1ff614SJack Yu { 0x0000CD11, 0xB7},
242fe1ff614SJack Yu { 0x0000CCD6, 0x00},
243fe1ff614SJack Yu { 0x0000CCD7, 0x03},
244fe1ff614SJack Yu { 0x0000CDD6, 0x00},
245fe1ff614SJack Yu { 0x0000CDD7, 0x03},
246fe1ff614SJack Yu { 0x0000CCD8, 0x00},
247fe1ff614SJack Yu { 0x0000CCD9, 0x03},
248fe1ff614SJack Yu { 0x0000CDD8, 0x00},
249fe1ff614SJack Yu { 0x0000CDD9, 0x03},
250fe1ff614SJack Yu { 0x0000CCDA, 0x00},
251fe1ff614SJack Yu { 0x0000CCDB, 0x03},
252fe1ff614SJack Yu { 0x0000CDDA, 0x00},
253fe1ff614SJack Yu { 0x0000CDDB, 0x03},
254fe1ff614SJack Yu { 0x0000C320, 0x20},
255fe1ff614SJack Yu { 0x0000C203, 0x9C},
256fe1ff614SJack Yu };
257fe1ff614SJack Yu
258fe1ff614SJack Yu static const struct reg_default rt1318_reg[] = {
259fe1ff614SJack Yu { 0xc000, 0x00 },
260fe1ff614SJack Yu { 0xc001, 0x43 },
261fe1ff614SJack Yu { 0xc003, 0x22 },
262fe1ff614SJack Yu { 0xc004, 0x44 },
263fe1ff614SJack Yu { 0xc005, 0x44 },
264fe1ff614SJack Yu { 0xc006, 0x33 },
265fe1ff614SJack Yu { 0xc007, 0x64 },
266fe1ff614SJack Yu { 0xc008, 0x05 },
267fe1ff614SJack Yu { 0xc00a, 0xfc },
268fe1ff614SJack Yu { 0xc00b, 0x0f },
269fe1ff614SJack Yu { 0xc00c, 0x0e },
270fe1ff614SJack Yu { 0xc00d, 0xef },
271fe1ff614SJack Yu { 0xc00e, 0xe5 },
272fe1ff614SJack Yu { 0xc00f, 0xff },
273fe1ff614SJack Yu { 0xc120, 0xc0 },
274fe1ff614SJack Yu { 0xc121, 0x00 },
275fe1ff614SJack Yu { 0xc122, 0x00 },
276fe1ff614SJack Yu { 0xc123, 0x14 },
277fe1ff614SJack Yu { 0xc125, 0x00 },
278fe1ff614SJack Yu { 0xc130, 0x59 },
279fe1ff614SJack Yu { 0xc200, 0x00 },
280fe1ff614SJack Yu { 0xc201, 0x00 },
281fe1ff614SJack Yu { 0xc202, 0x00 },
282fe1ff614SJack Yu { 0xc203, 0x04 },
283fe1ff614SJack Yu { 0xc204, 0x00 },
284fe1ff614SJack Yu { 0xc205, 0x00 },
285fe1ff614SJack Yu { 0xc206, 0x68 },
286fe1ff614SJack Yu { 0xc207, 0x70 },
287fe1ff614SJack Yu { 0xc208, 0x00 },
288fe1ff614SJack Yu { 0xc20a, 0x00 },
289fe1ff614SJack Yu { 0xc20b, 0x01 },
290fe1ff614SJack Yu { 0xc20c, 0x7f },
291fe1ff614SJack Yu { 0xc20d, 0x01 },
292fe1ff614SJack Yu { 0xc20e, 0x7f },
293fe1ff614SJack Yu { 0xc300, 0x00 },
294fe1ff614SJack Yu { 0xc301, 0x00 },
295fe1ff614SJack Yu { 0xc303, 0x80 },
296fe1ff614SJack Yu { 0xc320, 0x00 },
297fe1ff614SJack Yu { 0xc321, 0x09 },
298fe1ff614SJack Yu { 0xc322, 0x02 },
299fe1ff614SJack Yu { 0xc400, 0x00 },
300fe1ff614SJack Yu { 0xc401, 0x00 },
301fe1ff614SJack Yu { 0xc402, 0x00 },
302fe1ff614SJack Yu { 0xc403, 0x00 },
303fe1ff614SJack Yu { 0xc404, 0x00 },
304fe1ff614SJack Yu { 0xc405, 0x00 },
305fe1ff614SJack Yu { 0xc406, 0x00 },
306fe1ff614SJack Yu { 0xc407, 0x00 },
307fe1ff614SJack Yu { 0xc408, 0x00 },
308fe1ff614SJack Yu { 0xc410, 0x04 },
309fe1ff614SJack Yu { 0xc430, 0x00 },
310fe1ff614SJack Yu { 0xc431, 0x00 },
311fe1ff614SJack Yu { 0xca00, 0x10 },
312fe1ff614SJack Yu { 0xca01, 0x00 },
313fe1ff614SJack Yu { 0xca02, 0x0b },
314fe1ff614SJack Yu { 0xca10, 0x10 },
315fe1ff614SJack Yu { 0xca11, 0x00 },
316fe1ff614SJack Yu { 0xca12, 0x0b },
317fe1ff614SJack Yu { 0xce04, 0x08 },
318fe1ff614SJack Yu { 0xce05, 0x00 },
319fe1ff614SJack Yu { 0xce06, 0x00 },
320fe1ff614SJack Yu { 0xce07, 0x00 },
321fe1ff614SJack Yu { 0xce60, 0x63 },
322fe1ff614SJack Yu { 0xcf04, 0x08 },
323fe1ff614SJack Yu { 0xcf05, 0x00 },
324fe1ff614SJack Yu { 0xcf06, 0x00 },
325fe1ff614SJack Yu { 0xcf07, 0x00 },
326fe1ff614SJack Yu { 0xdb00, 0x00 },
327fe1ff614SJack Yu { 0xdb08, 0x40 },
328fe1ff614SJack Yu { 0xdb12, 0x00 },
329fe1ff614SJack Yu { 0xdb35, 0x00 },
330fe1ff614SJack Yu { 0xdbb5, 0x00 },
331fe1ff614SJack Yu { 0xdbb6, 0x40 },
332fe1ff614SJack Yu { 0xdbb7, 0x00 },
333fe1ff614SJack Yu { 0xdbb8, 0x00 },
334fe1ff614SJack Yu { 0xdbc5, 0x00 },
335fe1ff614SJack Yu { 0xdbc6, 0x00 },
336fe1ff614SJack Yu { 0xdbc7, 0x00 },
337fe1ff614SJack Yu { 0xdbc8, 0x00 },
338fe1ff614SJack Yu { 0xdd08, 0x40 },
339fe1ff614SJack Yu { 0xdd12, 0x00 },
340fe1ff614SJack Yu { 0xdd35, 0x00 },
341fe1ff614SJack Yu { 0xddb5, 0x00 },
342fe1ff614SJack Yu { 0xddb6, 0x40 },
343fe1ff614SJack Yu { 0xddb7, 0x00 },
344fe1ff614SJack Yu { 0xddb8, 0x00 },
345fe1ff614SJack Yu { 0xddc5, 0x00 },
346fe1ff614SJack Yu { 0xddc6, 0x00 },
347fe1ff614SJack Yu { 0xddc7, 0x00 },
348fe1ff614SJack Yu { 0xddc8, 0x00 },
349fe1ff614SJack Yu { 0xdd93, 0x00 },
350fe1ff614SJack Yu { 0xdd94, 0x64 },
351fe1ff614SJack Yu { 0xdf00, 0x00 },
352fe1ff614SJack Yu { 0xdf5f, 0x00 },
353fe1ff614SJack Yu { 0xdf60, 0x00 },
354fe1ff614SJack Yu { 0xe000, 0x08 },
355fe1ff614SJack Yu { 0xe300, 0xa0 },
356fe1ff614SJack Yu { 0xe400, 0x22 },
357fe1ff614SJack Yu { 0xe706, 0x2f },
358fe1ff614SJack Yu { 0xe707, 0x2f },
359fe1ff614SJack Yu { 0xe806, 0x2f },
360fe1ff614SJack Yu { 0xe807, 0x2f },
361fe1ff614SJack Yu { 0xea00, 0x43 },
362fe1ff614SJack Yu { 0xed00, 0x80 },
363fe1ff614SJack Yu { 0xed01, 0x0f },
364fe1ff614SJack Yu { 0xed02, 0xff },
365fe1ff614SJack Yu { 0xed03, 0x00 },
366fe1ff614SJack Yu { 0xed04, 0x00 },
367fe1ff614SJack Yu { 0xed05, 0x0f },
368fe1ff614SJack Yu { 0xed06, 0xff },
369fe1ff614SJack Yu { 0xf010, 0x10 },
370fe1ff614SJack Yu { 0xf011, 0xec },
371fe1ff614SJack Yu { 0xf012, 0x68 },
372fe1ff614SJack Yu { 0xf013, 0x21 },
373fe1ff614SJack Yu { 0xf102, 0x00 },
374fe1ff614SJack Yu { 0xf103, 0x00 },
375fe1ff614SJack Yu { 0xf104, 0x00 },
376fe1ff614SJack Yu { 0xf105, 0x00 },
377fe1ff614SJack Yu { 0xf106, 0x00 },
378fe1ff614SJack Yu { 0xf107, 0x00 },
379fe1ff614SJack Yu { 0xf108, 0x00 },
380fe1ff614SJack Yu { 0xf109, 0x00 },
381fe1ff614SJack Yu { 0xf10a, 0x03 },
382fe1ff614SJack Yu { 0xf10b, 0x40 },
383fe1ff614SJack Yu { 0xf20b, 0x28 },
384fe1ff614SJack Yu { 0xf20d, 0x00 },
385fe1ff614SJack Yu { 0xf212, 0x00 },
386fe1ff614SJack Yu { 0xf21a, 0x00 },
387fe1ff614SJack Yu { 0xf223, 0x40 },
388fe1ff614SJack Yu { 0xf224, 0x00 },
389fe1ff614SJack Yu { 0xf225, 0x00 },
390fe1ff614SJack Yu { 0xf226, 0x00 },
391fe1ff614SJack Yu { 0xf227, 0x00 },
392fe1ff614SJack Yu { 0xf242, 0x0c },
393fe1ff614SJack Yu { 0xf800, 0x00 },
394fe1ff614SJack Yu { 0xf801, 0x12 },
395fe1ff614SJack Yu { 0xf802, 0xe0 },
396fe1ff614SJack Yu { 0xf803, 0x2f },
397fe1ff614SJack Yu { 0xf804, 0x00 },
398fe1ff614SJack Yu { 0xf805, 0x00 },
399fe1ff614SJack Yu { 0xf806, 0x07 },
400fe1ff614SJack Yu { 0xf807, 0xff },
401fe1ff614SJack Yu };
402fe1ff614SJack Yu
rt1318_volatile_register(struct device * dev,unsigned int reg)403fe1ff614SJack Yu static bool rt1318_volatile_register(struct device *dev, unsigned int reg)
404fe1ff614SJack Yu {
405fe1ff614SJack Yu switch (reg) {
406fe1ff614SJack Yu case 0xc000:
407fe1ff614SJack Yu case 0xc301:
408fe1ff614SJack Yu case 0xc410:
409fe1ff614SJack Yu case 0xc430 ... 0xc431:
410fe1ff614SJack Yu case 0xdb06:
411fe1ff614SJack Yu case 0xdb12:
412fe1ff614SJack Yu case 0xdb1d ... 0xdb1f:
413fe1ff614SJack Yu case 0xdb35:
414fe1ff614SJack Yu case 0xdb37:
415fe1ff614SJack Yu case 0xdb8a ... 0xdb92:
416fe1ff614SJack Yu case 0xdbc5 ... 0xdbc8:
417fe1ff614SJack Yu case 0xdc2b ... 0xdc49:
418fe1ff614SJack Yu case 0xdd0b:
419fe1ff614SJack Yu case 0xdd12:
420fe1ff614SJack Yu case 0xdd1d ... 0xdd1f:
421fe1ff614SJack Yu case 0xdd35:
422fe1ff614SJack Yu case 0xdd8a ... 0xdd92:
423fe1ff614SJack Yu case 0xddc5 ... 0xddc8:
424fe1ff614SJack Yu case 0xde2b ... 0xde44:
425fe1ff614SJack Yu case 0xdf4a ... 0xdf55:
426fe1ff614SJack Yu case 0xe224 ... 0xe23b:
427fe1ff614SJack Yu case 0xea01:
428fe1ff614SJack Yu case 0xebc5:
429fe1ff614SJack Yu case 0xebc8:
430fe1ff614SJack Yu case 0xebcb ... 0xebcc:
431fe1ff614SJack Yu case 0xed03 ... 0xed06:
432fe1ff614SJack Yu case 0xf010 ... 0xf014:
433fe1ff614SJack Yu return true;
434fe1ff614SJack Yu
435fe1ff614SJack Yu default:
436fe1ff614SJack Yu return false;
437fe1ff614SJack Yu }
438fe1ff614SJack Yu }
439fe1ff614SJack Yu
rt1318_readable_register(struct device * dev,unsigned int reg)440fe1ff614SJack Yu static bool rt1318_readable_register(struct device *dev, unsigned int reg)
441fe1ff614SJack Yu {
442fe1ff614SJack Yu switch (reg) {
443fe1ff614SJack Yu case 0xc000 ... 0xc00f:
444fe1ff614SJack Yu case 0xc120 ... 0xc130:
445fe1ff614SJack Yu case 0xc200 ... 0xc20e:
446fe1ff614SJack Yu case 0xc300 ... 0xc303:
447fe1ff614SJack Yu case 0xc320 ... 0xc322:
448fe1ff614SJack Yu case 0xc400 ... 0xc408:
449fe1ff614SJack Yu case 0xc430 ... 0xc431:
450fe1ff614SJack Yu case 0xca00 ... 0xca02:
451fe1ff614SJack Yu case 0xca10 ... 0xca12:
452fe1ff614SJack Yu case 0xcb00 ... 0xcb0b:
453fe1ff614SJack Yu case 0xcc00 ... 0xcce5:
454fe1ff614SJack Yu case 0xcd00 ... 0xcde5:
455fe1ff614SJack Yu case 0xce00 ... 0xce6a:
456fe1ff614SJack Yu case 0xcf00 ... 0xcf53:
457fe1ff614SJack Yu case 0xd000 ... 0xd0cc:
458fe1ff614SJack Yu case 0xd100 ... 0xd1b9:
459fe1ff614SJack Yu case 0xdb00 ... 0xdc53:
460fe1ff614SJack Yu case 0xdd00 ... 0xde53:
461fe1ff614SJack Yu case 0xdf00 ... 0xdf6b:
462fe1ff614SJack Yu case 0xe000:
463fe1ff614SJack Yu case 0xe300:
464fe1ff614SJack Yu case 0xe400:
465fe1ff614SJack Yu case 0xe706 ... 0xe707:
466fe1ff614SJack Yu case 0xe806 ... 0xe807:
467fe1ff614SJack Yu case 0xea00:
468fe1ff614SJack Yu case 0xeb00 ... 0xebcc:
469fe1ff614SJack Yu case 0xec00 ... 0xecb9:
470fe1ff614SJack Yu case 0xed00 ... 0xed06:
471fe1ff614SJack Yu case 0xf010 ... 0xf014:
472fe1ff614SJack Yu case 0xf102 ... 0xf10b:
473fe1ff614SJack Yu case 0xf20b:
474fe1ff614SJack Yu case 0xf20d ... 0xf242:
475fe1ff614SJack Yu case 0xf800 ... 0xf807:
476fe1ff614SJack Yu return true;
477fe1ff614SJack Yu default:
478fe1ff614SJack Yu return false;
479fe1ff614SJack Yu }
480fe1ff614SJack Yu }
481fe1ff614SJack Yu
rt1318_dac_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)482fe1ff614SJack Yu static int rt1318_dac_event(struct snd_soc_dapm_widget *w,
483fe1ff614SJack Yu struct snd_kcontrol *kcontrol, int event)
484fe1ff614SJack Yu {
485fe1ff614SJack Yu struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
486fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
487fe1ff614SJack Yu
488fe1ff614SJack Yu switch (event) {
489fe1ff614SJack Yu case SND_SOC_DAPM_PRE_PMU:
490fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1,
491fe1ff614SJack Yu RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_HIGH);
492fe1ff614SJack Yu break;
493fe1ff614SJack Yu
494fe1ff614SJack Yu case SND_SOC_DAPM_POST_PMD:
495fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PWR_STA1,
496fe1ff614SJack Yu RT1318_PDB_CTRL_MASK, RT1318_PDB_CTRL_LOW);
497fe1ff614SJack Yu break;
498fe1ff614SJack Yu
499fe1ff614SJack Yu default:
500fe1ff614SJack Yu break;
501fe1ff614SJack Yu }
502fe1ff614SJack Yu return 0;
503fe1ff614SJack Yu }
504fe1ff614SJack Yu
rt1318_dvol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)505fe1ff614SJack Yu static int rt1318_dvol_put(struct snd_kcontrol *kcontrol,
506fe1ff614SJack Yu struct snd_ctl_elem_value *ucontrol)
507fe1ff614SJack Yu {
508fe1ff614SJack Yu struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
509fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
510fe1ff614SJack Yu
511fe1ff614SJack Yu rt1318->rt1318_dvol = ucontrol->value.integer.value[0];
512fe1ff614SJack Yu
513fe1ff614SJack Yu if (rt1318->rt1318_dvol <= RT1318_DVOL_STEP && rt1318->rt1318_dvol >= 0) {
514fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_DA_VOL_L_8,
515fe1ff614SJack Yu rt1318->rt1318_dvol >> 8);
516fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_DA_VOL_L_1_7,
517fe1ff614SJack Yu rt1318->rt1318_dvol & 0xff);
518fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_DA_VOL_R_8,
519fe1ff614SJack Yu rt1318->rt1318_dvol >> 8);
520fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_DA_VOL_R_1_7,
521fe1ff614SJack Yu rt1318->rt1318_dvol & 0xff);
522fe1ff614SJack Yu return 1;
523fe1ff614SJack Yu }
524fe1ff614SJack Yu
525fe1ff614SJack Yu return 0;
526fe1ff614SJack Yu }
527fe1ff614SJack Yu
rt1318_dvol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)528fe1ff614SJack Yu static int rt1318_dvol_get(struct snd_kcontrol *kcontrol,
529fe1ff614SJack Yu struct snd_ctl_elem_value *ucontrol)
530fe1ff614SJack Yu {
531fe1ff614SJack Yu struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
532fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
533fe1ff614SJack Yu
534fe1ff614SJack Yu ucontrol->value.integer.value[0] = rt1318->rt1318_dvol;
535fe1ff614SJack Yu
536fe1ff614SJack Yu return 0;
537fe1ff614SJack Yu }
538fe1ff614SJack Yu
539fe1ff614SJack Yu static const struct snd_kcontrol_new rt1318_snd_controls[] = {
540fe1ff614SJack Yu SOC_SINGLE_EXT("Amp Playback Volume", SND_SOC_NOPM, 0, 383, 0,
541fe1ff614SJack Yu rt1318_dvol_get, rt1318_dvol_put),
542fe1ff614SJack Yu };
543fe1ff614SJack Yu
544fe1ff614SJack Yu static const struct snd_soc_dapm_widget rt1318_dapm_widgets[] = {
545fe1ff614SJack Yu /* Audio Interface */
546fe1ff614SJack Yu SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
547fe1ff614SJack Yu /* DACs */
548fe1ff614SJack Yu SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
549fe1ff614SJack Yu rt1318_dac_event, SND_SOC_DAPM_PRE_PMU |
550fe1ff614SJack Yu SND_SOC_DAPM_POST_PMD),
551fe1ff614SJack Yu /* Output Lines */
552fe1ff614SJack Yu SND_SOC_DAPM_OUTPUT("Amp"),
553fe1ff614SJack Yu };
554fe1ff614SJack Yu
555fe1ff614SJack Yu static const struct snd_soc_dapm_route rt1318_dapm_routes[] = {
556fe1ff614SJack Yu {"DAC", NULL, "AIF1RX"},
557fe1ff614SJack Yu {"Amp", NULL, "DAC"},
558fe1ff614SJack Yu };
559fe1ff614SJack Yu
rt1318_get_clk_info(int sclk,int rate)560fe1ff614SJack Yu static int rt1318_get_clk_info(int sclk, int rate)
561fe1ff614SJack Yu {
562fe1ff614SJack Yu int i, pd[] = {1, 2, 4, 8, 16, 24};
563fe1ff614SJack Yu
564fe1ff614SJack Yu if (sclk <= 0 || rate <= 0)
565fe1ff614SJack Yu return -EINVAL;
566fe1ff614SJack Yu
567fe1ff614SJack Yu rate = rate << 8;
568fe1ff614SJack Yu for (i = 0; i < ARRAY_SIZE(pd); i++)
569fe1ff614SJack Yu if (sclk == rate * pd[i])
570fe1ff614SJack Yu return i;
571fe1ff614SJack Yu
572fe1ff614SJack Yu return -EINVAL;
573fe1ff614SJack Yu }
574fe1ff614SJack Yu
rt1318_clk_ip_info(struct snd_soc_component * component,int lrclk)575fe1ff614SJack Yu static int rt1318_clk_ip_info(struct snd_soc_component *component, int lrclk)
576fe1ff614SJack Yu {
577fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
578fe1ff614SJack Yu
579fe1ff614SJack Yu switch (lrclk) {
580fe1ff614SJack Yu case RT1318_LRCLK_48000:
581fe1ff614SJack Yu case RT1318_LRCLK_44100:
582fe1ff614SJack Yu case RT1318_LRCLK_16000:
583fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
584fe1ff614SJack Yu RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
585fe1ff614SJack Yu RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON4);
586fe1ff614SJack Yu break;
587fe1ff614SJack Yu case RT1318_LRCLK_96000:
588fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
589fe1ff614SJack Yu RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
590fe1ff614SJack Yu RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON2);
591fe1ff614SJack Yu break;
592fe1ff614SJack Yu case RT1318_LRCLK_192000:
593fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_SRC_TCON,
594fe1ff614SJack Yu RT1318_SRCIN_F12288_MASK | RT1318_SRCIN_DACLK_MASK,
595fe1ff614SJack Yu RT1318_SRCIN_TCON4 | RT1318_DACLK_TCON1);
596fe1ff614SJack Yu break;
597fe1ff614SJack Yu default:
598fe1ff614SJack Yu dev_err(component->dev, "Unsupported clock rate.\n");
599fe1ff614SJack Yu return -EINVAL;
600fe1ff614SJack Yu }
601fe1ff614SJack Yu
602fe1ff614SJack Yu return 0;
603fe1ff614SJack Yu }
604fe1ff614SJack Yu
rt1318_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)605fe1ff614SJack Yu static int rt1318_hw_params(struct snd_pcm_substream *substream,
606fe1ff614SJack Yu struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
607fe1ff614SJack Yu {
608fe1ff614SJack Yu struct snd_soc_component *component = dai->component;
609fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
610fe1ff614SJack Yu int data_len = 0, ch_len = 0;
611fe1ff614SJack Yu int pre_div, ret;
612fe1ff614SJack Yu
613fe1ff614SJack Yu rt1318->lrck = params_rate(params);
614fe1ff614SJack Yu pre_div = rt1318_get_clk_info(rt1318->sysclk, rt1318->lrck);
615fe1ff614SJack Yu if (pre_div < 0) {
616fe1ff614SJack Yu dev_err(component->dev, "Unsupported clock setting\n");
617fe1ff614SJack Yu return -EINVAL;
618fe1ff614SJack Yu }
619fe1ff614SJack Yu ret = rt1318_clk_ip_info(component, rt1318->lrck);
620fe1ff614SJack Yu if (ret < 0) {
621fe1ff614SJack Yu dev_err(component->dev, "Unsupported clock setting\n");
622fe1ff614SJack Yu return -EINVAL;
623fe1ff614SJack Yu }
624fe1ff614SJack Yu
625fe1ff614SJack Yu switch (params_width(params)) {
626fe1ff614SJack Yu case 16:
627fe1ff614SJack Yu break;
628fe1ff614SJack Yu case 20:
629fe1ff614SJack Yu data_len = RT1318_I2S_DL_20;
630fe1ff614SJack Yu ch_len = RT1318_I2S_DL_20;
631fe1ff614SJack Yu break;
632fe1ff614SJack Yu case 24:
633fe1ff614SJack Yu data_len = RT1318_I2S_DL_24;
634fe1ff614SJack Yu ch_len = RT1318_I2S_DL_24;
635fe1ff614SJack Yu break;
636fe1ff614SJack Yu case 32:
637fe1ff614SJack Yu data_len = RT1318_I2S_DL_32;
638fe1ff614SJack Yu ch_len = RT1318_I2S_DL_32;
639fe1ff614SJack Yu break;
640fe1ff614SJack Yu case 8:
641fe1ff614SJack Yu data_len = RT1318_I2S_DL_8;
642fe1ff614SJack Yu ch_len = RT1318_I2S_DL_8;
643fe1ff614SJack Yu break;
644fe1ff614SJack Yu default:
645fe1ff614SJack Yu return -EINVAL;
646fe1ff614SJack Yu }
647fe1ff614SJack Yu
648fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK2,
649fe1ff614SJack Yu RT1318_DIV_AP_MASK | RT1318_DIV_DAMOD_MASK,
650fe1ff614SJack Yu pre_div << RT1318_DIV_AP_SFT |
651fe1ff614SJack Yu pre_div << RT1318_DIV_DAMOD_SFT);
652fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK3,
653fe1ff614SJack Yu RT1318_AD_STO1_MASK | RT1318_AD_STO2_MASK,
654fe1ff614SJack Yu pre_div << RT1318_AD_STO1_SFT |
655fe1ff614SJack Yu pre_div << RT1318_AD_STO2_SFT);
656fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK4,
657fe1ff614SJack Yu RT1318_AD_ANA_STO1_MASK | RT1318_AD_ANA_STO2_MASK,
658fe1ff614SJack Yu pre_div << RT1318_AD_ANA_STO1_SFT |
659fe1ff614SJack Yu pre_div << RT1318_AD_ANA_STO2_SFT);
660fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK5,
661fe1ff614SJack Yu RT1318_DIV_FIFO_IN_MASK | RT1318_DIV_FIFO_OUT_MASK,
662fe1ff614SJack Yu pre_div << RT1318_DIV_FIFO_IN_SFT |
663fe1ff614SJack Yu pre_div << RT1318_DIV_FIFO_OUT_SFT);
664fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK6,
665fe1ff614SJack Yu RT1318_DIV_NLMS_MASK | RT1318_DIV_AD_MONO_MASK |
666fe1ff614SJack Yu RT1318_DIV_POST_G_MASK, pre_div << RT1318_DIV_NLMS_SFT |
667fe1ff614SJack Yu pre_div << RT1318_DIV_AD_MONO_SFT |
668fe1ff614SJack Yu pre_div << RT1318_DIV_POST_G_SFT);
669fe1ff614SJack Yu
670fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2,
671fe1ff614SJack Yu RT1318_I2S_DL_MASK, data_len << RT1318_I2S_DL_SFT);
672fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3,
673fe1ff614SJack Yu RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK,
674fe1ff614SJack Yu ch_len << RT1318_I2S_TX_CHL_SFT |
675fe1ff614SJack Yu ch_len << RT1318_I2S_RX_CHL_SFT);
676fe1ff614SJack Yu
677fe1ff614SJack Yu return 0;
678fe1ff614SJack Yu }
679fe1ff614SJack Yu
rt1318_set_dai_fmt(struct snd_soc_dai * dai,unsigned int fmt)680fe1ff614SJack Yu static int rt1318_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
681fe1ff614SJack Yu {
682fe1ff614SJack Yu struct snd_soc_component *component = dai->component;
683fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
684fe1ff614SJack Yu unsigned int reg_val = 0, reg_val2 = 0;
685fe1ff614SJack Yu
686fe1ff614SJack Yu switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
687fe1ff614SJack Yu case SND_SOC_DAIFMT_NB_NF:
688fe1ff614SJack Yu break;
689fe1ff614SJack Yu case SND_SOC_DAIFMT_IB_NF:
690fe1ff614SJack Yu reg_val2 |= RT1318_TDM_BCLK_INV;
691fe1ff614SJack Yu break;
692fe1ff614SJack Yu default:
693fe1ff614SJack Yu return -EINVAL;
694fe1ff614SJack Yu }
695fe1ff614SJack Yu
696fe1ff614SJack Yu switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
697fe1ff614SJack Yu case SND_SOC_DAIFMT_I2S:
698fe1ff614SJack Yu break;
699fe1ff614SJack Yu
700fe1ff614SJack Yu case SND_SOC_DAIFMT_LEFT_J:
701fe1ff614SJack Yu reg_val |= RT1318_FMT_LEFT_J;
702fe1ff614SJack Yu break;
703fe1ff614SJack Yu
704fe1ff614SJack Yu case SND_SOC_DAIFMT_DSP_A:
705fe1ff614SJack Yu reg_val |= RT1318_FMT_PCM_A_R;
706fe1ff614SJack Yu break;
707fe1ff614SJack Yu
708fe1ff614SJack Yu case SND_SOC_DAIFMT_DSP_B:
709fe1ff614SJack Yu reg_val |= RT1318_FMT_PCM_B_R;
710fe1ff614SJack Yu break;
711fe1ff614SJack Yu
712fe1ff614SJack Yu default:
713fe1ff614SJack Yu return -EINVAL;
714fe1ff614SJack Yu }
715fe1ff614SJack Yu
716fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1,
717fe1ff614SJack Yu RT1318_I2S_FMT_MASK, reg_val);
718fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL1,
719fe1ff614SJack Yu RT1318_TDM_BCLK_MASK, reg_val2);
720fe1ff614SJack Yu
721fe1ff614SJack Yu return 0;
722fe1ff614SJack Yu }
723fe1ff614SJack Yu
rt1318_set_dai_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)724fe1ff614SJack Yu static int rt1318_set_dai_sysclk(struct snd_soc_dai *dai,
725fe1ff614SJack Yu int clk_id, unsigned int freq, int dir)
726fe1ff614SJack Yu {
727fe1ff614SJack Yu struct snd_soc_component *component = dai->component;
728fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
729fe1ff614SJack Yu int reg_val = 0;
730fe1ff614SJack Yu
731fe1ff614SJack Yu if (freq == rt1318->sysclk && clk_id == rt1318->sysclk_src)
732fe1ff614SJack Yu return 0;
733fe1ff614SJack Yu
734fe1ff614SJack Yu switch (clk_id) {
735fe1ff614SJack Yu case RT1318_SCLK_S_BCLK:
736fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_BCLK;
737fe1ff614SJack Yu break;
738fe1ff614SJack Yu case RT1318_SCLK_S_SDW:
739fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_SDW;
740fe1ff614SJack Yu break;
741fe1ff614SJack Yu case RT1318_SCLK_S_PLL2F:
742fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_PLL2F;
743fe1ff614SJack Yu break;
744fe1ff614SJack Yu case RT1318_SCLK_S_PLL2B:
745fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_PLL2B;
746fe1ff614SJack Yu break;
747fe1ff614SJack Yu case RT1318_SCLK_S_MCLK:
748fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_MCLK;
749fe1ff614SJack Yu break;
750fe1ff614SJack Yu case RT1318_SCLK_S_RC0:
751fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_RC1;
752fe1ff614SJack Yu break;
753fe1ff614SJack Yu case RT1318_SCLK_S_RC1:
754fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_RC2;
755fe1ff614SJack Yu break;
756fe1ff614SJack Yu case RT1318_SCLK_S_RC2:
757fe1ff614SJack Yu reg_val |= RT1318_SYSCLK_RC3;
758fe1ff614SJack Yu break;
759fe1ff614SJack Yu default:
760fe1ff614SJack Yu dev_err(component->dev, "Invalid clock id (%d)\n", clk_id);
761fe1ff614SJack Yu return -EINVAL;
762fe1ff614SJack Yu }
763fe1ff614SJack Yu
764fe1ff614SJack Yu rt1318->sysclk = freq;
765fe1ff614SJack Yu rt1318->sysclk_src = clk_id;
766fe1ff614SJack Yu dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
767fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
768fe1ff614SJack Yu RT1318_SYSCLK_SEL_MASK, reg_val);
769fe1ff614SJack Yu
770fe1ff614SJack Yu return 0;
771fe1ff614SJack Yu }
772fe1ff614SJack Yu
773fe1ff614SJack Yu static const struct pll_calc_map pll_preset_table[] = {
774fe1ff614SJack Yu {512000, 4096000, 22, 190, 0, true, false},
775fe1ff614SJack Yu {1024000, 4096000, 22, 94, 0, true, false},
776fe1ff614SJack Yu {1024000, 16384000, 4, 190, 0, true, false},
777fe1ff614SJack Yu {1411200, 11289600, 6, 62, 0, true, false},
778fe1ff614SJack Yu {1536000, 12288000, 6, 62, 0, true, false},
779fe1ff614SJack Yu {2822400, 11289600, 6, 62, 0, true, false},
780fe1ff614SJack Yu {2822400, 45158400, 0, 62, 0, true, false},
781fe1ff614SJack Yu {2822400, 49152000, 0, 62, 0, true, false},
782fe1ff614SJack Yu {3072000, 12288000, 6, 62, 0, true, false},
783fe1ff614SJack Yu {3072000, 24576000, 2, 62, 0, true, false},
784fe1ff614SJack Yu {3072000, 49152000, 0, 62, 0, true, false},
785fe1ff614SJack Yu {6144000, 24576000, 2, 94, 4, false, false},
786fe1ff614SJack Yu {6144000, 49152000, 0, 30, 0, true, false},
787fe1ff614SJack Yu {6144000, 98304000, 0, 94, 4, false, true},
788fe1ff614SJack Yu {12288000, 49152000, 0, 62, 6, false, false},
789fe1ff614SJack Yu };
790fe1ff614SJack Yu
rt1318_pll_calc(const unsigned int freq_in,const unsigned int freq_out,struct rt1318_pll_code * pll_code)791fe1ff614SJack Yu static int rt1318_pll_calc(const unsigned int freq_in,
792fe1ff614SJack Yu const unsigned int freq_out, struct rt1318_pll_code *pll_code)
793fe1ff614SJack Yu {
794fe1ff614SJack Yu int max_n = RT1318_PLL_N_MAX, max_m = RT1318_PLL_M_MAX;
795fe1ff614SJack Yu int i, k, red, n_t, pll_out, in_t, out_t;
796fe1ff614SJack Yu int n = 0, m = 0, m_t = 0;
797fe1ff614SJack Yu int red_t = abs(freq_out - freq_in);
798fe1ff614SJack Yu bool m_bypass = false, k_bypass = false;
799fe1ff614SJack Yu
800fe1ff614SJack Yu if (RT1318_PLL_INP_MAX < freq_in || RT1318_PLL_INP_MIN > freq_in)
801fe1ff614SJack Yu return -EINVAL;
802fe1ff614SJack Yu
803fe1ff614SJack Yu for (i = 0; i < ARRAY_SIZE(pll_preset_table); i++) {
804fe1ff614SJack Yu if (freq_in == pll_preset_table[i].pll_in &&
805fe1ff614SJack Yu freq_out == pll_preset_table[i].pll_out) {
806fe1ff614SJack Yu k = pll_preset_table[i].k;
807fe1ff614SJack Yu m = pll_preset_table[i].m;
808fe1ff614SJack Yu n = pll_preset_table[i].n;
809fe1ff614SJack Yu m_bypass = pll_preset_table[i].m_bp;
810fe1ff614SJack Yu k_bypass = pll_preset_table[i].k_bp;
811fe1ff614SJack Yu goto code_find;
812fe1ff614SJack Yu }
813fe1ff614SJack Yu }
814fe1ff614SJack Yu
815fe1ff614SJack Yu k = 100000000 / freq_out - 2;
816fe1ff614SJack Yu if (k > RT1318_PLL_K_MAX)
817fe1ff614SJack Yu k = RT1318_PLL_K_MAX;
818fe1ff614SJack Yu if (k < 0) {
819fe1ff614SJack Yu k = 0;
820fe1ff614SJack Yu k_bypass = true;
821fe1ff614SJack Yu }
822fe1ff614SJack Yu for (n_t = 0; n_t <= max_n; n_t++) {
823fe1ff614SJack Yu in_t = freq_in / (k_bypass ? 1 : (k + 2));
824fe1ff614SJack Yu pll_out = freq_out / (n_t + 2);
825fe1ff614SJack Yu if (in_t < 0)
826fe1ff614SJack Yu continue;
827fe1ff614SJack Yu if (in_t == pll_out) {
828fe1ff614SJack Yu m_bypass = true;
829fe1ff614SJack Yu n = n_t;
830fe1ff614SJack Yu goto code_find;
831fe1ff614SJack Yu }
832fe1ff614SJack Yu red = abs(in_t - pll_out);
833fe1ff614SJack Yu if (red < red_t) {
834fe1ff614SJack Yu m_bypass = true;
835fe1ff614SJack Yu n = n_t;
836fe1ff614SJack Yu m = m_t;
837fe1ff614SJack Yu if (red == 0)
838fe1ff614SJack Yu goto code_find;
839fe1ff614SJack Yu red_t = red;
840fe1ff614SJack Yu }
841fe1ff614SJack Yu for (m_t = 0; m_t <= max_m; m_t++) {
842fe1ff614SJack Yu out_t = in_t / (m_t + 2);
843fe1ff614SJack Yu red = abs(out_t - pll_out);
844fe1ff614SJack Yu if (red < red_t) {
845fe1ff614SJack Yu m_bypass = false;
846fe1ff614SJack Yu n = n_t;
847fe1ff614SJack Yu m = m_t;
848fe1ff614SJack Yu if (red == 0)
849fe1ff614SJack Yu goto code_find;
850fe1ff614SJack Yu red_t = red;
851fe1ff614SJack Yu }
852fe1ff614SJack Yu }
853fe1ff614SJack Yu }
854fe1ff614SJack Yu pr_debug("Only get approximation about PLL\n");
855fe1ff614SJack Yu
856fe1ff614SJack Yu code_find:
857fe1ff614SJack Yu
858fe1ff614SJack Yu pll_code->m_bp = m_bypass;
859fe1ff614SJack Yu pll_code->k_bp = k_bypass;
860fe1ff614SJack Yu pll_code->m_code = m;
861fe1ff614SJack Yu pll_code->n_code = n;
862fe1ff614SJack Yu pll_code->k_code = k;
863fe1ff614SJack Yu return 0;
864fe1ff614SJack Yu }
865fe1ff614SJack Yu
rt1318_set_dai_pll(struct snd_soc_dai * dai,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)866fe1ff614SJack Yu static int rt1318_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
867fe1ff614SJack Yu unsigned int freq_in, unsigned int freq_out)
868fe1ff614SJack Yu {
869fe1ff614SJack Yu struct snd_soc_component *component = dai->component;
870fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
871fe1ff614SJack Yu struct rt1318_pll_code pll_code;
872fe1ff614SJack Yu int ret;
873fe1ff614SJack Yu
874fe1ff614SJack Yu if (!freq_in || !freq_out) {
875fe1ff614SJack Yu dev_dbg(component->dev, "PLL disabled\n");
876fe1ff614SJack Yu rt1318->pll_in = 0;
877fe1ff614SJack Yu rt1318->pll_out = 0;
878fe1ff614SJack Yu return 0;
879fe1ff614SJack Yu }
880fe1ff614SJack Yu
881fe1ff614SJack Yu if (source == rt1318->pll_src && freq_in == rt1318->pll_in &&
882fe1ff614SJack Yu freq_out == rt1318->pll_out)
883fe1ff614SJack Yu return 0;
884fe1ff614SJack Yu
885fe1ff614SJack Yu switch (source) {
886fe1ff614SJack Yu case RT1318_PLL_S_BCLK0:
887fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
888fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK0);
889fe1ff614SJack Yu break;
890fe1ff614SJack Yu case RT1318_PLL_S_BCLK1:
891fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
892fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_BCLK1);
893fe1ff614SJack Yu break;
894fe1ff614SJack Yu case RT1318_PLL_S_RC:
895fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
896fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_RC);
897fe1ff614SJack Yu break;
898fe1ff614SJack Yu case RT1318_PLL_S_MCLK:
899fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
900fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_MCLK);
901fe1ff614SJack Yu break;
902fe1ff614SJack Yu case RT1318_PLL_S_SDW_IN_PLL:
903fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
904fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_SDW1);
905fe1ff614SJack Yu break;
906fe1ff614SJack Yu case RT1318_PLL_S_SDW_0:
907fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
908fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_SDW2);
909fe1ff614SJack Yu break;
910fe1ff614SJack Yu case RT1318_PLL_S_SDW_1:
911fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
912fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_SDW3);
913fe1ff614SJack Yu break;
914fe1ff614SJack Yu case RT1318_PLL_S_SDW_2:
915fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_CLK1,
916fe1ff614SJack Yu RT1318_PLLIN_MASK, RT1318_PLLIN_SDW4);
917fe1ff614SJack Yu break;
918fe1ff614SJack Yu default:
919fe1ff614SJack Yu dev_err(component->dev, "Unknown PLL source %d\n", source);
920fe1ff614SJack Yu return -EINVAL;
921fe1ff614SJack Yu }
922fe1ff614SJack Yu
923fe1ff614SJack Yu ret = rt1318_pll_calc(freq_in, freq_out, &pll_code);
924fe1ff614SJack Yu if (ret < 0) {
925fe1ff614SJack Yu dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
926fe1ff614SJack Yu return ret;
927fe1ff614SJack Yu }
928fe1ff614SJack Yu
929fe1ff614SJack Yu dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n",
930fe1ff614SJack Yu pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
931fe1ff614SJack Yu pll_code.n_code, pll_code.k_code);
932fe1ff614SJack Yu
933fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PLL1_K,
934fe1ff614SJack Yu RT1318_K_PLL1_MASK, pll_code.k_code);
935fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PLL1_M,
936fe1ff614SJack Yu RT1318_M_PLL1_MASK, (pll_code.m_bp ? 0 : pll_code.m_code));
937fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_8,
938fe1ff614SJack Yu RT1318_N_8_PLL1_MASK, pll_code.n_code >> 8);
939fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_PLL1_N_7_0,
940fe1ff614SJack Yu RT1318_N_7_0_PLL1_MASK, pll_code.n_code);
941fe1ff614SJack Yu
942fe1ff614SJack Yu rt1318->pll_in = freq_in;
943fe1ff614SJack Yu rt1318->pll_out = freq_out;
944fe1ff614SJack Yu rt1318->pll_src = source;
945fe1ff614SJack Yu
946fe1ff614SJack Yu return 0;
947fe1ff614SJack Yu }
948fe1ff614SJack Yu
rt1318_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)949fe1ff614SJack Yu static int rt1318_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
950fe1ff614SJack Yu unsigned int rx_mask, int slots, int slot_width)
951fe1ff614SJack Yu {
952fe1ff614SJack Yu struct snd_soc_component *component = dai->component;
953fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
954fe1ff614SJack Yu unsigned int cn = 0, cl = 0, rx_slotnum;
955fe1ff614SJack Yu int ret = 0, first_bit;
956fe1ff614SJack Yu
957fe1ff614SJack Yu switch (slots) {
958fe1ff614SJack Yu case 4:
959fe1ff614SJack Yu cn |= RT1318_I2S_CH_TX_4CH;
960fe1ff614SJack Yu cn |= RT1318_I2S_CH_RX_4CH;
961fe1ff614SJack Yu break;
962fe1ff614SJack Yu case 6:
963fe1ff614SJack Yu cn |= RT1318_I2S_CH_TX_6CH;
964fe1ff614SJack Yu cn |= RT1318_I2S_CH_RX_6CH;
965fe1ff614SJack Yu break;
966fe1ff614SJack Yu case 8:
967fe1ff614SJack Yu cn |= RT1318_I2S_CH_TX_8CH;
968fe1ff614SJack Yu cn |= RT1318_I2S_CH_RX_8CH;
969fe1ff614SJack Yu break;
970fe1ff614SJack Yu case 2:
971fe1ff614SJack Yu break;
972fe1ff614SJack Yu default:
973fe1ff614SJack Yu return -EINVAL;
974fe1ff614SJack Yu }
975fe1ff614SJack Yu
976fe1ff614SJack Yu switch (slot_width) {
977fe1ff614SJack Yu case 20:
978fe1ff614SJack Yu cl |= RT1318_I2S_TX_CHL_20;
979fe1ff614SJack Yu cl |= RT1318_I2S_RX_CHL_20;
980fe1ff614SJack Yu break;
981fe1ff614SJack Yu case 24:
982fe1ff614SJack Yu cl |= RT1318_I2S_TX_CHL_24;
983fe1ff614SJack Yu cl |= RT1318_I2S_RX_CHL_24;
984fe1ff614SJack Yu break;
985fe1ff614SJack Yu case 32:
986fe1ff614SJack Yu cl |= RT1318_I2S_TX_CHL_32;
987fe1ff614SJack Yu cl |= RT1318_I2S_RX_CHL_32;
988fe1ff614SJack Yu break;
989fe1ff614SJack Yu case 8:
990fe1ff614SJack Yu cl |= RT1318_I2S_TX_CHL_8;
991fe1ff614SJack Yu cl |= RT1318_I2S_RX_CHL_8;
992fe1ff614SJack Yu break;
993fe1ff614SJack Yu case 16:
994fe1ff614SJack Yu break;
995fe1ff614SJack Yu default:
996fe1ff614SJack Yu return -EINVAL;
997fe1ff614SJack Yu }
998fe1ff614SJack Yu
999fe1ff614SJack Yu /* Rx slot configuration */
1000fe1ff614SJack Yu rx_slotnum = hweight_long(rx_mask);
1001fe1ff614SJack Yu if (rx_slotnum != 1) {
1002fe1ff614SJack Yu ret = -EINVAL;
1003fe1ff614SJack Yu dev_err(component->dev, "too many rx slots or zero slot\n");
1004fe1ff614SJack Yu goto _set_tdm_err_;
1005fe1ff614SJack Yu }
1006fe1ff614SJack Yu
1007fe1ff614SJack Yu first_bit = __ffs(rx_mask);
1008fe1ff614SJack Yu switch (first_bit) {
1009fe1ff614SJack Yu case 0:
1010fe1ff614SJack Yu case 2:
1011fe1ff614SJack Yu case 4:
1012fe1ff614SJack Yu case 6:
1013fe1ff614SJack Yu regmap_update_bits(rt1318->regmap,
1014fe1ff614SJack Yu RT1318_TDM_CTRL9,
1015fe1ff614SJack Yu RT1318_TDM_I2S_TX_L_DAC1_1_MASK |
1016fe1ff614SJack Yu RT1318_TDM_I2S_TX_R_DAC1_1_MASK,
1017fe1ff614SJack Yu (first_bit << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) |
1018fe1ff614SJack Yu ((first_bit + 1) << RT1318_TDM_I2S_TX_R_DAC1_1_SFT));
1019fe1ff614SJack Yu break;
1020fe1ff614SJack Yu case 1:
1021fe1ff614SJack Yu case 3:
1022fe1ff614SJack Yu case 5:
1023fe1ff614SJack Yu case 7:
1024fe1ff614SJack Yu regmap_update_bits(rt1318->regmap,
1025fe1ff614SJack Yu RT1318_TDM_CTRL9,
1026fe1ff614SJack Yu RT1318_TDM_I2S_TX_L_DAC1_1_MASK |
1027fe1ff614SJack Yu RT1318_TDM_I2S_TX_R_DAC1_1_MASK,
1028fe1ff614SJack Yu ((first_bit - 1) << RT1318_TDM_I2S_TX_L_DAC1_1_SFT) |
1029fe1ff614SJack Yu (first_bit << RT1318_TDM_I2S_TX_R_DAC1_1_SFT));
1030fe1ff614SJack Yu break;
1031fe1ff614SJack Yu default:
1032fe1ff614SJack Yu ret = -EINVAL;
1033fe1ff614SJack Yu goto _set_tdm_err_;
1034fe1ff614SJack Yu }
1035fe1ff614SJack Yu
1036fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL2,
1037fe1ff614SJack Yu RT1318_I2S_CH_TX_MASK | RT1318_I2S_CH_RX_MASK, cn);
1038fe1ff614SJack Yu regmap_update_bits(rt1318->regmap, RT1318_TDM_CTRL3,
1039fe1ff614SJack Yu RT1318_I2S_TX_CHL_MASK | RT1318_I2S_RX_CHL_MASK, cl);
1040fe1ff614SJack Yu
1041fe1ff614SJack Yu _set_tdm_err_:
1042fe1ff614SJack Yu return ret;
1043fe1ff614SJack Yu }
1044fe1ff614SJack Yu
rt1318_probe(struct snd_soc_component * component)1045fe1ff614SJack Yu static int rt1318_probe(struct snd_soc_component *component)
1046fe1ff614SJack Yu {
1047fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
1048fe1ff614SJack Yu
1049fe1ff614SJack Yu rt1318->component = component;
1050fe1ff614SJack Yu
1051fe1ff614SJack Yu schedule_work(&rt1318->cali_work);
1052fe1ff614SJack Yu rt1318->rt1318_dvol = RT1318_DVOL_STEP;
1053fe1ff614SJack Yu
1054fe1ff614SJack Yu return 0;
1055fe1ff614SJack Yu }
1056fe1ff614SJack Yu
rt1318_remove(struct snd_soc_component * component)1057fe1ff614SJack Yu static void rt1318_remove(struct snd_soc_component *component)
1058fe1ff614SJack Yu {
1059fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
1060fe1ff614SJack Yu
1061fe1ff614SJack Yu cancel_work_sync(&rt1318->cali_work);
1062fe1ff614SJack Yu }
1063fe1ff614SJack Yu
1064fe1ff614SJack Yu #ifdef CONFIG_PM
rt1318_suspend(struct snd_soc_component * component)1065fe1ff614SJack Yu static int rt1318_suspend(struct snd_soc_component *component)
1066fe1ff614SJack Yu {
1067fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
1068fe1ff614SJack Yu
1069fe1ff614SJack Yu regcache_cache_only(rt1318->regmap, true);
1070fe1ff614SJack Yu regcache_mark_dirty(rt1318->regmap);
1071fe1ff614SJack Yu return 0;
1072fe1ff614SJack Yu }
1073fe1ff614SJack Yu
rt1318_resume(struct snd_soc_component * component)1074fe1ff614SJack Yu static int rt1318_resume(struct snd_soc_component *component)
1075fe1ff614SJack Yu {
1076fe1ff614SJack Yu struct rt1318_priv *rt1318 = snd_soc_component_get_drvdata(component);
1077fe1ff614SJack Yu
1078fe1ff614SJack Yu regcache_cache_only(rt1318->regmap, false);
1079fe1ff614SJack Yu regcache_sync(rt1318->regmap);
1080fe1ff614SJack Yu return 0;
1081fe1ff614SJack Yu }
1082fe1ff614SJack Yu #else
1083fe1ff614SJack Yu #define rt1318_suspend NULL
1084fe1ff614SJack Yu #define rt1318_resume NULL
1085fe1ff614SJack Yu #endif
1086fe1ff614SJack Yu
1087fe1ff614SJack Yu #define RT1318_STEREO_RATES SNDRV_PCM_RATE_8000_192000
1088fe1ff614SJack Yu #define RT1318_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1089fe1ff614SJack Yu SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
1090fe1ff614SJack Yu
1091fe1ff614SJack Yu static const struct snd_soc_dai_ops rt1318_aif_dai_ops = {
1092fe1ff614SJack Yu .hw_params = rt1318_hw_params,
1093fe1ff614SJack Yu .set_fmt = rt1318_set_dai_fmt,
1094fe1ff614SJack Yu .set_sysclk = rt1318_set_dai_sysclk,
1095fe1ff614SJack Yu .set_pll = rt1318_set_dai_pll,
1096fe1ff614SJack Yu .set_tdm_slot = rt1318_set_tdm_slot,
1097fe1ff614SJack Yu };
1098fe1ff614SJack Yu
1099fe1ff614SJack Yu static struct snd_soc_dai_driver rt1318_dai[] = {
1100fe1ff614SJack Yu {
1101fe1ff614SJack Yu .name = "rt1318-aif",
1102fe1ff614SJack Yu .id = 0,
1103fe1ff614SJack Yu .playback = {
1104fe1ff614SJack Yu .stream_name = "AIF1 Playback",
1105fe1ff614SJack Yu .channels_min = 1,
1106fe1ff614SJack Yu .channels_max = 2,
1107fe1ff614SJack Yu .rates = RT1318_STEREO_RATES,
1108fe1ff614SJack Yu .formats = RT1318_FORMATS,
1109fe1ff614SJack Yu },
1110fe1ff614SJack Yu .ops = &rt1318_aif_dai_ops,
1111fe1ff614SJack Yu }
1112fe1ff614SJack Yu };
1113fe1ff614SJack Yu
1114fe1ff614SJack Yu static const struct snd_soc_component_driver soc_component_dev_rt1318 = {
1115fe1ff614SJack Yu .probe = rt1318_probe,
1116fe1ff614SJack Yu .remove = rt1318_remove,
1117fe1ff614SJack Yu .suspend = rt1318_suspend,
1118fe1ff614SJack Yu .resume = rt1318_resume,
1119fe1ff614SJack Yu .controls = rt1318_snd_controls,
1120fe1ff614SJack Yu .num_controls = ARRAY_SIZE(rt1318_snd_controls),
1121fe1ff614SJack Yu .dapm_widgets = rt1318_dapm_widgets,
1122fe1ff614SJack Yu .num_dapm_widgets = ARRAY_SIZE(rt1318_dapm_widgets),
1123fe1ff614SJack Yu .dapm_routes = rt1318_dapm_routes,
1124fe1ff614SJack Yu .num_dapm_routes = ARRAY_SIZE(rt1318_dapm_routes),
1125fe1ff614SJack Yu .use_pmdown_time = 1,
1126fe1ff614SJack Yu .endianness = 1,
1127fe1ff614SJack Yu };
1128fe1ff614SJack Yu
1129fe1ff614SJack Yu static const struct regmap_config rt1318_regmap = {
1130fe1ff614SJack Yu .reg_bits = 32,
1131fe1ff614SJack Yu .val_bits = 8,
1132fe1ff614SJack Yu .readable_reg = rt1318_readable_register,
1133fe1ff614SJack Yu .volatile_reg = rt1318_volatile_register,
1134fe1ff614SJack Yu .max_register = 0x41001888,
1135fe1ff614SJack Yu .reg_defaults = rt1318_reg,
1136fe1ff614SJack Yu .num_reg_defaults = ARRAY_SIZE(rt1318_reg),
1137fe1ff614SJack Yu .cache_type = REGCACHE_RBTREE,
1138fe1ff614SJack Yu .use_single_read = true,
1139fe1ff614SJack Yu .use_single_write = true,
1140fe1ff614SJack Yu };
1141fe1ff614SJack Yu
1142fe1ff614SJack Yu static const struct i2c_device_id rt1318_i2c_id[] = {
11436f9faf14SUwe Kleine-König { "rt1318" },
1144fe1ff614SJack Yu { }
1145fe1ff614SJack Yu };
1146fe1ff614SJack Yu MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id);
1147fe1ff614SJack Yu
1148fe1ff614SJack Yu static const struct of_device_id rt1318_of_match[] = {
1149fe1ff614SJack Yu { .compatible = "realtek,rt1318", },
1150*acac29faSCezary Rojewski { }
1151fe1ff614SJack Yu };
1152fe1ff614SJack Yu MODULE_DEVICE_TABLE(of, rt1318_of_match);
1153fe1ff614SJack Yu
1154fe1ff614SJack Yu #ifdef CONFIG_ACPI
1155fe1ff614SJack Yu static const struct acpi_device_id rt1318_acpi_match[] = {
1156*acac29faSCezary Rojewski { "10EC1318" },
1157*acac29faSCezary Rojewski { }
1158fe1ff614SJack Yu };
1159fe1ff614SJack Yu MODULE_DEVICE_TABLE(acpi, rt1318_acpi_match);
1160fe1ff614SJack Yu #endif
1161fe1ff614SJack Yu
rt1318_parse_dt(struct rt1318_priv * rt1318,struct device * dev)1162fe1ff614SJack Yu static int rt1318_parse_dt(struct rt1318_priv *rt1318, struct device *dev)
1163fe1ff614SJack Yu {
1164fe1ff614SJack Yu device_property_read_u32(dev, "realtek,r0_l",
1165fe1ff614SJack Yu &rt1318->pdata.init_r0_l);
1166fe1ff614SJack Yu device_property_read_u32(dev, "realtek,r0_r",
1167fe1ff614SJack Yu &rt1318->pdata.init_r0_r);
1168fe1ff614SJack Yu
1169fe1ff614SJack Yu return 0;
1170fe1ff614SJack Yu }
1171fe1ff614SJack Yu
rt1318_calibration_sequence(struct rt1318_priv * rt1318)1172fe1ff614SJack Yu static void rt1318_calibration_sequence(struct rt1318_priv *rt1318)
1173fe1ff614SJack Yu {
1174fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_CLK1, 0x22);
1175fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PLL1_N_7_0, 0x06);
1176fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xCC);
1177fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x40);
1178fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x40);
1179fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_SINE_GEN0, 0x20);
1180fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_SPK_VOL_TH, 0x00);
1181fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_FEEDBACK_PATH, 0x0B);
1182fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_TCON, 0x1C);
1183fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x58);
1184fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_TCON_RELATE, 0x78);
1185fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xC2);
1186fe1ff614SJack Yu }
1187fe1ff614SJack Yu
rt1318_r0_calculate(struct rt1318_priv * rt1318)1188fe1ff614SJack Yu static void rt1318_r0_calculate(struct rt1318_priv *rt1318)
1189fe1ff614SJack Yu {
1190fe1ff614SJack Yu unsigned int r0_l, r0_l_byte0, r0_l_byte1, r0_l_byte2, r0_l_byte3;
1191fe1ff614SJack Yu unsigned int r0_r, r0_r_byte0, r0_r_byte1, r0_r_byte2, r0_r_byte3;
1192fe1ff614SJack Yu unsigned int r0_l_integer, r0_l_factor, r0_r_integer, r0_r_factor;
1193fe1ff614SJack Yu unsigned int format = 16777216; /* 2^24 */
1194fe1ff614SJack Yu
1195fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_L_24, &r0_l_byte0);
1196fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_L_23_16, &r0_l_byte1);
1197fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_L_15_8, &r0_l_byte2);
1198fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_L_7_0, &r0_l_byte3);
1199fe1ff614SJack Yu r0_l = r0_l_byte0 << 24 | r0_l_byte1 << 16 | r0_l_byte2 << 8 | r0_l_byte3;
1200fe1ff614SJack Yu r0_l_integer = format / r0_l;
1201fe1ff614SJack Yu r0_l_factor = (format * 10) / r0_l - r0_l_integer * 10;
1202fe1ff614SJack Yu
1203fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_R_24, &r0_r_byte0);
1204fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_R_23_16, &r0_r_byte1);
1205fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_R_15_8, &r0_r_byte2);
1206fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_R_7_0, &r0_r_byte3);
1207fe1ff614SJack Yu r0_r = r0_r_byte0 << 24 | r0_r_byte1 << 16 | r0_r_byte2 << 8 | r0_r_byte3;
1208fe1ff614SJack Yu r0_r_integer = format / r0_r;
1209fe1ff614SJack Yu r0_r_factor = (format * 10) / r0_r - r0_r_integer * 10;
1210fe1ff614SJack Yu
1211fe1ff614SJack Yu dev_dbg(rt1318->component->dev, "r0_l_ch:%d.%d ohm\n", r0_l_integer, r0_l_factor);
1212fe1ff614SJack Yu dev_dbg(rt1318->component->dev, "r0_r_ch:%d.%d ohm\n", r0_r_integer, r0_r_factor);
1213fe1ff614SJack Yu }
1214fe1ff614SJack Yu
rt1318_r0_restore(struct rt1318_priv * rt1318)1215fe1ff614SJack Yu static void rt1318_r0_restore(struct rt1318_priv *rt1318)
1216fe1ff614SJack Yu {
1217fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_L_24,
1218fe1ff614SJack Yu (rt1318->pdata.init_r0_l >> 24) & 0xff);
1219fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_L_23_16,
1220fe1ff614SJack Yu (rt1318->pdata.init_r0_l >> 16) & 0xff);
1221fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_L_15_8,
1222fe1ff614SJack Yu (rt1318->pdata.init_r0_l >> 8) & 0xff);
1223fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_L_7_0,
1224fe1ff614SJack Yu (rt1318->pdata.init_r0_l >> 0) & 0xff);
1225fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_R_24,
1226fe1ff614SJack Yu (rt1318->pdata.init_r0_r >> 24) & 0xff);
1227fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_R_23_16,
1228fe1ff614SJack Yu (rt1318->pdata.init_r0_r >> 16) & 0xff);
1229fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_R_15_8,
1230fe1ff614SJack Yu (rt1318->pdata.init_r0_r >> 8) & 0xff);
1231fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PRE_R0_R_7_0,
1232fe1ff614SJack Yu (rt1318->pdata.init_r0_r >> 0) & 0xff);
1233fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_SEL_L, 0x80);
1234fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_SEL_R, 0x80);
1235fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_R0_CMP_L_FLAG, 0xc0);
1236fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_R0_CMP_R_FLAG, 0xc0);
1237fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_R0_EN_L, 0xc0);
1238fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_R0_EN_R, 0xc0);
1239fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_STP_TEMP_L, 0xcc);
1240fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_TCON, 0x9c);
1241fe1ff614SJack Yu }
1242fe1ff614SJack Yu
rt1318_calibrate(struct rt1318_priv * rt1318)1243fe1ff614SJack Yu static int rt1318_calibrate(struct rt1318_priv *rt1318)
1244fe1ff614SJack Yu {
1245fe1ff614SJack Yu int chk_cnt = 30, count = 0;
1246fe1ff614SJack Yu int val, val2;
1247fe1ff614SJack Yu
1248fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x1);
1249fe1ff614SJack Yu usleep_range(0, 10000);
1250fe1ff614SJack Yu rt1318_calibration_sequence(rt1318);
1251fe1ff614SJack Yu
1252fe1ff614SJack Yu while (count < chk_cnt) {
1253fe1ff614SJack Yu msleep(100);
1254fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val);
1255fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2);
1256fe1ff614SJack Yu val = (val >> 1) & 0x1;
1257fe1ff614SJack Yu val2 = (val2 >> 1) & 0x1;
1258fe1ff614SJack Yu if (val & val2) {
1259fe1ff614SJack Yu dev_dbg(rt1318->component->dev, "Calibration done.\n");
1260fe1ff614SJack Yu break;
1261fe1ff614SJack Yu }
1262fe1ff614SJack Yu count++;
1263fe1ff614SJack Yu if (count == chk_cnt) {
1264fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0);
1265fe1ff614SJack Yu return RT1318_R0_CALIB_NOT_DONE;
1266fe1ff614SJack Yu }
1267fe1ff614SJack Yu }
1268fe1ff614SJack Yu regmap_write(rt1318->regmap, RT1318_PWR_STA1, 0x0);
1269fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_CMP_L_FLAG, &val);
1270fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_R0_CMP_R_FLAG, &val2);
1271fe1ff614SJack Yu if ((val & 0x1) & (val2 & 0x1))
1272fe1ff614SJack Yu return RT1318_R0_IN_RANGE;
1273fe1ff614SJack Yu else
1274fe1ff614SJack Yu return RT1318_R0_OUT_OF_RANGE;
1275fe1ff614SJack Yu }
1276fe1ff614SJack Yu
rt1318_calibration_work(struct work_struct * work)1277fe1ff614SJack Yu static void rt1318_calibration_work(struct work_struct *work)
1278fe1ff614SJack Yu {
1279fe1ff614SJack Yu struct rt1318_priv *rt1318 =
1280fe1ff614SJack Yu container_of(work, struct rt1318_priv, cali_work);
1281fe1ff614SJack Yu int ret;
1282fe1ff614SJack Yu
1283fe1ff614SJack Yu if (rt1318->pdata.init_r0_l && rt1318->pdata.init_r0_r)
1284fe1ff614SJack Yu rt1318_r0_restore(rt1318);
1285fe1ff614SJack Yu else {
1286fe1ff614SJack Yu ret = rt1318_calibrate(rt1318);
1287fe1ff614SJack Yu if (ret == RT1318_R0_IN_RANGE)
1288fe1ff614SJack Yu rt1318_r0_calculate(rt1318);
1289fe1ff614SJack Yu dev_dbg(rt1318->component->dev, "Calibrate R0 result:%d\n", ret);
1290fe1ff614SJack Yu }
1291fe1ff614SJack Yu }
1292fe1ff614SJack Yu
rt1318_i2c_probe(struct i2c_client * i2c)1293fe1ff614SJack Yu static int rt1318_i2c_probe(struct i2c_client *i2c)
1294fe1ff614SJack Yu {
1295fe1ff614SJack Yu struct rt1318_platform_data *pdata = dev_get_platdata(&i2c->dev);
1296fe1ff614SJack Yu struct rt1318_priv *rt1318;
1297fe1ff614SJack Yu int ret, val, val2, dev_id;
1298fe1ff614SJack Yu
1299fe1ff614SJack Yu rt1318 = devm_kzalloc(&i2c->dev, sizeof(struct rt1318_priv),
1300fe1ff614SJack Yu GFP_KERNEL);
1301fe1ff614SJack Yu if (!rt1318)
1302fe1ff614SJack Yu return -ENOMEM;
1303fe1ff614SJack Yu
1304fe1ff614SJack Yu i2c_set_clientdata(i2c, rt1318);
1305fe1ff614SJack Yu
1306fe1ff614SJack Yu if (pdata)
1307fe1ff614SJack Yu rt1318->pdata = *pdata;
1308fe1ff614SJack Yu else
1309fe1ff614SJack Yu rt1318_parse_dt(rt1318, &i2c->dev);
1310fe1ff614SJack Yu
1311fe1ff614SJack Yu rt1318->regmap = devm_regmap_init_i2c(i2c, &rt1318_regmap);
1312fe1ff614SJack Yu if (IS_ERR(rt1318->regmap)) {
1313fe1ff614SJack Yu ret = PTR_ERR(rt1318->regmap);
1314fe1ff614SJack Yu dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
1315fe1ff614SJack Yu ret);
1316fe1ff614SJack Yu return ret;
1317fe1ff614SJack Yu }
1318fe1ff614SJack Yu
1319fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_DEV_ID1, &val);
1320fe1ff614SJack Yu regmap_read(rt1318->regmap, RT1318_DEV_ID2, &val2);
1321fe1ff614SJack Yu dev_id = (val << 8) | val2;
1322fe1ff614SJack Yu if (dev_id != 0x6821) {
1323fe1ff614SJack Yu dev_err(&i2c->dev,
1324fe1ff614SJack Yu "Device with ID register %#x is not rt1318\n",
1325fe1ff614SJack Yu dev_id);
1326fe1ff614SJack Yu return -ENODEV;
1327fe1ff614SJack Yu }
1328fe1ff614SJack Yu
1329fe1ff614SJack Yu ret = regmap_register_patch(rt1318->regmap, init_list,
1330fe1ff614SJack Yu ARRAY_SIZE(init_list));
1331fe1ff614SJack Yu if (ret != 0)
1332fe1ff614SJack Yu dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
1333fe1ff614SJack Yu
1334fe1ff614SJack Yu INIT_WORK(&rt1318->cali_work, rt1318_calibration_work);
1335fe1ff614SJack Yu
1336fe1ff614SJack Yu return devm_snd_soc_register_component(&i2c->dev,
1337fe1ff614SJack Yu &soc_component_dev_rt1318, rt1318_dai, ARRAY_SIZE(rt1318_dai));
1338fe1ff614SJack Yu }
1339fe1ff614SJack Yu
1340fe1ff614SJack Yu static struct i2c_driver rt1318_i2c_driver = {
1341fe1ff614SJack Yu .driver = {
1342fe1ff614SJack Yu .name = "rt1318",
1343fe1ff614SJack Yu .of_match_table = of_match_ptr(rt1318_of_match),
1344fe1ff614SJack Yu .acpi_match_table = ACPI_PTR(rt1318_acpi_match),
1345fe1ff614SJack Yu },
1346fe1ff614SJack Yu .probe = rt1318_i2c_probe,
1347fe1ff614SJack Yu .id_table = rt1318_i2c_id,
1348fe1ff614SJack Yu };
1349fe1ff614SJack Yu module_i2c_driver(rt1318_i2c_driver);
1350fe1ff614SJack Yu
1351fe1ff614SJack Yu MODULE_DESCRIPTION("ASoC RT1318 driver");
1352fe1ff614SJack Yu MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
1353fe1ff614SJack Yu MODULE_LICENSE("GPL");
1354