static int tegra_max98095_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	struct snd_soc_card *card = codec->card;
	struct tegra_max98095 *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
#endif
	int ret;

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	if (machine->codec_info[BASEBAND].i2s_id != -1)
		i2s->is_dam_used = true;
#endif

	if (machine->init_done)
		return 0;

	machine->init_done = true;

	if (gpio_is_valid(pdata->gpio_spkr_en)) {
		ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
		if (ret) {
			dev_err(card->dev, "cannot get spkr_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_SPKR_EN;

		gpio_direction_output(pdata->gpio_spkr_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_hp_mute)) {
		ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
		if (ret) {
			dev_err(card->dev, "cannot get hp_mute gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_HP_MUTE;

		gpio_direction_output(pdata->gpio_hp_mute, 0);
	}

	if (gpio_is_valid(pdata->gpio_int_mic_en)) {
		ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get int_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_INT_MIC_EN;

		/* Disable int mic; enable signal is active-high */
		gpio_direction_output(pdata->gpio_int_mic_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
		ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get ext_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_EXT_MIC_EN;

		/* Enable ext mic; enable signal is active-low */
		gpio_direction_output(pdata->gpio_ext_mic_en, 0);
	}

	ret = snd_soc_add_controls(codec, tegra_max98095_controls,
				   ARRAY_SIZE(tegra_max98095_controls));
	if (ret < 0)
		return ret;

	snd_soc_dapm_new_controls(dapm, tegra_max98095_dapm_widgets,
			ARRAY_SIZE(tegra_max98095_dapm_widgets));

	snd_soc_dapm_add_routes(dapm, enterprise_audio_map,
			ARRAY_SIZE(enterprise_audio_map));

	ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
			&tegra_max98095_hp_jack);
	if (ret < 0)
		return ret;

#ifdef CONFIG_SWITCH
	snd_soc_jack_notifier_register(&tegra_max98095_hp_jack,
		&headset_switch_nb);
#else /*gpio based headset detection*/
	snd_soc_jack_add_pins(&tegra_max98095_hp_jack,
		ARRAY_SIZE(tegra_max98095_hp_jack_pins),
		tegra_max98095_hp_jack_pins);
#endif

	ret = tegra_asoc_utils_register_ctls(&machine->util_data);
	if (ret < 0)
		return ret;

	/* max98095_headset_detect(codec, &tegra_max98095_hp_jack,
		SND_JACK_HEADSET); */

	snd_soc_dapm_nc_pin(dapm, "INA1");
	snd_soc_dapm_nc_pin(dapm, "INA2");
	snd_soc_dapm_nc_pin(dapm, "INB1");
	snd_soc_dapm_nc_pin(dapm, "INB2");
	snd_soc_dapm_sync(dapm);

	return 0;
}
static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	struct snd_soc_card *card = codec->card;
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
#endif
	int ret;

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	if (machine->codec_info[BASEBAND].i2s_id != -1)
		i2s->is_dam_used = true;
#endif

	if (machine->init_done)
		return 0;

	machine->init_done = true;

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	machine->pcard = card;
#endif

	if (machine_is_whistler()) {
		machine->audio_reg = regulator_get(NULL, "avddio_audio");
		if (IS_ERR(machine->audio_reg)) {
			dev_err(card->dev, "cannot get avddio_audio reg\n");
			ret = PTR_ERR(machine->audio_reg);
			return ret;
		}

		ret = regulator_enable(machine->audio_reg);
		if (ret) {
			dev_err(card->dev, "cannot enable avddio_audio reg\n");
			regulator_put(machine->audio_reg);
			machine->audio_reg = NULL;
			return ret;
		}
	}

	if (gpio_is_valid(pdata->gpio_spkr_en)) {
		ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
		if (ret) {
			dev_err(card->dev, "cannot get spkr_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_SPKR_EN;

		gpio_direction_output(pdata->gpio_spkr_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_hp_mute)) {
		ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
		if (ret) {
			dev_err(card->dev, "cannot get hp_mute gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_HP_MUTE;

		gpio_direction_output(pdata->gpio_hp_mute, 0);
	}

	if (gpio_is_valid(pdata->gpio_int_mic_en)) {
		ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get int_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_INT_MIC_EN;

		/* Disable int mic; enable signal is active-high */
		gpio_direction_output(pdata->gpio_int_mic_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
		ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get ext_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_EXT_MIC_EN;

		/* Enable ext mic; enable signal is active-low */
		gpio_direction_output(pdata->gpio_ext_mic_en, 0);
	}

	ret = snd_soc_add_card_controls(card, tegra_aic326x_controls,
				   ARRAY_SIZE(tegra_aic326x_controls));
	if (ret < 0)
		return ret;

	snd_soc_dapm_new_controls(dapm, tegra_aic326x_dapm_widgets,
					ARRAY_SIZE(tegra_aic326x_dapm_widgets));

	snd_soc_dapm_add_routes(dapm, aic326x_audio_map,
					ARRAY_SIZE(aic326x_audio_map));

	ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
			&tegra_aic326x_hp_jack);
	if (ret < 0)
		return ret;

	if (gpio_is_valid(pdata->gpio_hp_det)) {
		/* Headphone detection */
		tegra_aic326x_hp_jack_gpio.gpio = pdata->gpio_hp_det;
		snd_soc_jack_new(codec, "Headphone Jack",
				SND_JACK_HEADSET, &tegra_aic326x_hp_jack);

#ifndef CONFIG_SWITCH
	snd_soc_jack_add_pins(&tegra_aic326x_hp_jack,
		ARRAY_SIZE(tegra_aic326x_hp_jack_pins),
		tegra_aic326x_hp_jack_pins);
#else
		snd_soc_jack_notifier_register(&tegra_aic326x_hp_jack,
					&aic326x_headset_switch_nb);
#endif
		snd_soc_jack_add_gpios(&tegra_aic326x_hp_jack,
					1,
					&tegra_aic326x_hp_jack_gpio);

		machine->gpio_requested |= GPIO_HP_DET;
	}

#ifndef CONFIG_ARCH_TEGRA_11x_SOC
	/* update jack status during boot */
	aic3262_hs_jack_detect(codec, &tegra_aic326x_hp_jack,
		SND_JACK_HEADSET);
#endif

	/* Add call mode switch control */
	ret = snd_ctl_add(codec->card->snd_card,
			snd_ctl_new1(&tegra_aic326x_call_mode_control,
				machine));
	if (ret < 0)
		return ret;

	ret = tegra_asoc_utils_register_ctls(&machine->util_data);
	if (ret < 0)
		return ret;

	return 0;
}
int ctp_init(struct snd_soc_pcm_runtime *runtime)
{
	int ret;
	struct snd_soc_codec *codec = runtime->codec;
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	struct snd_soc_card *card = runtime->card;
	struct ctp_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
//#ifndef UART_DEBUG
//	static int hp_enable;
//#endif

	pr_debug("%s\n", __func__);

	/* Set codec bias level */
	ctp_set_bias_level(card, dapm, SND_SOC_BIAS_OFF);
	card->dapm.idle_bias_off = true;

	/* Add Jack specific widgets */
	ret = snd_soc_dapm_new_controls(dapm, ctp_dapm_widgets,
					ARRAY_SIZE(ctp_dapm_widgets));
	if (ret)
		return ret;

	/* Set up Jack specific audio path audio_map */
	snd_soc_dapm_add_routes(dapm, ctp_audio_map,
					ARRAY_SIZE(ctp_audio_map));
	/* Add Comms specefic controls */
	ctx->comms_ctl.ssp_bt_sco_master_mode = false;

/* Set ssp_voip to master mode by default */
#if 0
	ctx->comms_ctl.ssp_voip_master_mode = false;
#else
	ctx->comms_ctl.ssp_voip_master_mode = true;
	pr_debug("ctp_init ssp_voip_master_mode %d\n",
		ctx->comms_ctl.ssp_voip_master_mode);
#endif

	ctx->comms_ctl.ssp_modem_master_mode = false;

	ret = snd_soc_add_card_controls(card, ssp_comms_controls,
				ARRAY_SIZE(ssp_comms_controls));
	if (ret) {
		pr_err("Add Comms Controls failed %d",
				ret);
		return ret;
	}

	/* Keep the voice call paths active during
	suspend. Mark the end points ignore_suspend */
	snd_soc_dapm_ignore_suspend(dapm, "HPOL");
	snd_soc_dapm_ignore_suspend(dapm, "HPOR");

	snd_soc_dapm_ignore_suspend(dapm, "SPOL");
	snd_soc_dapm_ignore_suspend(dapm, "SPOR");

        snd_soc_dapm_ignore_suspend(dapm, "AIF2 Playback");
        snd_soc_dapm_ignore_suspend(dapm, "AIF2 Capture");
        snd_soc_dapm_ignore_suspend(dapm, "AIF2TX");
        snd_soc_dapm_ignore_suspend(dapm, "AIF2RX");
        snd_soc_dapm_ignore_suspend(dapm, "MonoP");
        snd_soc_dapm_ignore_suspend(dapm, "MonoN");
        snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
        snd_soc_dapm_ignore_suspend(dapm, "Headphone");
        snd_soc_dapm_ignore_suspend(dapm, "Ext Spk");
        snd_soc_dapm_ignore_suspend(dapm, "Int Mic");
        snd_soc_dapm_ignore_suspend(dapm, "Receiver");
        snd_soc_dapm_ignore_suspend(dapm, "DMIC L2");
        snd_soc_dapm_ignore_suspend(dapm, "DMIC R2");
        snd_soc_dapm_ignore_suspend(dapm, "IN1P");
        snd_soc_dapm_ignore_suspend(dapm, "IN1N");

	snd_soc_dapm_ignore_suspend(dapm, "IN2P");
	snd_soc_dapm_ignore_suspend(dapm, "IN2N");

	snd_soc_dapm_enable_pin(dapm, "Headset Mic");
	snd_soc_dapm_enable_pin(dapm, "Headphone");
	snd_soc_dapm_enable_pin(dapm, "Ext Spk");
	snd_soc_dapm_enable_pin(dapm, "Int Mic");
	snd_soc_dapm_enable_pin(dapm, "Receiver");

	mutex_lock(&codec->mutex);
	snd_soc_dapm_sync(dapm);
	mutex_unlock(&codec->mutex);

	/*Register switch Control as misc driver*/
	ret = misc_register(&switch_ctrl);
	if (ret)
		pr_err("%s: couldn't register control device\n",
			__func__);

	rt5647_codec = codec;

//#ifndef UART_DEBUG
//	/* use hard-coded GPIO value before IFWI ready */
//	/* hp_enable = get_gpio_by_name("AUDIO_DEBUG"); */
//	hp_enable = 172;
//	if (hp_enable > 0) {
//		pr_info("Get AUDIO_DEBUG name!\n");
//		ret = gpio_request_one(hp_enable, GPIOF_DIR_OUT, "AUDIO_DEBUG");
//		if (ret)
//			pr_err("gpio_request AUDIO_DEBUG failed!\n");
//
//		/*Set GPIO O(H) to default => Low:UART; High:headset */
//		gpio_direction_output(hp_enable, 1);
//		pr_info("AUDIO_DEBUG value = %d\n", gpio_get_value(hp_enable));
//	} else
//		pr_err("get_gpio AUDIO_DEBUG failed!\n");
//#endif
	return ret;
}
Example #4
0
static int aml_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
    struct snd_soc_card *card = rtd->card;
    struct snd_soc_codec *codec = rtd->codec;
    //struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dapm_context *dapm = &codec->dapm;
    struct aml_audio_private_data * p_aml_audio;
    int ret = 0;

    printk(KERN_DEBUG "enter %s \n", __func__);
    p_aml_audio = snd_soc_card_get_drvdata(card);

    /* Add specific widgets */
  //  snd_soc_dapm_new_controls(dapm, aml_asoc_dapm_widgets,
 //                ARRAY_SIZE(aml_asoc_dapm_widgets));
    /* set ADCLRC/GPIO1 Pin Function Select */
    snd_soc_update_bits(codec, WM8960_IFACE2, (1 << 6), (1 << 6));

    /* not connected */
    snd_soc_dapm_nc_pin(dapm, "LINPUT3");
    snd_soc_dapm_nc_pin(dapm, "RINPUT3");

    snd_soc_dapm_nc_pin(dapm, "OUT3");

    /* always connected */
    snd_soc_dapm_enable_pin(dapm, "Ext Spk");
    snd_soc_dapm_enable_pin(dapm, "Mic");

    /* disable connected */
    snd_soc_dapm_disable_pin(dapm, "HP");

    snd_soc_dapm_sync(dapm);
    ret = snd_soc_jack_new(codec, "hp switch", SND_JACK_HEADPHONE, &p_aml_audio->jack);
    if (ret) {
        printk(KERN_WARNING "Failed to alloc resource for hp switch\n");
    } else {
        ret = snd_soc_jack_add_pins(&p_aml_audio->jack, ARRAY_SIZE(jack_pins), jack_pins);
        if (ret) {
            printk(KERN_WARNING "Failed to setup hp pins\n");
        }
    }
#if HP_IRQ
    p_aml_audio->gpio_hp_det = of_get_named_gpio(card->dev->of_node,"wm8960_gpio",0);

    if (gpio_is_valid(p_aml_audio->gpio_hp_det)) {
        aml_audio_hp_jack_gpio.gpio = p_aml_audio->gpio_hp_det;
        snd_soc_jack_add_gpios(&p_aml_audio->jack,
                        1, &aml_audio_hp_jack_gpio);
    }
#endif
#if HP_DET
    init_timer(&p_aml_audio->timer);
    p_aml_audio->timer.function = aml_asoc_timer_func;
    p_aml_audio->timer.data = (unsigned long)p_aml_audio;
    p_aml_audio->data= (void*)card;

    INIT_WORK(&p_aml_audio->work, aml_asoc_work_func);
    mutex_init(&p_aml_audio->lock);

    mutex_lock(&p_aml_audio->lock);
    if (!p_aml_audio->timer_en) {
        aml_audio_start_timer(p_aml_audio, msecs_to_jiffies(100));
    }
    mutex_unlock(&p_aml_audio->lock);

#endif

//p_aml_audio->dis_hp_det = of_property_read_bool(card->dev->of_node,"dis_hp_det");
     ret = of_property_read_u32(card->dev->of_node,"dis_hp_det",(u32 *)&p_aml_audio->dis_hp_det);
     printk("******p_aml_audio->dis_hp_det=%d***\n",p_aml_audio->dis_hp_det);
    if(ret){
        printk("don't find match dis_hp_det\n");
        goto out1;
    }

    if(!p_aml_audio->dis_hp_det){
        printk("****mm**p_aml_audio->dis_hp_det\n");
        //JD2 as headphone detect
        snd_soc_update_bits(codec,27, 0x008, 0x008);// OUT3 buffer Enabled and disabled with HPL and HPR jack detect
        //INSERT_DELAY    [1]
        mdelay(1);
        ///GPIO1 output the "jack detect output"
        snd_soc_update_bits(codec,48, 0x03A, 0x03A);// JD2 used for Jack Detect Input, GPIO function = jack detect output

        snd_soc_update_bits(codec,24, 0x040, 0x040);// HPDETECT LOW = Speaker

        snd_soc_update_bits(codec, 23, 0x1D1, 0x1D1);
        mdelay(500);

    }
out1:

    return 0;
}
static int ctp_comms_dai_link_hw_params(struct snd_pcm_substream *substream,
				      struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *soc_card = rtd->card;
	struct ctp_mc_private *ctx = snd_soc_card_get_drvdata(soc_card);
	struct comms_mc_private *ctl = &(ctx->comms_ctl);

	int ret = 0;
	unsigned int tx_mask, rx_mask;
	unsigned int nb_slot = 0;
	unsigned int slot_width = 0;
	unsigned int tristate_offset = 0;
	unsigned int device = substream->pcm->device;


	pr_debug("ssp_bt_sco_master_mode %d\n", ctl->ssp_bt_sco_master_mode);
	pr_debug("ssp_voip_master_mode %d\n", ctl->ssp_voip_master_mode);
	pr_debug("ssp_modem_master_mode %d\n", ctl->ssp_modem_master_mode);

	switch (device) {
	case CTP_HT_COMMS_VOIP_DEV:
		/*
		 * set cpu DAI configuration
		 * frame_format = PSP_FORMAT
		 * ssp_serial_clk_mode = SSP_CLK_MODE_0
		 * ssp_frmsync_pol_bit = SSP_FRMS_ACTIVE_LOW
		 */
		ret = snd_soc_dai_set_fmt(cpu_dai,
				SND_SOC_DAIFMT_I2S |
				SSP_DAI_SCMODE_0 |
				SND_SOC_DAIFMT_NB_IF |
				(ctl->ssp_voip_master_mode ?
				SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBS_CFS));

		if (ret < 0) {
			pr_err("MFLD Comms Machine: Set FMT Fails %d\n",
							ret);
			return -EINVAL;
		}

		/*
		 * MSIC VOIP SSP Config
		 * ssp_active_tx_slots_map = 0x01
		 * ssp_active_rx_slots_map = 0x01
		 * frame_rate_divider_control = 1
		 * data_size = 32
		 * tristate = 1
		 * ssp_frmsync_timing_bit = 0, for SLAVE
		 * (NEXT_FRMS_ASS_AFTER_END_OF_T4)
		 * ssp_frmsync_timing_bit = 1, for MASTER
		 * (NEXT_FRMS_ASS_WITH_LSB_PREVIOUS_FRM)
		 *
		 *
		 */
		nb_slot = SSP_VOIP_SLOT_NB_SLOT;
		slot_width = SSP_VOIP_SLOT_WIDTH;
		tx_mask = SSP_VOIP_SLOT_TX_MASK;
		rx_mask = SSP_VOIP_SLOT_RX_MASK;

		tristate_offset = BIT(TRISTATE_BIT);
		break;

	default:
		pr_err("CTP Comms Machine: bad PCM Device ID = %d\n",
				device);
		return -EINVAL;
	}

	ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask,
			rx_mask, nb_slot, slot_width);

	if (ret < 0) {
		pr_err("CTP Comms Machine:  Set TDM Slot Fails %d\n",
				ret);
		return -EINVAL;
	}

	ret = snd_soc_dai_set_tristate(cpu_dai, tristate_offset);
	if (ret < 0) {
		pr_err("CTP Comms Machine: Set Tristate Fails %d\n",
				ret);
		return -EINVAL;
	}

	if (device == CTP_HT_COMMS_VOIP_DEV) {
		pr_debug("Call ctp_wm5102_hw_params to enable the PLL Codec\n");
		ctp_wm5102_hw_params(substream, params);
	}

	pr_debug("CTP Comms Machine: slot_width = %d\n",
			slot_width);
	pr_debug("CTP Comms Machine: tx_mask = %d\n",
			tx_mask);
	pr_debug("CTP Comms Machine: rx_mask = %d\n",
			rx_mask);
	pr_debug("CTP Comms Machine: tristate_offset = %d\n",
			tristate_offset);

	return 0;

} /* ctp_comms_dai_link_hw_params*/
Example #6
0
static int apq8016_sbc_dai_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_component *component;
	struct snd_soc_dai_link *dai_link = rtd->dai_link;
	struct snd_soc_card *card = rtd->card;
	struct apq8016_sbc_data *pdata = snd_soc_card_get_drvdata(card);
	int i, rval;

	switch (cpu_dai->id) {
	case MI2S_PRIMARY:
		writel(readl(pdata->spkr_iomux) | SPKR_CTL_PRI_WS_SLAVE_SEL_11,
			pdata->spkr_iomux);
		break;

	case MI2S_QUATERNARY:
		/* Configure the Quat MI2S to TLMM */
		writel(readl(pdata->mic_iomux) | MIC_CTRL_QUA_WS_SLAVE_SEL_10 |
			MIC_CTRL_TLMM_SCLK_EN,
			pdata->mic_iomux);
		break;
	case MI2S_TERTIARY:
		writel(readl(pdata->mic_iomux) | MIC_CTRL_TER_WS_SLAVE_SEL |
			MIC_CTRL_TLMM_SCLK_EN,
			pdata->mic_iomux);

		break;

	default:
		dev_err(card->dev, "unsupported cpu dai configuration\n");
		return -EINVAL;

	}

	if (!pdata->jack_setup) {
		struct snd_jack *jack;

		rval = snd_soc_card_jack_new(card, "Headset Jack",
					     SND_JACK_HEADSET |
					     SND_JACK_HEADPHONE |
					     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
					     SND_JACK_BTN_2 | SND_JACK_BTN_3 |
					     SND_JACK_BTN_4,
					     &pdata->jack, NULL, 0);

		if (rval < 0) {
			dev_err(card->dev, "Unable to add Headphone Jack\n");
			return rval;
		}

		jack = pdata->jack.jack;

		snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
		snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
		snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
		snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
		pdata->jack_setup = true;
	}

	for (i = 0 ; i < dai_link->num_codecs; i++) {
		struct snd_soc_dai *dai = rtd->codec_dais[i];

		component = dai->component;
		/* Set default mclk for internal codec */
		rval = snd_soc_component_set_sysclk(component, 0, 0, DEFAULT_MCLK_RATE,
				       SND_SOC_CLOCK_IN);
		if (rval != 0 && rval != -ENOTSUPP) {
			dev_warn(card->dev, "Failed to set mclk: %d\n", rval);
			return rval;
		}
		rval = snd_soc_component_set_jack(component, &pdata->jack, NULL);
		if (rval != 0 && rval != -ENOTSUPP) {
			dev_warn(card->dev, "Failed to set jack: %d\n", rval);
			return rval;
		}
	}

	return 0;
}
static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_dapm_context *dapm = &codec->dapm;
	struct snd_soc_card *card = codec->card;
	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
	struct tegra_wm8903_platform_data *pdata = machine->pdata;
	int ret;

	machine->bias_level = SND_SOC_BIAS_STANDBY;
///Eric
	Mycodec = codec;
///Eric
	if (gpio_is_valid(pdata->gpio_spkr_en)) {
		ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
		if (ret) {
			dev_err(card->dev, "cannot get spkr_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_SPKR_EN;

		gpio_direction_output(pdata->gpio_spkr_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_hp_mute)) {
		ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
		if (ret) {
			dev_err(card->dev, "cannot get hp_mute gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_HP_MUTE;

		gpio_direction_output(pdata->gpio_hp_mute, 0);
	}

	if (gpio_is_valid(pdata->gpio_int_mic_en)) {
		ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get int_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_INT_MIC_EN;

		/* Disable int mic; enable signal is active-high */
		gpio_direction_output(pdata->gpio_int_mic_en, 0);
	}

	if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
		ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
		if (ret) {
			dev_err(card->dev, "cannot get ext_mic_en gpio\n");
			return ret;
		}
		machine->gpio_requested |= GPIO_EXT_MIC_EN;

		/* Enable ext mic; enable signal is active-low */
		gpio_direction_output(pdata->gpio_ext_mic_en, 0);
	}

	if (machine_is_cardhu() || machine_is_ventana()) {
		ret = snd_soc_add_controls(codec, cardhu_controls,
				ARRAY_SIZE(cardhu_controls));
		if (ret < 0)
			return ret;

		snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets,
				ARRAY_SIZE(cardhu_dapm_widgets));
	}
	else {
		ret = snd_soc_add_controls(codec,
				tegra_wm8903_default_controls,
				ARRAY_SIZE(tegra_wm8903_default_controls));
		if (ret < 0)
			return ret;

		snd_soc_dapm_new_controls(dapm,
				tegra_wm8903_default_dapm_widgets,
				ARRAY_SIZE(tegra_wm8903_default_dapm_widgets));
	}

	if (machine_is_harmony()) {
		snd_soc_dapm_add_routes(dapm, harmony_audio_map,
					ARRAY_SIZE(harmony_audio_map));
	} else if (machine_is_cardhu() || machine_is_ventana()) {
		snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
					ARRAY_SIZE(cardhu_audio_map));
	} else if (machine_is_seaboard()) {
		snd_soc_dapm_add_routes(dapm, seaboard_audio_map,
					ARRAY_SIZE(seaboard_audio_map));
	} else if (machine_is_kaen()) {
		snd_soc_dapm_add_routes(dapm, kaen_audio_map,
					ARRAY_SIZE(kaen_audio_map));
	} else {
		snd_soc_dapm_add_routes(dapm, aebl_audio_map,
					ARRAY_SIZE(aebl_audio_map));
	}

	if (gpio_is_valid(pdata->gpio_hp_det)) {
		tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det;
		snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
				&tegra_wm8903_hp_jack);
#ifndef CONFIG_SWITCH
		snd_soc_jack_add_pins(&tegra_wm8903_hp_jack,
					ARRAY_SIZE(tegra_wm8903_hp_jack_pins),
					tegra_wm8903_hp_jack_pins);
#else
		snd_soc_jack_notifier_register(&tegra_wm8903_hp_jack,
					&tegra_wm8903_jack_detect_nb);
#endif
		snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack,
					1,
					&tegra_wm8903_hp_jack_gpio);
		machine->gpio_requested |= GPIO_HP_DET;
	}

	snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
			 &tegra_wm8903_mic_jack);
#ifndef CONFIG_SWITCH
	snd_soc_jack_add_pins(&tegra_wm8903_mic_jack,
			      ARRAY_SIZE(tegra_wm8903_mic_jack_pins),
			      tegra_wm8903_mic_jack_pins);
#else
	snd_soc_jack_notifier_register(&tegra_wm8903_mic_jack,
				&tegra_wm8903_jack_detect_nb);
#endif
	wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
			  machine_is_cardhu() ? SND_JACK_MICROPHONE : 0);

	snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");

	/* FIXME: Calculate automatically based on DAPM routes? */
/*	if (!machine_is_harmony() && !machine_is_ventana() &&
	    !machine_is_cardhu())
		snd_soc_dapm_nc_pin(dapm, "IN1L");
	if (!machine_is_seaboard() && !machine_is_aebl() &&
	    !machine_is_cardhu())
		snd_soc_dapm_nc_pin(dapm, "IN1R");
	snd_soc_dapm_nc_pin(dapm, "IN2L");
	if (!machine_is_kaen())
		snd_soc_dapm_nc_pin(dapm, "IN2R");*/

///Eric
	snd_soc_dapm_nc_pin(dapm, "IN1L");
	snd_soc_dapm_nc_pin(dapm, "IN1R");
///Eric

	snd_soc_dapm_nc_pin(dapm, "IN3L");
	snd_soc_dapm_nc_pin(dapm, "IN3R");

	if (machine_is_aebl()) {
		snd_soc_dapm_nc_pin(dapm, "LON");
		snd_soc_dapm_nc_pin(dapm, "RON");
		snd_soc_dapm_nc_pin(dapm, "ROP");
		snd_soc_dapm_nc_pin(dapm, "LOP");
	} else {
		snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
		snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
	}

	snd_soc_dapm_sync(dapm);

	return 0;
}
Example #8
0
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
{
	struct snd_soc_card *card = runtime->card;
	struct snd_soc_component *codec = runtime->codec_dai->component;
	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
	const struct snd_soc_dapm_route *custom_map;
	int num_routes;
	int ret;

	card->dapm.idle_bias_off = true;

	/* Start with RC clk for jack-detect (we disable MCLK below) */
	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
		snd_soc_component_update_bits(codec, RT5651_GLB_CLK,
			RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK);

	switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
	case BYT_RT5651_IN1_MAP:
		custom_map = byt_rt5651_intmic_in1_map;
		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
		break;
	case BYT_RT5651_IN2_MAP:
		custom_map = byt_rt5651_intmic_in2_map;
		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
		break;
	case BYT_RT5651_IN1_IN2_MAP:
		custom_map = byt_rt5651_intmic_in1_in2_map;
		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
		break;
	default:
		custom_map = byt_rt5651_intmic_dmic_map;
		num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
	}
	ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
	if (ret)
		return ret;

	if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5651_ssp2_aif2_map,
					ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5651_ssp0_aif1_map,
					ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5651_ssp0_aif2_map,
					ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
	} else {
		ret = snd_soc_dapm_add_routes(&card->dapm,
					byt_rt5651_ssp2_aif1_map,
					ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
	}
	if (ret)
		return ret;

	ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
					ARRAY_SIZE(byt_rt5651_controls));
	if (ret) {
		dev_err(card->dev, "unable to add card controls\n");
		return ret;
	}
	snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
	snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");

	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
		/*
		 * The firmware might enable the clock at
		 * boot (this information may or may not
		 * be reflected in the enable clock register).
		 * To change the rate we must disable the clock
		 * first to cover these cases. Due to common
		 * clock framework restrictions that do not allow
		 * to disable a clock that has not been enabled,
		 * we need to enable the clock first.
		 */
		ret = clk_prepare_enable(priv->mclk);
		if (!ret)
			clk_disable_unprepare(priv->mclk);

		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
			ret = clk_set_rate(priv->mclk, 25000000);
		else
			ret = clk_set_rate(priv->mclk, 19200000);

		if (ret)
			dev_err(card->dev, "unable to set MCLK rate\n");
	}

	if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
		ret = snd_soc_card_jack_new(runtime->card, "Headset",
				    SND_JACK_HEADSET | SND_JACK_BTN_0,
				    &priv->jack, bytcr_jack_pins,
				    ARRAY_SIZE(bytcr_jack_pins));
		if (ret) {
			dev_err(runtime->dev, "jack creation failed %d\n", ret);
			return ret;
		}

		snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
				 KEY_PLAYPAUSE);

		ret = snd_soc_component_set_jack(codec, &priv->jack, NULL);
		if (ret)
			return ret;
	}

	return 0;
}
Example #9
0
static int tegra_rt5631_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_rt5631 *machine = snd_soc_card_get_drvdata(card);

	int srate, mclk, i2s_daifmt;
	int err;

	srate = params_rate(params);
	switch (srate) {
	case 64000:
	case 88200:
	case 96000:
		mclk = 128 * srate;
		break;
	default:
		mclk = 384 * srate;
		break;
	}
	/* FIXME: Codec only requires >= 3MHz if OSR==0 */
	while (mclk < 6000000)
		mclk *= 2;

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		dev_err(card->dev, "Can't configure clocks\n");
		return err;
	}

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
		     SND_SOC_DAIFMT_CBS_CFS;

	/* Use DSP mode for mono on Tegra20 */
	if ((params_channels(params) != 2) &&
	    (machine_is_ventana() || machine_is_harmony() ||
	    machine_is_kaen() || machine_is_aebl()))
		i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
	else
		i2s_daifmt |= SND_SOC_DAIFMT_I2S;

	err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "codec_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "cpu_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
					SND_SOC_CLOCK_IN);
	if (err < 0) {
		dev_err(card->dev, "codec_dai clock not set\n");
		return err;
	}

	return 0;
}
static int tegra_aic326x_voice_call_hw_params(
			struct snd_pcm_substream *substream,
			struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
	int srate, mclk, rate, i2s_daifmt;
	int err, pcmdiv, vxclkdiv;

	srate = params_rate(params);
	mclk = tegra_aic326x_get_mclk(srate);
	if (mclk < 0)
		return mclk;

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF;

	i2s_daifmt |= pdata->i2s_param[VOICE_CODEC].is_i2s_master ?
		SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;

	switch (pdata->i2s_param[VOICE_CODEC].i2s_mode) {
	case TEGRA_DAIFMT_I2S:
		i2s_daifmt |= SND_SOC_DAIFMT_I2S;
		break;
	case TEGRA_DAIFMT_DSP_A:
		i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
		break;
	case TEGRA_DAIFMT_DSP_B:
		i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
		break;
	case TEGRA_DAIFMT_LEFT_J:
		i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
		break;
	case TEGRA_DAIFMT_RIGHT_J:
		i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
		break;
	default:
		dev_err(card->dev,
		"Can't configure i2s format\n");
		return -EINVAL;
	}

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	rate = clk_get_rate(machine->util_data.clk_cdev1);

	err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "codec_dai fmt not set\n");
		return err;
	}


	err = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , rate,
			params_rate(params));

	if (err < 0) {
		dev_err(card->dev, "codec_dai PLL clock not set\n");
		return err;
	}

	if (!machine_is_tegra_enterprise()) {
		if (params_rate(params) == 8000) {
			/* Change these Settings for 8KHz*/
			pcmdiv = 1;
			/* BB expecting 2048Khz bclk */
			vxclkdiv = 27;
		} else if (params_rate(params) == 16000) {
			pcmdiv = 1;
			/* BB expecting 2048Khz bclk */
			vxclkdiv = 27;
		} else {
			dev_err(card->dev, "codec_dai unsupported voice rate\n");
			return -EINVAL;
		}
	}

	//snd_soc_dai_set_clkdiv(codec_dai, ASI2_BCLK_N, vxclkdiv);
	//snd_soc_dai_set_clkdiv(codec_dai, ASI2_WCLK_N, pcmdiv);

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	/* codec configuration */
	machine->codec_info[VOICE_CODEC].rate = params_rate(params);
	machine->codec_info[VOICE_CODEC].channels = params_channels(params);
#endif

	machine->is_device_bt = 0;

	return 0;
}
Example #11
0
static int aml_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
    struct snd_soc_card *card = rtd->card;
    struct snd_soc_codec *codec = rtd->codec;
    struct snd_soc_dapm_context *dapm = &codec->dapm;
    struct aml_audio_private_data * p_aml_audio;
    int ret = 0;
    int hp_paraments[5];
    
    printk(KERN_DEBUG "enter %s \n", __func__);
    p_aml_audio = snd_soc_card_get_drvdata(card);
    
    ret = snd_soc_add_card_controls(codec->card, aml_m8_controls,
                ARRAY_SIZE(aml_m8_controls));
    if (ret)
       return ret;

    /* Add specific widgets */
    snd_soc_dapm_new_controls(dapm, aml_asoc_dapm_widgets,
                  ARRAY_SIZE(aml_asoc_dapm_widgets));
    if (ret)
        return ret;
    
#if HP_DET

    p_aml_audio->sdev.name = "h2w";//for report headphone to android
    ret = switch_dev_register(&p_aml_audio->sdev);
    if (ret < 0){
        printk(KERN_ERR "ASoC: register hp switch dev failed\n");
        return ret;
    }

    p_aml_audio->mic_sdev.name = "mic_dev";//for micphone detect
    ret = switch_dev_register(&p_aml_audio->mic_sdev);
    if (ret < 0){
        printk(KERN_ERR "ASoC: register mic switch dev failed\n");
        return ret;
    }

    ret = snd_soc_jack_new(codec, "hp switch", SND_JACK_HEADPHONE, &p_aml_audio->jack);
    if (ret < 0) {
        printk(KERN_WARNING "Failed to alloc resource for hp switch\n");
    } else {
        ret = snd_soc_jack_add_pins(&p_aml_audio->jack, ARRAY_SIZE(jack_pins), jack_pins);
        if (ret < 0) {
            printk(KERN_WARNING "Failed to setup hp pins\n");
        }
    }

    p_aml_audio->mic_det = of_property_read_bool(card->dev->of_node,"mic_det");

    printk("entern %s : mic_det=%d \n",__func__,p_aml_audio->mic_det);
    ret = of_property_read_u32_array(card->dev->of_node, "hp_paraments", &hp_paraments[0], 5);
    if(ret){
        printk("falied to get hp detect paraments from dts file\n");
    }else{
        p_aml_audio->hp_val_h  = hp_paraments[0];  // hp adc value higher base, hp unplugged
        p_aml_audio->hp_val_l  = hp_paraments[1];  // hp adc value low base, 3 section hp plugged.
        p_aml_audio->mic_val   = hp_paraments[2];  // hp adc value mic detect value.
        p_aml_audio->hp_detal  = hp_paraments[3];  // hp adc value test toerance
        p_aml_audio->hp_adc_ch = hp_paraments[4];  // get adc value from which adc port for hp detect

        printk("hp detect paraments: h=%d,l=%d,mic=%d,det=%d,ch=%d \n",p_aml_audio->hp_val_h,p_aml_audio->hp_val_l,
            p_aml_audio->mic_val,p_aml_audio->hp_detal,p_aml_audio->hp_adc_ch);
    }
    init_timer(&p_aml_audio->timer);
    p_aml_audio->timer.function = aml_asoc_timer_func;
    p_aml_audio->timer.data = (unsigned long)p_aml_audio;
    p_aml_audio->data= (void*)card;

    INIT_WORK(&p_aml_audio->work, aml_asoc_work_func);
    mutex_init(&p_aml_audio->lock);

    mutex_lock(&p_aml_audio->lock);
    if (!p_aml_audio->timer_en) {
        aml_audio_start_timer(p_aml_audio, msecs_to_jiffies(100));
    }
    mutex_unlock(&p_aml_audio->lock);

#endif

    return 0;
}
static int tegra_aic326x_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(rtd->card);
	struct codec_config *codec_info;
	struct codec_config *bb_info;
	struct codec_config *hifi_info;
	int codec_index;

	if (!i2s->is_dam_used)
		return 0;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/*
		*make apbif tx to i2s rx connection if this is the only client
		*using i2s for playback
		*/
		if (i2s->playback_ref_count == 1) {
			tegra30_ahub_set_rx_cif_source(
				TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
				i2s->txcif);
			tegra30_ahub_enable_clocks();
		}

	} else {
		i2s->is_call_mode_rec = machine->is_call_mode;
		if (!i2s->is_call_mode_rec)
			return 0;

		if (machine->is_device_bt)
			codec_index = BT_SCO;
		else
			codec_index = VOICE_CODEC;

		codec_info = &machine->codec_info[codec_index];
		bb_info = &machine->codec_info[BASEBAND];
		hifi_info = &machine->codec_info[HIFI_CODEC];

		/* allocate a dams for voice call recording */

		i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();

		if (i2s->call_record_dam_ifc < 0)
			return i2s->call_record_dam_ifc;

		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
			TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
			TEGRA30_DAM_CHIN1);
		tegra30_dam_enable_clock(i2s->call_record_dam_ifc);

		i2s->call_record_dam_ifc2 = tegra30_dam_allocate_controller();

		if (i2s->call_record_dam_ifc2 < 0)
			return i2s->call_record_dam_ifc2;

		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
			TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_allocate_channel(i2s->call_record_dam_ifc2,
			TEGRA30_DAM_CHIN1);
		tegra30_dam_enable_clock(i2s->call_record_dam_ifc2);

		/* configure the dams */
		/* DAM0 SRC bb rate to hifi rate */
		tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc,
			codec_info->rate, codec_info->channels,
			codec_info->bitsize, 1, hifi_info->rate,
			hifi_info->channels, hifi_info->bitsize);
		/* DAM1 UL + DL Mix */
		tegra_aic326x_set_dam_cif(i2s->call_record_dam_ifc2,
			codec_info->rate, codec_info->channels,
			codec_info->bitsize, 1, bb_info->rate,
			bb_info->channels, bb_info->bitsize);

		/* setup the connections for voice call record */
		tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
			(i2s->call_record_dam_ifc2*2),
			TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
			(i2s->call_record_dam_ifc2*2),
			TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
		tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
			(i2s->call_record_dam_ifc*2),
			TEGRA30_AHUB_TXCIF_DAM0_TX0 +
			i2s->call_record_dam_ifc2);
		tegra30_ahub_set_rx_cif_source(i2s->rxcif,
			TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);
#ifndef CONFIG_ARCH_TEGRA_3x_SOC
		/* Configure DAM0 for SRC */
		if (bb_info->rate != hifi_info->rate) {
			tegra30_dam_write_coeff_ram(i2s->call_record_dam_ifc,
						bb_info->rate, hifi_info->rate);
			tegra30_dam_set_farrow_param(i2s->call_record_dam_ifc,
						bb_info->rate, hifi_info->rate);
			tegra30_dam_set_biquad_fixed_coef(
						i2s->call_record_dam_ifc);
			tegra30_dam_enable_coeff_ram(i2s->call_record_dam_ifc);
			tegra30_dam_set_filter_stages(i2s->call_record_dam_ifc,
							bb_info->rate,
							hifi_info->rate);
		}
#endif
		/* enable the dam */
		tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
				TEGRA30_DAM_CHIN1);
		tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
				TEGRA30_DAM_CHIN0_SRC);
		tegra30_dam_enable(i2s->call_record_dam_ifc2,
					TEGRA30_DAM_ENABLE,
					TEGRA30_DAM_CHIN1);
		tegra30_dam_enable(i2s->call_record_dam_ifc2,
					TEGRA30_DAM_ENABLE,
					TEGRA30_DAM_CHIN0_SRC);
	}

	return 0;
}
static int tegra_aic326x_bt_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
	int err, srate, mclk, min_mclk, sample_size, i2s_daifmt;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
#endif

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		sample_size = 16;
		break;
	default:
		return -EINVAL;
	}

	srate = params_rate(params);

	mclk = tegra_aic326x_get_mclk(srate);
	if (mclk < 0)
		return mclk;

	min_mclk = 64 * srate;

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % min_mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
	i2s_daifmt |= pdata->i2s_param[BT_SCO].is_i2s_master ?
			SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;

	switch (pdata->i2s_param[BT_SCO].i2s_mode) {
		case TEGRA_DAIFMT_I2S :
			i2s_daifmt |= SND_SOC_DAIFMT_I2S;
			break;
		case TEGRA_DAIFMT_DSP_A :
			i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
			break;
		case TEGRA_DAIFMT_DSP_B :
			i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
			break;
		case TEGRA_DAIFMT_LEFT_J :
			i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
			break;
		case TEGRA_DAIFMT_RIGHT_J :
			i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
			break;
		default :
			dev_err(card->dev, "Can't configure i2s format\n");
			return -EINVAL;
	}

	err = snd_soc_dai_set_fmt(rtd->cpu_dai, i2s_daifmt);

	if (err < 0) {
		dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
		return err;
	}

#ifdef CONFIG_ARCH_TEGRA_2x_SOC
	err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
					TEGRA20_DAS_DAP_ID_4);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}

	err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
					TEGRA20_DAS_DAP_SEL_DAC2);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}
#else
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && i2s->is_dam_used)
		tegra_aic326x_set_dam_cif(i2s->dam_ifc, params_rate(params),
			params_channels(params), sample_size, 0, 0, 0, 0);
#endif

	return 0;
}
static int tegra_aic326x_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_aic326x *machine = snd_soc_card_get_drvdata(card);
	struct tegra_asoc_platform_data *pdata = machine->pdata;
	int srate, mclk, sample_size, i2s_daifmt;
	int err, rate;

	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		sample_size = 16;
		break;
	default:
		return -EINVAL;
	}

	srate = params_rate(params);

	mclk = tegra_aic326x_get_mclk(srate);
	if (mclk < 0)
		return mclk;

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
	i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
			SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;

	switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
		case TEGRA_DAIFMT_I2S :
			i2s_daifmt |= SND_SOC_DAIFMT_I2S;
			break;
		case TEGRA_DAIFMT_DSP_A :
			i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
			break;
		case TEGRA_DAIFMT_DSP_B :
			i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
			break;
		case TEGRA_DAIFMT_LEFT_J :
			i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
			break;
		case TEGRA_DAIFMT_RIGHT_J :
			i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
			break;
		default :
			dev_err(card->dev, "Can't configure i2s format\n");
			return -EINVAL;
	}

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	rate = clk_get_rate(machine->util_data.clk_cdev1);

	err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "codec_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "cpu_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_pll(codec_dai, 0, AIC3262_PLL_CLKIN_MCLK1 , rate,
		params_rate(params));

#ifdef CONFIG_ARCH_TEGRA_2x_SOC
	err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
					TEGRA20_DAS_DAP_ID_1);
	if (err < 0) {
		dev_err(card->dev, "failed to set dap-dac path\n");
		return err;
	}

	err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
					TEGRA20_DAS_DAP_SEL_DAC1);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}
#endif
	return 0;
}
Example #15
0
static int sdm845_snd_startup(struct snd_pcm_substream *substream)
{
	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
	unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	int j;
	int ret;

	switch (cpu_dai->id) {
	case PRIMARY_MI2S_RX:
	case PRIMARY_MI2S_TX:
		codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF;
		if (++(data->pri_mi2s_clk_count) == 1) {
			snd_soc_dai_set_sysclk(cpu_dai,
				Q6AFE_LPASS_CLK_ID_MCLK_1,
				DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
			snd_soc_dai_set_sysclk(cpu_dai,
				Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
				MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
		}
		snd_soc_dai_set_fmt(cpu_dai, fmt);
		snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
		break;

	case SECONDARY_MI2S_TX:
		if (++(data->sec_mi2s_clk_count) == 1) {
			snd_soc_dai_set_sysclk(cpu_dai,
				Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
				MI2S_BCLK_RATE,	SNDRV_PCM_STREAM_CAPTURE);
		}
		snd_soc_dai_set_fmt(cpu_dai, fmt);
		break;

	case QUATERNARY_TDM_RX_0:
	case QUATERNARY_TDM_TX_0:
		if (++(data->quat_tdm_clk_count) == 1) {
			snd_soc_dai_set_sysclk(cpu_dai,
				Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
				TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
		}

		codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;

		for (j = 0; j < rtd->num_codecs; j++) {
			codec_dai = rtd->codec_dais[j];

			if (!strcmp(codec_dai->component->name_prefix,
				    "Left")) {
				ret = snd_soc_dai_set_fmt(
						codec_dai, codec_dai_fmt);
				if (ret < 0) {
					dev_err(rtd->dev,
						"Left TDM fmt err:%d\n", ret);
					return ret;
				}
			}

			if (!strcmp(codec_dai->component->name_prefix,
				    "Right")) {
				ret = snd_soc_dai_set_fmt(
						codec_dai, codec_dai_fmt);
				if (ret < 0) {
					dev_err(rtd->dev,
						"Right TDM slot err:%d\n", ret);
					return ret;
				}
			}
		}
		break;

	default:
		pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
		break;
	}
	return 0;
}
Example #16
0
static int tegra_max98088_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    struct snd_soc_codec *codec = rtd->codec;
    struct snd_soc_card *card = codec->card;
    struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
    struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
#endif
    int srate, mclk, sample_size, i2s_daifmt;
    int err;
    struct clk *clk;
    int rate;

    switch (params_format(params)) {
    case SNDRV_PCM_FORMAT_S16_LE:
        sample_size = 16;
        break;
    default:
        return -EINVAL;
    }

    srate = params_rate(params);
    switch (srate) {
    case 8000:
    case 16000:
    case 24000:
    case 32000:
    case 48000:
    case 64000:
    case 96000:
        mclk = 12288000;
        break;
    case 11025:
    case 22050:
    case 44100:
    case 88200:
        mclk = 11289600;
        break;
    default:
        mclk = 12000000;
        break;
    }


#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
    clk = clk_get_sys(NULL, "cdev1");
#else
    clk = clk_get_sys("extern1", NULL);
#endif
    if (IS_ERR(clk)) {
        dev_err(card->dev, "Can't retrieve clk cdev1\n");
        err = PTR_ERR(clk);
        return err;
    }

    rate = clk_get_rate(clk);
    printk("extern1 rate=%d\n",rate);

#if TEGRA30_I2S_MASTER_PLAYBACK
    i2s_daifmt = SND_SOC_DAIFMT_I2S |
                 SND_SOC_DAIFMT_NB_NF |
                 SND_SOC_DAIFMT_CBS_CFS;
#else
    i2s_daifmt = SND_SOC_DAIFMT_I2S |
                 SND_SOC_DAIFMT_NB_NF |
                 SND_SOC_DAIFMT_CBM_CFM;
    mclk = rate;
#endif

    err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
    if (err < 0) {
        if (!(machine->util_data.set_mclk % mclk))
            mclk = machine->util_data.set_mclk;
        else {
            dev_err(card->dev, "Can't configure clocks\n");
            return err;
        }
    }

    tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

    err = snd_soc_dai_set_fmt(codec_dai,i2s_daifmt);
    if (err < 0) {
        dev_err(card->dev, "codec_dai fmt not set\n");
        return err;
    }

    err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
    if (err < 0) {
        dev_err(card->dev, "cpu_dai fmt not set\n");
        return err;
    }

    err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
                                 SND_SOC_CLOCK_IN);
    if (err < 0) {
        dev_err(card->dev, "codec_dai clock not set\n");
        return err;
    }

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
        tegra_max98088_set_dam_cif(i2s->dam_ifc, srate,
                                   params_channels(params), sample_size, 0, 0, 0, 0);
#endif

    return 0;
}
Example #17
0
static int fsl_asoc_card_set_bias_level(struct snd_soc_card *card,
					struct snd_soc_dapm_context *dapm,
					enum snd_soc_bias_level level)
{
	struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(card);
	struct snd_soc_pcm_runtime *rtd;
	struct snd_soc_dai *codec_dai;
	struct codec_priv *codec_priv = &priv->codec_priv;
	struct device *dev = card->dev;
	unsigned int pll_out;
	int ret;

	rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name);
	codec_dai = rtd->codec_dai;
	if (dapm->dev != codec_dai->dev)
		return 0;

	switch (level) {
	case SND_SOC_BIAS_PREPARE:
		if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
			break;

		if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
			pll_out = priv->sample_rate * 384;
		else
			pll_out = priv->sample_rate * 256;

		ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id,
					  codec_priv->mclk_id,
					  codec_priv->mclk_freq, pll_out);
		if (ret) {
			dev_err(dev, "failed to start FLL: %d\n", ret);
			return ret;
		}

		ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->fll_id,
					     pll_out, SND_SOC_CLOCK_IN);
		if (ret) {
			dev_err(dev, "failed to set SYSCLK: %d\n", ret);
			return ret;
		}
		break;

	case SND_SOC_BIAS_STANDBY:
		if (dapm->bias_level != SND_SOC_BIAS_PREPARE)
			break;

		ret = snd_soc_dai_set_sysclk(codec_dai, codec_priv->mclk_id,
					     codec_priv->mclk_freq,
					     SND_SOC_CLOCK_IN);
		if (ret) {
			dev_err(dev, "failed to switch away from FLL: %d\n", ret);
			return ret;
		}

		ret = snd_soc_dai_set_pll(codec_dai, codec_priv->pll_id, 0, 0, 0);
		if (ret) {
			dev_err(dev, "failed to stop FLL: %d\n", ret);
			return ret;
		}
		break;

	default:
		break;
	}

	return 0;
}
Example #18
0
static int tegra_bt_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
    struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(rtd->cpu_dai);
#endif
    struct snd_soc_card *card = rtd->card;
    struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
    int err, srate, mclk, min_mclk, sample_size;

    switch (params_format(params)) {
    case SNDRV_PCM_FORMAT_S16_LE:
        sample_size = 16;
        break;
    default:
        return -EINVAL;
    }

    srate = params_rate(params);
    switch (srate) {
    case 11025:
    case 22050:
    case 44100:
    case 88200:
        mclk = 11289600;
        break;
    case 8000:
    case 16000:
    case 32000:
    case 48000:
    case 64000:
    case 96000:
        mclk = 12288000;
        break;
    default:
        return -EINVAL;
    }
    min_mclk = 64 * srate;

    err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
    if (err < 0) {
        if (!(machine->util_data.set_mclk % min_mclk))
            mclk = machine->util_data.set_mclk;
        else {
            dev_err(card->dev, "Can't configure clocks\n");
            return err;
        }
    }

    tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

    err = snd_soc_dai_set_fmt(rtd->cpu_dai,
                              SND_SOC_DAIFMT_DSP_A |
                              SND_SOC_DAIFMT_NB_NF |
                              SND_SOC_DAIFMT_CBS_CFS);
    if (err < 0) {
        dev_err(rtd->codec->card->dev, "cpu_dai fmt not set\n");
        return err;
    }

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
        tegra_max98088_set_dam_cif(i2s->dam_ifc, params_rate(params),
                                   params_channels(params), sample_size, 0, 0, 0, 0);
#endif

    return 0;
}
static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
	int srate, mclk, min_mclk;
	int err;

	srate = params_rate(params);
	switch (srate) {
	case 11025:
	case 22050:
	case 44100:
	case 88200:
		mclk = 11289600;
		break;
	case 8000:
	case 16000:
	case 32000:
	case 48000:
	case 64000:
	case 96000:
		mclk = 12288000;
		break;
	default:
		return -EINVAL;
	}
	min_mclk = 64 * srate;

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % min_mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	err = snd_soc_dai_set_fmt(cpu_dai,
					SND_SOC_DAIFMT_DSP_A |
					SND_SOC_DAIFMT_NB_NF |
					SND_SOC_DAIFMT_CBS_CFS);
	if (err < 0) {
		dev_err(card->dev, "cpu_dai fmt not set\n");
		return err;
	}

#ifdef CONFIG_ARCH_TEGRA_2x_SOC
	err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC2,
					TEGRA20_DAS_DAP_ID_4);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}

	err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_4,
					TEGRA20_DAS_DAP_SEL_DAC2);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}
#endif
	return 0;
}
Example #20
0
static int tegra_max98088_startup(struct snd_pcm_substream *substream)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
    struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
    struct tegra_max98088 *machine = snd_soc_card_get_drvdata(rtd->card);
    struct codec_config *codec_info;
    struct codec_config *bb_info;
    int codec_index;

    if (!i2s->is_dam_used)
        return 0;

    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
        /*dam configuration*/
        if (!i2s->dam_ch_refcount)
            i2s->dam_ifc = tegra30_dam_allocate_controller();

        tegra30_dam_allocate_channel(i2s->dam_ifc, TEGRA30_DAM_CHIN1);
        i2s->dam_ch_refcount++;
        tegra30_dam_enable_clock(i2s->dam_ifc);

        tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
                                       (i2s->dam_ifc*2), i2s->txcif);

        /*
        *make the dam tx to i2s rx connection if this is the only client
        *using i2s for playback
        */
        if (i2s->playback_ref_count == 1)
            tegra30_ahub_set_rx_cif_source(
                TEGRA30_AHUB_RXCIF_I2S0_RX0 + i2s->id,
                TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->dam_ifc);

        /* enable the dam*/
        tegra30_dam_enable(i2s->dam_ifc, TEGRA30_DAM_ENABLE,
                           TEGRA30_DAM_CHIN1);
    } else {

        i2s->is_call_mode_rec = machine->is_call_mode;

        if (!i2s->is_call_mode_rec)
            return 0;

        if (machine->is_device_bt)
            codec_index = BT_SCO;
        else
            codec_index = HIFI_CODEC;

        codec_info = &machine->codec_info[codec_index];
        bb_info = &machine->codec_info[BASEBAND];

        /* allocate a dam for voice call recording */

        i2s->call_record_dam_ifc = tegra30_dam_allocate_controller();
        tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
                                     TEGRA30_DAM_CHIN0_SRC);
        tegra30_dam_allocate_channel(i2s->call_record_dam_ifc,
                                     TEGRA30_DAM_CHIN1);
        tegra30_dam_enable_clock(i2s->call_record_dam_ifc);

        /* configure the dam */
        tegra_max98088_set_dam_cif(i2s->call_record_dam_ifc,
                                   codec_info->rate, codec_info->channels,
                                   codec_info->bitsize, 1, bb_info->rate,
                                   bb_info->channels, bb_info->bitsize);

        /* setup the connections for voice call record */

        tegra30_ahub_unset_rx_cif_source(i2s->rxcif);
        tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX0 +
                                       (i2s->call_record_dam_ifc*2),
                                       TEGRA30_AHUB_TXCIF_I2S0_TX0 + bb_info->i2s_id);
        tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_DAM0_RX1 +
                                       (i2s->call_record_dam_ifc*2),
                                       TEGRA30_AHUB_TXCIF_I2S0_TX0 + codec_info->i2s_id);
        tegra30_ahub_set_rx_cif_source(i2s->rxcif,
                                       TEGRA30_AHUB_TXCIF_DAM0_TX0 + i2s->call_record_dam_ifc);

        /* enable the dam*/

        tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
                           TEGRA30_DAM_CHIN1);
        tegra30_dam_enable(i2s->call_record_dam_ifc, TEGRA30_DAM_ENABLE,
                           TEGRA30_DAM_CHIN0_SRC);
    }

    return 0;
}
static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
	int srate, mclk, i2s_daifmt;
	int err;
	struct clk *clk_m;
	int rate;

	srate = params_rate(params);
	switch (srate) {
	case 64000:
	case 88200:
	case 96000:
		mclk = 128 * srate;
		break;
	default:
		mclk = 256 * srate;
		break;
	}



	clk_m = clk_get_sys(NULL, "clk_m");
	if (IS_ERR(clk_m)) {
		dev_err(card->dev, "Can't retrieve clk clk_m\n");
		err = PTR_ERR(clk_m);
		return err;
	}
	rate = clk_get_rate(clk_m);
	printk("extern1 rate=%d\n",rate);

#if TEGRA30_I2S_MASTER_PLAYBACK
	/* FIXME: Codec only requires >= 3MHz if OSR==0 */
	while (mclk < 6000000)
		mclk *= 2;

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
		     SND_SOC_DAIFMT_CBS_CFS;
#else
	mclk = rate;

	i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
		     SND_SOC_DAIFMT_CBM_CFM;
#endif


	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	/* Use DSP mode for mono on Tegra20 */
	if ((params_channels(params) != 2) &&
	    (machine_is_ventana() || machine_is_harmony() ||
	    machine_is_kaen() || machine_is_aebl()))
		i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
	else
		i2s_daifmt |= SND_SOC_DAIFMT_I2S;

	err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "codec_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "cpu_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
					SND_SOC_CLOCK_IN);
	if (err < 0) {
		dev_err(card->dev, "codec_dai clock not set\n");
		return err;
	}
///Eric		
//Webber increase drc gain 9db
        snd_soc_write(codec, WM8903_DRC_0, 0x89BF);
        snd_soc_write(codec, WM8903_DRC_1, 0x149F);
        snd_soc_write(codec, WM8903_DRC_2, 0x0010);
        snd_soc_write(codec, WM8903_DRC_3, 0x0180);                
//Webber
	 snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, 0xb0);
        snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, 0xb0);
        snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, 0x33);
        snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, 0xB3);
///Eric
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
	err = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAP_SEL_DAC1,
					TEGRA20_DAS_DAP_ID_1);
	if (err < 0) {
		dev_err(card->dev, "failed to set dap-dac path\n");
		return err;
	}

	err = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
					TEGRA20_DAS_DAP_SEL_DAC1);
	if (err < 0) {
		dev_err(card->dev, "failed to set dac-dap path\n");
		return err;
	}
#endif
	return 0;
}
Example #22
0
static int tegra_voice_call_hw_params(struct snd_pcm_substream *substream,
                                      struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct snd_soc_dai *codec_dai = rtd->codec_dai;
    struct snd_soc_codec *codec = rtd->codec;
    struct snd_soc_card *card = codec->card;
    struct tegra_max98088 *machine = snd_soc_card_get_drvdata(card);
    int srate, mclk;
    int err;

    srate = params_rate(params);
    switch (srate) {
    case 8000:
    case 16000:
    case 24000:
    case 32000:
    case 48000:
    case 64000:
    case 96000:
        mclk = 12288000;
        break;
    case 11025:
    case 22050:
    case 44100:
    case 88200:
        mclk = 11289600;
        break;
    default:
        return -EINVAL;
        break;
    }

    err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
    if (err < 0) {
        if (!(machine->util_data.set_mclk % mclk))
            mclk = machine->util_data.set_mclk;
        else {
            dev_err(card->dev, "Can't configure clocks\n");
            return err;
        }
    }

    tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

    err = snd_soc_dai_set_fmt(codec_dai,
                              SND_SOC_DAIFMT_I2S |
                              SND_SOC_DAIFMT_NB_NF |
                              SND_SOC_DAIFMT_CBS_CFS);
    if (err < 0) {
        dev_err(card->dev, "codec_dai fmt not set\n");
        return err;
    }

    err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
                                 SND_SOC_CLOCK_IN);
    if (err < 0) {
        dev_err(card->dev, "codec_dai clock not set\n");
        return err;
    }

#ifndef CONFIG_ARCH_TEGRA_2x_SOC
    /* codec configuration */
    machine->codec_info[HIFI_CODEC].rate = params_rate(params);
    machine->codec_info[HIFI_CODEC].channels = params_channels(params);
    machine->codec_info[HIFI_CODEC].bitsize = 16;
    machine->codec_info[HIFI_CODEC].is_i2smaster = 1;
    machine->codec_info[HIFI_CODEC].is_format_dsp = 0;

    /* baseband configuration */
    machine->codec_info[BASEBAND].bitsize = 16;
    machine->codec_info[BASEBAND].is_i2smaster = 1;
    machine->codec_info[BASEBAND].is_format_dsp = 1;
#endif

    machine->is_device_bt = 0;

    return 0;
}
static int t0_wm1811_init_paiftx(struct snd_soc_pcm_runtime *rtd)
{
	struct snd_soc_codec *codec = rtd->codec;
	struct wm1811_machine_priv *wm1811
		= snd_soc_card_get_drvdata(codec->card);
	struct snd_soc_dai *aif1_dai = rtd->codec_dai;
	struct wm8994 *control = codec->control_data;
	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
	int ret;

	midas_snd_set_mclk(true, false);

	rtd->codec_dai->driver->playback.channels_max =
				rtd->cpu_dai->driver->playback.channels_max;

	ret = snd_soc_add_controls(codec, t0_controls,
					ARRAY_SIZE(t0_controls));

	ret = snd_soc_dapm_new_controls(&codec->dapm, t0_dapm_widgets,
					   ARRAY_SIZE(t0_dapm_widgets));
	if (ret != 0)
		dev_err(codec->dev, "Failed to add DAPM widgets: %d\n", ret);

	ret = snd_soc_dapm_add_routes(&codec->dapm, t0_dapm_routes,
					   ARRAY_SIZE(t0_dapm_routes));
	if (ret != 0)
		dev_err(codec->dev, "Failed to add DAPM routes: %d\n", ret);

	ret = snd_soc_dai_set_sysclk(aif1_dai, WM8994_SYSCLK_MCLK2,
				     MIDAS_DEFAULT_MCLK2, SND_SOC_CLOCK_IN);
	if (ret < 0)
		dev_err(codec->dev, "Failed to boot clocking\n");

	/* Force AIF1CLK on as it will be master for jack detection */
	if (wm8994->revision > 1) {
		ret = snd_soc_dapm_force_enable_pin(&codec->dapm, "AIF1CLK");
		if (ret < 0)
			dev_err(codec->dev, "Failed to enable AIF1CLK: %d\n",
					ret);
	}

	ret = snd_soc_dapm_disable_pin(&codec->dapm, "S5P RP");
	if (ret < 0)
		dev_err(codec->dev, "Failed to disable S5P RP: %d\n", ret);

	snd_soc_dapm_ignore_suspend(&codec->dapm, "RCV");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "SPK");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "HP");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "Headset Mic");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "Sub Mic");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "Main Mic");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF1DACDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF2DACDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF3DACDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF1ADCDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF2ADCDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "AIF3ADCDAT");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "FM In");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "LINE");
	snd_soc_dapm_ignore_suspend(&codec->dapm, "HDMI");

	wm1811->codec = codec;

	t0_micd_set_rate(codec);

#ifdef CONFIG_SEC_DEV_JACK
	/* By default use idle_bias_off, will override for WM8994 */
	codec->dapm.idle_bias_off = 0;
#else /* CONFIG_SEC_DEV_JACK */
	wm1811->jack.status = 0;

	ret = snd_soc_jack_new(codec, "T0 Jack",
				SND_JACK_HEADSET | SND_JACK_BTN_0 |
				SND_JACK_BTN_1 | SND_JACK_BTN_2,
				&wm1811->jack);

	if (ret < 0)
		dev_err(codec->dev, "Failed to create jack: %d\n", ret);

	ret = snd_jack_set_key(wm1811->jack.jack, SND_JACK_BTN_0, KEY_MEDIA);

	if (ret < 0)
		dev_err(codec->dev, "Failed to set KEY_MEDIA: %d\n", ret);

	ret = snd_jack_set_key(wm1811->jack.jack, SND_JACK_BTN_1,
							KEY_VOLUMEDOWN);
	if (ret < 0)
		dev_err(codec->dev, "Failed to set KEY_VOLUMEUP: %d\n", ret);

	ret = snd_jack_set_key(wm1811->jack.jack, SND_JACK_BTN_2,
							KEY_VOLUMEUP);

	if (ret < 0)
		dev_err(codec->dev, "Failed to set KEY_VOLUMEDOWN: %d\n", ret);

	if (wm8994->revision > 1) {
		dev_info(codec->dev, "wm1811: Rev %c support mic detection\n",
			'A' + wm8994->revision);
		ret = wm8958_mic_detect(codec, &wm1811->jack, t0_micdet,
			wm1811);

		if (ret < 0)
			dev_err(codec->dev, "Failed start detection: %d\n",
				ret);
	} else {
		dev_info(codec->dev, "wm1811: Rev %c doesn't support mic detection\n",
			'A' + wm8994->revision);
		codec->dapm.idle_bias_off = 0;
	}
	/* To wakeup for earjack event in suspend mode */
	enable_irq_wake(control->irq);

	wake_lock_init(&wm1811->jackdet_wake_lock,
					WAKE_LOCK_SUSPEND, "T0_jackdet");

	/* To support PBA function test */
	jack_class = class_create(THIS_MODULE, "audio");

	if (IS_ERR(jack_class))
		pr_err("Failed to create class\n");

	jack_dev = device_create(jack_class, NULL, 0, codec, "earjack");

	if (device_create_file(jack_dev, &dev_attr_select_jack) < 0)
		pr_err("Failed to create device file (%s)!\n",
			dev_attr_select_jack.attr.name);

	if (device_create_file(jack_dev, &dev_attr_key_state) < 0)
		pr_err("Failed to create device file (%s)!\n",
			dev_attr_key_state.attr.name);

	if (device_create_file(jack_dev, &dev_attr_state) < 0)
		pr_err("Failed to create device file (%s)!\n",
			dev_attr_state.attr.name);

	if (device_create_file(jack_dev, &dev_attr_reselect_jack) < 0)
		pr_err("Failed to create device file (%s)!\n",
			dev_attr_reselect_jack.attr.name);

#endif /* CONFIG_SEC_DEV_JACK */
	return snd_soc_dapm_sync(&codec->dapm);
}
Example #24
0
static int tegra_rt5640_jack_notifier(struct notifier_block *self,
			      unsigned long action, void *dev)
{
	struct snd_soc_jack *jack = dev;
	struct snd_soc_codec *codec = jack->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
	struct tegra_rt5640_platform_data *pdata = machine->pdata;
	enum headset_state state = BIT_NO_HEADSET;
	unsigned char status_jack;
#if 0
	if (jack == &tegra_rt5640_hp_jack) {
		if (action) {
			/* Enable ext mic; enable signal is active-low */
			gpio_direction_output(pdata->gpio_ext_mic_en, 0);
			if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
				status_jack = rt5639_headset_detect(codec, 1);
			else if (!strncmp(machine->pdata->codec_name, "rt5640",
									    6))
				status_jack = rt5640_headset_detect(codec, 1);

			machine->jack_status &= ~SND_JACK_HEADPHONE;
			machine->jack_status &= ~SND_JACK_MICROPHONE;
			if (status_jack == RT5639_HEADPHO_DET ||
			    status_jack == RT5640_HEADPHO_DET)
					machine->jack_status |=
							SND_JACK_HEADPHONE;
			else if (status_jack == RT5639_HEADSET_DET ||
				 status_jack == RT5640_HEADSET_DET) {
					machine->jack_status |=
							SND_JACK_HEADPHONE;
					machine->jack_status |=
							SND_JACK_MICROPHONE;
			}
		} else {
			/* Disable ext mic; enable signal is active-low */
			gpio_direction_output(pdata->gpio_ext_mic_en, 1);
			if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
				rt5639_headset_detect(codec, 0);
			else if (!strncmp(machine->pdata->codec_name, "rt5640",
									    6))
				rt5640_headset_detect(codec, 0);

			machine->jack_status &= ~SND_JACK_HEADPHONE;
			machine->jack_status &= ~SND_JACK_MICROPHONE;
		}
	}
#endif
	switch (machine->jack_status) {
	case SND_JACK_HEADPHONE:
		state = BIT_HEADSET_NO_MIC;
		break;
	case SND_JACK_HEADSET:
		state = BIT_HEADSET;
		break;
	case SND_JACK_MICROPHONE:
		/* mic: would not report */
	default:
		state = BIT_NO_HEADSET;
	}

	switch_set_state(&tegra_rt5640_headset_switch, state);

	return NOTIFY_OK;
}
static int ctp_wm5102_init(struct snd_soc_pcm_runtime *runtime)
{
	int ret;
	struct snd_soc_card *card = runtime->card;
	struct ctp_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
	struct snd_soc_codec *codec;
	struct snd_soc_dapm_context *dapm;

	codec = ctp_get_codec(card, "wm5102-codec");
	if (!codec)
		return -EIO;
	dapm = &codec->dapm;

	/* Set codec bias level */
	ctp_set_bias_level(card, dapm, SND_SOC_BIAS_OFF);
	card->dapm.idle_bias_off = true;

	/* Disable MICBIAS3 bypass mode and set CAP mode.
	* Capacitors are connected to DMIC on 1525-EV1 board */
	snd_soc_update_bits(codec, ARIZONA_MIC_BIAS_CTRL_3,
			ARIZONA_MICB1_BYPASS_MASK | ARIZONA_MICB1_EXT_CAP_MASK,
			ARIZONA_MICB1_EXT_CAP);

	/* Set codec clock */
	ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
				ARIZONA_CLK_SRC_FLL1,
				SYSCLK_RATE,
				SND_SOC_CLOCK_IN);
	if (ret != 0) {
		pr_err("failed: %d\n", ret);
		return ret;
	}

	/* Add Jack specific widgets */
	ret = snd_soc_dapm_new_controls(dapm, ctp_dapm_widgets,
					ARRAY_SIZE(ctp_dapm_widgets));
	if (ret)
		return ret;

	/* Set up Jack specific audio path audio_map */
	snd_soc_dapm_add_routes(dapm, ctp_audio_map,
					ARRAY_SIZE(ctp_audio_map));
	/* Add Comms specefic controls */
	ctx->comms_ctl.ssp_bt_sco_master_mode = false;
	ctx->comms_ctl.ssp_voip_master_mode = false;
	ctx->comms_ctl.ssp_modem_master_mode = false;

	ret = snd_soc_add_card_controls(card, ssp_comms_controls,
				ARRAY_SIZE(ssp_comms_controls));
	if (ret) {
		pr_err("Add Comms Controls failed %d",
				ret);
		return ret;
	}
	/* Keep the voice call paths active during
	suspend. Mark the end points ignore_suspend */
	snd_soc_dapm_ignore_suspend(dapm, "HPOUT1R");
	snd_soc_dapm_ignore_suspend(dapm, "HPOUT1L");

	snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
	snd_soc_dapm_disable_pin(dapm, "SPKOUTLP");
	snd_soc_dapm_disable_pin(dapm, "SPKOUTLN");
	snd_soc_dapm_ignore_suspend(dapm, "SPKOUTRP");
	snd_soc_dapm_ignore_suspend(dapm, "SPKOUTRN");
	mutex_lock(&codec->mutex);
	snd_soc_dapm_sync(dapm);
	mutex_unlock(&codec->mutex);
	return ret;
}
static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
					struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *codec_dai = rtd->codec_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_codec *codec = rtd->codec;
	struct snd_soc_card *card = codec->card;
	struct tegra_p1852 *machine = snd_soc_card_get_drvdata(card);
	int srate, mclk;
	int i2s_daifmt = 0;
	int err;
	struct tegra_p1852_platform_data *pdata;
	int codec_id = codec_dai->id;

	pdata = machine->pdata;

	srate = params_rate(params);
	switch (srate) {
	case 64000:
	case 88200:
	case 96000:
		mclk = 128 * srate;
		break;
	default:
		mclk = 256 * srate;
		break;
	}

	err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
	if (err < 0) {
		if (!(machine->util_data.set_mclk % mclk))
			mclk = machine->util_data.set_mclk;
		else {
			dev_err(card->dev, "Can't configure clocks\n");
			return err;
		}
	}

	tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);

	if (pdata->codec_info[codec_id].master)
		i2s_daifmt |= SND_SOC_DAIFMT_CBM_CFM;
	else
		i2s_daifmt |= SND_SOC_DAIFMT_CBS_CFS;

	switch (pdata->codec_info[codec_id].i2s_format) {
	case format_tdm:
		i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
		break;
	case format_i2s:
		i2s_daifmt |= SND_SOC_DAIFMT_I2S;
		break;
	case format_rjm:
		i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
		break;
	case format_ljm:
		i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
		break;
	default:
		break;
	}

	err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
	if (err < 0)
		dev_info(card->dev, "codec_dai fmt not set\n");

	err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
	if (err < 0) {
		dev_err(card->dev, "cpu_dai fmt not set\n");
		return err;
	}

	err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
					SND_SOC_CLOCK_IN);
	if (err < 0)
		dev_info(card->dev, "codec_dai clock not set\n");

	return 0;
}