1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Support for Digigram Lola PCI-e boards
5 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/delay.h>
11 #include <sound/core.h>
12 #include <sound/pcm.h>
15 unsigned int lola_sample_rate_convert(unsigned int coded
)
20 switch (coded
& 0x3) {
21 case 0: freq
= 48000; break;
22 case 1: freq
= 44100; break;
23 case 2: freq
= 32000; break;
24 default: return 0; /* error */
27 /* multiplier / devisor */
28 switch (coded
& 0x1c) {
31 case (1 << 2): freq
*= 2; break;
32 case (2 << 2): freq
*= 4; break;
33 case (5 << 2): freq
/= 2; break;
34 case (6 << 2): freq
/= 4; break;
35 default: return 0; /* error */
39 switch (coded
& 0x60) {
41 case (1 << 5): freq
= (freq
* 999) / 1000; break;
42 case (2 << 5): freq
= (freq
* 1001) / 1000; break;
43 default: return 0; /* error */
52 #define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000
53 #define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000
55 static bool check_gran_clock_compatibility(struct lola
*chip
,
59 if (!chip
->granularity
)
62 if (val
< LOLA_GRANULARITY_MIN
|| val
> LOLA_GRANULARITY_MAX
||
63 (val
% LOLA_GRANULARITY_STEP
) != 0)
66 if (val
== LOLA_GRANULARITY_MIN
) {
67 if (freq
> LOLA_MAXFREQ_AT_GRANULARITY_MIN
)
69 } else if (val
< LOLA_GRANULARITY_MAX
) {
70 if (freq
> LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX
)
76 int lola_set_granularity(struct lola
*chip
, unsigned int val
, bool force
)
81 if (val
== chip
->granularity
)
84 /* change Gran only if there are no streams allocated ! */
85 if (chip
->audio_in_alloc_mask
|| chip
->audio_out_alloc_mask
)
88 if (!check_gran_clock_compatibility(chip
, val
,
89 chip
->clock
.cur_freq
))
93 chip
->granularity
= val
;
94 val
/= LOLA_GRANULARITY_STEP
;
96 /* audio function group */
97 err
= lola_codec_write(chip
, 1, LOLA_VERB_SET_GRANULARITY_STEPS
,
101 /* this can be a very slow function !!! */
102 usleep_range(400 * val
, 20000);
103 return lola_codec_flush(chip
);
107 * Clock widget handling
110 int lola_init_clock_widget(struct lola
*chip
, int nid
)
113 int i
, j
, nitems
, nb_verbs
, idx
, idx_list
;
116 err
= lola_read_param(chip
, nid
, LOLA_PAR_AUDIO_WIDGET_CAP
, &val
);
118 dev_err(chip
->card
->dev
, "Can't read wcaps for 0x%x\n", nid
);
122 if ((val
& 0xfff00000) != 0x01f00000) { /* test SubType and Type */
123 dev_dbg(chip
->card
->dev
, "No valid clock widget\n");
127 chip
->clock
.nid
= nid
;
128 chip
->clock
.items
= val
& 0xff;
129 dev_dbg(chip
->card
->dev
, "clock_list nid=%x, entries=%d\n", nid
,
131 if (chip
->clock
.items
> MAX_SAMPLE_CLOCK_COUNT
) {
132 dev_err(chip
->card
->dev
, "CLOCK_LIST too big: %d\n",
137 nitems
= chip
->clock
.items
;
138 nb_verbs
= (nitems
+ 3) / 4;
141 for (i
= 0; i
< nb_verbs
; i
++) {
143 unsigned short items
[4];
145 err
= lola_codec_read(chip
, nid
, LOLA_VERB_GET_CLOCK_LIST
,
146 idx
, 0, &val
, &res_ex
);
148 dev_err(chip
->card
->dev
, "Can't read CLOCK_LIST\n");
152 items
[0] = val
& 0xfff;
153 items
[1] = (val
>> 16) & 0xfff;
154 items
[2] = res_ex
& 0xfff;
155 items
[3] = (res_ex
>> 16) & 0xfff;
157 for (j
= 0; j
< 4; j
++) {
158 unsigned char type
= items
[j
] >> 8;
159 unsigned int freq
= items
[j
] & 0xff;
160 int format
= LOLA_CLOCK_FORMAT_NONE
;
161 bool add_clock
= true;
162 if (type
== LOLA_CLOCK_TYPE_INTERNAL
) {
163 freq
= lola_sample_rate_convert(freq
);
164 if (freq
< chip
->sample_rate_min
)
166 else if (freq
== 48000) {
167 chip
->clock
.cur_index
= idx_list
;
168 chip
->clock
.cur_freq
= 48000;
169 chip
->clock
.cur_valid
= true;
171 } else if (type
== LOLA_CLOCK_TYPE_VIDEO
) {
172 freq
= lola_sample_rate_convert(freq
);
173 if (freq
< chip
->sample_rate_min
)
175 /* video clock has a format (0:NTSC, 1:PAL)*/
177 format
= LOLA_CLOCK_FORMAT_NTSC
;
179 format
= LOLA_CLOCK_FORMAT_PAL
;
182 struct lola_sample_clock
*sc
;
183 sc
= &chip
->clock
.sample_clock
[idx_list
];
187 /* keep the index used with the board */
188 chip
->clock
.idx_lookup
[idx_list
] = idx
;
200 /* enable unsolicited events of the clock widget */
201 int lola_enable_clock_events(struct lola
*chip
)
206 err
= lola_codec_read(chip
, chip
->clock
.nid
,
207 LOLA_VERB_SET_UNSOLICITED_ENABLE
,
208 LOLA_UNSOLICITED_ENABLE
| LOLA_UNSOLICITED_TAG
,
213 dev_warn(chip
->card
->dev
, "error in enable_clock_events %d\n",
220 int lola_set_clock_index(struct lola
*chip
, unsigned int idx
)
225 err
= lola_codec_read(chip
, chip
->clock
.nid
,
226 LOLA_VERB_SET_CLOCK_SELECT
,
227 chip
->clock
.idx_lookup
[idx
],
232 dev_warn(chip
->card
->dev
, "error in set_clock %d\n", res
);
238 bool lola_update_ext_clock_freq(struct lola
*chip
, unsigned int val
)
242 /* the current EXTERNAL clock information gets updated by interrupt
243 * with an unsolicited response
247 tag
= (val
>> LOLA_UNSOL_RESP_TAG_OFFSET
) & LOLA_UNSOLICITED_TAG_MASK
;
248 if (tag
!= LOLA_UNSOLICITED_TAG
)
251 /* only for current = external clocks */
252 if (chip
->clock
.sample_clock
[chip
->clock
.cur_index
].type
!=
253 LOLA_CLOCK_TYPE_INTERNAL
) {
254 chip
->clock
.cur_freq
= lola_sample_rate_convert(val
& 0x7f);
255 chip
->clock
.cur_valid
= (val
& 0x100) != 0;
260 int lola_set_clock(struct lola
*chip
, int idx
)
265 if (idx
== chip
->clock
.cur_index
) {
266 /* current clock is allowed */
267 freq
= chip
->clock
.cur_freq
;
268 valid
= chip
->clock
.cur_valid
;
269 } else if (chip
->clock
.sample_clock
[idx
].type
==
270 LOLA_CLOCK_TYPE_INTERNAL
) {
271 /* internal clocks allowed */
272 freq
= chip
->clock
.sample_clock
[idx
].freq
;
279 if (!check_gran_clock_compatibility(chip
, chip
->granularity
, freq
))
282 if (idx
!= chip
->clock
.cur_index
) {
283 int err
= lola_set_clock_index(chip
, idx
);
286 /* update new settings */
287 chip
->clock
.cur_index
= idx
;
288 chip
->clock
.cur_freq
= freq
;
289 chip
->clock
.cur_valid
= true;
294 int lola_set_sample_rate(struct lola
*chip
, int rate
)
298 if (chip
->clock
.cur_freq
== rate
&& chip
->clock
.cur_valid
)
300 /* search for new dwClockIndex */
301 for (i
= 0; i
< chip
->clock
.items
; i
++) {
302 if (chip
->clock
.sample_clock
[i
].type
== LOLA_CLOCK_TYPE_INTERNAL
&&
303 chip
->clock
.sample_clock
[i
].freq
== rate
)
306 if (i
>= chip
->clock
.items
)
308 return lola_set_clock(chip
, i
);