1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PMac Burgundy lowlevel functions 4 * 5 * Copyright (c) by Takashi Iwai <tiwai@suse.de> 6 * code based on dmasound.c. 7 */ 8 9 #include <linux/io.h> 10 #include <linux/init.h> 11 #include <linux/delay.h> 12 #include <linux/of.h> 13 #include <sound/core.h> 14 #include "pmac.h" 15 #include "burgundy.h" 16 17 18 /* Waits for busy flag to clear */ 19 static inline void 20 snd_pmac_burgundy_busy_wait(struct snd_pmac *chip) 21 { 22 int timeout = 50; 23 while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--) 24 udelay(1); 25 if (timeout < 0) 26 printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); 27 } 28 29 static inline void 30 snd_pmac_burgundy_extend_wait(struct snd_pmac *chip) 31 { 32 int timeout; 33 timeout = 50; 34 while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) 35 udelay(1); 36 if (timeout < 0) 37 printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n"); 38 timeout = 50; 39 while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--) 40 udelay(1); 41 if (timeout < 0) 42 printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n"); 43 } 44 45 static void 46 snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val) 47 { 48 out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); 49 snd_pmac_burgundy_busy_wait(chip); 50 out_le32(&chip->awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); 51 snd_pmac_burgundy_busy_wait(chip); 52 out_le32(&chip->awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); 53 snd_pmac_burgundy_busy_wait(chip); 54 out_le32(&chip->awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); 55 snd_pmac_burgundy_busy_wait(chip); 56 } 57 58 static unsigned 59 snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr) 60 { 61 unsigned val = 0; 62 63 guard(spinlock_irqsave)(&chip->reg_lock); 64 65 out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); 66 snd_pmac_burgundy_busy_wait(chip); 67 snd_pmac_burgundy_extend_wait(chip); 68 val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; 69 70 out_le32(&chip->awacs->codec_ctrl, addr + 0x100100); 71 snd_pmac_burgundy_busy_wait(chip); 72 snd_pmac_burgundy_extend_wait(chip); 73 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<8; 74 75 out_le32(&chip->awacs->codec_ctrl, addr + 0x100200); 76 snd_pmac_burgundy_busy_wait(chip); 77 snd_pmac_burgundy_extend_wait(chip); 78 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<16; 79 80 out_le32(&chip->awacs->codec_ctrl, addr + 0x100300); 81 snd_pmac_burgundy_busy_wait(chip); 82 snd_pmac_burgundy_extend_wait(chip); 83 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24; 84 85 return val; 86 } 87 88 static void 89 snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, 90 unsigned int val) 91 { 92 out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); 93 snd_pmac_burgundy_busy_wait(chip); 94 } 95 96 static unsigned 97 snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr) 98 { 99 unsigned val = 0; 100 101 guard(spinlock_irqsave)(&chip->reg_lock); 102 103 out_le32(&chip->awacs->codec_ctrl, addr + 0x100000); 104 snd_pmac_burgundy_busy_wait(chip); 105 snd_pmac_burgundy_extend_wait(chip); 106 val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff; 107 108 return val; 109 } 110 111 #define BASE2ADDR(base) ((base) << 12) 112 #define ADDR2BASE(addr) ((addr) >> 12) 113 114 /* 115 * Burgundy volume: 0 - 100, stereo, word reg 116 */ 117 static void 118 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address, 119 long *volume, int shift) 120 { 121 int hardvolume, lvolume, rvolume; 122 123 if (volume[0] < 0 || volume[0] > 100 || 124 volume[1] < 0 || volume[1] > 100) 125 return; /* -EINVAL */ 126 lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; 127 rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; 128 129 hardvolume = lvolume + (rvolume << shift); 130 if (shift == 8) 131 hardvolume |= hardvolume << 16; 132 133 snd_pmac_burgundy_wcw(chip, address, hardvolume); 134 } 135 136 static void 137 snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address, 138 long *volume, int shift) 139 { 140 int wvolume; 141 142 wvolume = snd_pmac_burgundy_rcw(chip, address); 143 144 volume[0] = wvolume & 0xff; 145 if (volume[0] >= BURGUNDY_VOLUME_OFFSET) 146 volume[0] -= BURGUNDY_VOLUME_OFFSET; 147 else 148 volume[0] = 0; 149 volume[1] = (wvolume >> shift) & 0xff; 150 if (volume[1] >= BURGUNDY_VOLUME_OFFSET) 151 volume[1] -= BURGUNDY_VOLUME_OFFSET; 152 else 153 volume[1] = 0; 154 } 155 156 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol, 157 struct snd_ctl_elem_info *uinfo) 158 { 159 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 160 uinfo->count = 2; 161 uinfo->value.integer.min = 0; 162 uinfo->value.integer.max = 100; 163 return 0; 164 } 165 166 static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol, 167 struct snd_ctl_elem_value *ucontrol) 168 { 169 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 170 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 171 int shift = (kcontrol->private_value >> 8) & 0xff; 172 snd_pmac_burgundy_read_volume(chip, addr, 173 ucontrol->value.integer.value, shift); 174 return 0; 175 } 176 177 static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol, 178 struct snd_ctl_elem_value *ucontrol) 179 { 180 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 181 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 182 int shift = (kcontrol->private_value >> 8) & 0xff; 183 long nvoices[2]; 184 185 snd_pmac_burgundy_write_volume(chip, addr, 186 ucontrol->value.integer.value, shift); 187 snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift); 188 return (nvoices[0] != ucontrol->value.integer.value[0] || 189 nvoices[1] != ucontrol->value.integer.value[1]); 190 } 191 192 #define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \ 193 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 194 .info = snd_pmac_burgundy_info_volume,\ 195 .get = snd_pmac_burgundy_get_volume,\ 196 .put = snd_pmac_burgundy_put_volume,\ 197 .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) } 198 199 /* 200 * Burgundy volume: 0 - 100, stereo, 2-byte reg 201 */ 202 static void 203 snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address, 204 long *volume, int off) 205 { 206 int lvolume, rvolume; 207 208 off |= off << 2; 209 lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; 210 rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; 211 212 snd_pmac_burgundy_wcb(chip, address + off, lvolume); 213 snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume); 214 } 215 216 static void 217 snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address, 218 long *volume, int off) 219 { 220 volume[0] = snd_pmac_burgundy_rcb(chip, address + off); 221 if (volume[0] >= BURGUNDY_VOLUME_OFFSET) 222 volume[0] -= BURGUNDY_VOLUME_OFFSET; 223 else 224 volume[0] = 0; 225 volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100); 226 if (volume[1] >= BURGUNDY_VOLUME_OFFSET) 227 volume[1] -= BURGUNDY_VOLUME_OFFSET; 228 else 229 volume[1] = 0; 230 } 231 232 static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol, 233 struct snd_ctl_elem_info *uinfo) 234 { 235 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 236 uinfo->count = 2; 237 uinfo->value.integer.min = 0; 238 uinfo->value.integer.max = 100; 239 return 0; 240 } 241 242 static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol, 243 struct snd_ctl_elem_value *ucontrol) 244 { 245 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 246 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 247 int off = kcontrol->private_value & 0x300; 248 snd_pmac_burgundy_read_volume_2b(chip, addr, 249 ucontrol->value.integer.value, off); 250 return 0; 251 } 252 253 static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol, 254 struct snd_ctl_elem_value *ucontrol) 255 { 256 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 257 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 258 int off = kcontrol->private_value & 0x300; 259 long nvoices[2]; 260 261 snd_pmac_burgundy_write_volume_2b(chip, addr, 262 ucontrol->value.integer.value, off); 263 snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off); 264 return (nvoices[0] != ucontrol->value.integer.value[0] || 265 nvoices[1] != ucontrol->value.integer.value[1]); 266 } 267 268 #define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \ 269 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 270 .info = snd_pmac_burgundy_info_volume_2b,\ 271 .get = snd_pmac_burgundy_get_volume_2b,\ 272 .put = snd_pmac_burgundy_put_volume_2b,\ 273 .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) } 274 275 /* 276 * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg 277 */ 278 static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol, 279 struct snd_ctl_elem_info *uinfo) 280 { 281 int stereo = (kcontrol->private_value >> 24) & 1; 282 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 283 uinfo->count = stereo + 1; 284 uinfo->value.integer.min = 0; 285 uinfo->value.integer.max = 15; 286 return 0; 287 } 288 289 static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol, 290 struct snd_ctl_elem_value *ucontrol) 291 { 292 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 293 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 294 int stereo = (kcontrol->private_value >> 24) & 1; 295 int atten = (kcontrol->private_value >> 25) & 1; 296 int oval; 297 298 oval = snd_pmac_burgundy_rcb(chip, addr); 299 if (atten) 300 oval = ~oval & 0xff; 301 ucontrol->value.integer.value[0] = oval & 0xf; 302 if (stereo) 303 ucontrol->value.integer.value[1] = (oval >> 4) & 0xf; 304 return 0; 305 } 306 307 static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol, 308 struct snd_ctl_elem_value *ucontrol) 309 { 310 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 311 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 312 int stereo = (kcontrol->private_value >> 24) & 1; 313 int atten = (kcontrol->private_value >> 25) & 1; 314 int oval, val; 315 316 oval = snd_pmac_burgundy_rcb(chip, addr); 317 if (atten) 318 oval = ~oval & 0xff; 319 val = ucontrol->value.integer.value[0]; 320 if (stereo) 321 val |= ucontrol->value.integer.value[1] << 4; 322 else 323 val |= ucontrol->value.integer.value[0] << 4; 324 if (atten) 325 val = ~val & 0xff; 326 snd_pmac_burgundy_wcb(chip, addr, val); 327 return val != oval; 328 } 329 330 #define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \ 331 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 332 .info = snd_pmac_burgundy_info_gain,\ 333 .get = snd_pmac_burgundy_get_gain,\ 334 .put = snd_pmac_burgundy_put_gain,\ 335 .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) } 336 337 /* 338 * Burgundy switch: 0/1, mono/stereo, word reg 339 */ 340 static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol, 341 struct snd_ctl_elem_info *uinfo) 342 { 343 int stereo = (kcontrol->private_value >> 24) & 1; 344 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 345 uinfo->count = stereo + 1; 346 uinfo->value.integer.min = 0; 347 uinfo->value.integer.max = 1; 348 return 0; 349 } 350 351 static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol, 352 struct snd_ctl_elem_value *ucontrol) 353 { 354 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 355 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 356 int lmask = 1 << (kcontrol->private_value & 0xff); 357 int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); 358 int stereo = (kcontrol->private_value >> 24) & 1; 359 int val = snd_pmac_burgundy_rcw(chip, addr); 360 ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; 361 if (stereo) 362 ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; 363 return 0; 364 } 365 366 static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol, 367 struct snd_ctl_elem_value *ucontrol) 368 { 369 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 370 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 371 int lmask = 1 << (kcontrol->private_value & 0xff); 372 int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); 373 int stereo = (kcontrol->private_value >> 24) & 1; 374 int val, oval; 375 oval = snd_pmac_burgundy_rcw(chip, addr); 376 val = oval & ~(lmask | (stereo ? rmask : 0)); 377 if (ucontrol->value.integer.value[0]) 378 val |= lmask; 379 if (stereo && ucontrol->value.integer.value[1]) 380 val |= rmask; 381 snd_pmac_burgundy_wcw(chip, addr, val); 382 return val != oval; 383 } 384 385 #define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \ 386 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 387 .info = snd_pmac_burgundy_info_switch_w,\ 388 .get = snd_pmac_burgundy_get_switch_w,\ 389 .put = snd_pmac_burgundy_put_switch_w,\ 390 .private_value = ((lbit) | ((rbit) << 8)\ 391 | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } 392 393 /* 394 * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask 395 */ 396 static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol, 397 struct snd_ctl_elem_info *uinfo) 398 { 399 int stereo = (kcontrol->private_value >> 24) & 1; 400 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 401 uinfo->count = stereo + 1; 402 uinfo->value.integer.min = 0; 403 uinfo->value.integer.max = 1; 404 return 0; 405 } 406 407 static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol, 408 struct snd_ctl_elem_value *ucontrol) 409 { 410 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 411 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 412 int lmask = kcontrol->private_value & 0xff; 413 int rmask = (kcontrol->private_value >> 8) & 0xff; 414 int stereo = (kcontrol->private_value >> 24) & 1; 415 int val = snd_pmac_burgundy_rcb(chip, addr); 416 ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; 417 if (stereo) 418 ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; 419 return 0; 420 } 421 422 static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol, 423 struct snd_ctl_elem_value *ucontrol) 424 { 425 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 426 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 427 int lmask = kcontrol->private_value & 0xff; 428 int rmask = (kcontrol->private_value >> 8) & 0xff; 429 int stereo = (kcontrol->private_value >> 24) & 1; 430 int val, oval; 431 oval = snd_pmac_burgundy_rcb(chip, addr); 432 val = oval & ~(lmask | rmask); 433 if (ucontrol->value.integer.value[0]) 434 val |= lmask; 435 if (stereo && ucontrol->value.integer.value[1]) 436 val |= rmask; 437 snd_pmac_burgundy_wcb(chip, addr, val); 438 return val != oval; 439 } 440 441 #define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \ 442 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 443 .info = snd_pmac_burgundy_info_switch_b,\ 444 .get = snd_pmac_burgundy_get_switch_b,\ 445 .put = snd_pmac_burgundy_put_switch_b,\ 446 .private_value = ((lmask) | ((rmask) << 8)\ 447 | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } 448 449 /* 450 * Burgundy mixers 451 */ 452 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = { 453 BURGUNDY_VOLUME_W("Master Playback Volume", 0, 454 MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8), 455 BURGUNDY_VOLUME_W("CD Capture Volume", 0, 456 MASK_ADDR_BURGUNDY_VOLCD, 16), 457 BURGUNDY_VOLUME_2B("Input Capture Volume", 0, 458 MASK_ADDR_BURGUNDY_VOLMIX01, 2), 459 BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0, 460 MASK_ADDR_BURGUNDY_VOLMIX23, 0), 461 BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0, 462 MASK_ADDR_BURGUNDY_GAINCD, 1, 0), 463 BURGUNDY_SWITCH_W("Master Capture Switch", 0, 464 MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0), 465 BURGUNDY_SWITCH_W("CD Capture Switch", 0, 466 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1), 467 BURGUNDY_SWITCH_W("CD Playback Switch", 0, 468 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1), 469 /* BURGUNDY_SWITCH_W("Loop Capture Switch", 0, 470 * MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1), 471 * BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0, 472 * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0), 473 * BURGUNDY_SWITCH_B("Mixer Capture Switch", 0, 474 * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0), 475 * BURGUNDY_SWITCH_B("PCM out Capture Switch", 0, 476 * MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0), 477 */ BURGUNDY_SWITCH_B("PCM Capture Switch", 0, 478 MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0) 479 }; 480 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = { 481 BURGUNDY_VOLUME_W("Line in Capture Volume", 0, 482 MASK_ADDR_BURGUNDY_VOLLINE, 16), 483 BURGUNDY_VOLUME_W("Mic Capture Volume", 0, 484 MASK_ADDR_BURGUNDY_VOLMIC, 16), 485 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, 486 MASK_ADDR_BURGUNDY_GAINLINE, 1, 0), 487 BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0, 488 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 489 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, 490 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 491 BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 492 MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1), 493 BURGUNDY_VOLUME_B("Headphone Playback Volume", 0, 494 MASK_ADDR_BURGUNDY_ATTENHP, 1, 1), 495 BURGUNDY_SWITCH_W("Line in Capture Switch", 0, 496 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1), 497 BURGUNDY_SWITCH_W("Mic Capture Switch", 0, 498 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), 499 BURGUNDY_SWITCH_W("Line in Playback Switch", 0, 500 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1), 501 BURGUNDY_SWITCH_W("Mic Playback Switch", 0, 502 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), 503 BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0, 504 MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) 505 }; 506 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = { 507 BURGUNDY_VOLUME_W("Line in Capture Volume", 0, 508 MASK_ADDR_BURGUNDY_VOLMIC, 16), 509 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, 510 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 511 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0, 512 MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1), 513 BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 514 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 515 BURGUNDY_SWITCH_W("Line in Capture Switch", 0, 516 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), 517 BURGUNDY_SWITCH_W("Line in Playback Switch", 0, 518 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), 519 /* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0, 520 * MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */ 521 }; 522 static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac = 523 BURGUNDY_SWITCH_B("Master Playback Switch", 0, 524 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 525 BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT, 526 BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1); 527 static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac = 528 BURGUNDY_SWITCH_B("Master Playback Switch", 0, 529 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 530 BURGUNDY_OUTPUT_INTERN 531 | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 532 static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac = 533 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, 534 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 535 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 536 static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac = 537 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0, 538 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 539 BURGUNDY_OUTPUT_INTERN, 0, 0); 540 static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac = 541 BURGUNDY_SWITCH_B("Line out Playback Switch", 0, 542 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 543 BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1); 544 static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac = 545 BURGUNDY_SWITCH_B("Line out Playback Switch", 0, 546 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 547 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 548 static const struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac = 549 BURGUNDY_SWITCH_B("Headphone Playback Switch", 0, 550 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 551 BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1); 552 553 554 #ifdef PMAC_SUPPORT_AUTOMUTE 555 /* 556 * auto-mute stuffs 557 */ 558 static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip) 559 { 560 return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0; 561 } 562 563 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify) 564 { 565 if (chip->auto_mute) { 566 int imac = of_machine_is_compatible("iMac"); 567 int reg, oreg; 568 reg = oreg = snd_pmac_burgundy_rcb(chip, 569 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); 570 reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT 571 | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) 572 : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT 573 | BURGUNDY_OUTPUT_INTERN); 574 if (snd_pmac_burgundy_detect_headphone(chip)) 575 reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) 576 : (BURGUNDY_OUTPUT_LEFT 577 | BURGUNDY_OUTPUT_RIGHT); 578 else 579 reg |= imac ? (BURGUNDY_OUTPUT_LEFT 580 | BURGUNDY_OUTPUT_RIGHT) 581 : (BURGUNDY_OUTPUT_INTERN); 582 if (do_notify && reg == oreg) 583 return; 584 snd_pmac_burgundy_wcb(chip, 585 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg); 586 if (do_notify) { 587 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 588 &chip->master_sw_ctl->id); 589 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 590 &chip->speaker_sw_ctl->id); 591 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 592 &chip->hp_detect_ctl->id); 593 } 594 } 595 } 596 #endif /* PMAC_SUPPORT_AUTOMUTE */ 597 598 599 /* 600 * initialize burgundy 601 */ 602 int snd_pmac_burgundy_init(struct snd_pmac *chip) 603 { 604 int imac = of_machine_is_compatible("iMac"); 605 int i, err; 606 607 /* Checks to see the chip is alive and kicking */ 608 if ((in_le32(&chip->awacs->codec_ctrl) & MASK_ERRCODE) == 0xf0000) { 609 printk(KERN_WARNING "pmac burgundy: disabled by MacOS :-(\n"); 610 return 1; 611 } 612 613 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES, 614 DEF_BURGUNDY_OUTPUTENABLES); 615 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 616 DEF_BURGUNDY_MORE_OUTPUTENABLES); 617 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 618 DEF_BURGUNDY_OUTPUTSELECTS); 619 620 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21, 621 DEF_BURGUNDY_INPSEL21); 622 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3, 623 imac ? DEF_BURGUNDY_INPSEL3_IMAC 624 : DEF_BURGUNDY_INPSEL3_PMAC); 625 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD, 626 DEF_BURGUNDY_GAINCD); 627 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE, 628 DEF_BURGUNDY_GAINLINE); 629 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMIC, 630 DEF_BURGUNDY_GAINMIC); 631 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMODEM, 632 DEF_BURGUNDY_GAINMODEM); 633 634 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 635 DEF_BURGUNDY_ATTENSPEAKER); 636 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 637 DEF_BURGUNDY_ATTENLINEOUT); 638 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENHP, 639 DEF_BURGUNDY_ATTENHP); 640 641 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 642 DEF_BURGUNDY_MASTER_VOLUME); 643 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLCD, 644 DEF_BURGUNDY_VOLCD); 645 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLLINE, 646 DEF_BURGUNDY_VOLLINE); 647 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC, 648 DEF_BURGUNDY_VOLMIC); 649 650 if (chip->hp_stat_mask == 0) { 651 /* set headphone-jack detection bit */ 652 if (imac) 653 chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER 654 | BURGUNDY_HPDETECT_IMAC_LOWER 655 | BURGUNDY_HPDETECT_IMAC_SIDE; 656 else 657 chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK; 658 } 659 /* 660 * build burgundy mixers 661 */ 662 strscpy(chip->card->mixername, "PowerMac Burgundy"); 663 664 for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) { 665 err = snd_ctl_add(chip->card, 666 snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip)); 667 if (err < 0) 668 return err; 669 } 670 for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac) 671 : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) { 672 err = snd_ctl_add(chip->card, 673 snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i] 674 : &snd_pmac_burgundy_mixers_pmac[i], chip)); 675 if (err < 0) 676 return err; 677 } 678 chip->master_sw_ctl = snd_ctl_new1(imac 679 ? &snd_pmac_burgundy_master_sw_imac 680 : &snd_pmac_burgundy_master_sw_pmac, chip); 681 err = snd_ctl_add(chip->card, chip->master_sw_ctl); 682 if (err < 0) 683 return err; 684 chip->master_sw_ctl = snd_ctl_new1(imac 685 ? &snd_pmac_burgundy_line_sw_imac 686 : &snd_pmac_burgundy_line_sw_pmac, chip); 687 err = snd_ctl_add(chip->card, chip->master_sw_ctl); 688 if (err < 0) 689 return err; 690 if (imac) { 691 chip->master_sw_ctl = snd_ctl_new1( 692 &snd_pmac_burgundy_hp_sw_imac, chip); 693 err = snd_ctl_add(chip->card, chip->master_sw_ctl); 694 if (err < 0) 695 return err; 696 } 697 chip->speaker_sw_ctl = snd_ctl_new1(imac 698 ? &snd_pmac_burgundy_speaker_sw_imac 699 : &snd_pmac_burgundy_speaker_sw_pmac, chip); 700 err = snd_ctl_add(chip->card, chip->speaker_sw_ctl); 701 if (err < 0) 702 return err; 703 #ifdef PMAC_SUPPORT_AUTOMUTE 704 err = snd_pmac_add_automute(chip); 705 if (err < 0) 706 return err; 707 708 chip->detect_headphone = snd_pmac_burgundy_detect_headphone; 709 chip->update_automute = snd_pmac_burgundy_update_automute; 710 snd_pmac_burgundy_update_automute(chip, 0); /* update the status only */ 711 #endif 712 713 return 0; 714 } 715