📄 dmasound_awacs.c
字号:
msleep(100); awacs_write(awacs_reg[6] + MASK_ADDR6); msleep(2); awacs_write(awacs_reg[1] + MASK_ADDR1); awacs_write(awacs_reg[7] + MASK_ADDR7); } if (awacs) { if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) out_le32(&awacs->byteswap, BS_VAL); else out_le32(&awacs->byteswap, 0); }}#ifdef CONFIG_PMAC_PBOOK/* * Save state when going to sleep, restore it afterwards. *//* FIXME: sort out disabling/re-enabling of read stuff as well */static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when){ unsigned long flags; switch (when) { case PBOOK_SLEEP_NOW: LOCK(); awacs_sleeping = 1; /* Tell the rest of the driver we are now going to sleep */ mb(); if (awacs_revision == AWACS_SCREAMER || awacs_revision == AWACS_AWACS) { awacs_reg1_save = awacs_reg[1]; awacs_reg[1] |= MASK_AMUTE | MASK_CMUTE; awacs_write(MASK_ADDR1 | awacs_reg[1]); } PMacSilence(); /* stop rx - if going - a bit of a daft user... but */ out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16)); /* deny interrupts */ if (awacs) disable_irq(awacs_irq); disable_irq(awacs_tx_irq); disable_irq(awacs_rx_irq); /* Chip specific sleep code */ switch (awacs_revision) { case AWACS_TUMBLER: case AWACS_SNAPPER: write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); tas_enter_sleep(); write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); break ; case AWACS_DACA: daca_enter_sleep(); break ; case AWACS_BURGUNDY: break ; case AWACS_SCREAMER: case AWACS_AWACS: default: out_le32(&awacs->control, 0x11) ; break ; } /* Disable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0); /* According to Darwin, we do that after turning off the sound * chip clock. All this will have to be cleaned up once we properly * parse the OF sound-objects */ if ((machine_is_compatible("PowerBook3,1") || machine_is_compatible("PowerBook3,2")) && awacs) { awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1; awacs_write(MASK_ADDR1 | awacs_reg[1]); msleep(200); } break; case PBOOK_WAKE: /* Enable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1); if ((machine_is_compatible("PowerBook3,1") || machine_is_compatible("PowerBook3,2")) && awacs) { msleep(100); awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1); awacs_write(MASK_ADDR1 | awacs_reg[1]); msleep(300); } else msleep(1000); /* restore settings */ switch (awacs_revision) { case AWACS_TUMBLER: case AWACS_SNAPPER: write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); msleep(100); write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol); msleep(150); tas_leave_sleep(); /* Stub for now */ headphone_intr(0,NULL,NULL); break; case AWACS_DACA: msleep(10); /* Check this !!! */ daca_leave_sleep(); break ; /* dont know how yet */ case AWACS_BURGUNDY: break ; case AWACS_SCREAMER: case AWACS_AWACS: default: load_awacs() ; break ; } /* Recalibrate chip */ if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); /* Make sure dma is stopped */ PMacSilence(); if (awacs) enable_irq(awacs_irq); enable_irq(awacs_tx_irq); enable_irq(awacs_rx_irq); if (awacs) { /* OK, allow ints back again */ out_le32(&awacs->control, MASK_IEPC | (awacs_rate_index << 8) | 0x11 | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); } if (macio_base && is_pbook_g3) { /* FIXME: should restore the setup we had...*/ out_8(macio_base + 0x37, 3); } else if (is_pbook_3X00) { in_8(latch_base + 0x190); } /* Remove mute */ if (awacs_revision == AWACS_SCREAMER || awacs_revision == AWACS_AWACS) { awacs_reg[1] = awacs_reg1_save; awacs_write(MASK_ADDR1 | awacs_reg[1]); } awacs_sleeping = 0; /* Resume pending sounds. */ /* we don't try to restart input... */ spin_lock_irqsave(&dmasound.lock, flags); __PMacPlay(); spin_unlock_irqrestore(&dmasound.lock, flags); UNLOCK(); } return PBOOK_SLEEP_OK;}#endif /* CONFIG_PMAC_PBOOK *//* All the burgundy functions: *//* Waits for busy flag to clear */inline static voidawacs_burgundy_busy_wait(void){ int count = 50; /* > 2 samples at 44k1 */ while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--) udelay(1) ;}inline static voidawacs_burgundy_extend_wait(void){ int count = 50 ; /* > 2 samples at 44k1 */ while ((!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) && count--) udelay(1) ; count = 50; while ((in_le32(&awacs->codec_stat) & MASK_EXTEND) && count--) udelay(1);}static voidawacs_burgundy_wcw(unsigned addr, unsigned val){ out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff)); awacs_burgundy_busy_wait(); out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff)); awacs_burgundy_busy_wait(); out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff)); awacs_burgundy_busy_wait(); out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff)); awacs_burgundy_busy_wait();}static unsignedawacs_burgundy_rcw(unsigned addr){ unsigned val = 0; unsigned long flags; /* should have timeouts here */ spin_lock_irqsave(&dmasound.lock, flags); out_le32(&awacs->codec_ctrl, addr + 0x100000); awacs_burgundy_busy_wait(); awacs_burgundy_extend_wait(); val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; out_le32(&awacs->codec_ctrl, addr + 0x100100); awacs_burgundy_busy_wait(); awacs_burgundy_extend_wait(); val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8; out_le32(&awacs->codec_ctrl, addr + 0x100200); awacs_burgundy_busy_wait(); awacs_burgundy_extend_wait(); val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16; out_le32(&awacs->codec_ctrl, addr + 0x100300); awacs_burgundy_busy_wait(); awacs_burgundy_extend_wait(); val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24; spin_unlock_irqrestore(&dmasound.lock, flags); return val;}static voidawacs_burgundy_wcb(unsigned addr, unsigned val){ out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff)); awacs_burgundy_busy_wait();}static unsignedawacs_burgundy_rcb(unsigned addr){ unsigned val = 0; unsigned long flags; /* should have timeouts here */ spin_lock_irqsave(&dmasound.lock, flags); out_le32(&awacs->codec_ctrl, addr + 0x100000); awacs_burgundy_busy_wait(); awacs_burgundy_extend_wait(); val += (in_le32(&awacs->codec_stat) >> 4) & 0xff; spin_unlock_irqrestore(&dmasound.lock, flags); return val;}static intawacs_burgundy_check(void){ /* Checks to see the chip is alive and kicking */ int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE; return error == 0xf0000;}static intawacs_burgundy_init(void){ if (awacs_burgundy_check()) { printk(KERN_WARNING "dmasound_pmac: burgundy not working :-(\n"); return 1; } awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES, DEF_BURGUNDY_OUTPUTENABLES); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, DEF_BURGUNDY_MORE_OUTPUTENABLES); awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS, DEF_BURGUNDY_OUTPUTSELECTS); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21, DEF_BURGUNDY_INPSEL21); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3, DEF_BURGUNDY_INPSEL3); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD, DEF_BURGUNDY_GAINCD); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE, DEF_BURGUNDY_GAINLINE); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC, DEF_BURGUNDY_GAINMIC); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM, DEF_BURGUNDY_GAINMODEM); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, DEF_BURGUNDY_ATTENSPEAKER); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT, DEF_BURGUNDY_ATTENLINEOUT); awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP, DEF_BURGUNDY_ATTENHP); awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME, DEF_BURGUNDY_MASTER_VOLUME); awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD, DEF_BURGUNDY_VOLCD); awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE, DEF_BURGUNDY_VOLLINE); awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC, DEF_BURGUNDY_VOLMIC); return 0;}static voidawacs_burgundy_write_volume(unsigned address, int volume){ int hardvolume,lvolume,rvolume; lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0; rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0; hardvolume = lvolume + (rvolume << 16); awacs_burgundy_wcw(address, hardvolume);}static intawacs_burgundy_read_volume(unsigned address){ int softvolume,wvolume; wvolume = awacs_burgundy_rcw(address); softvolume = (wvolume & 0xff) - 155; softvolume += (((wvolume >> 16) & 0xff) - 155)<<8; return softvolume > 0 ? softvolume : 0;}static intawacs_burgundy_read_mvolume(unsigned address){ int lvolume,rvolume,wvolume; wvolume = awacs_burgundy_rcw(address); wvolume &= 0xffff; rvolume = (wvolume & 0xff) - 155; lvolume = ((wvolume & 0xff00)>>8) - 155; return lvolume + (rvolume << 8);}static voidawacs_burgundy_write_mvolume(unsigned address, int volume){ int lvolume,rvolume,hardvolume; lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0; rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0; hardvolume = lvolume + (rvolume << 8); hardvolume += (hardvolume << 16); awacs_burgundy_wcw(address, hardvolume);}/* End burgundy functions *//* Set up output volumes on machines with the 'perch/whisper' extension card. * this has an SGS i2c chip (7433) which is accessed using the cuda. * * TODO: split this out and make use of the other parts of the SGS chip to * do Bass, Treble etc. */static voidawacs_enable_amp(int spkr_vol){#ifdef CONFIG_ADB_CUDA struct adb_request req; if (sys_ctrler != SYS_CTRLER_CUDA) return; /* turn on headphones */ cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, 4, 0); while (!req.complete) cuda_poll(); cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, 6, 0); while (!req.complete) cuda_poll(); /* turn on speaker */ cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100); while (!req.complete) cuda_poll(); cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100); while (!req.complete) cuda_poll(); cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a, 1, 0x29); while (!req.complete) cuda_poll();#endif /* CONFIG_ADB_CUDA */}/*** Mid level stuff *********************************************************//* * /dev/mixer abstraction */static void do_line_lev(int data){ line_lev = data ; awacs_reg[0] &= ~MASK_MUX_AUDIN; if ((data & 0xff) >= 50) awacs_reg[0] |= MASK_MUX_AUDIN; awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_ip_gain(int data){ ip_gain = data ; data &= 0xff; awacs_reg[0] &= ~MASK_GAINLINE; if (awacs_revision == AWACS_SCREAMER) { awacs_reg[6] &= ~MASK_MIC_BOOST ; if (data >= 33) { awacs_reg[0] |= MASK_GAINLINE; if( data >= 66) awacs_reg[6] |= MASK_MIC_BOOST ; } awacs_write(MASK_ADDR6 | awacs_reg[6]) ; } else { if (data >= 50) awacs_reg[0] |= MASK_GAINLINE; } awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_mic_lev(int data){ mic_lev = data ; data &= 0xff; awacs_reg[0] &= ~MASK_MUX_MIC; if (data >= 50) awacs_reg[0] |= MASK_MUX_MIC; awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_cd_lev(int data){ cd_lev = data ; awacs_reg[0] &= ~MASK_MUX_CD; if ((data & 0xff) >= 50) awacs_reg[0] |= MASK_MUX_CD; awacs_write(MASK_ADDR0 | awacs_reg[0]);}static void do_rec_lev(int data){ int left, right ; rec_lev = data ; /* need to fudge this to use the volume setter routine */ left = 100 - (data & 0xff) ; if( left < 0 ) left = 0 ; right = 100 - ((data >> 8) & 0xff) ; if( right < 0 ) right = 0 ; left |= (right << 8 ); left = awacs_volume_setter(left, 0, 0, 4);}static void do_passthru_vol(int data){ passthru_vol = data ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -