Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
a1daf67d
Commit
a1daf67d
authored
Jul 30, 2009
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'gta02-audio' into for-2.6.32
parents
3a39f832
82c4362e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
509 additions
and
0 deletions
+509
-0
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/Kconfig
+9
-0
sound/soc/s3c24xx/Makefile
sound/soc/s3c24xx/Makefile
+2
-0
sound/soc/s3c24xx/neo1973_gta02_wm8753.c
sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+498
-0
No files found.
sound/soc/s3c24xx/Kconfig
View file @
a1daf67d
...
...
@@ -38,6 +38,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753
Say Y if you want to add support for SoC audio on smdk2440
with the WM8753.
config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
select SND_S3C24XX_SOC_I2S
select SND_SOC_WM8753
help
This driver provides audio support for the Openmoko Neo FreeRunner
smartphone.
config SND_S3C24XX_SOC_JIVE_WM8750
tristate "SoC I2S Audio support for Jive"
depends on SND_S3C24XX_SOC && MACH_JIVE
...
...
sound/soc/s3c24xx/Makefile
View file @
a1daf67d
...
...
@@ -16,12 +16,14 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
# S3C24XX Machine Support
snd-soc-jive-wm8750-objs
:=
jive_wm8750.o
snd-soc-neo1973-wm8753-objs
:=
neo1973_wm8753.o
snd-soc-neo1973-gta02-wm8753-objs
:=
neo1973_gta02_wm8753.o
snd-soc-smdk2443-wm9710-objs
:=
smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs
:=
ln2440sbc_alc650.o
snd-soc-s3c24xx-uda134x-objs
:=
s3c24xx_uda134x.o
obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750)
+=
snd-soc-jive-wm8750.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753)
+=
snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753)
+=
snd-soc-neo1973-gta02-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710)
+=
snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650)
+=
snd-soc-ln2440sbc-alc650.o
obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X)
+=
snd-soc-s3c24xx-uda134x.o
sound/soc/s3c24xx/neo1973_gta02_wm8753.c
0 → 100644
View file @
a1daf67d
/*
* neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02)
*
* Copyright 2007 Openmoko Inc
* Author: Graeme Gregory <graeme@openmoko.org>
* Copyright 2007 Wolfson Microelectronics PLC.
* Author: Graeme Gregory <linux@wolfsonmicro.com>
* Copyright 2009 Wolfson Microelectronics
*
* 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.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <asm/mach-types.h>
#include <plat/regs-iis.h>
#include <mach/regs-clock.h>
#include <asm/io.h>
#include <mach/gta02.h>
#include "../codecs/wm8753.h"
#include "s3c24xx-pcm.h"
#include "s3c24xx-i2s.h"
static
struct
snd_soc_card
neo1973_gta02
;
static
int
neo1973_gta02_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_dai
*
codec_dai
=
rtd
->
dai
->
codec_dai
;
struct
snd_soc_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
=
snd_soc_dai_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
=
snd_soc_dai_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
=
snd_soc_dai_set_sysclk
(
codec_dai
,
WM8753_MCLK
,
pll_out
,
SND_SOC_CLOCK_IN
);
if
(
ret
<
0
)
return
ret
;
/* set MCLK division for sample rate */
ret
=
snd_soc_dai_set_clkdiv
(
cpu_dai
,
S3C24XX_DIV_MCLK
,
S3C2410_IISMOD_32FS
);
if
(
ret
<
0
)
return
ret
;
/* set codec BCLK division for sample rate */
ret
=
snd_soc_dai_set_clkdiv
(
codec_dai
,
WM8753_BCLKDIV
,
bclk
);
if
(
ret
<
0
)
return
ret
;
/* set prescaler division for sample rate */
ret
=
snd_soc_dai_set_clkdiv
(
cpu_dai
,
S3C24XX_DIV_PRESCALER
,
S3C24XX_PRESCALE
(
4
,
4
));
if
(
ret
<
0
)
return
ret
;
/* codec PLL input is PCLK/4 */
ret
=
snd_soc_dai_set_pll
(
codec_dai
,
WM8753_PLL1
,
iis_clkrate
/
4
,
pll_out
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
neo1973_gta02_hifi_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
dai
->
codec_dai
;
/* disable the PLL */
return
snd_soc_dai_set_pll
(
codec_dai
,
WM8753_PLL1
,
0
,
0
);
}
/*
* Neo1973 WM8753 HiFi DAI opserations.
*/
static
struct
snd_soc_ops
neo1973_gta02_hifi_ops
=
{
.
hw_params
=
neo1973_gta02_hifi_hw_params
,
.
hw_free
=
neo1973_gta02_hifi_hw_free
,
};
static
int
neo1973_gta02_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_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
=
snd_soc_dai_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
=
snd_soc_dai_set_sysclk
(
codec_dai
,
WM8753_PCMCLK
,
12288000
,
SND_SOC_CLOCK_IN
);
if
(
ret
<
0
)
return
ret
;
/* set codec PCM division for sample rate */
ret
=
snd_soc_dai_set_clkdiv
(
codec_dai
,
WM8753_PCMDIV
,
pcmdiv
);
if
(
ret
<
0
)
return
ret
;
/* configue and enable PLL for 12.288MHz output */
ret
=
snd_soc_dai_set_pll
(
codec_dai
,
WM8753_PLL2
,
iis_clkrate
/
4
,
12288000
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
int
neo1973_gta02_voice_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
codec_dai
=
rtd
->
dai
->
codec_dai
;
/* disable the PLL */
return
snd_soc_dai_set_pll
(
codec_dai
,
WM8753_PLL2
,
0
,
0
);
}
static
struct
snd_soc_ops
neo1973_gta02_voice_ops
=
{
.
hw_params
=
neo1973_gta02_voice_hw_params
,
.
hw_free
=
neo1973_gta02_voice_hw_free
,
};
#define LM4853_AMP 1
#define LM4853_SPK 2
static
u8
lm4853_state
;
/* This has no effect, it exists only to maintain compatibility with
* existing ALSA state files.
*/
static
int
lm4853_set_state
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
int
val
=
ucontrol
->
value
.
integer
.
value
[
0
];
if
(
val
)
lm4853_state
|=
LM4853_AMP
;
else
lm4853_state
&=
~
LM4853_AMP
;
return
0
;
}
static
int
lm4853_get_state
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
ucontrol
->
value
.
integer
.
value
[
0
]
=
lm4853_state
&
LM4853_AMP
;
return
0
;
}
static
int
lm4853_set_spk
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
int
val
=
ucontrol
->
value
.
integer
.
value
[
0
];
if
(
val
)
{
lm4853_state
|=
LM4853_SPK
;
gpio_set_value
(
GTA02_GPIO_HP_IN
,
0
);
}
else
{
lm4853_state
&=
~
LM4853_SPK
;
gpio_set_value
(
GTA02_GPIO_HP_IN
,
1
);
}
return
0
;
}
static
int
lm4853_get_spk
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
ucontrol
->
value
.
integer
.
value
[
0
]
=
(
lm4853_state
&
LM4853_SPK
)
>>
1
;
return
0
;
}
static
int
lm4853_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
gpio_set_value
(
GTA02_GPIO_AMP_SHUT
,
SND_SOC_DAPM_EVENT_OFF
(
value
));
return
0
;
}
static
const
struct
snd_soc_dapm_widget
wm8753_dapm_widgets
[]
=
{
SND_SOC_DAPM_SPK
(
"Stereo Out"
,
lm4853_event
),
SND_SOC_DAPM_LINE
(
"GSM Line Out"
,
NULL
),
SND_SOC_DAPM_LINE
(
"GSM Line In"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Headset Mic"
,
NULL
),
SND_SOC_DAPM_MIC
(
"Handset Mic"
,
NULL
),
SND_SOC_DAPM_SPK
(
"Handset Spk"
,
NULL
),
};
/* example machine audio_mapnections */
static
const
struct
snd_soc_dapm_route
audio_map
[]
=
{
/* Connections to the lm4853 amp */
{
"Stereo Out"
,
NULL
,
"LOUT1"
},
{
"Stereo Out"
,
NULL
,
"ROUT1"
},
/* Connections to the GSM Module */
{
"GSM Line Out"
,
NULL
,
"MONO1"
},
{
"GSM Line Out"
,
NULL
,
"MONO2"
},
{
"RXP"
,
NULL
,
"GSM Line In"
},
{
"RXN"
,
NULL
,
"GSM Line In"
},
/* Connections to Headset */
{
"MIC1"
,
NULL
,
"Mic Bias"
},
{
"Mic Bias"
,
NULL
,
"Headset Mic"
},
/* Call Mic */
{
"MIC2"
,
NULL
,
"Mic Bias"
},
{
"MIC2N"
,
NULL
,
"Mic Bias"
},
{
"Mic Bias"
,
NULL
,
"Handset Mic"
},
/* Call Speaker */
{
"Handset Spk"
,
NULL
,
"LOUT2"
},
{
"Handset Spk"
,
NULL
,
"ROUT2"
},
/* Connect the ALC pins */
{
"ACIN"
,
NULL
,
"ACOP"
},
};
static
const
struct
snd_kcontrol_new
wm8753_neo1973_gta02_controls
[]
=
{
SOC_DAPM_PIN_SWITCH
(
"Stereo Out"
),
SOC_DAPM_PIN_SWITCH
(
"GSM Line Out"
),
SOC_DAPM_PIN_SWITCH
(
"GSM Line In"
),
SOC_DAPM_PIN_SWITCH
(
"Headset Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Handset Mic"
),
SOC_DAPM_PIN_SWITCH
(
"Handset Spk"
),
/* This has no effect, it exists only to maintain compatibility with
* existing ALSA state files.
*/
SOC_SINGLE_EXT
(
"Amp State Switch"
,
6
,
0
,
1
,
0
,
lm4853_get_state
,
lm4853_set_state
),
SOC_SINGLE_EXT
(
"Amp Spk Switch"
,
7
,
0
,
1
,
0
,
lm4853_get_spk
,
lm4853_set_spk
),
};
/*
* This is an example machine initialisation for a wm8753 connected to a
* neo1973 GTA02.
*/
static
int
neo1973_gta02_wm8753_init
(
struct
snd_soc_codec
*
codec
)
{
int
err
;
/* set up NC codec pins */
snd_soc_dapm_nc_pin
(
codec
,
"OUT3"
);
snd_soc_dapm_nc_pin
(
codec
,
"OUT4"
);
snd_soc_dapm_nc_pin
(
codec
,
"LINE1"
);
snd_soc_dapm_nc_pin
(
codec
,
"LINE2"
);
/* Add neo1973 gta02 specific widgets */
snd_soc_dapm_new_controls
(
codec
,
wm8753_dapm_widgets
,
ARRAY_SIZE
(
wm8753_dapm_widgets
));
/* add neo1973 gta02 specific controls */
err
=
snd_soc_add_controls
(
codec
,
wm8753_neo1973_gta02_controls
,
ARRAY_SIZE
(
wm8753_neo1973_gta02_controls
));
if
(
err
<
0
)
return
err
;
/* set up neo1973 gta02 specific audio path audio_map */
snd_soc_dapm_add_routes
(
codec
,
audio_map
,
ARRAY_SIZE
(
audio_map
));
/* set endpoints to default off mode */
snd_soc_dapm_disable_pin
(
codec
,
"Stereo Out"
);
snd_soc_dapm_disable_pin
(
codec
,
"GSM Line Out"
);
snd_soc_dapm_disable_pin
(
codec
,
"GSM Line In"
);
snd_soc_dapm_disable_pin
(
codec
,
"Headset Mic"
);
snd_soc_dapm_disable_pin
(
codec
,
"Handset Mic"
);
snd_soc_dapm_disable_pin
(
codec
,
"Handset Spk"
);
snd_soc_dapm_sync
(
codec
);
return
0
;
}
/*
* BT Codec DAI
*/
static
struct
snd_soc_dai
bt_dai
=
{
.
name
=
"Bluetooth"
,
.
id
=
0
,
.
playback
=
{
.
channels_min
=
1
,
.
channels_max
=
1
,
.
rates
=
SNDRV_PCM_RATE_8000
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,},
.
capture
=
{
.
channels_min
=
1
,
.
channels_max
=
1
,
.
rates
=
SNDRV_PCM_RATE_8000
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,},
};
static
struct
snd_soc_dai_link
neo1973_gta02_dai
[]
=
{
{
/* Hifi Playback - for similatious use with voice below */
.
name
=
"WM8753"
,
.
stream_name
=
"WM8753 HiFi"
,
.
cpu_dai
=
&
s3c24xx_i2s_dai
,
.
codec_dai
=
&
wm8753_dai
[
WM8753_DAI_HIFI
],
.
init
=
neo1973_gta02_wm8753_init
,
.
ops
=
&
neo1973_gta02_hifi_ops
,
},
{
/* Voice via BT */
.
name
=
"Bluetooth"
,
.
stream_name
=
"Voice"
,
.
cpu_dai
=
&
bt_dai
,
.
codec_dai
=
&
wm8753_dai
[
WM8753_DAI_VOICE
],
.
ops
=
&
neo1973_gta02_voice_ops
,
},
};
static
struct
snd_soc_card
neo1973_gta02
=
{
.
name
=
"neo1973-gta02"
,
.
platform
=
&
s3c24xx_soc_platform
,
.
dai_link
=
neo1973_gta02_dai
,
.
num_links
=
ARRAY_SIZE
(
neo1973_gta02_dai
),
};
static
struct
snd_soc_device
neo1973_gta02_snd_devdata
=
{
.
card
=
&
neo1973_gta02
,
.
codec_dev
=
&
soc_codec_dev_wm8753
,
};
static
struct
platform_device
*
neo1973_gta02_snd_device
;
static
int
__init
neo1973_gta02_init
(
void
)
{
int
ret
;
if
(
!
machine_is_neo1973_gta02
())
{
printk
(
KERN_INFO
"Only GTA02 is supported by this ASoC driver
\n
"
);
return
-
ENODEV
;
}
/* register bluetooth DAI here */
ret
=
snd_soc_register_dai
(
&
bt_dai
);
if
(
ret
)
return
ret
;
neo1973_gta02_snd_device
=
platform_device_alloc
(
"soc-audio"
,
-
1
);
if
(
!
neo1973_gta02_snd_device
)
return
-
ENOMEM
;
platform_set_drvdata
(
neo1973_gta02_snd_device
,
&
neo1973_gta02_snd_devdata
);
neo1973_gta02_snd_devdata
.
dev
=
&
neo1973_gta02_snd_device
->
dev
;
ret
=
platform_device_add
(
neo1973_gta02_snd_device
);
if
(
ret
)
{
platform_device_put
(
neo1973_gta02_snd_device
);
return
ret
;
}
/* Initialise GPIOs used by amp */
ret
=
gpio_request
(
GTA02_GPIO_HP_IN
,
"GTA02_HP_IN"
);
if
(
ret
)
{
pr_err
(
"gta02_wm8753: Failed to register GPIO %d
\n
"
,
GTA02_GPIO_HP_IN
);
goto
err_unregister_device
;
}
ret
=
gpio_direction_output
(
GTA02_GPIO_AMP_HP_IN
,
1
);
if
(
ret
)
{
pr_err
(
"gta02_wm8753: Failed to configure GPIO %d
\n
"
,
GTA02_GPIO_HP_IN
);
goto
err_free_gpio_hp_in
;
}
ret
=
gpio_request
(
GTA02_GPIO_AMP_SHUT
,
"GTA02_AMP_SHUT"
);
if
(
ret
)
{
pr_err
(
"gta02_wm8753: Failed to register GPIO %d
\n
"
,
GTA02_GPIO_AMP_SHUT
);
goto
err_free_gpio_hp_in
;
}
ret
=
gpio_direction_output
(
GTA02_GPIO_AMP_SHUT
,
1
);
if
(
ret
)
{
pr_err
(
"gta02_wm8753: Failed to configure GPIO %d
\n
"
,
GTA02_GPIO_AMP_SHUT
);
goto
err_free_gpio_amp_shut
;
}
return
0
;
err_free_gpio_amp_shut:
gpio_free
(
GTA02_GPIO_AMP_SHUT
);
err_free_gpio_hp_in:
gpio_free
(
GTA02_GPIO_HP_IN
);
err_unregister_device:
platform_device_unregister
(
neo1973_gta02_snd_device
);
return
ret
;
}
module_init
(
neo1973_gta02_init
);
static
void
__exit
neo1973_gta02_exit
(
void
)
{
snd_soc_unregister_dai
(
&
bt_dai
);
platform_device_unregister
(
neo1973_gta02_snd_device
);
gpio_free
(
GTA02_GPIO_HP_IN
);
gpio_free
(
GTA02_GPIO_AMP_SHUT
);
}
module_exit
(
neo1973_gta02_exit
);
/* Module information */
MODULE_AUTHOR
(
"Graeme Gregory, graeme@openmoko.org"
);
MODULE_DESCRIPTION
(
"ALSA SoC WM8753 Neo1973 GTA02"
);
MODULE_LICENSE
(
"GPL"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment