コード例 #1
0
ファイル: sscape.c プロジェクト: FatSunHYS/OSCourseDesign
/*
 * Override for the CS4231 capture format function. 
 * The AD1845 has much simpler format and rate selection.
 */
static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format)
{
	unsigned long flags;
	unsigned rate = params_rate(params);

	/*
	 * The AD1845 can't handle sample frequencies 
	 * outside of 4 kHZ to 50 kHZ
	 */
	if (rate > 50000)
		rate = 50000;
	else if (rate < 4000)
		rate = 4000;

	spin_lock_irqsave(&chip->reg_lock, flags);

	/*
	 * Program the AD1845 correctly for the playback stream.
	 * Note that we do NOT need to toggle the MCE bit because
	 * the CAPTURE_ENABLE bit of the Interface Configuration
	 * register is set.
	 *
	 * NOTE: We seem to need to write to the MSB before the LSB
	 *       to get the correct sample frequency.
	 */
	snd_cs4231_out(chip, CS4231_REC_FORMAT, (format & 0xf0));
	snd_cs4231_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8));
	snd_cs4231_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate);

	spin_unlock_irqrestore(&chip->reg_lock, flags);
}
コード例 #2
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr)
{
    unsigned long flags;
    unsigned char rate = divisor_to_rate_register(params->rate_den);
    
    spin_lock_irqsave(&chip->reg_lock, flags);
    /* set fast capture format change and clean capture FIFO */
    snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x20);
    snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
    snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
    snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
}
コード例 #3
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr)
{
    unsigned long flags;
    unsigned char rate = divisor_to_rate_register(params->rate_den);
    
    spin_lock_irqsave(&chip->reg_lock, flags);
    /* set fast playback format change and clean playback FIFO */
    snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] | 0x10);
    snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
    snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
    snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
}
コード例 #4
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
    struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
    unsigned long flags;
    int change;
    unsigned short enable, val;
    
    enable = ucontrol->value.integer.value[0] & 1;

    mutex_lock(&chip->mce_mutex);
    snd_cs4231_mce_up(chip);
    spin_lock_irqsave(&chip->reg_lock, flags);
    val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
    change = val != chip->image[CS4231_ALT_FEATURE_1];
    snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, val);
    val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
    snd_cs4236_ctrl_out(chip, 4, val);
    udelay(100);
    val &= ~0x40;
    snd_cs4236_ctrl_out(chip, 4, val);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
    snd_cs4231_mce_down(chip);
    mutex_unlock(&chip->mce_mutex);

#if 0
    printk("set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
            snd_cs4231_in(chip, CS4231_ALT_FEATURE_1),
            snd_cs4236_ctrl_in(chip, 3),
            snd_cs4236_ctrl_in(chip, 4),
            snd_cs4236_ctrl_in(chip, 5),
            snd_cs4236_ctrl_in(chip, 6),
            snd_cs4236_ctrl_in(chip, 8));
#endif
    return change;
}
コード例 #5
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
    struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
    unsigned long flags;
    int left_reg = kcontrol->private_value & 0xff;
    int right_reg = (kcontrol->private_value >> 8) & 0xff;
    int shift_left = (kcontrol->private_value >> 16) & 0x07;
    int shift_right = (kcontrol->private_value >> 19) & 0x07;
    int mask = (kcontrol->private_value >> 24) & 0xff;
    int invert = (kcontrol->private_value >> 22) & 1;
    int change;
    unsigned short val1, val2;
    
    val1 = ucontrol->value.integer.value[0] & mask;
    val2 = ucontrol->value.integer.value[1] & mask;
    if (invert) {
        val1 = mask - val1;
        val2 = mask - val2;
    }
    val1 <<= shift_left;
    val2 <<= shift_right;
    spin_lock_irqsave(&chip->reg_lock, flags);
    val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
    val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
    change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
    snd_cs4231_out(chip, left_reg, val1);
    snd_cs4236_ext_out(chip, right_reg, val2);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
    return change;
}
コード例 #6
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static void snd_cs4236_resume(struct snd_cs4231 *chip)
{
    int reg;
    unsigned long flags;
    
    snd_cs4231_mce_up(chip);
    spin_lock_irqsave(&chip->reg_lock, flags);
    for (reg = 0; reg < 32; reg++) {
        switch (reg) {
        case CS4236_EXT_REG:
        case CS4231_VERSION:
        case 27:    /* why? CS4235 - master left */
        case 29:    /* why? CS4235 - master right */
            break;
        default:
            snd_cs4231_out(chip, reg, chip->image[reg]);
            break;
        }
    }
    for (reg = 0; reg < 18; reg++)
        snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]);
    for (reg = 2; reg < 9; reg++) {
        switch (reg) {
        case 7:
            break;
        default:
            snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]);
        }
    }
    spin_unlock_irqrestore(&chip->reg_lock, flags);
    snd_cs4231_mce_down(chip);
}
コード例 #7
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
    struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
    unsigned long flags;
    int change;
    unsigned short val1, val2;
    
    val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]);
    val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]);
    spin_lock_irqsave(&chip->reg_lock, flags);
    val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
    val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
    change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
    snd_cs4231_out(chip, CS4235_LEFT_MASTER, val1);
    snd_cs4231_out(chip, CS4235_RIGHT_MASTER, val2);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
    return change;
}
コード例 #8
0
ファイル: sscape.c プロジェクト: FatSunHYS/OSCourseDesign
/*
 * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
 * is very much like a CS4231, with a few extra bits. We will
 * try to support at least some of the extra bits by overriding
 * some of the CS4231 callback.
 */
static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1)
{
	register struct soundscape *sscape = get_card_soundscape(card);
	struct snd_cs4231 *chip;
	int err;

#define CS4231_SHARE_HARDWARE  (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2)
	/*
	 * The AD1845 PCM device is only half-duplex, and so
	 * we only give it one DMA channel ...
	 */
	if ((err = snd_cs4231_create(card,
				     port, -1, irq, dma1, dma1,
				     CS4231_HW_DETECT,
				     CS4231_HWSHARE_DMA1, &chip)) == 0) {
		unsigned long flags;
		struct snd_pcm *pcm;

#define AD1845_FREQ_SEL_ENABLE  0x08

#define AD1845_PWR_DOWN_CTRL   0x1b
#define AD1845_CRYS_CLOCK_SEL  0x1d

/*
 * It turns out that the PLAYBACK_ENABLE bit is set
 * by the lowlevel driver ...
 *
#define AD1845_IFACE_CONFIG  \
           (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
    snd_cs4231_mce_up(chip);
    spin_lock_irqsave(&chip->reg_lock, flags);
    snd_cs4231_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
    spin_unlock_irqrestore(&chip->reg_lock, flags);
    snd_cs4231_mce_down(chip);
 */

		/*
		 * The input clock frequency on the SoundScape must
		 * be 14.31818 MHz, because we must set this register
		 * to get the playback to sound correct ...
		 */
		snd_cs4231_mce_up(chip);
		spin_lock_irqsave(&chip->reg_lock, flags);
		snd_cs4231_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20);
		spin_unlock_irqrestore(&chip->reg_lock, flags);
		snd_cs4231_mce_down(chip);

		/*
		 * More custom configuration:
		 * a) select "mode 2", and provide a current drive of 8 mA
		 * b) enable frequency selection (for capture/playback)
		 */
		spin_lock_irqsave(&chip->reg_lock, flags);
		snd_cs4231_out(chip, CS4231_MISC_INFO, (CS4231_MODE2 | 0x10));
		snd_cs4231_out(chip, AD1845_PWR_DOWN_CTRL, snd_cs4231_in(chip, AD1845_PWR_DOWN_CTRL) | AD1845_FREQ_SEL_ENABLE);
		spin_unlock_irqrestore(&chip->reg_lock, flags);

		if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) {
			snd_printk(KERN_ERR "sscape: No PCM device for AD1845 chip\n");
			goto _error;
		}

		if ((err = snd_cs4231_mixer(chip)) < 0) {
			snd_printk(KERN_ERR "sscape: No mixer device for AD1845 chip\n");
			goto _error;
		}

		if ((err = snd_ctl_add(card, snd_ctl_new1(&midi_mixer_ctl, chip))) < 0) {
			snd_printk(KERN_ERR "sscape: Could not create MIDI mixer control\n");
			goto _error;
		}

		strcpy(card->driver, "SoundScape");
		strcpy(card->shortname, pcm->name);
		snprintf(card->longname, sizeof(card->longname),
		         "%s at 0x%lx, IRQ %d, DMA %d\n",
		         pcm->name, chip->port, chip->irq, chip->dma1);
		chip->set_playback_format = ad1845_playback_format;
		chip->set_capture_format = ad1845_capture_format;
		sscape->chip = chip;
	}

	_error:
	return err;
}
コード例 #9
0
ファイル: cs4236_lib.c プロジェクト: 274914765/C
int snd_cs4236_create(struct snd_card *card,
              unsigned long port,
              unsigned long cport,
              int irq, int dma1, int dma2,
              unsigned short hardware,
              unsigned short hwshare,
              struct snd_cs4231 ** rchip)
{
    struct snd_cs4231 *chip;
    unsigned char ver1, ver2;
    unsigned int reg;
    int err;

    *rchip = NULL;
    if (hardware == CS4231_HW_DETECT)
        hardware = CS4231_HW_DETECT3;
    if (cport < 0x100) {
        snd_printk("please, specify control port for CS4236+ chips\n");
        return -ENODEV;
    }
    if ((err = snd_cs4231_create(card, port, cport, irq, dma1, dma2, hardware, hwshare, &chip)) < 0)
        return err;

    if (!(chip->hardware & CS4231_HW_CS4236B_MASK)) {
            snd_printk("CS4236+: MODE3 and extended registers not available, hardware=0x%x\n",chip->hardware);
        snd_device_free(card, chip);
        return -ENODEV;
    }
#if 0
    {
        int idx;
        for (idx = 0; idx < 8; idx++)
            snd_printk("CD%i = 0x%x\n", idx, inb(chip->cport + idx));
        for (idx = 0; idx < 9; idx++)
            snd_printk("C%i = 0x%x\n", idx, snd_cs4236_ctrl_in(chip, idx));
    }
#endif
    ver1 = snd_cs4236_ctrl_in(chip, 1);
    ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
    snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2);
    if (ver1 != ver2) {
        snd_printk("CS4236+ chip detected, but control port 0x%lx is not valid\n", cport);
        snd_device_free(card, chip);
        return -ENODEV;
    }
    snd_cs4236_ctrl_out(chip, 0, 0x00);
    snd_cs4236_ctrl_out(chip, 2, 0xff);
    snd_cs4236_ctrl_out(chip, 3, 0x00);
    snd_cs4236_ctrl_out(chip, 4, 0x80);
    snd_cs4236_ctrl_out(chip, 5, ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | IEC958_AES0_CON_EMPHASIS_NONE);
    snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
    snd_cs4236_ctrl_out(chip, 7, 0x00);
    /* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 output */
    /* is working with this setup, other hardware should have */
    /* different signal paths and this value should be selectable */
    /* in the future */
    snd_cs4236_ctrl_out(chip, 8, 0x8c);
    chip->rate_constraint = snd_cs4236_xrate;
    chip->set_playback_format = snd_cs4236_playback_format;
    chip->set_capture_format = snd_cs4236_capture_format;
#ifdef CONFIG_PM
    chip->suspend = snd_cs4236_suspend;
    chip->resume = snd_cs4236_resume;
#endif

    /* initialize extended registers */
    for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
        snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]);

        /* initialize compatible but more featured registers */
    snd_cs4231_out(chip, CS4231_LEFT_INPUT, 0x40);
    snd_cs4231_out(chip, CS4231_RIGHT_INPUT, 0x40);
    snd_cs4231_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
    snd_cs4231_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
    snd_cs4231_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
    snd_cs4231_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
    snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
    snd_cs4231_out(chip, CS4231_LEFT_LINE_IN, 0xff);
    snd_cs4231_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
    switch (chip->hardware) {
    case CS4231_HW_CS4235:
    case CS4231_HW_CS4239:
        snd_cs4231_out(chip, CS4235_LEFT_MASTER, 0xff);
        snd_cs4231_out(chip, CS4235_RIGHT_MASTER, 0xff);
        break;
    }

    *rchip = chip;
    return 0;
}