Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148199
b: refs/heads/master
c: 7154b3e
h: refs/heads/master
i:
  148197: 18cedf6
  148195: e464e9b
  148191: 41bf825
v: v3
  • Loading branch information
Joonyoung Shim authored and Mark Brown committed Apr 20, 2009
1 parent 39df492 commit c4fb983
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6b87a91f5417226c7fe62100b0e7217e7096b789
refs/heads/master: 7154b3e80203ee91f9ba7d0a43d3daa05c49d9e9
173 changes: 168 additions & 5 deletions trunk/sound/soc/codecs/twl4030.c
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,144 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}

static int twl4030_voice_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
u8 infreq;
u8 mode;

/* If the system master clock is not 26MHz, the voice PCM interface is
* not avilable.
*/
infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL)
& TWL4030_APLL_INFREQ;

if (infreq != TWL4030_APLL_INFREQ_26000KHZ) {
printk(KERN_ERR "TWL4030 voice startup: "
"MCLK is not 26MHz, call set_sysclk() on init\n");
return -EINVAL;
}

/* If the codec mode is not option2, the voice PCM interface is not
* avilable.
*/
mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
& TWL4030_OPT_MODE;

if (mode != TWL4030_OPTION_2) {
printk(KERN_ERR "TWL4030 voice startup: "
"the codec mode is not option2\n");
return -EINVAL;
}

return 0;
}

static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec;
u8 old_mode, mode;

/* bit rate */
old_mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE)
& ~(TWL4030_CODECPDZ);
mode = old_mode;

switch (params_rate(params)) {
case 8000:
mode &= ~(TWL4030_SEL_16K);
break;
case 16000:
mode |= TWL4030_SEL_16K;
break;
default:
printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
params_rate(params));
return -EINVAL;
}

if (mode != old_mode) {
/* change rate and set CODECPDZ */
twl4030_codec_enable(codec, 0);
twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
twl4030_codec_enable(codec, 1);
}

return 0;
}

static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
u8 infreq;

switch (freq) {
case 26000000:
infreq = TWL4030_APLL_INFREQ_26000KHZ;
break;
default:
printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n",
freq);
return -EINVAL;
}

infreq |= TWL4030_APLL_EN;
twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);

return 0;
}

static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
u8 old_format, format;

/* get format */
old_format = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
format = old_format;

/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFM:
format &= ~(TWL4030_VIF_SLAVE_EN);
break;
case SND_SOC_DAIFMT_CBS_CFS:
format |= TWL4030_VIF_SLAVE_EN;
break;
default:
return -EINVAL;
}

/* clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_IB_NF:
format &= ~(TWL4030_VIF_FORMAT);
break;
case SND_SOC_DAIFMT_NB_IF:
format |= TWL4030_VIF_FORMAT;
break;
default:
return -EINVAL;
}

if (format != old_format) {
/* change format and set CODECPDZ */
twl4030_codec_enable(codec, 0);
twl4030_write(codec, TWL4030_REG_VOICE_IF, format);
twl4030_codec_enable(codec, 1);
}

return 0;
}

#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)

Expand All @@ -1495,7 +1633,15 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
.set_fmt = twl4030_set_dai_fmt,
};

struct snd_soc_dai twl4030_dai = {
static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
.startup = twl4030_voice_startup,
.hw_params = twl4030_voice_hw_params,
.set_sysclk = twl4030_voice_set_dai_sysclk,
.set_fmt = twl4030_voice_set_dai_fmt,
};

struct snd_soc_dai twl4030_dai[] = {
{
.name = "twl4030",
.playback = {
.stream_name = "Playback",
Expand All @@ -1510,6 +1656,23 @@ struct snd_soc_dai twl4030_dai = {
.rates = TWL4030_RATES,
.formats = TWL4030_FORMATS,},
.ops = &twl4030_dai_ops,
},
{
.name = "twl4030 Voice",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &twl4030_dai_voice_ops,
},
};
EXPORT_SYMBOL_GPL(twl4030_dai);

Expand Down Expand Up @@ -1550,8 +1713,8 @@ static int twl4030_init(struct snd_soc_device *socdev)
codec->read = twl4030_read_reg_cache;
codec->write = twl4030_write;
codec->set_bias_level = twl4030_set_bias_level;
codec->dai = &twl4030_dai;
codec->num_dai = 1;
codec->dai = twl4030_dai;
codec->num_dai = ARRAY_SIZE(twl4030_dai),
codec->reg_cache_size = sizeof(twl4030_reg);
codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
GFP_KERNEL);
Expand Down Expand Up @@ -1645,13 +1808,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);

static int __init twl4030_modinit(void)
{
return snd_soc_register_dai(&twl4030_dai);
return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
}
module_init(twl4030_modinit);

static void __exit twl4030_exit(void)
{
snd_soc_unregister_dai(&twl4030_dai);
snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
}
module_exit(twl4030_exit);

Expand Down
18 changes: 17 additions & 1 deletion trunk/sound/soc/codecs/twl4030.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
#define TWL4030_SEL_16K 0x04
#define TWL4030_CODECPDZ 0x02
#define TWL4030_OPT_MODE 0x01
#define TWL4030_OPTION_1 (1 << 0)
#define TWL4030_OPTION_2 (0 << 0)

/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */

Expand Down Expand Up @@ -171,6 +173,17 @@
#define TWL4030_CLK256FS_EN 0x02
#define TWL4030_AIF_EN 0x01

/* VOICE_IF (0x0F) Fields */

#define TWL4030_VIF_SLAVE_EN 0x80
#define TWL4030_VIF_DIN_EN 0x40
#define TWL4030_VIF_DOUT_EN 0x20
#define TWL4030_VIF_SWAP 0x10
#define TWL4030_VIF_FORMAT 0x08
#define TWL4030_VIF_TRI_EN 0x04
#define TWL4030_VIF_SUB_EN 0x02
#define TWL4030_VIF_EN 0x01

/* EAR_CTL (0x21) */
#define TWL4030_EAR_GAIN 0x30

Expand Down Expand Up @@ -236,7 +249,10 @@
#define TWL4030_SMOOTH_ANAVOL_EN 0x02
#define TWL4030_DIGMIC_LR_SWAP_EN 0x01

extern struct snd_soc_dai twl4030_dai;
#define TWL4030_DAI_HIFI 0
#define TWL4030_DAI_VOICE 1

extern struct snd_soc_dai twl4030_dai[2];
extern struct snd_soc_codec_device soc_codec_dev_twl4030;

#endif /* End of __TWL4030_AUDIO_H__ */
2 changes: 1 addition & 1 deletion trunk/sound/soc/omap/omap2evm.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static struct snd_soc_dai_link omap2evm_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap2evm_ops,
};

Expand Down
2 changes: 1 addition & 1 deletion trunk/sound/soc/omap/omap3beagle.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static struct snd_soc_dai_link omap3beagle_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3beagle_ops,
};

Expand Down
4 changes: 2 additions & 2 deletions trunk/sound/soc/omap/omap3pandora.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,14 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
.name = "PCM1773",
.stream_name = "HiFi Out",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3pandora_out_ops,
.init = omap3pandora_out_init,
}, {
.name = "TWL4030",
.stream_name = "Line/Mic In",
.cpu_dai = &omap_mcbsp_dai[1],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &omap3pandora_in_ops,
.init = omap3pandora_in_init,
}
Expand Down
2 changes: 1 addition & 1 deletion trunk/sound/soc/omap/overo.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static struct snd_soc_dai_link overo_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.ops = &overo_ops,
};

Expand Down
2 changes: 1 addition & 1 deletion trunk/sound/soc/omap/sdp3430.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static struct snd_soc_dai_link sdp3430_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
.cpu_dai = &omap_mcbsp_dai[0],
.codec_dai = &twl4030_dai,
.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
.init = sdp3430_twl4030_init,
.ops = &sdp3430_ops,
};
Expand Down

0 comments on commit c4fb983

Please sign in to comment.