[alsa-devel] [PATCH v2] ARM: pxa: add support for Raumfeld DDX
This new product features a STA32x codec. To support it, some rework of the regulator initialization for the Raumfeld platform is necessary.
Signed-off-by: Daniel Mack zonque@gmail.com Cc: Mark Brown <broonie at opensource.wolfsonmicro.com> Cc: Liam Girdwood <lrg at ti.com> Cc: Eric Miao <eric.y.miao at gmail.com> Cc: Sven Neumann s.neumann@raumfeld.com Cc: Johannes Stezenbach js@sig21.net ---
v2 of this patch has clocking fixes and superseeds the older version.
As there are more changes in sound/soc than in arch/arm, I think it should best go through Mark's AsoC tree.
arch/arm/mach-pxa/raumfeld.c | 119 +++++++++++++++++--- sound/soc/pxa/Kconfig | 2 + sound/soc/pxa/raumfeld.c | 247 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 336 insertions(+), 32 deletions(-)
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 7856fe4..22366ff 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -850,7 +850,7 @@ struct regulator_init_data audio_va_initdata = { }, };
-static struct fixed_voltage_config audio_va_config = { +static struct fixed_voltage_config cs4270_va_config = { .supply_name = "audio_va", .microvolts = 5000000, .gpio = GPIO_AUDIO_VA_ENABLE, @@ -859,47 +859,114 @@ static struct fixed_voltage_config audio_va_config = { .init_data = &audio_va_initdata, };
-static struct platform_device audio_va_device = { +static struct platform_device cs4270_va_device = { .name = "reg-fixed-voltage", .id = 0, .dev = { - .platform_data = &audio_va_config, + .platform_data = &cs4270_va_config, }, };
/* Dummy supplies for Codec's VD/VLC */
-static struct regulator_consumer_supply audio_dummy_supplies[] = { +static struct regulator_consumer_supply cs4270_dummy_supplies[] = { REGULATOR_SUPPLY("vd", "0-0048"), REGULATOR_SUPPLY("vlc", "0-0048"), };
-struct regulator_init_data audio_dummy_initdata = { - .consumer_supplies = audio_dummy_supplies, - .num_consumer_supplies = ARRAY_SIZE(audio_dummy_supplies), +struct regulator_init_data cs4270_dummy_initdata = { + .consumer_supplies = cs4270_dummy_supplies, + .num_consumer_supplies = ARRAY_SIZE(cs4270_dummy_supplies), .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, };
-static struct fixed_voltage_config audio_dummy_config = { - .supply_name = "audio_vd", +static struct fixed_voltage_config cs4270_dummy_config = { + .supply_name = "cs4270_vd", .microvolts = 3300000, .gpio = -1, - .init_data = &audio_dummy_initdata, + .init_data = &cs4270_dummy_initdata, };
-static struct platform_device audio_supply_dummy_device = { +static struct platform_device cs4270_supply_dummy_device = { .name = "reg-fixed-voltage", .id = 1, .dev = { - .platform_data = &audio_dummy_config, + .platform_data = &cs4270_dummy_config, }, };
-static struct platform_device *audio_regulator_devices[] = { - &audio_va_device, - &audio_supply_dummy_device, +static struct platform_device *cs4270_regulator_devices[] = { + &cs4270_va_device, + &cs4270_supply_dummy_device, +}; + +/* Fixed regulator for sta32x Vdda supply + * 0-001a maps to the sta32x codec devname (derived from i2c bus num + addr) + */ + +static struct regulator_consumer_supply sta32x_va_consumer_supply = + REGULATOR_SUPPLY("Vdda", "0-001a"); + +struct regulator_init_data sta32x_va_initdata = { + .consumer_supplies = &sta32x_va_consumer_supply, + .num_consumer_supplies = 1, + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config sta32x_va_config = { + .supply_name = "audio_va", + .microvolts = 3300000, + .gpio = GPIO_AUDIO_VA_ENABLE, + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &sta32x_va_initdata, +}; + +static struct platform_device sta32x_va_device = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &sta32x_va_config, + }, +}; + +/* Dummy supplies for sta32x codec's Vdd3/Vcc */ + +static struct regulator_consumer_supply sta32x_dummy_supplies[] = { + REGULATOR_SUPPLY("Vdd3", "0-001a"), + REGULATOR_SUPPLY("Vcc", "0-001a"), +}; + +struct regulator_init_data sta32x_dummy_initdata = { + .consumer_supplies = sta32x_dummy_supplies, + .num_consumer_supplies = ARRAY_SIZE(sta32x_dummy_supplies), + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, +}; + +static struct fixed_voltage_config sta32x_dummy_config = { + .supply_name = "audio_vd", + .microvolts = 3300000, + .gpio = -1, + .init_data = &sta32x_dummy_initdata, +}; + +static struct platform_device sta32x_supply_dummy_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &sta32x_dummy_config, + }, +}; + +static struct platform_device *sta32x_regulator_devices[] = { + &sta32x_va_device, + &sta32x_supply_dummy_device, };
/** @@ -948,6 +1015,11 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { .addr = 0x48, };
+static struct i2c_board_info raumfeld_ddx_i2c_board_info __initdata = { + .type = "sta326", + .addr = 0x1a, +}; + static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, }; @@ -987,7 +1059,10 @@ static void __init raumfeld_audio_init(void) else gpio_direction_output(GPIO_MCLK_RESET, 1);
- platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices)); + if ((system_rev & 0xff00) == 0x0400) + platform_add_devices(ARRAY_AND_SIZE(sta32x_regulator_devices)); + else + platform_add_devices(ARRAY_AND_SIZE(cs4270_regulator_devices)); }
static void __init raumfeld_common_init(void) @@ -1060,7 +1135,11 @@ static void __init raumfeld_connector_init(void) { pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_connector_pin_config)); spi_register_board_info(ARRAY_AND_SIZE(connector_spi_devices)); - i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1); + + if ((system_rev & 0xff00) == 0x0400) + i2c_register_board_info(0, &raumfeld_ddx_i2c_board_info, 1); + else + i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
platform_device_register(&smc91x_device);
@@ -1072,7 +1151,11 @@ static void __init raumfeld_speaker_init(void) { pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_speaker_pin_config)); spi_register_board_info(ARRAY_AND_SIZE(speaker_spi_devices)); - i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1); + + if ((system_rev & 0xff00) == 0x0400) + i2c_register_board_info(0, &raumfeld_ddx_i2c_board_info, 1); + else + i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
platform_device_register(&smc91x_device); platform_device_register(&rotary_encoder_device); diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 33ebc46..e6db56a 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -152,6 +152,8 @@ config SND_SOC_RAUMFELD select SND_PXA_SOC_SSP select SND_SOC_CS4270 select SND_SOC_AK4104 + select SND_SOC_STA32X + select SND_SOC_WM8782 help Say Y if you want to add support for SoC audio on Raumfeld devices
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 1a591f1..7d4f1bf 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c @@ -21,6 +21,7 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/soc.h>
#include <asm/mach-types.h> @@ -225,6 +226,175 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .hw_params = raumfeld_ak4104_hw_params, };
+/* STA32X */ +static int raumfeld_sta32x_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + /* fixed MCLK of 11.2896MHz */ + snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_176400); + + /* PXA DMA cannot do zero extend for 24bit samples, + * thus only 16bit (two samples packet into 32bit word) + * or 32bit samples are possible + */ + snd_pcm_hw_constraint_mask64(substream->runtime, + SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE); + + /* we have a fixed MCLK, set it here so ALSA knows + * the supported sample rates and can resample if necessary + */ + return snd_soc_dai_set_sysclk(codec_dai, 0, 11289600, 0); +} + +static void raumfeld_sta32x_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + + /* set freq to 0 to enable all possible codec sample rates */ + snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); +} + +static int raumfeld_sta32x_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; + unsigned int fmt, clk = 0; + int ret = 0; + + // fixed MCLK of 11.2896MHz + switch (params_rate(params)) { + case 44100: + case 88200: + case 176400: + clk = 11289600; + break; + default: + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S32_BE: + /* this enables network mode for 2 * 32bit samples */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 0, 2, 32); + if (ret < 0) + return ret; + break; + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + /* this disables network mode */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 0, 16); + if (ret < 0) + return ret; + break; + default: + return -EINVAL; + } + + fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + + /* setup the CODEC DAI */ + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0); + if (ret < 0) + return ret; + + /* setup the CPU DAI */ + ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, clk, 1); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops raumfeld_sta32x_ops = { + .startup = raumfeld_sta32x_startup, + .shutdown = raumfeld_sta32x_shutdown, + .hw_params = raumfeld_sta32x_hw_params, +}; + +/* WM8782 */ +static int raumfeld_wm8782_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; + unsigned int fmt, clk = 0; + int ret = 0; + + // fixed MCLK of 11.2896MHz + switch (params_rate(params)) { + case 44100: + clk = 11289600; + break; + default: + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + break; + default: + return -EINVAL; + } + + fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + + /* setup the CPU DAI */ + ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, clk, 1); + if (ret < 0) + return ret; + + return 0; +} + +static struct snd_soc_ops raumfeld_wm8782_ops = { + .hw_params = raumfeld_wm8782_hw_params, +}; + #define DAI_LINK_CS4270 \ { \ .name = "CS4270", \ @@ -247,6 +417,28 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .codec_name = "spi0.0", \ }
+#define DAI_LINK_STA32X \ +{ \ + .name = "STA32X", \ + .stream_name = "Playback", \ + .cpu_dai_name = "pxa-ssp-dai.0", \ + .platform_name = "pxa-pcm-audio", \ + .codec_dai_name = "STA32X", \ + .ops = &raumfeld_sta32x_ops, \ + .codec_name = "sta32x.0-001a", \ +} + +#define DAI_LINK_WM8782 \ +{ \ + .name = "wm8782", \ + .stream_name = "wm8782", \ + .cpu_dai_name = "pxa-ssp-dai.0", \ + .platform_name = "pxa-pcm-audio", \ + .codec_dai_name = "wm8782", \ + .codec_name = "wm8782.0", \ + .ops = &raumfeld_wm8782_ops, \ +} + static struct snd_soc_dai_link snd_soc_raumfeld_connector_dai[] = { DAI_LINK_CS4270, @@ -258,6 +450,12 @@ static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] = DAI_LINK_CS4270, };
+static struct snd_soc_dai_link snd_soc_raumfeld_ddx_dai[] = +{ + DAI_LINK_STA32X, + DAI_LINK_WM8782, +}; + static struct snd_soc_card snd_soc_raumfeld_connector = { .name = "Raumfeld Connector", .dai_link = snd_soc_raumfeld_connector_dai, @@ -274,7 +472,15 @@ static struct snd_soc_card snd_soc_raumfeld_speaker = { .resume_pre = raumfeld_analog_resume, };
-static struct platform_device *raumfeld_audio_device; +static struct snd_soc_card snd_soc_raumfeld_ddx = { + .name = "Raumfeld DDX", + .dai_link = snd_soc_raumfeld_ddx_dai, + .num_links = ARRAY_SIZE(snd_soc_raumfeld_ddx_dai), + .suspend_post = raumfeld_analog_suspend, + .resume_pre = raumfeld_analog_resume, +}; + +static struct platform_device *raumfeld_audio_device, *wm8782_device;
static int __init raumfeld_audio_init(void) { @@ -284,26 +490,39 @@ static int __init raumfeld_audio_init(void) !machine_is_raumfeld_connector()) return 0;
- max9486_client = i2c_new_device(i2c_get_adapter(0), - &max9486_hwmon_info); + if ((system_rev & 0xff00) == 0x0400) { + wm8782_device = platform_device_alloc("wm8782", 0); + if (!wm8782_device) + return -ENOMEM;
- if (!max9486_client) - return -ENOMEM; + platform_device_add(wm8782_device); + } else { + max9486_client = i2c_new_device(i2c_get_adapter(0), + &max9486_hwmon_info); + + if (!max9486_client) + return -ENOMEM;
- set_max9485_clk(MAX9485_MCLK_FREQ_122880); + set_max9485_clk(MAX9485_MCLK_FREQ_122880); + }
- /* Register analog device */ + /* Register audio device */ raumfeld_audio_device = platform_device_alloc("soc-audio", 0); if (!raumfeld_audio_device) return -ENOMEM;
- if (machine_is_raumfeld_speaker()) + if ((system_rev & 0xff00) == 0x0400) platform_set_drvdata(raumfeld_audio_device, - &snd_soc_raumfeld_speaker); - - if (machine_is_raumfeld_connector()) - platform_set_drvdata(raumfeld_audio_device, - &snd_soc_raumfeld_connector); + &snd_soc_raumfeld_ddx); + else { + if (machine_is_raumfeld_speaker()) + platform_set_drvdata(raumfeld_audio_device, + &snd_soc_raumfeld_speaker); + + if (machine_is_raumfeld_connector()) + platform_set_drvdata(raumfeld_audio_device, + &snd_soc_raumfeld_connector); + }
ret = platform_device_add(raumfeld_audio_device); if (ret < 0) @@ -317,8 +536,8 @@ static void __exit raumfeld_audio_exit(void) { raumfeld_enable_audio(false);
+ platform_device_unregister(wm8782_device); platform_device_unregister(raumfeld_audio_device); - i2c_unregister_device(max9486_client);
gpio_free(GPIO_MCLK_RESET);
Ping? Does anyone want me to split this into two pieces maybe?
Daniel
On 11/08/2011 11:16 AM, Daniel Mack wrote:
This new product features a STA32x codec. To support it, some rework of the regulator initialization for the Raumfeld platform is necessary.
Signed-off-by: Daniel Mack zonque@gmail.com Cc: Mark Brown <broonie at opensource.wolfsonmicro.com> Cc: Liam Girdwood <lrg at ti.com> Cc: Eric Miao <eric.y.miao at gmail.com> Cc: Sven Neumann s.neumann@raumfeld.com Cc: Johannes Stezenbach js@sig21.net
v2 of this patch has clocking fixes and superseeds the older version.
As there are more changes in sound/soc than in arch/arm, I think it should best go through Mark's AsoC tree.
arch/arm/mach-pxa/raumfeld.c | 119 +++++++++++++++++--- sound/soc/pxa/Kconfig | 2 + sound/soc/pxa/raumfeld.c | 247 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 336 insertions(+), 32 deletions(-)
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 7856fe4..22366ff 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -850,7 +850,7 @@ struct regulator_init_data audio_va_initdata = { }, };
-static struct fixed_voltage_config audio_va_config = { +static struct fixed_voltage_config cs4270_va_config = { .supply_name = "audio_va", .microvolts = 5000000, .gpio = GPIO_AUDIO_VA_ENABLE, @@ -859,47 +859,114 @@ static struct fixed_voltage_config audio_va_config = { .init_data = &audio_va_initdata, };
-static struct platform_device audio_va_device = { +static struct platform_device cs4270_va_device = { .name = "reg-fixed-voltage", .id = 0, .dev = {
.platform_data = &audio_va_config,
},.platform_data = &cs4270_va_config,
};
/* Dummy supplies for Codec's VD/VLC */
-static struct regulator_consumer_supply audio_dummy_supplies[] = { +static struct regulator_consumer_supply cs4270_dummy_supplies[] = { REGULATOR_SUPPLY("vd", "0-0048"), REGULATOR_SUPPLY("vlc", "0-0048"), };
-struct regulator_init_data audio_dummy_initdata = {
- .consumer_supplies = audio_dummy_supplies,
- .num_consumer_supplies = ARRAY_SIZE(audio_dummy_supplies),
+struct regulator_init_data cs4270_dummy_initdata = {
- .consumer_supplies = cs4270_dummy_supplies,
- .num_consumer_supplies = ARRAY_SIZE(cs4270_dummy_supplies), .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, },
};
-static struct fixed_voltage_config audio_dummy_config = {
- .supply_name = "audio_vd",
+static struct fixed_voltage_config cs4270_dummy_config = {
- .supply_name = "cs4270_vd", .microvolts = 3300000, .gpio = -1,
- .init_data = &audio_dummy_initdata,
- .init_data = &cs4270_dummy_initdata,
};
-static struct platform_device audio_supply_dummy_device = { +static struct platform_device cs4270_supply_dummy_device = { .name = "reg-fixed-voltage", .id = 1, .dev = {
.platform_data = &audio_dummy_config,
},.platform_data = &cs4270_dummy_config,
};
-static struct platform_device *audio_regulator_devices[] = {
- &audio_va_device,
- &audio_supply_dummy_device,
+static struct platform_device *cs4270_regulator_devices[] = {
- &cs4270_va_device,
- &cs4270_supply_dummy_device,
+};
+/* Fixed regulator for sta32x Vdda supply
- 0-001a maps to the sta32x codec devname (derived from i2c bus num + addr)
- */
+static struct regulator_consumer_supply sta32x_va_consumer_supply =
- REGULATOR_SUPPLY("Vdda", "0-001a");
+struct regulator_init_data sta32x_va_initdata = {
- .consumer_supplies = &sta32x_va_consumer_supply,
- .num_consumer_supplies = 1,
- .constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
+};
+static struct fixed_voltage_config sta32x_va_config = {
- .supply_name = "audio_va",
- .microvolts = 3300000,
- .gpio = GPIO_AUDIO_VA_ENABLE,
- .enable_high = 1,
- .enabled_at_boot = 0,
- .init_data = &sta32x_va_initdata,
+};
+static struct platform_device sta32x_va_device = {
- .name = "reg-fixed-voltage",
- .id = 0,
- .dev = {
.platform_data = &sta32x_va_config,
- },
+};
+/* Dummy supplies for sta32x codec's Vdd3/Vcc */
+static struct regulator_consumer_supply sta32x_dummy_supplies[] = {
- REGULATOR_SUPPLY("Vdd3", "0-001a"),
- REGULATOR_SUPPLY("Vcc", "0-001a"),
+};
+struct regulator_init_data sta32x_dummy_initdata = {
- .consumer_supplies = sta32x_dummy_supplies,
- .num_consumer_supplies = ARRAY_SIZE(sta32x_dummy_supplies),
- .constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
+};
+static struct fixed_voltage_config sta32x_dummy_config = {
- .supply_name = "audio_vd",
- .microvolts = 3300000,
- .gpio = -1,
- .init_data = &sta32x_dummy_initdata,
+};
+static struct platform_device sta32x_supply_dummy_device = {
- .name = "reg-fixed-voltage",
- .id = 1,
- .dev = {
.platform_data = &sta32x_dummy_config,
- },
+};
+static struct platform_device *sta32x_regulator_devices[] = {
- &sta32x_va_device,
- &sta32x_supply_dummy_device,
};
/** @@ -948,6 +1015,11 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { .addr = 0x48, };
+static struct i2c_board_info raumfeld_ddx_i2c_board_info __initdata = {
- .type = "sta326",
- .addr = 0x1a,
+};
static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, }; @@ -987,7 +1059,10 @@ static void __init raumfeld_audio_init(void) else gpio_direction_output(GPIO_MCLK_RESET, 1);
- platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices));
- if ((system_rev & 0xff00) == 0x0400)
platform_add_devices(ARRAY_AND_SIZE(sta32x_regulator_devices));
- else
platform_add_devices(ARRAY_AND_SIZE(cs4270_regulator_devices));
}
static void __init raumfeld_common_init(void) @@ -1060,7 +1135,11 @@ static void __init raumfeld_connector_init(void) { pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_connector_pin_config)); spi_register_board_info(ARRAY_AND_SIZE(connector_spi_devices));
- i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
if ((system_rev & 0xff00) == 0x0400)
i2c_register_board_info(0, &raumfeld_ddx_i2c_board_info, 1);
else
i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
platform_device_register(&smc91x_device);
@@ -1072,7 +1151,11 @@ static void __init raumfeld_speaker_init(void) { pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_speaker_pin_config)); spi_register_board_info(ARRAY_AND_SIZE(speaker_spi_devices));
- i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
if ((system_rev & 0xff00) == 0x0400)
i2c_register_board_info(0, &raumfeld_ddx_i2c_board_info, 1);
else
i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
platform_device_register(&smc91x_device); platform_device_register(&rotary_encoder_device);
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 33ebc46..e6db56a 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -152,6 +152,8 @@ config SND_SOC_RAUMFELD select SND_PXA_SOC_SSP select SND_SOC_CS4270 select SND_SOC_AK4104
- select SND_SOC_STA32X
- select SND_SOC_WM8782 help Say Y if you want to add support for SoC audio on Raumfeld devices
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 1a591f1..7d4f1bf 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c @@ -21,6 +21,7 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <sound/pcm.h> +#include <sound/pcm_params.h> #include <sound/soc.h>
#include <asm/mach-types.h> @@ -225,6 +226,175 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .hw_params = raumfeld_ak4104_hw_params, };
+/* STA32X */ +static int raumfeld_sta32x_startup(struct snd_pcm_substream *substream) +{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- /* fixed MCLK of 11.2896MHz */
- snd_pcm_hw_constraint_mask64(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_176400);
- /* PXA DMA cannot do zero extend for 24bit samples,
* thus only 16bit (two samples packet into 32bit word)
* or 32bit samples are possible
*/
- snd_pcm_hw_constraint_mask64(substream->runtime,
SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE);
- /* we have a fixed MCLK, set it here so ALSA knows
* the supported sample rates and can resample if necessary
*/
- return snd_soc_dai_set_sysclk(codec_dai, 0, 11289600, 0);
+}
+static void raumfeld_sta32x_shutdown(struct snd_pcm_substream *substream) +{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- /* set freq to 0 to enable all possible codec sample rates */
- snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
+}
+static int raumfeld_sta32x_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;
- unsigned int fmt, clk = 0;
- int ret = 0;
- // fixed MCLK of 11.2896MHz
- switch (params_rate(params)) {
- case 44100:
- case 88200:
- case 176400:
clk = 11289600;
break;
- default:
return -EINVAL;
- }
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S32_LE:
- case SNDRV_PCM_FORMAT_S32_BE:
/* this enables network mode for 2 * 32bit samples */
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 0, 2, 32);
if (ret < 0)
return ret;
break;
- case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FORMAT_S16_BE:
/* this disables network mode */
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 0, 16);
if (ret < 0)
return ret;
break;
- default:
return -EINVAL;
- }
- fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
- /* setup the CODEC DAI */
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0);
- if (ret < 0)
return ret;
- /* setup the CPU DAI */
- ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, clk, 1);
- if (ret < 0)
return ret;
- return 0;
+}
+static struct snd_soc_ops raumfeld_sta32x_ops = {
- .startup = raumfeld_sta32x_startup,
- .shutdown = raumfeld_sta32x_shutdown,
- .hw_params = raumfeld_sta32x_hw_params,
+};
+/* WM8782 */ +static int raumfeld_wm8782_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;
- unsigned int fmt, clk = 0;
- int ret = 0;
- // fixed MCLK of 11.2896MHz
- switch (params_rate(params)) {
- case 44100:
clk = 11289600;
break;
- default:
return -EINVAL;
- }
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FORMAT_S16_BE:
break;
- default:
return -EINVAL;
- }
- fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
- /* setup the CPU DAI */
- ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
- if (ret < 0)
return ret;
- ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, clk, 1);
- if (ret < 0)
return ret;
- return 0;
+}
+static struct snd_soc_ops raumfeld_wm8782_ops = {
- .hw_params = raumfeld_wm8782_hw_params,
+};
#define DAI_LINK_CS4270 \ { \ .name = "CS4270", \ @@ -247,6 +417,28 @@ static struct snd_soc_ops raumfeld_ak4104_ops = { .codec_name = "spi0.0", \ }
+#define DAI_LINK_STA32X \ +{ \
- .name = "STA32X", \
- .stream_name = "Playback", \
- .cpu_dai_name = "pxa-ssp-dai.0", \
- .platform_name = "pxa-pcm-audio", \
- .codec_dai_name = "STA32X", \
- .ops = &raumfeld_sta32x_ops, \
- .codec_name = "sta32x.0-001a", \
+}
+#define DAI_LINK_WM8782 \ +{ \
- .name = "wm8782", \
- .stream_name = "wm8782", \
- .cpu_dai_name = "pxa-ssp-dai.0", \
- .platform_name = "pxa-pcm-audio", \
- .codec_dai_name = "wm8782", \
- .codec_name = "wm8782.0", \
- .ops = &raumfeld_wm8782_ops, \
+}
static struct snd_soc_dai_link snd_soc_raumfeld_connector_dai[] = { DAI_LINK_CS4270, @@ -258,6 +450,12 @@ static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] = DAI_LINK_CS4270, };
+static struct snd_soc_dai_link snd_soc_raumfeld_ddx_dai[] = +{
- DAI_LINK_STA32X,
- DAI_LINK_WM8782,
+};
static struct snd_soc_card snd_soc_raumfeld_connector = { .name = "Raumfeld Connector", .dai_link = snd_soc_raumfeld_connector_dai, @@ -274,7 +472,15 @@ static struct snd_soc_card snd_soc_raumfeld_speaker = { .resume_pre = raumfeld_analog_resume, };
-static struct platform_device *raumfeld_audio_device; +static struct snd_soc_card snd_soc_raumfeld_ddx = {
- .name = "Raumfeld DDX",
- .dai_link = snd_soc_raumfeld_ddx_dai,
- .num_links = ARRAY_SIZE(snd_soc_raumfeld_ddx_dai),
- .suspend_post = raumfeld_analog_suspend,
- .resume_pre = raumfeld_analog_resume,
+};
+static struct platform_device *raumfeld_audio_device, *wm8782_device;
static int __init raumfeld_audio_init(void) { @@ -284,26 +490,39 @@ static int __init raumfeld_audio_init(void) !machine_is_raumfeld_connector()) return 0;
- max9486_client = i2c_new_device(i2c_get_adapter(0),
&max9486_hwmon_info);
- if ((system_rev & 0xff00) == 0x0400) {
wm8782_device = platform_device_alloc("wm8782", 0);
if (!wm8782_device)
return -ENOMEM;
- if (!max9486_client)
return -ENOMEM;
platform_device_add(wm8782_device);
- } else {
max9486_client = i2c_new_device(i2c_get_adapter(0),
&max9486_hwmon_info);
if (!max9486_client)
return -ENOMEM;
- set_max9485_clk(MAX9485_MCLK_FREQ_122880);
set_max9485_clk(MAX9485_MCLK_FREQ_122880);
- }
- /* Register analog device */
- /* Register audio device */ raumfeld_audio_device = platform_device_alloc("soc-audio", 0); if (!raumfeld_audio_device) return -ENOMEM;
- if (machine_is_raumfeld_speaker())
- if ((system_rev & 0xff00) == 0x0400) platform_set_drvdata(raumfeld_audio_device,
&snd_soc_raumfeld_speaker);
- if (machine_is_raumfeld_connector())
platform_set_drvdata(raumfeld_audio_device,
&snd_soc_raumfeld_connector);
&snd_soc_raumfeld_ddx);
else {
if (machine_is_raumfeld_speaker())
platform_set_drvdata(raumfeld_audio_device,
&snd_soc_raumfeld_speaker);
if (machine_is_raumfeld_connector())
platform_set_drvdata(raumfeld_audio_device,
&snd_soc_raumfeld_connector);
}
ret = platform_device_add(raumfeld_audio_device); if (ret < 0)
@@ -317,8 +536,8 @@ static void __exit raumfeld_audio_exit(void) { raumfeld_enable_audio(false);
- platform_device_unregister(wm8782_device); platform_device_unregister(raumfeld_audio_device);
i2c_unregister_device(max9486_client);
gpio_free(GPIO_MCLK_RESET);
participants (1)
-
Daniel Mack