Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ALSA] snd-powermac: Burgundy mixers for B&W and iMac

Add mixer controls and correct headphone detection bits for PowerMac
G3 B&W and iMac G3 Tray-loading, both having Burgundy chipset.

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Risto Suominen and committed by
Takashi Iwai
44deee12 7ae44cfa

+385 -87
+360 -81
sound/ppc/burgundy.c
··· 211 211 nvoices[1] != ucontrol->value.integer.value[1]); 212 212 } 213 213 214 - #define BURGUNDY_VOLUME(xname, xindex, addr, shift) \ 214 + #define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \ 215 215 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 216 216 .info = snd_pmac_burgundy_info_volume,\ 217 217 .get = snd_pmac_burgundy_get_volume,\ 218 218 .put = snd_pmac_burgundy_put_volume,\ 219 219 .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) } 220 220 221 - /* lineout/speaker */ 222 - 223 - static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol, 224 - struct snd_ctl_elem_info *uinfo) 221 + /* 222 + * Burgundy volume: 0 - 100, stereo, 2-byte reg 223 + */ 224 + static void 225 + snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address, 226 + long *volume, int off) 225 227 { 226 - int stereo = (kcontrol->private_value >> 24) & 1; 227 - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 228 - uinfo->count = stereo + 1; 228 + int lvolume, rvolume; 229 + 230 + off |= off << 2; 231 + lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0; 232 + rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0; 233 + 234 + snd_pmac_burgundy_wcb(chip, address + off, lvolume); 235 + snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume); 236 + } 237 + 238 + static void 239 + snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address, 240 + long *volume, int off) 241 + { 242 + volume[0] = snd_pmac_burgundy_rcb(chip, address + off); 243 + if (volume[0] >= BURGUNDY_VOLUME_OFFSET) 244 + volume[0] -= BURGUNDY_VOLUME_OFFSET; 245 + else 246 + volume[0] = 0; 247 + volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100); 248 + if (volume[1] >= BURGUNDY_VOLUME_OFFSET) 249 + volume[1] -= BURGUNDY_VOLUME_OFFSET; 250 + else 251 + volume[1] = 0; 252 + } 253 + 254 + static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol, 255 + struct snd_ctl_elem_info *uinfo) 256 + { 257 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 258 + uinfo->count = 2; 229 259 uinfo->value.integer.min = 0; 230 - uinfo->value.integer.max = 1; 260 + uinfo->value.integer.max = 100; 231 261 return 0; 232 262 } 233 263 234 - static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol, 235 - struct snd_ctl_elem_value *ucontrol) 264 + static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol, 265 + struct snd_ctl_elem_value *ucontrol) 236 266 { 237 267 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 238 - int lmask = kcontrol->private_value & 0xff; 239 - int rmask = (kcontrol->private_value >> 8) & 0xff; 240 - int stereo = (kcontrol->private_value >> 24) & 1; 241 - int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); 242 - ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; 243 - if (stereo) 244 - ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; 268 + unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 269 + int off = kcontrol->private_value & 0x300; 270 + snd_pmac_burgundy_read_volume_2b(chip, addr, 271 + ucontrol->value.integer.value, off); 245 272 return 0; 246 273 } 247 274 248 - static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol, 249 - struct snd_ctl_elem_value *ucontrol) 275 + static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol, 276 + struct snd_ctl_elem_value *ucontrol) 250 277 { 251 278 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 252 - int lmask = kcontrol->private_value & 0xff; 253 - int rmask = (kcontrol->private_value >> 8) & 0xff; 254 - int stereo = (kcontrol->private_value >> 24) & 1; 255 - int val, oval; 256 - oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); 257 - val = oval & ~(lmask | rmask); 258 - if (ucontrol->value.integer.value[0]) 259 - val |= lmask; 260 - if (stereo && ucontrol->value.integer.value[1]) 261 - val |= rmask; 262 - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val); 263 - return val != oval; 279 + unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 280 + int off = kcontrol->private_value & 0x300; 281 + long nvoices[2]; 282 + 283 + snd_pmac_burgundy_write_volume_2b(chip, addr, 284 + ucontrol->value.integer.value, off); 285 + snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off); 286 + return (nvoices[0] != ucontrol->value.integer.value[0] || 287 + nvoices[1] != ucontrol->value.integer.value[1]); 264 288 } 265 289 266 - #define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \ 290 + #define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \ 267 291 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 268 - .info = snd_pmac_burgundy_info_switch_out,\ 269 - .get = snd_pmac_burgundy_get_switch_out,\ 270 - .put = snd_pmac_burgundy_put_switch_out,\ 271 - .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) } 292 + .info = snd_pmac_burgundy_info_volume_2b,\ 293 + .get = snd_pmac_burgundy_get_volume_2b,\ 294 + .put = snd_pmac_burgundy_put_volume_2b,\ 295 + .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) } 272 296 273 - /* line/speaker output volume */ 274 - static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol, 275 - struct snd_ctl_elem_info *uinfo) 297 + /* 298 + * Burgundy gain/attenuation: 0 - 15, mono/stereo, byte reg 299 + */ 300 + static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol, 301 + struct snd_ctl_elem_info *uinfo) 276 302 { 277 303 int stereo = (kcontrol->private_value >> 24) & 1; 278 304 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; ··· 308 282 return 0; 309 283 } 310 284 311 - static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol, 312 - struct snd_ctl_elem_value *ucontrol) 285 + static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol, 286 + struct snd_ctl_elem_value *ucontrol) 313 287 { 314 288 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 315 289 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 316 290 int stereo = (kcontrol->private_value >> 24) & 1; 291 + int atten = (kcontrol->private_value >> 25) & 1; 317 292 int oval; 318 293 319 - oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff; 294 + oval = snd_pmac_burgundy_rcb(chip, addr); 295 + if (atten) 296 + oval = ~oval & 0xff; 320 297 ucontrol->value.integer.value[0] = oval & 0xf; 321 298 if (stereo) 322 299 ucontrol->value.integer.value[1] = (oval >> 4) & 0xf; 323 300 return 0; 324 301 } 325 302 326 - static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol, 327 - struct snd_ctl_elem_value *ucontrol) 303 + static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol, 304 + struct snd_ctl_elem_value *ucontrol) 328 305 { 329 306 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 330 307 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff); 331 308 int stereo = (kcontrol->private_value >> 24) & 1; 332 - unsigned int oval, val; 309 + int atten = (kcontrol->private_value >> 25) & 1; 310 + int oval, val; 333 311 334 - oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff; 335 - val = ucontrol->value.integer.value[0] & 15; 312 + oval = snd_pmac_burgundy_rcb(chip, addr); 313 + if (atten) 314 + oval = ~oval & 0xff; 315 + val = ucontrol->value.integer.value[0]; 336 316 if (stereo) 337 - val |= (ucontrol->value.integer.value[1] & 15) << 4; 317 + val |= ucontrol->value.integer.value[1] << 4; 338 318 else 339 - val |= val << 4; 340 - val = ~val & 0xff; 319 + val |= ucontrol->value.integer.value[0] << 4; 320 + if (atten) 321 + val = ~val & 0xff; 341 322 snd_pmac_burgundy_wcb(chip, addr, val); 342 323 return val != oval; 343 324 } 344 325 345 - #define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \ 326 + #define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \ 346 327 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 347 - .info = snd_pmac_burgundy_info_volume_out,\ 348 - .get = snd_pmac_burgundy_get_volume_out,\ 349 - .put = snd_pmac_burgundy_put_volume_out,\ 350 - .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) } 328 + .info = snd_pmac_burgundy_info_gain,\ 329 + .get = snd_pmac_burgundy_get_gain,\ 330 + .put = snd_pmac_burgundy_put_gain,\ 331 + .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) } 351 332 333 + /* 334 + * Burgundy switch: 0/1, mono/stereo, word reg 335 + */ 336 + static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol, 337 + struct snd_ctl_elem_info *uinfo) 338 + { 339 + int stereo = (kcontrol->private_value >> 24) & 1; 340 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 341 + uinfo->count = stereo + 1; 342 + uinfo->value.integer.min = 0; 343 + uinfo->value.integer.max = 1; 344 + return 0; 345 + } 346 + 347 + static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol, 348 + struct snd_ctl_elem_value *ucontrol) 349 + { 350 + struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 351 + unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 352 + int lmask = 1 << (kcontrol->private_value & 0xff); 353 + int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); 354 + int stereo = (kcontrol->private_value >> 24) & 1; 355 + int val = snd_pmac_burgundy_rcw(chip, addr); 356 + ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; 357 + if (stereo) 358 + ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; 359 + return 0; 360 + } 361 + 362 + static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol, 363 + struct snd_ctl_elem_value *ucontrol) 364 + { 365 + struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 366 + unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 367 + int lmask = 1 << (kcontrol->private_value & 0xff); 368 + int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff); 369 + int stereo = (kcontrol->private_value >> 24) & 1; 370 + int val, oval; 371 + oval = snd_pmac_burgundy_rcw(chip, addr); 372 + val = oval & ~(lmask | (stereo ? rmask : 0)); 373 + if (ucontrol->value.integer.value[0]) 374 + val |= lmask; 375 + if (stereo && ucontrol->value.integer.value[1]) 376 + val |= rmask; 377 + snd_pmac_burgundy_wcw(chip, addr, val); 378 + return val != oval; 379 + } 380 + 381 + #define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \ 382 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 383 + .info = snd_pmac_burgundy_info_switch_w,\ 384 + .get = snd_pmac_burgundy_get_switch_w,\ 385 + .put = snd_pmac_burgundy_put_switch_w,\ 386 + .private_value = ((lbit) | ((rbit) << 8)\ 387 + | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } 388 + 389 + /* 390 + * Burgundy switch: 0/1, mono/stereo, byte reg, bit mask 391 + */ 392 + static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol, 393 + struct snd_ctl_elem_info *uinfo) 394 + { 395 + int stereo = (kcontrol->private_value >> 24) & 1; 396 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 397 + uinfo->count = stereo + 1; 398 + uinfo->value.integer.min = 0; 399 + uinfo->value.integer.max = 1; 400 + return 0; 401 + } 402 + 403 + static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol, 404 + struct snd_ctl_elem_value *ucontrol) 405 + { 406 + struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 407 + unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 408 + int lmask = kcontrol->private_value & 0xff; 409 + int rmask = (kcontrol->private_value >> 8) & 0xff; 410 + int stereo = (kcontrol->private_value >> 24) & 1; 411 + int val = snd_pmac_burgundy_rcb(chip, addr); 412 + ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0; 413 + if (stereo) 414 + ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0; 415 + return 0; 416 + } 417 + 418 + static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol, 419 + struct snd_ctl_elem_value *ucontrol) 420 + { 421 + struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 422 + unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff); 423 + int lmask = kcontrol->private_value & 0xff; 424 + int rmask = (kcontrol->private_value >> 8) & 0xff; 425 + int stereo = (kcontrol->private_value >> 24) & 1; 426 + int val, oval; 427 + oval = snd_pmac_burgundy_rcb(chip, addr); 428 + val = oval & ~(lmask | rmask); 429 + if (ucontrol->value.integer.value[0]) 430 + val |= lmask; 431 + if (stereo && ucontrol->value.integer.value[1]) 432 + val |= rmask; 433 + snd_pmac_burgundy_wcb(chip, addr, val); 434 + return val != oval; 435 + } 436 + 437 + #define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \ 438 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ 439 + .info = snd_pmac_burgundy_info_switch_b,\ 440 + .get = snd_pmac_burgundy_get_switch_b,\ 441 + .put = snd_pmac_burgundy_put_switch_b,\ 442 + .private_value = ((lmask) | ((rmask) << 8)\ 443 + | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) } 444 + 445 + /* 446 + * Burgundy mixers 447 + */ 352 448 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = { 353 - BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8), 354 - BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16), 355 - BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16), 356 - BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16), 357 - BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0), 358 - /*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/ 359 - BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1), 360 - }; 361 - static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata = 362 - BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 363 - static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata = 364 - BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0); 449 + BURGUNDY_VOLUME_W("Master Playback Volume", 0, 450 + MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8), 451 + BURGUNDY_VOLUME_W("CD Capture Volume", 0, 452 + MASK_ADDR_BURGUNDY_VOLCD, 16), 453 + BURGUNDY_VOLUME_2B("Input Capture Volume", 0, 454 + MASK_ADDR_BURGUNDY_VOLMIX01, 2), 455 + BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0, 456 + MASK_ADDR_BURGUNDY_VOLMIX23, 0), 457 + BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0, 458 + MASK_ADDR_BURGUNDY_GAINCD, 1, 0), 459 + BURGUNDY_SWITCH_W("Master Capture Switch", 0, 460 + MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0), 461 + BURGUNDY_SWITCH_W("CD Capture Switch", 0, 462 + MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1), 463 + BURGUNDY_SWITCH_W("CD Playback Switch", 0, 464 + MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1), 465 + /* BURGUNDY_SWITCH_W("Loop Capture Switch", 0, 466 + * MASK_ADDR_BURGUNDY_CAPTURESELECTS, 8, 24, 1), 467 + * BURGUNDY_SWITCH_B("Mixer out Capture Switch", 0, 468 + * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x02, 0, 0), 469 + * BURGUNDY_SWITCH_B("Mixer Capture Switch", 0, 470 + * MASK_ADDR_BURGUNDY_HOSTIFAD, 0x01, 0, 0), 471 + * BURGUNDY_SWITCH_B("PCM out Capture Switch", 0, 472 + * MASK_ADDR_BURGUNDY_HOSTIFEH, 0x02, 0, 0), 473 + */ BURGUNDY_SWITCH_B("PCM Capture Switch", 0, 474 + MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0) 475 + }; 476 + static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] __initdata = { 477 + BURGUNDY_VOLUME_W("Line in Capture Volume", 0, 478 + MASK_ADDR_BURGUNDY_VOLLINE, 16), 479 + BURGUNDY_VOLUME_W("Mic Capture Volume", 0, 480 + MASK_ADDR_BURGUNDY_VOLMIC, 16), 481 + BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, 482 + MASK_ADDR_BURGUNDY_GAINLINE, 1, 0), 483 + BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0, 484 + MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 485 + BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0, 486 + MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 487 + BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 488 + MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1), 489 + BURGUNDY_VOLUME_B("Headphone Playback Volume", 0, 490 + MASK_ADDR_BURGUNDY_ATTENHP, 1, 1), 491 + BURGUNDY_SWITCH_W("Line in Capture Switch", 0, 492 + MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1), 493 + BURGUNDY_SWITCH_W("Mic Capture Switch", 0, 494 + MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), 495 + BURGUNDY_SWITCH_W("Line in Playback Switch", 0, 496 + MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1), 497 + BURGUNDY_SWITCH_W("Mic Playback Switch", 0, 498 + MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), 499 + BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0, 500 + MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) 501 + }; 502 + static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] __initdata = { 503 + BURGUNDY_VOLUME_W("Line in Capture Volume", 0, 504 + MASK_ADDR_BURGUNDY_VOLMIC, 16), 505 + BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0, 506 + MASK_ADDR_BURGUNDY_GAINMIC, 1, 0), 507 + BURGUNDY_VOLUME_B("PC Speaker Playback Volume", 0, 508 + MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1), 509 + BURGUNDY_VOLUME_B("Line out Playback Volume", 0, 510 + MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1), 511 + BURGUNDY_SWITCH_W("Line in Capture Switch", 0, 512 + MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1), 513 + BURGUNDY_SWITCH_W("Line in Playback Switch", 0, 514 + MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1), 515 + /* BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0, 516 + * MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */ 517 + }; 518 + static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac __initdata = 519 + BURGUNDY_SWITCH_B("Master Playback Switch", 0, 520 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 521 + BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT, 522 + BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1); 523 + static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac __initdata = 524 + BURGUNDY_SWITCH_B("Master Playback Switch", 0, 525 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 526 + BURGUNDY_OUTPUT_INTERN 527 + | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 528 + static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac __initdata = 529 + BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0, 530 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 531 + BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 532 + static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac __initdata = 533 + BURGUNDY_SWITCH_B("PC Speaker Playback Switch", 0, 534 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 535 + BURGUNDY_OUTPUT_INTERN, 0, 0); 536 + static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac __initdata = 537 + BURGUNDY_SWITCH_B("Line out Playback Switch", 0, 538 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 539 + BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1); 540 + static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac __initdata = 541 + BURGUNDY_SWITCH_B("Line out Playback Switch", 0, 542 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 543 + BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1); 544 + static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac __initdata = 545 + BURGUNDY_SWITCH_B("Headphone Playback Switch", 0, 546 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 547 + BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1); 365 548 366 549 367 550 #ifdef PMAC_SUPPORT_AUTOMUTE ··· 585 350 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify) 586 351 { 587 352 if (chip->auto_mute) { 353 + int imac = machine_is_compatible("iMac"); 588 354 int reg, oreg; 589 - reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); 590 - reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN); 355 + reg = oreg = snd_pmac_burgundy_rcb(chip, 356 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES); 357 + reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT 358 + | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) 359 + : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT 360 + | BURGUNDY_OUTPUT_INTERN); 591 361 if (snd_pmac_burgundy_detect_headphone(chip)) 592 - reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT; 362 + reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT) 363 + : (BURGUNDY_OUTPUT_LEFT 364 + | BURGUNDY_OUTPUT_RIGHT); 593 365 else 594 - reg |= BURGUNDY_OUTPUT_INTERN; 366 + reg |= imac ? (BURGUNDY_OUTPUT_LEFT 367 + | BURGUNDY_OUTPUT_RIGHT) 368 + : (BURGUNDY_OUTPUT_INTERN); 595 369 if (do_notify && reg == oreg) 596 370 return; 597 - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg); 371 + snd_pmac_burgundy_wcb(chip, 372 + MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg); 598 373 if (do_notify) { 599 374 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, 600 375 &chip->master_sw_ctl->id); ··· 623 378 */ 624 379 int __init snd_pmac_burgundy_init(struct snd_pmac *chip) 625 380 { 381 + int imac = machine_is_compatible("iMac"); 626 382 int i, err; 627 383 628 384 /* Checks to see the chip is alive and kicking */ ··· 632 386 return 1; 633 387 } 634 388 635 - snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES, 389 + snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES, 636 390 DEF_BURGUNDY_OUTPUTENABLES); 637 391 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, 638 392 DEF_BURGUNDY_MORE_OUTPUTENABLES); ··· 642 396 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21, 643 397 DEF_BURGUNDY_INPSEL21); 644 398 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3, 645 - DEF_BURGUNDY_INPSEL3); 399 + imac ? DEF_BURGUNDY_INPSEL3_IMAC 400 + : DEF_BURGUNDY_INPSEL3_PMAC); 646 401 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD, 647 402 DEF_BURGUNDY_GAINCD); 648 403 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE, ··· 669 422 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC, 670 423 DEF_BURGUNDY_VOLMIC); 671 424 672 - if (chip->hp_stat_mask == 0) 425 + if (chip->hp_stat_mask == 0) { 673 426 /* set headphone-jack detection bit */ 674 - chip->hp_stat_mask = 0x04; 675 - 427 + if (imac) 428 + chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER 429 + | BURGUNDY_HPDETECT_IMAC_LOWER 430 + | BURGUNDY_HPDETECT_IMAC_SIDE; 431 + else 432 + chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK; 433 + } 676 434 /* 677 435 * build burgundy mixers 678 436 */ 679 437 strcpy(chip->card->mixername, "PowerMac Burgundy"); 680 438 681 439 for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) { 682 - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0) 440 + err = snd_ctl_add(chip->card, 441 + snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip)); 442 + if (err < 0) 683 443 return err; 684 444 } 685 - chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip); 445 + for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac) 446 + : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) { 447 + err = snd_ctl_add(chip->card, 448 + snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i] 449 + : &snd_pmac_burgundy_mixers_pmac[i], chip)); 450 + if (err < 0) 451 + return err; 452 + } 453 + chip->master_sw_ctl = snd_ctl_new1(imac 454 + ? &snd_pmac_burgundy_master_sw_imac 455 + : &snd_pmac_burgundy_master_sw_pmac, chip); 686 456 if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) 687 457 return err; 688 - chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip); 458 + chip->master_sw_ctl = snd_ctl_new1(imac 459 + ? &snd_pmac_burgundy_line_sw_imac 460 + : &snd_pmac_burgundy_line_sw_pmac, chip); 461 + err = snd_ctl_add(chip->card, chip->master_sw_ctl); 462 + if (err < 0) 463 + return err; 464 + if (imac) { 465 + chip->master_sw_ctl = snd_ctl_new1( 466 + &snd_pmac_burgundy_hp_sw_imac, chip); 467 + err = snd_ctl_add(chip->card, chip->master_sw_ctl); 468 + if (err < 0) 469 + return err; 470 + } 471 + chip->speaker_sw_ctl = snd_ctl_new1(imac 472 + ? &snd_pmac_burgundy_speaker_sw_imac 473 + : &snd_pmac_burgundy_speaker_sw_pmac, chip); 689 474 if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) 690 475 return err; 691 476 #ifdef PMAC_SUPPORT_AUTOMUTE
+25 -6
sound/ppc/burgundy.h
··· 22 22 #ifndef __BURGUNDY_H 23 23 #define __BURGUNDY_H 24 24 25 + #define MASK_ADDR_BURGUNDY_INPBOOST (0x10 << 12) 25 26 #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) 26 27 #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) 27 28 ··· 36 35 #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12) 37 36 #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12) 38 37 38 + #define MASK_ADDR_BURGUNDY_CAPTURESELECTS (0x2A << 12) 39 39 #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12) 40 + #define MASK_ADDR_BURGUNDY_VOLMIX01 (0x2D << 12) 41 + #define MASK_ADDR_BURGUNDY_VOLMIX23 (0x2E << 12) 40 42 #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12) 41 43 42 44 #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12) ··· 49 45 #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12) 50 46 #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12) 51 47 #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12) 48 + #define MASK_ADDR_BURGUNDY_ATTENMONO (0x65 << 12) 49 + 50 + #define MASK_ADDR_BURGUNDY_HOSTIFAD (0x78 << 12) 51 + #define MASK_ADDR_BURGUNDY_HOSTIFEH (0x79 << 12) 52 52 53 53 #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1) 54 54 #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2) ··· 67 59 68 60 /* These are all default values for the burgundy */ 69 61 #define DEF_BURGUNDY_INPSEL21 (0xAA) 70 - #define DEF_BURGUNDY_INPSEL3 (0x0A) 62 + #define DEF_BURGUNDY_INPSEL3_IMAC (0x0A) 63 + #define DEF_BURGUNDY_INPSEL3_PMAC (0x05) 71 64 72 65 #define DEF_BURGUNDY_GAINCD (0x33) 73 66 #define DEF_BURGUNDY_GAINLINE (0x44) 74 67 #define DEF_BURGUNDY_GAINMIC (0x44) 75 68 #define DEF_BURGUNDY_GAINMODEM (0x06) 76 69 77 - /* Remember: lowest volume here is 0x9b */ 70 + /* Remember: lowest volume here is 0x9B (155) */ 78 71 #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC) 79 72 #define DEF_BURGUNDY_VOLLINE (0x00000000) 80 73 #define DEF_BURGUNDY_VOLMIC (0x00000000) 81 74 #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC) 82 75 83 - #define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f) 84 - #define DEF_BURGUNDY_OUTPUTENABLES (0x0A) 76 + #define DEF_BURGUNDY_OUTPUTSELECTS (0x010F010F) 77 + #define DEF_BURGUNDY_OUTPUTENABLES (0x0100000A) 85 78 86 79 /* #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) */ /* too loud */ 87 80 #define DEF_BURGUNDY_MASTER_VOLUME (0xDDDDDDDD) ··· 93 84 #define DEF_BURGUNDY_ATTENLINEOUT (0xCC) 94 85 #define DEF_BURGUNDY_ATTENHP (0xCC) 95 86 96 - /* OUTPUTENABLES bits */ 87 + /* MORE_OUTPUTENABLES bits */ 97 88 #define BURGUNDY_OUTPUT_LEFT 0x02 98 89 #define BURGUNDY_OUTPUT_RIGHT 0x04 90 + #define BURGUNDY_LINEOUT_LEFT 0x08 91 + #define BURGUNDY_LINEOUT_RIGHT 0x10 92 + #define BURGUNDY_HP_LEFT 0x20 93 + #define BURGUNDY_HP_RIGHT 0x40 99 94 #define BURGUNDY_OUTPUT_INTERN 0x80 100 95 101 - /* volume offset */ 96 + /* Headphone detection bits */ 97 + #define BURGUNDY_HPDETECT_PMAC_BACK 0x04 98 + #define BURGUNDY_HPDETECT_IMAC_SIDE 0x04 99 + #define BURGUNDY_HPDETECT_IMAC_UPPER 0x08 100 + #define BURGUNDY_HPDETECT_IMAC_LOWER 0x01 101 + 102 + /* Volume offset */ 102 103 #define BURGUNDY_VOLUME_OFFSET 155 103 104 104 105 #endif /* __BURGUNDY_H */