⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 neo1973_wm8753.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * neo1973_wm8753.c  --  SoC audio for Neo1973 * * Copyright 2007 Wolfson Microelectronics PLC. * Author: Graeme Gregory *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * *  Revision history *    20th Jan 2007   Initial version. *    05th Feb 2007   Rename all to Neo1973 * */#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/platform_device.h>#include <linux/i2c.h>#include <sound/driver.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/soc.h>#include <sound/soc-dapm.h>#include <asm/mach-types.h>#include <asm/hardware/scoop.h>#include <asm/arch/regs-iis.h>#include <asm/arch/regs-clock.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include <asm/arch/audio.h>#include <asm/io.h>#include <asm/arch/spi-gpio.h>#include "../codecs/wm8753.h"#include "lm4857.h"#include "s3c24xx-pcm.h"#include "s3c24xx-i2s.h"/* define the scenarios */#define NEO_AUDIO_OFF			0#define NEO_GSM_CALL_AUDIO_HANDSET	1#define NEO_GSM_CALL_AUDIO_HEADSET	2#define NEO_GSM_CALL_AUDIO_BLUETOOTH	3#define NEO_STEREO_TO_SPEAKERS		4#define NEO_STEREO_TO_HEADPHONES	5#define NEO_CAPTURE_HANDSET		6#define NEO_CAPTURE_HEADSET		7#define NEO_CAPTURE_BLUETOOTH		8static struct snd_soc_machine neo1973;static struct i2c_client *i2c;static int neo1973_hifi_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_codec_dai *codec_dai = rtd->dai->codec_dai;	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;	unsigned int pll_out = 0, bclk = 0;	int ret = 0;	unsigned long iis_clkrate;	iis_clkrate = s3c24xx_i2s_get_clockrate();	switch (params_rate(params)) {	case 8000:	case 16000:		pll_out = 12288000;		break;	case 48000:		bclk = WM8753_BCLK_DIV_4;		pll_out = 12288000;		break;	case 96000:		bclk = WM8753_BCLK_DIV_2;		pll_out = 12288000;		break;	case 11025:		bclk = WM8753_BCLK_DIV_16;		pll_out = 11289600;		break;	case 22050:		bclk = WM8753_BCLK_DIV_8;		pll_out = 11289600;		break;	case 44100:		bclk = WM8753_BCLK_DIV_4;		pll_out = 11289600;		break;	case 88200:		bclk = WM8753_BCLK_DIV_2;		pll_out = 11289600;		break;	}	/* set codec DAI configuration */	ret = codec_dai->dai_ops.set_fmt(codec_dai,		SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |		SND_SOC_DAIFMT_CBM_CFM);	if (ret < 0)		return ret;	/* set cpu DAI configuration */	ret = cpu_dai->dai_ops.set_fmt(cpu_dai,		SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |		SND_SOC_DAIFMT_CBM_CFM);	if (ret < 0)		return ret;	/* set the codec system clock for DAC and ADC */	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out,		SND_SOC_CLOCK_IN);	if (ret < 0)		return ret;	/* set MCLK division for sample rate */	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,		S3C2410_IISMOD_32FS );	if (ret < 0)		return ret;	/* set codec BCLK division for sample rate */	ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);	if (ret < 0)		return ret;	/* set prescaler division for sample rate */	ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,		S3C24XX_PRESCALE(4,4));	if (ret < 0)		return ret;	/* codec PLL input is PCLK/4 */	ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1,		iis_clkrate / 4, pll_out);	if (ret < 0)		return ret;	return 0;}static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream){	struct snd_soc_pcm_runtime *rtd = substream->private_data;	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;	/* disable the PLL */	return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0);}/* * Neo1973 WM8753 HiFi DAI opserations. */static struct snd_soc_ops neo1973_hifi_ops = {	.hw_params = neo1973_hifi_hw_params,	.hw_free = neo1973_hifi_hw_free,};static int neo1973_voice_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_codec_dai *codec_dai = rtd->dai->codec_dai;	unsigned int pcmdiv = 0;	int ret = 0;	unsigned long iis_clkrate;	iis_clkrate = s3c24xx_i2s_get_clockrate();	if (params_rate(params) != 8000)		return -EINVAL;	if (params_channels(params) != 1)		return -EINVAL;	pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */	/* todo: gg check mode (DSP_B) against CSR datasheet */	/* set codec DAI configuration */	ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);	if (ret < 0)		return ret;	/* set the codec system clock for DAC and ADC */	ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,		SND_SOC_CLOCK_IN);	if (ret < 0)		return ret;	/* set codec PCM division for sample rate */	ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);	if (ret < 0)		return ret;	/* configue and enable PLL for 12.288MHz output */	ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2,		iis_clkrate / 4, 12288000);	if (ret < 0)		return ret;	return 0;}static int neo1973_voice_hw_free(struct snd_pcm_substream *substream){	struct snd_soc_pcm_runtime *rtd = substream->private_data;	struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;	/* disable the PLL */	return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0);}static struct snd_soc_ops neo1973_voice_ops = {	.hw_params = neo1973_voice_hw_params,	.hw_free = neo1973_voice_hw_free,};static int neo1973_scenario = 0;static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	ucontrol->value.integer.value[0] = neo1973_scenario;	return 0;}static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario){	switch(neo1973_scenario) {	case NEO_AUDIO_OFF:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_GSM_CALL_AUDIO_HANDSET:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);		break;	case NEO_GSM_CALL_AUDIO_HEADSET:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_GSM_CALL_AUDIO_BLUETOOTH:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_STEREO_TO_SPEAKERS:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_STEREO_TO_HEADPHONES:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_CAPTURE_HANDSET:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);		break;	case NEO_CAPTURE_HEADSET:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	case NEO_CAPTURE_BLUETOOTH:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);		break;	default:		snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);		snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);		snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);		snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);		snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);	}	snd_soc_dapm_sync_endpoints(codec);	return 0;}static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);	if (neo1973_scenario == ucontrol->value.integer.value[0])		return 0;	neo1973_scenario = ucontrol->value.integer.value[0];	set_scenario_endpoints(codec, neo1973_scenario);	return 1;}static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};static void lm4857_write_regs(void){	if (i2c_master_send(i2c, lm4857_regs, 4) != 4)		printk(KERN_ERR "lm4857: i2c write failed\n");}static int lm4857_get_reg(struct snd_kcontrol *kcontrol,	struct snd_ctl_elem_value *ucontrol){	int reg=kcontrol->private_value & 0xFF;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -