예제 #1
0
파일: lola_pcm.c 프로젝트: yejerry/linux
static int lola_init_stream(struct lola *chip, struct lola_stream *str,
                            int idx, int nid, int dir)
{
    unsigned int val;
    int err;

    str->nid = nid;
    str->index = idx;
    str->dsd = idx;
    if (dir == PLAY)
        str->dsd += MAX_STREAM_IN_COUNT;
    err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
    if (err < 0) {
        dev_err(chip->card->dev, "Can't read wcaps for 0x%x\n", nid);
        return err;
    }
    if (dir == PLAY) {
        /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1) */
        if ((val & 0x00f00dff) != 0x00000010) {
            dev_err(chip->card->dev,
                    "Invalid wcaps 0x%x for 0x%x\n",
                    val, nid);
            return -EINVAL;
        }
    } else {
        /* test TYPE and bits 0..11 (no test bit9 : Digital = 0/1)
         * (bug : ignore bit8: Conn list = 0/1)
         */
        if ((val & 0x00f00cff) != 0x00100010) {
            dev_err(chip->card->dev,
                    "Invalid wcaps 0x%x for 0x%x\n",
                    val, nid);
            return -EINVAL;
        }
        /* test bit9:DIGITAL and bit12:SRC_PRESENT*/
        if ((val & 0x00001200) == 0x00001200)
            chip->input_src_caps_mask |= (1 << idx);
    }

    err = lola_read_param(chip, nid, LOLA_PAR_STREAM_FORMATS, &val);
    if (err < 0) {
        dev_err(chip->card->dev, "Can't read FORMATS 0x%x\n", nid);
        return err;
    }
    val &= 3;
    if (val == 3)
        str->can_float = true;
    if (!(val & 1)) {
        dev_err(chip->card->dev,
                "Invalid formats 0x%x for 0x%x", val, nid);
        return -EINVAL;
    }
    return 0;
}
예제 #2
0
int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
{
	unsigned int val;
	int err;

	err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
		return err;
	}

	if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */
		snd_printdd("No valid mixer widget\n");
		return 0;
	}

	chip->mixer.nid = nid;
	chip->mixer.caps = val;
	chip->mixer.array = (struct lola_mixer_array __iomem *)
		(chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);

	/* reserve memory to copy mixer data for sleep mode transitions */
	chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));

	/* mixer matrix sources are physical input data and play streams */
	chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
	chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;

	/* mixer matrix destinations are record streams and physical output */
	chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
	chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;

<<<<<<< HEAD
예제 #3
0
static int __devinit lola_init_pin(struct lola *chip, struct lola_pin *pin,
				   int dir, int nid)
{
	unsigned int val;
	int err;

	pin->nid = nid;
	err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
		return err;
	}
	val &= 0x00f00fff; /* test TYPE and bits 0..11 */
	if (val == 0x00400200)    /* Type = 4, Digital = 1 */
		pin->is_analog = false;
	else if (val == 0x0040000a && dir == CAPT) /* Dig=0, InAmp/ovrd */
		pin->is_analog = true;
	else if (val == 0x0040000c && dir == PLAY) /* Dig=0, OutAmp/ovrd */
		pin->is_analog = true;
	else {
		printk(KERN_ERR SFX "Invalid wcaps 0x%x for 0x%x\n", val, nid);
		return -EINVAL;
	}

	/* analog parameters only following, so continue in case of Digital pin
	 */
	if (!pin->is_analog)
		return 0;

	if (dir == PLAY)
		err = lola_read_param(chip, nid, LOLA_PAR_AMP_OUT_CAP, &val);
	else
		err = lola_read_param(chip, nid, LOLA_PAR_AMP_IN_CAP, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read AMP-caps for 0x%x\n", nid);
		return err;
	}

	pin->amp_mute = LOLA_AMP_MUTE_CAPABLE(val);
	pin->amp_step_size = LOLA_AMP_STEP_SIZE(val);
	pin->amp_num_steps = LOLA_AMP_NUM_STEPS(val);
	if (pin->amp_num_steps) {
		/* zero as mute state */
		pin->amp_num_steps++;
		pin->amp_step_size++;
	}
	pin->amp_offset = LOLA_AMP_OFFSET(val);

	err = lola_codec_read(chip, nid, LOLA_VERB_GET_MAX_LEVEL, 0, 0, &val,
			      NULL);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't get MAX_LEVEL 0x%x\n", nid);
		return err;
	}
	pin->max_level = val & 0x3ff;   /* 10 bits */

	pin->config_default_reg = 0;
	pin->fixed_gain_list_len = 0;
	pin->cur_gain_step = 0;

	return 0;
}
예제 #4
0
int __devinit lola_init_mixer_widget(struct lola *chip, int nid)
{
	unsigned int val;
	int err;

	err = lola_read_param(chip, nid, LOLA_PAR_AUDIO_WIDGET_CAP, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read wcaps for 0x%x\n", nid);
		return err;
	}

	if ((val & 0xfff00000) != 0x02f00000) { /* test SubType and Type */
		snd_printdd("No valid mixer widget\n");
		return 0;
	}

	chip->mixer.nid = nid;
	chip->mixer.caps = val;
	chip->mixer.array = (struct lola_mixer_array __iomem *)
		(chip->bar[BAR1].remap_addr + LOLA_BAR1_SOURCE_GAIN_ENABLE);

	/* reserve memory to copy mixer data for sleep mode transitions */
	chip->mixer.array_saved = vmalloc(sizeof(struct lola_mixer_array));

	/* mixer matrix sources are physical input data and play streams */
	chip->mixer.src_stream_outs = chip->pcm[PLAY].num_streams;
	chip->mixer.src_phys_ins = chip->pin[CAPT].num_pins;

	/* mixer matrix destinations are record streams and physical output */
	chip->mixer.dest_stream_ins = chip->pcm[CAPT].num_streams;
	chip->mixer.dest_phys_outs = chip->pin[PLAY].num_pins;

	/* mixer matrix may have unused areas between PhysIn and
	 * Play or Record and PhysOut zones
	 */
	chip->mixer.src_stream_out_ofs = chip->mixer.src_phys_ins +
		LOLA_MIXER_SRC_INPUT_PLAY_SEPARATION(val);
	chip->mixer.dest_phys_out_ofs = chip->mixer.dest_stream_ins +
		LOLA_MIXER_DEST_REC_OUTPUT_SEPARATION(val);

	/* example : MixerMatrix of LoLa881 (LoLa16161 uses unused zones)
	 * +-+  0-------8------16-------8------16
	 * | |  |       |       |       |       |
	 * |s|  | INPUT |       | INPUT |       |
	 * | |->|  ->   |unused |  ->   |unused |
	 * |r|  |CAPTURE|       | OUTPUT|       |
	 * | |  |  MIX  |       |  MIX  |       |
	 * |c|  8--------------------------------
	 * | |  |       |       |       |       |
	 * | |  |       |       |       |       |
	 * |g|  |unused |unused |unused |unused |
	 * | |  |       |       |       |       |
	 * |a|  |       |       |       |       |
	 * | |  16-------------------------------
	 * |i|  |       |       |       |       |
	 * | |  | PLAYBK|       | PLAYBK|       |
	 * |n|->|  ->   |unused |  ->   |unused |
	 * | |  |CAPTURE|       | OUTPUT|       |
	 * | |  |  MIX  |       |  MIX  |       |
	 * |a|  8--------------------------------
	 * |r|  |       |       |       |       |
	 * |r|  |       |       |       |       |
	 * |a|  |unused |unused |unused |unused |
	 * |y|  |       |       |       |       |
	 * | |  |       |       |       |       |
	 * +++  16--|---------------|------------
	 *      +---V---------------V-----------+
	 *      |  dest_mix_gain_enable array   |
	 *      +-------------------------------+
	 */
	/* example : MixerMatrix of LoLa280
	 * +-+  0-------8-2
	 * | |  |       | |
	 * |s|  | INPUT | |     INPUT
	 * |r|->|  ->   | |      ->
	 * |c|  |CAPTURE| | <-  OUTPUT
	 * | |  |  MIX  | |      MIX
	 * |g|  8----------
	 * |a|  |       | |
	 * |i|  | PLAYBK| |     PLAYBACK
	 * |n|->|  ->   | |      ->
	 * | |  |CAPTURE| | <-  OUTPUT
	 * |a|  |  MIX  | |      MIX
	 * |r|  8---|----|-
	 * |r|  +---V----V-------------------+
	 * |a|  | dest_mix_gain_enable array |
	 * |y|  +----------------------------+
	 */
	if (chip->mixer.src_stream_out_ofs > MAX_AUDIO_INOUT_COUNT ||
	    chip->mixer.dest_phys_out_ofs > MAX_STREAM_IN_COUNT) {
		printk(KERN_ERR SFX "Invalid mixer widget size\n");
		return -EINVAL;
	}

	chip->mixer.src_mask = ((1U << chip->mixer.src_phys_ins) - 1) |
		(((1U << chip->mixer.src_stream_outs) - 1)
		 << chip->mixer.src_stream_out_ofs);
	chip->mixer.dest_mask = ((1U << chip->mixer.dest_stream_ins) - 1) |
		(((1U << chip->mixer.dest_phys_outs) - 1)
		 << chip->mixer.dest_phys_out_ofs);

	snd_printdd("Mixer src_mask=%x, dest_mask=%x\n",
		    chip->mixer.src_mask, chip->mixer.dest_mask);

	return 0;
}
예제 #5
0
static int __devinit lola_parse_tree(struct lola *chip)
{
	unsigned int val;
	int nid, err;

	err = lola_read_param(chip, 0, LOLA_PAR_VENDOR_ID, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read VENDOR_ID\n");
		return err;
	}
	val >>= 16;
	if (val != 0x1369) {
		printk(KERN_ERR SFX "Unknown codec vendor 0x%x\n", val);
		return -EINVAL;
	}

	err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid);
		return err;
	}
	if (val != 1) {
		printk(KERN_ERR SFX "Unknown function type %d\n", val);
		return -EINVAL;
	}

	err = lola_read_param(chip, 1, LOLA_PAR_SPECIFIC_CAPS, &val);
	if (err < 0) {
		printk(KERN_ERR SFX "Can't read SPECCAPS\n");
		return err;
	}
	chip->lola_caps = val;
	chip->pin[CAPT].num_pins = LOLA_AFG_INPUT_PIN_COUNT(chip->lola_caps);
	chip->pin[PLAY].num_pins = LOLA_AFG_OUTPUT_PIN_COUNT(chip->lola_caps);
	snd_printdd(SFX "speccaps=0x%x, pins in=%d, out=%d\n",
		    chip->lola_caps,
		    chip->pin[CAPT].num_pins, chip->pin[PLAY].num_pins);

	if (chip->pin[CAPT].num_pins > MAX_AUDIO_INOUT_COUNT ||
	    chip->pin[PLAY].num_pins > MAX_AUDIO_INOUT_COUNT) {
		printk(KERN_ERR SFX "Invalid Lola-spec caps 0x%x\n", val);
		return -EINVAL;
	}

	nid = 0x02;
	err = lola_init_pcm(chip, CAPT, &nid);
	if (err < 0)
		return err;
	err = lola_init_pcm(chip, PLAY, &nid);
	if (err < 0)
		return err;

	err = lola_init_pins(chip, CAPT, &nid);
	if (err < 0)
		return err;
	err = lola_init_pins(chip, PLAY, &nid);
	if (err < 0)
		return err;

	if (LOLA_AFG_CLOCK_WIDGET_PRESENT(chip->lola_caps)) {
		err = lola_init_clock_widget(chip, nid);
		if (err < 0)
			return err;
		nid++;
	}
	if (LOLA_AFG_MIXER_WIDGET_PRESENT(chip->lola_caps)) {
		err = lola_init_mixer_widget(chip, nid);
		if (err < 0)
			return err;
		nid++;
	}

	/*                                               */
	err = lola_enable_clock_events(chip);
	if (err < 0)
		return err;

	/*                                                           
                                                
  */
	if (!chip->cold_reset) {
		lola_reset_setups(chip);
		chip->cold_reset = 1;
	} else {
		/*                                              */
		if (chip->granularity != LOLA_GRANULARITY_MIN)
			lola_set_granularity(chip, chip->granularity, true);
	}

	return 0;
}