0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/io.h>
0010 #include <linux/init.h>
0011 #include <linux/delay.h>
0012 #include <sound/core.h>
0013 #include "pmac.h"
0014 #include "burgundy.h"
0015
0016
0017
0018 static inline void
0019 snd_pmac_burgundy_busy_wait(struct snd_pmac *chip)
0020 {
0021 int timeout = 50;
0022 while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--)
0023 udelay(1);
0024 if (timeout < 0)
0025 printk(KERN_DEBUG "burgundy_busy_wait: timeout\n");
0026 }
0027
0028 static inline void
0029 snd_pmac_burgundy_extend_wait(struct snd_pmac *chip)
0030 {
0031 int timeout;
0032 timeout = 50;
0033 while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
0034 udelay(1);
0035 if (timeout < 0)
0036 printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n");
0037 timeout = 50;
0038 while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
0039 udelay(1);
0040 if (timeout < 0)
0041 printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n");
0042 }
0043
0044 static void
0045 snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val)
0046 {
0047 out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
0048 snd_pmac_burgundy_busy_wait(chip);
0049 out_le32(&chip->awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));
0050 snd_pmac_burgundy_busy_wait(chip);
0051 out_le32(&chip->awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));
0052 snd_pmac_burgundy_busy_wait(chip);
0053 out_le32(&chip->awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));
0054 snd_pmac_burgundy_busy_wait(chip);
0055 }
0056
0057 static unsigned
0058 snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
0059 {
0060 unsigned val = 0;
0061 unsigned long flags;
0062
0063 spin_lock_irqsave(&chip->reg_lock, flags);
0064
0065 out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
0066 snd_pmac_burgundy_busy_wait(chip);
0067 snd_pmac_burgundy_extend_wait(chip);
0068 val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff;
0069
0070 out_le32(&chip->awacs->codec_ctrl, addr + 0x100100);
0071 snd_pmac_burgundy_busy_wait(chip);
0072 snd_pmac_burgundy_extend_wait(chip);
0073 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<8;
0074
0075 out_le32(&chip->awacs->codec_ctrl, addr + 0x100200);
0076 snd_pmac_burgundy_busy_wait(chip);
0077 snd_pmac_burgundy_extend_wait(chip);
0078 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<16;
0079
0080 out_le32(&chip->awacs->codec_ctrl, addr + 0x100300);
0081 snd_pmac_burgundy_busy_wait(chip);
0082 snd_pmac_burgundy_extend_wait(chip);
0083 val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24;
0084
0085 spin_unlock_irqrestore(&chip->reg_lock, flags);
0086
0087 return val;
0088 }
0089
0090 static void
0091 snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr,
0092 unsigned int val)
0093 {
0094 out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
0095 snd_pmac_burgundy_busy_wait(chip);
0096 }
0097
0098 static unsigned
0099 snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
0100 {
0101 unsigned val = 0;
0102 unsigned long flags;
0103
0104 spin_lock_irqsave(&chip->reg_lock, flags);
0105
0106 out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
0107 snd_pmac_burgundy_busy_wait(chip);
0108 snd_pmac_burgundy_extend_wait(chip);
0109 val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff;
0110
0111 spin_unlock_irqrestore(&chip->reg_lock, flags);
0112
0113 return val;
0114 }
0115
0116 #define BASE2ADDR(base) ((base) << 12)
0117 #define ADDR2BASE(addr) ((addr) >> 12)
0118
0119
0120
0121
0122 static void
0123 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
0124 long *volume, int shift)
0125 {
0126 int hardvolume, lvolume, rvolume;
0127
0128 if (volume[0] < 0 || volume[0] > 100 ||
0129 volume[1] < 0 || volume[1] > 100)
0130 return;
0131 lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
0132 rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
0133
0134 hardvolume = lvolume + (rvolume << shift);
0135 if (shift == 8)
0136 hardvolume |= hardvolume << 16;
0137
0138 snd_pmac_burgundy_wcw(chip, address, hardvolume);
0139 }
0140
0141 static void
0142 snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
0143 long *volume, int shift)
0144 {
0145 int wvolume;
0146
0147 wvolume = snd_pmac_burgundy_rcw(chip, address);
0148
0149 volume[0] = wvolume & 0xff;
0150 if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
0151 volume[0] -= BURGUNDY_VOLUME_OFFSET;
0152 else
0153 volume[0] = 0;
0154 volume[1] = (wvolume >> shift) & 0xff;
0155 if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
0156 volume[1] -= BURGUNDY_VOLUME_OFFSET;
0157 else
0158 volume[1] = 0;
0159 }
0160
0161 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
0162 struct snd_ctl_elem_info *uinfo)
0163 {
0164 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0165 uinfo->count = 2;
0166 uinfo->value.integer.min = 0;
0167 uinfo->value.integer.max = 100;
0168 return 0;
0169 }
0170
0171 static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
0172 struct snd_ctl_elem_value *ucontrol)
0173 {
0174 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0175 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0176 int shift = (kcontrol->private_value >> 8) & 0xff;
0177 snd_pmac_burgundy_read_volume(chip, addr,
0178 ucontrol->value.integer.value, shift);
0179 return 0;
0180 }
0181
0182 static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
0183 struct snd_ctl_elem_value *ucontrol)
0184 {
0185 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0186 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0187 int shift = (kcontrol->private_value >> 8) & 0xff;
0188 long nvoices[2];
0189
0190 snd_pmac_burgundy_write_volume(chip, addr,
0191 ucontrol->value.integer.value, shift);
0192 snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
0193 return (nvoices[0] != ucontrol->value.integer.value[0] ||
0194 nvoices[1] != ucontrol->value.integer.value[1]);
0195 }
0196
0197 #define BURGUNDY_VOLUME_W(xname, xindex, addr, shift) \
0198 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
0199 .info = snd_pmac_burgundy_info_volume,\
0200 .get = snd_pmac_burgundy_get_volume,\
0201 .put = snd_pmac_burgundy_put_volume,\
0202 .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
0203
0204
0205
0206
0207 static void
0208 snd_pmac_burgundy_write_volume_2b(struct snd_pmac *chip, unsigned int address,
0209 long *volume, int off)
0210 {
0211 int lvolume, rvolume;
0212
0213 off |= off << 2;
0214 lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
0215 rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
0216
0217 snd_pmac_burgundy_wcb(chip, address + off, lvolume);
0218 snd_pmac_burgundy_wcb(chip, address + off + 0x500, rvolume);
0219 }
0220
0221 static void
0222 snd_pmac_burgundy_read_volume_2b(struct snd_pmac *chip, unsigned int address,
0223 long *volume, int off)
0224 {
0225 volume[0] = snd_pmac_burgundy_rcb(chip, address + off);
0226 if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
0227 volume[0] -= BURGUNDY_VOLUME_OFFSET;
0228 else
0229 volume[0] = 0;
0230 volume[1] = snd_pmac_burgundy_rcb(chip, address + off + 0x100);
0231 if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
0232 volume[1] -= BURGUNDY_VOLUME_OFFSET;
0233 else
0234 volume[1] = 0;
0235 }
0236
0237 static int snd_pmac_burgundy_info_volume_2b(struct snd_kcontrol *kcontrol,
0238 struct snd_ctl_elem_info *uinfo)
0239 {
0240 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0241 uinfo->count = 2;
0242 uinfo->value.integer.min = 0;
0243 uinfo->value.integer.max = 100;
0244 return 0;
0245 }
0246
0247 static int snd_pmac_burgundy_get_volume_2b(struct snd_kcontrol *kcontrol,
0248 struct snd_ctl_elem_value *ucontrol)
0249 {
0250 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0251 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0252 int off = kcontrol->private_value & 0x300;
0253 snd_pmac_burgundy_read_volume_2b(chip, addr,
0254 ucontrol->value.integer.value, off);
0255 return 0;
0256 }
0257
0258 static int snd_pmac_burgundy_put_volume_2b(struct snd_kcontrol *kcontrol,
0259 struct snd_ctl_elem_value *ucontrol)
0260 {
0261 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0262 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0263 int off = kcontrol->private_value & 0x300;
0264 long nvoices[2];
0265
0266 snd_pmac_burgundy_write_volume_2b(chip, addr,
0267 ucontrol->value.integer.value, off);
0268 snd_pmac_burgundy_read_volume_2b(chip, addr, nvoices, off);
0269 return (nvoices[0] != ucontrol->value.integer.value[0] ||
0270 nvoices[1] != ucontrol->value.integer.value[1]);
0271 }
0272
0273 #define BURGUNDY_VOLUME_2B(xname, xindex, addr, off) \
0274 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
0275 .info = snd_pmac_burgundy_info_volume_2b,\
0276 .get = snd_pmac_burgundy_get_volume_2b,\
0277 .put = snd_pmac_burgundy_put_volume_2b,\
0278 .private_value = ((ADDR2BASE(addr) & 0xff) | ((off) << 8)) }
0279
0280
0281
0282
0283 static int snd_pmac_burgundy_info_gain(struct snd_kcontrol *kcontrol,
0284 struct snd_ctl_elem_info *uinfo)
0285 {
0286 int stereo = (kcontrol->private_value >> 24) & 1;
0287 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0288 uinfo->count = stereo + 1;
0289 uinfo->value.integer.min = 0;
0290 uinfo->value.integer.max = 15;
0291 return 0;
0292 }
0293
0294 static int snd_pmac_burgundy_get_gain(struct snd_kcontrol *kcontrol,
0295 struct snd_ctl_elem_value *ucontrol)
0296 {
0297 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0298 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0299 int stereo = (kcontrol->private_value >> 24) & 1;
0300 int atten = (kcontrol->private_value >> 25) & 1;
0301 int oval;
0302
0303 oval = snd_pmac_burgundy_rcb(chip, addr);
0304 if (atten)
0305 oval = ~oval & 0xff;
0306 ucontrol->value.integer.value[0] = oval & 0xf;
0307 if (stereo)
0308 ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
0309 return 0;
0310 }
0311
0312 static int snd_pmac_burgundy_put_gain(struct snd_kcontrol *kcontrol,
0313 struct snd_ctl_elem_value *ucontrol)
0314 {
0315 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0316 unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
0317 int stereo = (kcontrol->private_value >> 24) & 1;
0318 int atten = (kcontrol->private_value >> 25) & 1;
0319 int oval, val;
0320
0321 oval = snd_pmac_burgundy_rcb(chip, addr);
0322 if (atten)
0323 oval = ~oval & 0xff;
0324 val = ucontrol->value.integer.value[0];
0325 if (stereo)
0326 val |= ucontrol->value.integer.value[1] << 4;
0327 else
0328 val |= ucontrol->value.integer.value[0] << 4;
0329 if (atten)
0330 val = ~val & 0xff;
0331 snd_pmac_burgundy_wcb(chip, addr, val);
0332 return val != oval;
0333 }
0334
0335 #define BURGUNDY_VOLUME_B(xname, xindex, addr, stereo, atten) \
0336 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
0337 .info = snd_pmac_burgundy_info_gain,\
0338 .get = snd_pmac_burgundy_get_gain,\
0339 .put = snd_pmac_burgundy_put_gain,\
0340 .private_value = (ADDR2BASE(addr) | ((stereo) << 24) | ((atten) << 25)) }
0341
0342
0343
0344
0345 static int snd_pmac_burgundy_info_switch_w(struct snd_kcontrol *kcontrol,
0346 struct snd_ctl_elem_info *uinfo)
0347 {
0348 int stereo = (kcontrol->private_value >> 24) & 1;
0349 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0350 uinfo->count = stereo + 1;
0351 uinfo->value.integer.min = 0;
0352 uinfo->value.integer.max = 1;
0353 return 0;
0354 }
0355
0356 static int snd_pmac_burgundy_get_switch_w(struct snd_kcontrol *kcontrol,
0357 struct snd_ctl_elem_value *ucontrol)
0358 {
0359 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0360 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
0361 int lmask = 1 << (kcontrol->private_value & 0xff);
0362 int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
0363 int stereo = (kcontrol->private_value >> 24) & 1;
0364 int val = snd_pmac_burgundy_rcw(chip, addr);
0365 ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
0366 if (stereo)
0367 ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
0368 return 0;
0369 }
0370
0371 static int snd_pmac_burgundy_put_switch_w(struct snd_kcontrol *kcontrol,
0372 struct snd_ctl_elem_value *ucontrol)
0373 {
0374 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0375 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
0376 int lmask = 1 << (kcontrol->private_value & 0xff);
0377 int rmask = 1 << ((kcontrol->private_value >> 8) & 0xff);
0378 int stereo = (kcontrol->private_value >> 24) & 1;
0379 int val, oval;
0380 oval = snd_pmac_burgundy_rcw(chip, addr);
0381 val = oval & ~(lmask | (stereo ? rmask : 0));
0382 if (ucontrol->value.integer.value[0])
0383 val |= lmask;
0384 if (stereo && ucontrol->value.integer.value[1])
0385 val |= rmask;
0386 snd_pmac_burgundy_wcw(chip, addr, val);
0387 return val != oval;
0388 }
0389
0390 #define BURGUNDY_SWITCH_W(xname, xindex, addr, lbit, rbit, stereo) \
0391 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
0392 .info = snd_pmac_burgundy_info_switch_w,\
0393 .get = snd_pmac_burgundy_get_switch_w,\
0394 .put = snd_pmac_burgundy_put_switch_w,\
0395 .private_value = ((lbit) | ((rbit) << 8)\
0396 | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
0397
0398
0399
0400
0401 static int snd_pmac_burgundy_info_switch_b(struct snd_kcontrol *kcontrol,
0402 struct snd_ctl_elem_info *uinfo)
0403 {
0404 int stereo = (kcontrol->private_value >> 24) & 1;
0405 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0406 uinfo->count = stereo + 1;
0407 uinfo->value.integer.min = 0;
0408 uinfo->value.integer.max = 1;
0409 return 0;
0410 }
0411
0412 static int snd_pmac_burgundy_get_switch_b(struct snd_kcontrol *kcontrol,
0413 struct snd_ctl_elem_value *ucontrol)
0414 {
0415 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0416 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
0417 int lmask = kcontrol->private_value & 0xff;
0418 int rmask = (kcontrol->private_value >> 8) & 0xff;
0419 int stereo = (kcontrol->private_value >> 24) & 1;
0420 int val = snd_pmac_burgundy_rcb(chip, addr);
0421 ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
0422 if (stereo)
0423 ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
0424 return 0;
0425 }
0426
0427 static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
0428 struct snd_ctl_elem_value *ucontrol)
0429 {
0430 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
0431 unsigned int addr = BASE2ADDR((kcontrol->private_value >> 16) & 0xff);
0432 int lmask = kcontrol->private_value & 0xff;
0433 int rmask = (kcontrol->private_value >> 8) & 0xff;
0434 int stereo = (kcontrol->private_value >> 24) & 1;
0435 int val, oval;
0436 oval = snd_pmac_burgundy_rcb(chip, addr);
0437 val = oval & ~(lmask | rmask);
0438 if (ucontrol->value.integer.value[0])
0439 val |= lmask;
0440 if (stereo && ucontrol->value.integer.value[1])
0441 val |= rmask;
0442 snd_pmac_burgundy_wcb(chip, addr, val);
0443 return val != oval;
0444 }
0445
0446 #define BURGUNDY_SWITCH_B(xname, xindex, addr, lmask, rmask, stereo) \
0447 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
0448 .info = snd_pmac_burgundy_info_switch_b,\
0449 .get = snd_pmac_burgundy_get_switch_b,\
0450 .put = snd_pmac_burgundy_put_switch_b,\
0451 .private_value = ((lmask) | ((rmask) << 8)\
0452 | (ADDR2BASE(addr) << 16) | ((stereo) << 24)) }
0453
0454
0455
0456
0457 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
0458 BURGUNDY_VOLUME_W("Master Playback Volume", 0,
0459 MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
0460 BURGUNDY_VOLUME_W("CD Capture Volume", 0,
0461 MASK_ADDR_BURGUNDY_VOLCD, 16),
0462 BURGUNDY_VOLUME_2B("Input Capture Volume", 0,
0463 MASK_ADDR_BURGUNDY_VOLMIX01, 2),
0464 BURGUNDY_VOLUME_2B("Mixer Playback Volume", 0,
0465 MASK_ADDR_BURGUNDY_VOLMIX23, 0),
0466 BURGUNDY_VOLUME_B("CD Gain Capture Volume", 0,
0467 MASK_ADDR_BURGUNDY_GAINCD, 1, 0),
0468 BURGUNDY_SWITCH_W("Master Capture Switch", 0,
0469 MASK_ADDR_BURGUNDY_OUTPUTENABLES, 24, 0, 0),
0470 BURGUNDY_SWITCH_W("CD Capture Switch", 0,
0471 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 0, 16, 1),
0472 BURGUNDY_SWITCH_W("CD Playback Switch", 0,
0473 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 0, 16, 1),
0474
0475
0476
0477
0478
0479
0480
0481
0482 BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
0483 MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
0484 };
0485 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
0486 BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
0487 MASK_ADDR_BURGUNDY_VOLLINE, 16),
0488 BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
0489 MASK_ADDR_BURGUNDY_VOLMIC, 16),
0490 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
0491 MASK_ADDR_BURGUNDY_GAINLINE, 1, 0),
0492 BURGUNDY_VOLUME_B("Mic Gain Capture Volume", 0,
0493 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
0494 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0,
0495 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
0496 BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
0497 MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1, 1),
0498 BURGUNDY_VOLUME_B("Headphone Playback Volume", 0,
0499 MASK_ADDR_BURGUNDY_ATTENHP, 1, 1),
0500 BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
0501 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 1, 17, 1),
0502 BURGUNDY_SWITCH_W("Mic Capture Switch", 0,
0503 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
0504 BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
0505 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 1, 17, 1),
0506 BURGUNDY_SWITCH_W("Mic Playback Switch", 0,
0507 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
0508 BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
0509 MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
0510 };
0511 static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
0512 BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
0513 MASK_ADDR_BURGUNDY_VOLMIC, 16),
0514 BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
0515 MASK_ADDR_BURGUNDY_GAINMIC, 1, 0),
0516 BURGUNDY_VOLUME_B("Speaker Playback Volume", 0,
0517 MASK_ADDR_BURGUNDY_ATTENMONO, 0, 1),
0518 BURGUNDY_VOLUME_B("Line out Playback Volume", 0,
0519 MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1, 1),
0520 BURGUNDY_SWITCH_W("Line in Capture Switch", 0,
0521 MASK_ADDR_BURGUNDY_CAPTURESELECTS, 2, 18, 1),
0522 BURGUNDY_SWITCH_W("Line in Playback Switch", 0,
0523 MASK_ADDR_BURGUNDY_OUTPUTSELECTS, 2, 18, 1),
0524
0525
0526 };
0527 static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
0528 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
0529 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0530 BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
0531 BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
0532 static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
0533 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
0534 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0535 BURGUNDY_OUTPUT_INTERN
0536 | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
0537 static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
0538 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
0539 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0540 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
0541 static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
0542 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
0543 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0544 BURGUNDY_OUTPUT_INTERN, 0, 0);
0545 static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
0546 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
0547 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0548 BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
0549 static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
0550 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
0551 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0552 BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
0553 static const struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
0554 BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
0555 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0556 BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
0557
0558
0559 #ifdef PMAC_SUPPORT_AUTOMUTE
0560
0561
0562
0563 static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
0564 {
0565 return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
0566 }
0567
0568 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
0569 {
0570 if (chip->auto_mute) {
0571 int imac = of_machine_is_compatible("iMac");
0572 int reg, oreg;
0573 reg = oreg = snd_pmac_burgundy_rcb(chip,
0574 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
0575 reg &= imac ? ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
0576 | BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
0577 : ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT
0578 | BURGUNDY_OUTPUT_INTERN);
0579 if (snd_pmac_burgundy_detect_headphone(chip))
0580 reg |= imac ? (BURGUNDY_HP_LEFT | BURGUNDY_HP_RIGHT)
0581 : (BURGUNDY_OUTPUT_LEFT
0582 | BURGUNDY_OUTPUT_RIGHT);
0583 else
0584 reg |= imac ? (BURGUNDY_OUTPUT_LEFT
0585 | BURGUNDY_OUTPUT_RIGHT)
0586 : (BURGUNDY_OUTPUT_INTERN);
0587 if (do_notify && reg == oreg)
0588 return;
0589 snd_pmac_burgundy_wcb(chip,
0590 MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
0591 if (do_notify) {
0592 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
0593 &chip->master_sw_ctl->id);
0594 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
0595 &chip->speaker_sw_ctl->id);
0596 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
0597 &chip->hp_detect_ctl->id);
0598 }
0599 }
0600 }
0601 #endif
0602
0603
0604
0605
0606
0607 int snd_pmac_burgundy_init(struct snd_pmac *chip)
0608 {
0609 int imac = of_machine_is_compatible("iMac");
0610 int i, err;
0611
0612
0613 if ((in_le32(&chip->awacs->codec_ctrl) & MASK_ERRCODE) == 0xf0000) {
0614 printk(KERN_WARNING "pmac burgundy: disabled by MacOS :-(\n");
0615 return 1;
0616 }
0617
0618 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
0619 DEF_BURGUNDY_OUTPUTENABLES);
0620 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
0621 DEF_BURGUNDY_MORE_OUTPUTENABLES);
0622 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTSELECTS,
0623 DEF_BURGUNDY_OUTPUTSELECTS);
0624
0625 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
0626 DEF_BURGUNDY_INPSEL21);
0627 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
0628 imac ? DEF_BURGUNDY_INPSEL3_IMAC
0629 : DEF_BURGUNDY_INPSEL3_PMAC);
0630 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
0631 DEF_BURGUNDY_GAINCD);
0632 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
0633 DEF_BURGUNDY_GAINLINE);
0634 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMIC,
0635 DEF_BURGUNDY_GAINMIC);
0636 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMODEM,
0637 DEF_BURGUNDY_GAINMODEM);
0638
0639 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENSPEAKER,
0640 DEF_BURGUNDY_ATTENSPEAKER);
0641 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENLINEOUT,
0642 DEF_BURGUNDY_ATTENLINEOUT);
0643 snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENHP,
0644 DEF_BURGUNDY_ATTENHP);
0645
0646 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_MASTER_VOLUME,
0647 DEF_BURGUNDY_MASTER_VOLUME);
0648 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLCD,
0649 DEF_BURGUNDY_VOLCD);
0650 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLLINE,
0651 DEF_BURGUNDY_VOLLINE);
0652 snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
0653 DEF_BURGUNDY_VOLMIC);
0654
0655 if (chip->hp_stat_mask == 0) {
0656
0657 if (imac)
0658 chip->hp_stat_mask = BURGUNDY_HPDETECT_IMAC_UPPER
0659 | BURGUNDY_HPDETECT_IMAC_LOWER
0660 | BURGUNDY_HPDETECT_IMAC_SIDE;
0661 else
0662 chip->hp_stat_mask = BURGUNDY_HPDETECT_PMAC_BACK;
0663 }
0664
0665
0666
0667 strcpy(chip->card->mixername, "PowerMac Burgundy");
0668
0669 for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
0670 err = snd_ctl_add(chip->card,
0671 snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip));
0672 if (err < 0)
0673 return err;
0674 }
0675 for (i = 0; i < (imac ? ARRAY_SIZE(snd_pmac_burgundy_mixers_imac)
0676 : ARRAY_SIZE(snd_pmac_burgundy_mixers_pmac)); i++) {
0677 err = snd_ctl_add(chip->card,
0678 snd_ctl_new1(imac ? &snd_pmac_burgundy_mixers_imac[i]
0679 : &snd_pmac_burgundy_mixers_pmac[i], chip));
0680 if (err < 0)
0681 return err;
0682 }
0683 chip->master_sw_ctl = snd_ctl_new1(imac
0684 ? &snd_pmac_burgundy_master_sw_imac
0685 : &snd_pmac_burgundy_master_sw_pmac, chip);
0686 err = snd_ctl_add(chip->card, chip->master_sw_ctl);
0687 if (err < 0)
0688 return err;
0689 chip->master_sw_ctl = snd_ctl_new1(imac
0690 ? &snd_pmac_burgundy_line_sw_imac
0691 : &snd_pmac_burgundy_line_sw_pmac, chip);
0692 err = snd_ctl_add(chip->card, chip->master_sw_ctl);
0693 if (err < 0)
0694 return err;
0695 if (imac) {
0696 chip->master_sw_ctl = snd_ctl_new1(
0697 &snd_pmac_burgundy_hp_sw_imac, chip);
0698 err = snd_ctl_add(chip->card, chip->master_sw_ctl);
0699 if (err < 0)
0700 return err;
0701 }
0702 chip->speaker_sw_ctl = snd_ctl_new1(imac
0703 ? &snd_pmac_burgundy_speaker_sw_imac
0704 : &snd_pmac_burgundy_speaker_sw_pmac, chip);
0705 err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);
0706 if (err < 0)
0707 return err;
0708 #ifdef PMAC_SUPPORT_AUTOMUTE
0709 err = snd_pmac_add_automute(chip);
0710 if (err < 0)
0711 return err;
0712
0713 chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
0714 chip->update_automute = snd_pmac_burgundy_update_automute;
0715 snd_pmac_burgundy_update_automute(chip, 0);
0716 #endif
0717
0718 return 0;
0719 }