1 /* 2 * Support for Digigram Lola PCI-e boards 3 * 4 * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program; if not, write to the Free Software Foundation, Inc., 59 18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/init.h> 23 #include <linux/delay.h> 24 #include <sound/core.h> 25 #include <sound/pcm.h> 26 #include "lola.h" 27 28 unsigned int lola_sample_rate_convert(unsigned int coded) 29 { 30 unsigned int freq; 31 32 /* base frequency */ 33 switch (coded & 0x3) { 34 case 0: freq = 48000; break; 35 case 1: freq = 44100; break; 36 case 2: freq = 32000; break; 37 default: return 0; /* error */ 38 } 39 40 /* multiplier / devisor */ 41 switch (coded & 0x1c) { 42 case (0 << 2): break; 43 case (4 << 2): break; 44 case (1 << 2): freq *= 2; break; 45 case (2 << 2): freq *= 4; break; 46 case (5 << 2): freq /= 2; break; 47 case (6 << 2): freq /= 4; break; 48 default: return 0; /* error */ 49 } 50 51 /* ajustement */ 52 switch (coded & 0x60) { 53 case (0 << 5): break; 54 case (1 << 5): freq = (freq * 999) / 1000; break; 55 case (2 << 5): freq = (freq * 1001) / 1000; break; 56 default: return 0; /* error */ 57 } 58 return freq; 59 } 60 61 /* 62 * Granualrity 63 */ 64 65 #define LOLA_MAXFREQ_AT_GRANULARITY_MIN 48000 66 #define LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX 96000 67 68 static bool check_gran_clock_compatibility(struct lola *chip, 69 unsigned int val, 70 unsigned int freq) 71 { 72 if (!chip->granularity) 73 return true; 74 75 if (val < LOLA_GRANULARITY_MIN || val > LOLA_GRANULARITY_MAX || 76 (val % LOLA_GRANULARITY_STEP) != 0) 77 return false; 78 79 if (val == LOLA_GRANULARITY_MIN) { 80 if (freq > LOLA_MAXFREQ_AT_GRANULARITY_MIN) 81 return false; 82 } else if (val < LOLA_GRANULARITY_MAX) { 83 if (freq > LOLA_MAXFREQ_AT_GRANULARITY_BELOW_MAX) 84 return false; 85 } 86 return true; 87 } 88 89 int lola_set_granularity(struct lola *chip, unsigned int val, bool force) 90 { 91 int err; 92 93 if (!force) { 94 if (val == chip->granularity) 95 return 0; 96 #if 0 97 /* change Gran only if there are no streams allocated ! */ 98 if (chip->audio_in_alloc_mask || chip->audio_out_alloc_mask) 99 return -EBUSY; 100 #endif 101 if (!check_gran_clock_compatibility(chip, val, 102 chip->clock.cur_freq)) 103 return -EINVAL; 104 } 105 106 chip->granularity = val; 107 val /= LOLA_GRANULARITY_STEP; 108 109 /* audio function group */ 110 err = lola_codec_write(chip, 1, LOLA_VERB_SET_GRANULARITY_STEPS, 111 val, 0); 112 if (err < 0) 113 return err; 114 /* this can be a very slow function !!! */ 115 usleep_range(400 * val, 20000); 116 return lola_codec_flush(chip); 117 } 118 119 /* 120 * Clock widget handling 121 */ 122 123 int lola_init_clock_widget(struct lola *chip, int nid) 124 { 125 unsigned int val; 126 int i, j, nitems, nb_verbs, idx, idx_list; 127 int err; 128 129 err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val); 130 if (err < 0) { 131 printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid); 132 return err; 133 } 134 135 if ((val & 0xfff00000) != 0x01f00000) { /* test SubType and Type */ 136 snd_printdd("No valid clock widget\n"); 137 return 0; 138 } 139 140 chip->clock.nid = nid; 141 chip->clock.items = val & 0xff; 142 snd_printdd("clock_list nid=%x, entries=%d\n", nid, 143 chip->clock.items); 144 if (chip->clock.items > MAX_SAMPLE_CLOCK_COUNT) { 145 printk(KERN_ERR SFX "CLOCK_LIST too big: %d\n", 146 chip->clock.items); 147 return -EINVAL; 148 } 149 150 nitems = chip->clock.items; 151 nb_verbs = (nitems + 3) / 4; 152 idx = 0; 153 idx_list = 0; 154 for (i = 0; i < nb_verbs; i++) { 155 unsigned int res_ex; 156 unsigned short items[4]; 157 158 err = lola_codec_read(chip, nid, LOLA_VERB_GET_CLOCK_LIST, 159 idx, 0, &val, &res_ex); 160 if (err < 0) { 161 printk(KERN_ERR SFX "Can't read CLOCK_LIST\n"); 162 return -EINVAL; 163 } 164 165 items[0] = val & 0xfff; 166 items[1] = (val >> 16) & 0xfff; 167 items[2] = res_ex & 0xfff; 168 items[3] = (res_ex >> 16) & 0xfff; 169 170 for (j = 0; j < 4; j++) { 171 unsigned char type = items[j] >> 8; 172 unsigned int freq = items[j] & 0xff; 173 int format = LOLA_CLOCK_FORMAT_NONE; 174 bool add_clock = true; 175 if (type == LOLA_CLOCK_TYPE_INTERNAL) { 176 freq = lola_sample_rate_convert(freq); 177 if (freq < chip->sample_rate_min) 178 add_clock = false; 179 else if (freq == 48000) { 180 chip->clock.cur_index = idx_list; 181 chip->clock.cur_freq = 48000; 182 chip->clock.cur_valid = true; 183 } 184 } else if (type == LOLA_CLOCK_TYPE_VIDEO) { 185 freq = lola_sample_rate_convert(freq); 186 if (freq < chip->sample_rate_min) 187 add_clock = false; 188 /* video clock has a format (0:NTSC, 1:PAL)*/ 189 if (items[j] & 0x80) 190 format = LOLA_CLOCK_FORMAT_NTSC; 191 else 192 format = LOLA_CLOCK_FORMAT_PAL; 193 } 194 if (add_clock) { 195 struct lola_sample_clock *sc; 196 sc = &chip->clock.sample_clock[idx_list]; 197 sc->type = type; 198 sc->format = format; 199 sc->freq = freq; 200 /* keep the index used with the board */ 201 chip->clock.idx_lookup[idx_list] = idx; 202 idx_list++; 203 } else { 204 chip->clock.items--; 205 } 206 if (++idx >= nitems) 207 break; 208 } 209 } 210 return 0; 211 } 212 213 /* enable unsolicited events of the clock widget */ 214 int lola_enable_clock_events(struct lola *chip) 215 { 216 unsigned int res; 217 int err; 218 219 err = lola_codec_read(chip, chip->clock.nid, 220 LOLA_VERB_SET_UNSOLICITED_ENABLE, 221 LOLA_UNSOLICITED_ENABLE | LOLA_UNSOLICITED_TAG, 222 0, &res, NULL); 223 if (err < 0) 224 return err; 225 if (res) { 226 printk(KERN_WARNING SFX "error in enable_clock_events %d\n", 227 res); 228 return -EINVAL; 229 } 230 return 0; 231 } 232 233 int lola_set_clock_index(struct lola *chip, unsigned int idx) 234 { 235 unsigned int res; 236 int err; 237 238 err = lola_codec_read(chip, chip->clock.nid, 239 LOLA_VERB_SET_CLOCK_SELECT, 240 chip->clock.idx_lookup[idx], 241 0, &res, NULL); 242 if (err < 0) 243 return err; 244 if (res) { 245 printk(KERN_WARNING SFX "error in set_clock %d\n", res); 246 return -EINVAL; 247 } 248 return 0; 249 } 250 251 bool lola_update_ext_clock_freq(struct lola *chip, unsigned int val) 252 { 253 unsigned int tag; 254 255 /* the current EXTERNAL clock information gets updated by interrupt 256 * with an unsolicited response 257 */ 258 if (!val) 259 return false; 260 tag = (val >> LOLA_UNSOL_RESP_TAG_OFFSET) & LOLA_UNSOLICITED_TAG_MASK; 261 if (tag != LOLA_UNSOLICITED_TAG) 262 return false; 263 264 /* only for current = external clocks */ 265 if (chip->clock.sample_clock[chip->clock.cur_index].type != 266 LOLA_CLOCK_TYPE_INTERNAL) { 267 chip->clock.cur_freq = lola_sample_rate_convert(val & 0x7f); 268 chip->clock.cur_valid = (val & 0x100) != 0; 269 } 270 return true; 271 } 272 273 int lola_set_clock(struct lola *chip, int idx) 274 { 275 int freq = 0; 276 bool valid = false; 277 278 if (idx == chip->clock.cur_index) { 279 /* current clock is allowed */ 280 freq = chip->clock.cur_freq; 281 valid = chip->clock.cur_valid; 282 } else if (chip->clock.sample_clock[idx].type == 283 LOLA_CLOCK_TYPE_INTERNAL) { 284 /* internal clocks allowed */ 285 freq = chip->clock.sample_clock[idx].freq; 286 valid = true; 287 } 288 289 if (!freq || !valid) 290 return -EINVAL; 291 292 if (!check_gran_clock_compatibility(chip, chip->granularity, freq)) 293 return -EINVAL; 294 295 if (idx != chip->clock.cur_index) { 296 int err = lola_set_clock_index(chip, idx); 297 if (err < 0) 298 return err; 299 /* update new settings */ 300 chip->clock.cur_index = idx; 301 chip->clock.cur_freq = freq; 302 chip->clock.cur_valid = true; 303 } 304 return 0; 305 } 306 307 int lola_set_sample_rate(struct lola *chip, int rate) 308 { 309 int i; 310 311 if (chip->clock.cur_freq == rate && chip->clock.cur_valid) 312 return 0; 313 /* search for new dwClockIndex */ 314 for (i = 0; i < chip->clock.items; i++) { 315 if (chip->clock.sample_clock[i].type == LOLA_CLOCK_TYPE_INTERNAL && 316 chip->clock.sample_clock[i].freq == rate) 317 break; 318 } 319 if (i >= chip->clock.items) 320 return -EINVAL; 321 return lola_set_clock(chip, i); 322 } 323 324