Commit 55eafeb5 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/rt5665', 'asoc/topic/rt5670',...

Merge remote-tracking branches 'asoc/topic/rt5665', 'asoc/topic/rt5670', 'asoc/topic/rt5677' and 'asoc/topic/samsung' into asoc-next
...@@ -7,9 +7,6 @@ Required properties: ...@@ -7,9 +7,6 @@ Required properties:
- model - the user-visible name of this sound complex - model - the user-visible name of this sound complex
- clocks - should contain entries matching clock names in the clock-names - clocks - should contain entries matching clock names in the clock-names
property property
- clock-names - should contain following entries:
- "epll" - indicating the EPLL output clock
- "i2s_rclk" - indicating the RCLK (root) clock of the I2S0 controller
- samsung,audio-widgets - this property specifies off-codec audio elements - samsung,audio-widgets - this property specifies off-codec audio elements
like headphones or speakers, for details see widgets.txt like headphones or speakers, for details see widgets.txt
- samsung,audio-routing - a list of the connections between audio - samsung,audio-routing - a list of the connections between audio
...@@ -46,9 +43,6 @@ sound { ...@@ -46,9 +43,6 @@ sound {
"IN1", "Mic Jack", "IN1", "Mic Jack",
"Mic Jack", "MICBIAS"; "Mic Jack", "MICBIAS";
clocks = <&clock CLK_FOUT_EPLL>, <&i2s0 CLK_I2S_RCLK_SRC>;
clock-names = "epll", "sclk_i2s";
cpu { cpu {
sound-dai = <&i2s0 0>; sound-dai = <&i2s0 0>;
}; };
......
/*
* linux/sound/rt5677.h -- Platform data for RT5677
*
* Copyright 2013 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_SND_RT5677_H
#define __LINUX_SND_RT5677_H
enum rt5677_dmic2_clk {
RT5677_DMIC_CLK1 = 0,
RT5677_DMIC_CLK2 = 1,
};
struct rt5677_platform_data {
/* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */
bool in1_diff;
bool in2_diff;
bool lout1_diff;
bool lout2_diff;
bool lout3_diff;
/* DMIC2 clock source selection */
enum rt5677_dmic2_clk dmic2_clk_pin;
/* configures GPIO, 0 - floating, 1 - pulldown, 2 - pullup */
u8 gpio_config[6];
/* jd1 can select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively */
unsigned int jd1_gpio;
/* jd2 and jd3 can select 0 ~ 3 as
OFF, GPIO4, GPIO5 and GPIO6 respectively */
unsigned int jd2_gpio;
unsigned int jd3_gpio;
/* Set MICBIAS1 VDD 1v8 or 3v3 */
bool micbias1_vdd_3v3;
};
#endif
...@@ -1381,6 +1381,16 @@ static void rt5665_jack_detect_handler(struct work_struct *work) ...@@ -1381,6 +1381,16 @@ static void rt5665_jack_detect_handler(struct work_struct *work)
mutex_unlock(&rt5665->calibrate_mutex); mutex_unlock(&rt5665->calibrate_mutex);
} }
static const char * const rt5665_clk_sync[] = {
"I2S1_1", "I2S1_2", "I2S2", "I2S3", "IF2 Slave", "IF3 Slave"
};
static const struct soc_enum rt5665_enum[] = {
SOC_ENUM_SINGLE(RT5665_I2S1_SDP, 11, 5, rt5665_clk_sync),
SOC_ENUM_SINGLE(RT5665_I2S2_SDP, 11, 5, rt5665_clk_sync),
SOC_ENUM_SINGLE(RT5665_I2S3_SDP, 11, 5, rt5665_clk_sync),
};
static const struct snd_kcontrol_new rt5665_snd_controls[] = { static const struct snd_kcontrol_new rt5665_snd_controls[] = {
/* Headphone Output Volume */ /* Headphone Output Volume */
SOC_DOUBLE_R_EXT_TLV("Headphone Playback Volume", RT5665_HPL_GAIN, SOC_DOUBLE_R_EXT_TLV("Headphone Playback Volume", RT5665_HPL_GAIN,
...@@ -1392,6 +1402,9 @@ static const struct snd_kcontrol_new rt5665_snd_controls[] = { ...@@ -1392,6 +1402,9 @@ static const struct snd_kcontrol_new rt5665_snd_controls[] = {
RT5665_L_VOL_SFT, 15, 1, snd_soc_get_volsw, RT5665_L_VOL_SFT, 15, 1, snd_soc_get_volsw,
rt5665_mono_vol_put, mono_vol_tlv), rt5665_mono_vol_put, mono_vol_tlv),
SOC_SINGLE_TLV("MONOVOL Playback Volume", RT5665_MONO_OUT,
RT5665_L_VOL_SFT, 39, 1, out_vol_tlv),
/* Output Volume */ /* Output Volume */
SOC_DOUBLE_TLV("OUT Playback Volume", RT5665_LOUT, RT5665_L_VOL_SFT, SOC_DOUBLE_TLV("OUT Playback Volume", RT5665_LOUT, RT5665_L_VOL_SFT,
RT5665_R_VOL_SFT, 39, 1, out_vol_tlv), RT5665_R_VOL_SFT, 39, 1, out_vol_tlv),
...@@ -1446,6 +1459,11 @@ static const struct snd_kcontrol_new rt5665_snd_controls[] = { ...@@ -1446,6 +1459,11 @@ static const struct snd_kcontrol_new rt5665_snd_controls[] = {
SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5665_STO2_ADC_BOOST, SOC_DOUBLE_TLV("STO2 ADC Boost Gain Volume", RT5665_STO2_ADC_BOOST,
RT5665_STO2_ADC_L_BST_SFT, RT5665_STO2_ADC_R_BST_SFT, RT5665_STO2_ADC_L_BST_SFT, RT5665_STO2_ADC_R_BST_SFT,
3, 0, adc_bst_tlv), 3, 0, adc_bst_tlv),
/* I2S3 CLK Source */
SOC_ENUM("I2S1 Master Clk Sel", rt5665_enum[0]),
SOC_ENUM("I2S2 Master Clk Sel", rt5665_enum[1]),
SOC_ENUM("I2S3 Master Clk Sel", rt5665_enum[2]),
}; };
/** /**
...@@ -4098,9 +4116,12 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream, ...@@ -4098,9 +4116,12 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream,
rt5665->lrck[dai->id] = params_rate(params); rt5665->lrck[dai->id] = params_rate(params);
pre_div = rl6231_get_clk_info(rt5665->sysclk, rt5665->lrck[dai->id]); pre_div = rl6231_get_clk_info(rt5665->sysclk, rt5665->lrck[dai->id]);
if (pre_div < 0) { if (pre_div < 0) {
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n", dev_warn(codec->dev, "Force using PLL");
rt5665->lrck[dai->id], dai->id); snd_soc_codec_set_pll(codec, 0, RT5665_PLL1_S_MCLK,
return -EINVAL; rt5665->sysclk, rt5665->lrck[dai->id] * 512);
snd_soc_codec_set_sysclk(codec, RT5665_SCLK_S_PLL1, 0,
rt5665->lrck[dai->id] * 512, 0);
pre_div = 1;
} }
frame_size = snd_soc_params_to_frame_size(params); frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0) { if (frame_size < 0) {
...@@ -4183,6 +4204,15 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream, ...@@ -4183,6 +4204,15 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream,
break; break;
} }
if (rt5665->master[RT5665_AIF2_1] || rt5665->master[RT5665_AIF2_2]) {
snd_soc_update_bits(codec, RT5665_I2S_M_CLK_CTRL_1,
RT5665_I2S2_M_PD_MASK, pre_div << RT5665_I2S2_M_PD_SFT);
}
if (rt5665->master[RT5665_AIF3]) {
snd_soc_update_bits(codec, RT5665_I2S_M_CLK_CTRL_1,
RT5665_I2S3_M_PD_MASK, pre_div << RT5665_I2S3_M_PD_SFT);
}
return 0; return 0;
} }
...@@ -4259,7 +4289,7 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id, ...@@ -4259,7 +4289,7 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir) int source, unsigned int freq, int dir)
{ {
struct rt5665_priv *rt5665 = snd_soc_codec_get_drvdata(codec); struct rt5665_priv *rt5665 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0; unsigned int reg_val = 0, src = 0;
if (freq == rt5665->sysclk && clk_id == rt5665->sysclk_src) if (freq == rt5665->sysclk && clk_id == rt5665->sysclk_src)
return 0; return 0;
...@@ -4267,12 +4297,15 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id, ...@@ -4267,12 +4297,15 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id,
switch (clk_id) { switch (clk_id) {
case RT5665_SCLK_S_MCLK: case RT5665_SCLK_S_MCLK:
reg_val |= RT5665_SCLK_SRC_MCLK; reg_val |= RT5665_SCLK_SRC_MCLK;
src = RT5665_CLK_SRC_MCLK;
break; break;
case RT5665_SCLK_S_PLL1: case RT5665_SCLK_S_PLL1:
reg_val |= RT5665_SCLK_SRC_PLL1; reg_val |= RT5665_SCLK_SRC_PLL1;
src = RT5665_CLK_SRC_PLL1;
break; break;
case RT5665_SCLK_S_RCCLK: case RT5665_SCLK_S_RCCLK:
reg_val |= RT5665_SCLK_SRC_RCCLK; reg_val |= RT5665_SCLK_SRC_RCCLK;
src = RT5665_CLK_SRC_RCCLK;
break; break;
default: default:
dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
...@@ -4280,6 +4313,16 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id, ...@@ -4280,6 +4313,16 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id,
} }
snd_soc_update_bits(codec, RT5665_GLB_CLK, snd_soc_update_bits(codec, RT5665_GLB_CLK,
RT5665_SCLK_SRC_MASK, reg_val); RT5665_SCLK_SRC_MASK, reg_val);
if (rt5665->master[RT5665_AIF2_1] || rt5665->master[RT5665_AIF2_2]) {
snd_soc_update_bits(codec, RT5665_I2S_M_CLK_CTRL_1,
RT5665_I2S2_SRC_MASK, src << RT5665_I2S2_SRC_SFT);
}
if (rt5665->master[RT5665_AIF3]) {
snd_soc_update_bits(codec, RT5665_I2S_M_CLK_CTRL_1,
RT5665_I2S3_SRC_MASK, src << RT5665_I2S3_SRC_SFT);
}
rt5665->sysclk = freq; rt5665->sysclk = freq;
rt5665->sysclk_src = clk_id; rt5665->sysclk_src = clk_id;
...@@ -4927,7 +4970,7 @@ MODULE_DEVICE_TABLE(of, rt5665_of_match); ...@@ -4927,7 +4970,7 @@ MODULE_DEVICE_TABLE(of, rt5665_of_match);
#endif #endif
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static struct acpi_device_id rt5665_acpi_match[] = { static const struct acpi_device_id rt5665_acpi_match[] = {
{"10EC5665", 0,}, {"10EC5665", 0,},
{"10EC5666", 0,}, {"10EC5666", 0,},
{"10EC5668", 0,}, {"10EC5668", 0,},
......
...@@ -1628,6 +1628,27 @@ ...@@ -1628,6 +1628,27 @@
#define RT5665_PWR_CLK1M_PD (0x0 << 8) #define RT5665_PWR_CLK1M_PD (0x0 << 8)
#define RT5665_PWR_CLK1M_PU (0x1 << 8) #define RT5665_PWR_CLK1M_PU (0x1 << 8)
/* I2S Master Mode Clock Control 1 (0x00a0) */
#define RT5665_CLK_SRC_MCLK (0x0)
#define RT5665_CLK_SRC_PLL1 (0x1)
#define RT5665_CLK_SRC_RCCLK (0x2)
#define RT5665_I2S_PD_1 (0x0)
#define RT5665_I2S_PD_2 (0x1)
#define RT5665_I2S_PD_3 (0x2)
#define RT5665_I2S_PD_4 (0x3)
#define RT5665_I2S_PD_6 (0x4)
#define RT5665_I2S_PD_8 (0x5)
#define RT5665_I2S_PD_12 (0x6)
#define RT5665_I2S_PD_16 (0x7)
#define RT5665_I2S2_SRC_MASK (0x3 << 12)
#define RT5665_I2S2_SRC_SFT 12
#define RT5665_I2S2_M_PD_MASK (0x7 << 8)
#define RT5665_I2S2_M_PD_SFT 8
#define RT5665_I2S3_SRC_MASK (0x3 << 4)
#define RT5665_I2S3_SRC_SFT 4
#define RT5665_I2S3_M_PD_MASK (0x7 << 0)
#define RT5665_I2S3_M_PD_SFT 0
/* EQ Control 1 (0x00b0) */ /* EQ Control 1 (0x00b0) */
#define RT5665_EQ_SRC_DAC (0x0 << 15) #define RT5665_EQ_SRC_DAC (0x0 << 15)
......
...@@ -1151,20 +1151,15 @@ static const char * const rt5670_stereo_adc1_src[] = { ...@@ -1151,20 +1151,15 @@ static const char * const rt5670_stereo_adc1_src[] = {
static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER, static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc1_enum, RT5670_STO1_ADC_MIXER,
RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
static const struct snd_kcontrol_new rt5670_sto_adc_l1_mux = static const struct snd_kcontrol_new rt5670_sto_adc_1_mux =
SOC_DAPM_ENUM("Stereo1 ADC L1 source", rt5670_stereo1_adc1_enum); SOC_DAPM_ENUM("Stereo1 ADC 1 Mux", rt5670_stereo1_adc1_enum);
static const struct snd_kcontrol_new rt5670_sto_adc_r1_mux =
SOC_DAPM_ENUM("Stereo1 ADC R1 source", rt5670_stereo1_adc1_enum);
static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER, static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER,
RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src); RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
static const struct snd_kcontrol_new rt5670_sto2_adc_l1_mux = static const struct snd_kcontrol_new rt5670_sto2_adc_1_mux =
SOC_DAPM_ENUM("Stereo2 ADC L1 source", rt5670_stereo2_adc1_enum); SOC_DAPM_ENUM("Stereo2 ADC 1 Mux", rt5670_stereo2_adc1_enum);
static const struct snd_kcontrol_new rt5670_sto2_adc_r1_mux =
SOC_DAPM_ENUM("Stereo2 ADC R1 source", rt5670_stereo2_adc1_enum);
/* MX-27 MX-26 [11] */ /* MX-27 MX-26 [11] */
static const char * const rt5670_stereo_adc2_src[] = { static const char * const rt5670_stereo_adc2_src[] = {
...@@ -1174,20 +1169,15 @@ static const char * const rt5670_stereo_adc2_src[] = { ...@@ -1174,20 +1169,15 @@ static const char * const rt5670_stereo_adc2_src[] = {
static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER, static SOC_ENUM_SINGLE_DECL(rt5670_stereo1_adc2_enum, RT5670_STO1_ADC_MIXER,
RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
static const struct snd_kcontrol_new rt5670_sto_adc_l2_mux = static const struct snd_kcontrol_new rt5670_sto_adc_2_mux =
SOC_DAPM_ENUM("Stereo1 ADC L2 source", rt5670_stereo1_adc2_enum); SOC_DAPM_ENUM("Stereo1 ADC 2 Mux", rt5670_stereo1_adc2_enum);
static const struct snd_kcontrol_new rt5670_sto_adc_r2_mux =
SOC_DAPM_ENUM("Stereo1 ADC R2 source", rt5670_stereo1_adc2_enum);
static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER, static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER,
RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src); RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
static const struct snd_kcontrol_new rt5670_sto2_adc_l2_mux = static const struct snd_kcontrol_new rt5670_sto2_adc_2_mux =
SOC_DAPM_ENUM("Stereo2 ADC L2 source", rt5670_stereo2_adc2_enum); SOC_DAPM_ENUM("Stereo2 ADC 2 Mux", rt5670_stereo2_adc2_enum);
static const struct snd_kcontrol_new rt5670_sto2_adc_r2_mux =
SOC_DAPM_ENUM("Stereo2 ADC R2 source", rt5670_stereo2_adc2_enum);
/* MX-27 MX26 [10] */ /* MX-27 MX26 [10] */
static const char * const rt5670_stereo_adc_src[] = { static const char * const rt5670_stereo_adc_src[] = {
...@@ -1642,23 +1632,23 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { ...@@ -1642,23 +1632,23 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = {
SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto1_dmic_mux), &rt5670_sto1_dmic_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo1 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto_adc_l2_mux), &rt5670_sto_adc_2_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo1 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto_adc_r2_mux), &rt5670_sto_adc_2_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo1 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto_adc_l1_mux), &rt5670_sto_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo1 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto_adc_r1_mux), &rt5670_sto_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_dmic_mux), &rt5670_sto2_dmic_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 ADC L2 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_l2_mux), &rt5670_sto2_adc_2_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 ADC R2 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_r2_mux), &rt5670_sto2_adc_2_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 ADC L1 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_l1_mux), &rt5670_sto2_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 ADC R1 Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_r1_mux), &rt5670_sto2_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_lr_mux), &rt5670_sto2_adc_lr_mux),
SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MUX("Mono DMIC L Mux", SND_SOC_NOPM, 0, 0,
...@@ -2743,6 +2733,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = { ...@@ -2743,6 +2733,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
.formats = RT5670_FORMATS, .formats = RT5670_FORMATS,
}, },
.ops = &rt5670_aif_dai_ops, .ops = &rt5670_aif_dai_ops,
.symmetric_rates = 1,
}, },
{ {
.name = "rt5670-aif2", .name = "rt5670-aif2",
...@@ -2762,6 +2753,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = { ...@@ -2762,6 +2753,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
.formats = RT5670_FORMATS, .formats = RT5670_FORMATS,
}, },
.ops = &rt5670_aif_dai_ops, .ops = &rt5670_aif_dai_ops,
.symmetric_rates = 1,
}, },
}; };
...@@ -2859,6 +2851,17 @@ static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = { ...@@ -2859,6 +2851,17 @@ static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = {
{} {}
}; };
static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode3[] = {
{
.ident = "Dell Venue 8 Pro 5855",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5855"),
},
},
{}
};
static int rt5670_i2c_probe(struct i2c_client *i2c, static int rt5670_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -2888,6 +2891,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, ...@@ -2888,6 +2891,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P; rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true; rt5670->pdata.dev_gpio = true;
rt5670->pdata.jd_mode = 2; rt5670->pdata.jd_mode = 2;
} else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode3)) {
rt5670->pdata.dmic_en = true;
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true;
rt5670->pdata.jd_mode = 3;
} }
rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/property.h> #include <linux/property.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -779,9 +780,7 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on) ...@@ -779,9 +780,7 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
return 0; return 0;
} }
static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0); static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0);
...@@ -4624,35 +4623,27 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset) ...@@ -4624,35 +4623,27 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
struct regmap_irq_chip_data *data = rt5677->irq_data; struct regmap_irq_chip_data *data = rt5677->irq_data;
int irq; int irq;
if (offset >= RT5677_GPIO1 && offset <= RT5677_GPIO3) { if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) ||
if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) || (rt5677->pdata.jd1_gpio == 2 &&
(rt5677->pdata.jd1_gpio == 2 && offset == RT5677_GPIO2) ||
offset == RT5677_GPIO2) || (rt5677->pdata.jd1_gpio == 3 &&
(rt5677->pdata.jd1_gpio == 3 && offset == RT5677_GPIO3)) {
offset == RT5677_GPIO3)) { irq = RT5677_IRQ_JD1;
irq = RT5677_IRQ_JD1; } else if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) ||
} else { (rt5677->pdata.jd2_gpio == 2 &&
return -ENXIO; offset == RT5677_GPIO5) ||
} (rt5677->pdata.jd2_gpio == 3 &&
} offset == RT5677_GPIO6)) {
irq = RT5677_IRQ_JD2;
if (offset >= RT5677_GPIO4 && offset <= RT5677_GPIO6) { } else if ((rt5677->pdata.jd3_gpio == 1 &&
if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) || offset == RT5677_GPIO4) ||
(rt5677->pdata.jd2_gpio == 2 && (rt5677->pdata.jd3_gpio == 2 &&
offset == RT5677_GPIO5) || offset == RT5677_GPIO5) ||
(rt5677->pdata.jd2_gpio == 3 && (rt5677->pdata.jd3_gpio == 3 &&
offset == RT5677_GPIO6)) { offset == RT5677_GPIO6)) {
irq = RT5677_IRQ_JD2; irq = RT5677_IRQ_JD3;
} else if ((rt5677->pdata.jd3_gpio == 1 && } else {
offset == RT5677_GPIO4) || return -ENXIO;
(rt5677->pdata.jd3_gpio == 2 &&
offset == RT5677_GPIO5) ||
(rt5677->pdata.jd3_gpio == 3 &&
offset == RT5677_GPIO6)) {
irq = RT5677_IRQ_JD3;
} else {
return -ENXIO;
}
} }
return regmap_irq_get_virq(data, irq); return regmap_irq_get_virq(data, irq);
...@@ -5021,24 +5012,21 @@ static const struct regmap_config rt5677_regmap = { ...@@ -5021,24 +5012,21 @@ static const struct regmap_config rt5677_regmap = {
static const struct i2c_device_id rt5677_i2c_id[] = { static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", RT5677 }, { "rt5677", RT5677 },
{ "rt5676", RT5676 }, { "rt5676", RT5676 },
{ "RT5677CE:00", RT5677 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
static const struct of_device_id rt5677_of_match[] = { static const struct of_device_id rt5677_of_match[] = {
{ .compatible = "realtek,rt5677", }, { .compatible = "realtek,rt5677", RT5677 },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, rt5677_of_match); MODULE_DEVICE_TABLE(of, rt5677_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id rt5677_acpi_match[] = { static const struct acpi_device_id rt5677_acpi_match[] = {
{ "RT5677CE", RT5677 }, { "RT5677CE", RT5677 },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match);
#endif
static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677, static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
struct device *dev) struct device *dev)
...@@ -5148,7 +5136,6 @@ static void rt5677_free_irq(struct i2c_client *i2c) ...@@ -5148,7 +5136,6 @@ static void rt5677_free_irq(struct i2c_client *i2c)
static int rt5677_i2c_probe(struct i2c_client *i2c, static int rt5677_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct rt5677_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5677_priv *rt5677; struct rt5677_priv *rt5677;
int ret; int ret;
unsigned int val; unsigned int val;
...@@ -5160,16 +5147,25 @@ static int rt5677_i2c_probe(struct i2c_client *i2c, ...@@ -5160,16 +5147,25 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt5677); i2c_set_clientdata(i2c, rt5677);
rt5677->type = id->driver_data; if (i2c->dev.of_node) {
const struct of_device_id *match_id;
match_id = of_match_device(rt5677_of_match, &i2c->dev);
if (match_id)
rt5677->type = (enum rt5677_type)match_id->data;
if (pdata)
rt5677->pdata = *pdata;
else if (i2c->dev.of_node)
rt5677_read_device_properties(rt5677, &i2c->dev); rt5677_read_device_properties(rt5677, &i2c->dev);
else if (ACPI_HANDLE(&i2c->dev)) } else if (ACPI_HANDLE(&i2c->dev)) {
const struct acpi_device_id *acpi_id;
acpi_id = acpi_match_device(rt5677_acpi_match, &i2c->dev);
if (acpi_id)
rt5677->type = (enum rt5677_type)acpi_id->driver_data;
rt5677_read_acpi_properties(rt5677, &i2c->dev); rt5677_read_acpi_properties(rt5677, &i2c->dev);
else } else {
return -EINVAL; return -EINVAL;
}
/* pow-ldo2 and reset are optional. The codec pins may be statically /* pow-ldo2 and reset are optional. The codec pins may be statically
* connected on the board without gpios. If the gpio device property * connected on the board without gpios. If the gpio device property
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef __RT5677_H__ #ifndef __RT5677_H__
#define __RT5677_H__ #define __RT5677_H__
#include <sound/rt5677.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
...@@ -1761,6 +1760,35 @@ enum { ...@@ -1761,6 +1760,35 @@ enum {
RT5677_I2S4_SOURCE = (0x1 << 18), RT5677_I2S4_SOURCE = (0x1 << 18),
}; };
enum rt5677_dmic2_clk {
RT5677_DMIC_CLK1 = 0,
RT5677_DMIC_CLK2 = 1,
};
struct rt5677_platform_data {
/* IN1/IN2/LOUT1/LOUT2/LOUT3 can optionally be differential */
bool in1_diff;
bool in2_diff;
bool lout1_diff;
bool lout2_diff;
bool lout3_diff;
/* DMIC2 clock source selection */
enum rt5677_dmic2_clk dmic2_clk_pin;
/* configures GPIO, 0 - floating, 1 - pulldown, 2 - pullup */
u8 gpio_config[6];
/* jd1 can select 0 ~ 3 as OFF, GPIO1, GPIO2 and GPIO3 respectively */
unsigned int jd1_gpio;
/* jd2 and jd3 can select 0 ~ 3 as
OFF, GPIO4, GPIO5 and GPIO6 respectively */
unsigned int jd2_gpio;
unsigned int jd3_gpio;
/* Set MICBIAS1 VDD 1v8 or 3v3 */
bool micbias1_vdd_3v3;
};
struct rt5677_priv { struct rt5677_priv {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct rt5677_platform_data pdata; struct rt5677_platform_data pdata;
......
...@@ -50,6 +50,7 @@ struct samsung_i2s_variant_regs { ...@@ -50,6 +50,7 @@ struct samsung_i2s_variant_regs {
struct samsung_i2s_dai_data { struct samsung_i2s_dai_data {
u32 quirks; u32 quirks;
unsigned int pcm_rates;
const struct samsung_i2s_variant_regs *i2s_variant_regs; const struct samsung_i2s_variant_regs *i2s_variant_regs;
}; };
...@@ -550,7 +551,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, ...@@ -550,7 +551,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
goto err; goto err;
} }
clk_prepare_enable(i2s->op_clk); ret = clk_prepare_enable(i2s->op_clk);
if (ret)
goto err;
i2s->rclk_srcrate = clk_get_rate(i2s->op_clk); i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
/* Over-ride the other's */ /* Over-ride the other's */
...@@ -1076,13 +1079,13 @@ static const struct snd_soc_component_driver samsung_i2s_component = { ...@@ -1076,13 +1079,13 @@ static const struct snd_soc_component_driver samsung_i2s_component = {
.name = "samsung-i2s", .name = "samsung-i2s",
}; };
#define SAMSUNG_I2S_RATES SNDRV_PCM_RATE_8000_96000
#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ #define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE) SNDRV_PCM_FMTBIT_S24_LE)
static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev,
const struct samsung_i2s_dai_data *i2s_dai_data,
bool sec)
{ {
struct i2s_dai *i2s; struct i2s_dai *i2s;
...@@ -1101,13 +1104,13 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) ...@@ -1101,13 +1104,13 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->i2s_dai_drv.resume = i2s_resume; i2s->i2s_dai_drv.resume = i2s_resume;
i2s->i2s_dai_drv.playback.channels_min = 1; i2s->i2s_dai_drv.playback.channels_min = 1;
i2s->i2s_dai_drv.playback.channels_max = 2; i2s->i2s_dai_drv.playback.channels_max = 2;
i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES; i2s->i2s_dai_drv.playback.rates = i2s_dai_data->pcm_rates;
i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS; i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
if (!sec) { if (!sec) {
i2s->i2s_dai_drv.capture.channels_min = 1; i2s->i2s_dai_drv.capture.channels_min = 1;
i2s->i2s_dai_drv.capture.channels_max = 2; i2s->i2s_dai_drv.capture.channels_max = 2;
i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES; i2s->i2s_dai_drv.capture.rates = i2s_dai_data->pcm_rates;
i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS; i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
} }
return i2s; return i2s;
...@@ -1132,10 +1135,19 @@ static int i2s_runtime_suspend(struct device *dev) ...@@ -1132,10 +1135,19 @@ static int i2s_runtime_suspend(struct device *dev)
static int i2s_runtime_resume(struct device *dev) static int i2s_runtime_resume(struct device *dev)
{ {
struct i2s_dai *i2s = dev_get_drvdata(dev); struct i2s_dai *i2s = dev_get_drvdata(dev);
int ret;
clk_prepare_enable(i2s->clk); ret = clk_prepare_enable(i2s->clk);
if (i2s->op_clk) if (ret)
clk_prepare_enable(i2s->op_clk); return ret;
if (i2s->op_clk) {
ret = clk_prepare_enable(i2s->op_clk);
if (ret) {
clk_disable_unprepare(i2s->clk);
return ret;
}
}
writel(i2s->suspend_i2scon, i2s->addr + I2SCON); writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
writel(i2s->suspend_i2smod, i2s->addr + I2SMOD); writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
...@@ -1242,7 +1254,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) ...@@ -1242,7 +1254,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
i2s_dai_data = (struct samsung_i2s_dai_data *) i2s_dai_data = (struct samsung_i2s_dai_data *)
platform_get_device_id(pdev)->driver_data; platform_get_device_id(pdev)->driver_data;
pri_dai = i2s_alloc_dai(pdev, false); pri_dai = i2s_alloc_dai(pdev, i2s_dai_data, false);
if (!pri_dai) { if (!pri_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_pri\n"); dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
return -ENOMEM; return -ENOMEM;
...@@ -1316,7 +1328,7 @@ static int samsung_i2s_probe(struct platform_device *pdev) ...@@ -1316,7 +1328,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
goto err_disable_clk; goto err_disable_clk;
if (quirks & QUIRK_SEC_DAI) { if (quirks & QUIRK_SEC_DAI) {
sec_dai = i2s_alloc_dai(pdev, true); sec_dai = i2s_alloc_dai(pdev, i2s_dai_data, true);
if (!sec_dai) { if (!sec_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_sec\n"); dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1376,13 +1388,9 @@ static int samsung_i2s_probe(struct platform_device *pdev) ...@@ -1376,13 +1388,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
static int samsung_i2s_remove(struct platform_device *pdev) static int samsung_i2s_remove(struct platform_device *pdev)
{ {
struct i2s_dai *pri_dai, *sec_dai; struct i2s_dai *pri_dai;
pri_dai = dev_get_drvdata(&pdev->dev); pri_dai = dev_get_drvdata(&pdev->dev);
sec_dai = pri_dai->sec_dai;
pri_dai->sec_dai = NULL;
sec_dai->pri_dai = NULL;
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
...@@ -1452,29 +1460,34 @@ static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = { ...@@ -1452,29 +1460,34 @@ static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = {
static const struct samsung_i2s_dai_data i2sv3_dai_type = { static const struct samsung_i2s_dai_data i2sv3_dai_type = {
.quirks = QUIRK_NO_MUXPSR, .quirks = QUIRK_NO_MUXPSR,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv3_regs, .i2s_variant_regs = &i2sv3_regs,
}; };
static const struct samsung_i2s_dai_data i2sv5_dai_type = { static const struct samsung_i2s_dai_data i2sv5_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_IDMA, QUIRK_SUPPORTS_IDMA,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv3_regs, .i2s_variant_regs = &i2sv3_regs,
}; };
static const struct samsung_i2s_dai_data i2sv6_dai_type = { static const struct samsung_i2s_dai_data i2sv6_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA, QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv6_regs, .i2s_variant_regs = &i2sv6_regs,
}; };
static const struct samsung_i2s_dai_data i2sv7_dai_type = { static const struct samsung_i2s_dai_data i2sv7_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_TDM, QUIRK_SUPPORTS_TDM,
.pcm_rates = SNDRV_PCM_RATE_8000_192000,
.i2s_variant_regs = &i2sv7_regs, .i2s_variant_regs = &i2sv7_regs,
}; };
static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = { static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR, .quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv5_i2s1_regs, .i2s_variant_regs = &i2sv5_i2s1_regs,
}; };
......
...@@ -325,7 +325,7 @@ static int idma_close(struct snd_pcm_substream *substream) ...@@ -325,7 +325,7 @@ static int idma_close(struct snd_pcm_substream *substream)
return 0; return 0;
} }
static struct snd_pcm_ops idma_ops = { static const struct snd_pcm_ops idma_ops = {
.open = idma_open, .open = idma_open,
.close = idma_close, .close = idma_close,
.ioctl = snd_pcm_lib_ioctl, .ioctl = snd_pcm_lib_ioctl,
...@@ -399,7 +399,7 @@ void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr) ...@@ -399,7 +399,7 @@ void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
} }
EXPORT_SYMBOL_GPL(idma_reg_addr_init); EXPORT_SYMBOL_GPL(idma_reg_addr_init);
static struct snd_soc_platform_driver asoc_idma_platform = { static const struct snd_soc_platform_driver asoc_idma_platform = {
.ops = &idma_ops, .ops = &idma_ops,
.pcm_new = idma_new, .pcm_new = idma_new,
.pcm_free = idma_free, .pcm_free = idma_free,
......
...@@ -79,7 +79,7 @@ static int jive_hw_params(struct snd_pcm_substream *substream, ...@@ -79,7 +79,7 @@ static int jive_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static struct snd_soc_ops jive_ops = { static const struct snd_soc_ops jive_ops = {
.hw_params = jive_hw_params, .hw_params = jive_hw_params,
}; };
......
...@@ -19,8 +19,8 @@ struct odroid_priv { ...@@ -19,8 +19,8 @@ struct odroid_priv {
struct snd_soc_card card; struct snd_soc_card card;
struct snd_soc_dai_link dai_link; struct snd_soc_dai_link dai_link;
struct clk *pll; struct clk *clk_i2s_bus;
struct clk *rclk; struct clk *sclk_i2s;
}; };
static int odroid_card_startup(struct snd_pcm_substream *substream) static int odroid_card_startup(struct snd_pcm_substream *substream)
...@@ -58,13 +58,18 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream, ...@@ -58,13 +58,18 @@ static int odroid_card_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
ret = clk_set_rate(priv->pll, pll_freq + 1); ret = clk_set_rate(priv->clk_i2s_bus, pll_freq / 2 + 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
rclk_freq = params_rate(params) * 256 * 4; /*
* We add 1 to the rclk_freq value in order to avoid too low clock
* frequency values due to the EPLL output frequency not being exact
* multiple of the audio sampling rate.
*/
rclk_freq = params_rate(params) * 256 + 1;
ret = clk_set_rate(priv->rclk, rclk_freq); ret = clk_set_rate(priv->sclk_i2s, rclk_freq);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -118,14 +123,6 @@ static int odroid_audio_probe(struct platform_device *pdev) ...@@ -118,14 +123,6 @@ static int odroid_audio_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(card, priv); snd_soc_card_set_drvdata(card, priv);
priv->pll = devm_clk_get(dev, "epll");
if (IS_ERR(priv->pll))
return PTR_ERR(priv->pll);
priv->rclk = devm_clk_get(dev, "i2s_rclk");
if (IS_ERR(priv->rclk))
return PTR_ERR(priv->rclk);
ret = snd_soc_of_parse_card_name(card, "model"); ret = snd_soc_of_parse_card_name(card, "model");
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -171,14 +168,31 @@ static int odroid_audio_probe(struct platform_device *pdev) ...@@ -171,14 +168,31 @@ static int odroid_audio_probe(struct platform_device *pdev)
link->name = "Primary"; link->name = "Primary";
link->stream_name = link->name; link->stream_name = link->name;
priv->sclk_i2s = of_clk_get_by_name(link->cpu_of_node, "i2s_opclk1");
if (IS_ERR(priv->sclk_i2s)) {
ret = PTR_ERR(priv->sclk_i2s);
goto err_put_i2s_n;
}
priv->clk_i2s_bus = of_clk_get_by_name(link->cpu_of_node, "iis");
if (IS_ERR(priv->clk_i2s_bus)) {
ret = PTR_ERR(priv->clk_i2s_bus);
goto err_put_sclk;
}
ret = devm_snd_soc_register_card(dev, card); ret = devm_snd_soc_register_card(dev, card);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "snd_soc_register_card() failed: %d\n", ret); dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
goto err_put_i2s_n; goto err_put_clk_i2s;
} }
return 0; return 0;
err_put_clk_i2s:
clk_put(priv->clk_i2s_bus);
err_put_sclk:
clk_put(priv->sclk_i2s);
err_put_i2s_n: err_put_i2s_n:
of_node_put(link->cpu_of_node); of_node_put(link->cpu_of_node);
err_put_codec_n: err_put_codec_n:
...@@ -192,6 +206,8 @@ static int odroid_audio_remove(struct platform_device *pdev) ...@@ -192,6 +206,8 @@ static int odroid_audio_remove(struct platform_device *pdev)
of_node_put(priv->dai_link.cpu_of_node); of_node_put(priv->dai_link.cpu_of_node);
odroid_put_codec_of_nodes(&priv->dai_link); odroid_put_codec_of_nodes(&priv->dai_link);
clk_put(priv->sclk_i2s);
clk_put(priv->clk_i2s_bus);
return 0; return 0;
} }
......
...@@ -522,7 +522,9 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) ...@@ -522,7 +522,9 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to get audio-bus clock\n"); dev_err(&pdev->dev, "failed to get audio-bus clock\n");
return PTR_ERR(pcm->cclk); return PTR_ERR(pcm->cclk);
} }
clk_prepare_enable(pcm->cclk); ret = clk_prepare_enable(pcm->cclk);
if (ret)
return ret;
/* record our pcm structure for later use in the callbacks */ /* record our pcm structure for later use in the callbacks */
dev_set_drvdata(&pdev->dev, pcm); dev_set_drvdata(&pdev->dev, pcm);
...@@ -533,7 +535,9 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev) ...@@ -533,7 +535,9 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
ret = PTR_ERR(pcm->pclk); ret = PTR_ERR(pcm->pclk);
goto err_dis_cclk; goto err_dis_cclk;
} }
clk_prepare_enable(pcm->pclk); ret = clk_prepare_enable(pcm->pclk);
if (ret)
goto err_dis_cclk;
s3c_pcm_stereo_in[pdev->id].addr = mem_res->start + S3C_PCM_RXFIFO; s3c_pcm_stereo_in[pdev->id].addr = mem_res->start + S3C_PCM_RXFIFO;
s3c_pcm_stereo_out[pdev->id].addr = mem_res->start + S3C_PCM_TXFIFO; s3c_pcm_stereo_out[pdev->id].addr = mem_res->start + S3C_PCM_TXFIFO;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#undef S3C_IIS_V2_SUPPORTED #undef S3C_IIS_V2_SUPPORTED
#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \ #if defined(CONFIG_CPU_S3C2412) \
|| defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_CPU_S5PV210) || defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_CPU_S5PV210)
#define S3C_IIS_V2_SUPPORTED #define S3C_IIS_V2_SUPPORTED
#endif #endif
...@@ -634,11 +634,10 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, ...@@ -634,11 +634,10 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai,
i2s->iis_pclk = clk_get(dev, "iis"); i2s->iis_pclk = clk_get(dev, "iis");
if (IS_ERR(i2s->iis_pclk)) { if (IS_ERR(i2s->iis_pclk)) {
dev_err(dev, "failed to get iis_clock\n"); dev_err(dev, "failed to get iis_clock\n");
iounmap(i2s->regs);
return -ENOENT; return -ENOENT;
} }
clk_enable(i2s->iis_pclk); clk_prepare_enable(i2s->iis_pclk);
/* Mark ourselves as in TXRX mode so we can run through our cleanup /* Mark ourselves as in TXRX mode so we can run through our cleanup
* process without warnings. */ * process without warnings. */
...@@ -652,6 +651,15 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai, ...@@ -652,6 +651,15 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai,
} }
EXPORT_SYMBOL_GPL(s3c_i2sv2_probe); EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
void s3c_i2sv2_cleanup(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s)
{
clk_disable_unprepare(i2s->iis_pclk);
clk_put(i2s->iis_pclk);
i2s->iis_pclk = NULL;
}
EXPORT_SYMBOL_GPL(s3c_i2sv2_cleanup);
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
{ {
......
...@@ -91,6 +91,13 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, ...@@ -91,6 +91,13 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s, struct s3c_i2sv2_info *i2s,
unsigned long base); unsigned long base);
/**
* s3c_i2sv2_cleanup - cleanup resources allocated in s3c_i2sv2_probe
* @dai: The ASoC DAI structure supplied to the original probe.
* @i2s: Our local i2s structure to fill in.
*/
extern void s3c_i2sv2_cleanup(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s);
/** /**
* s3c_i2sv2_register_component - register component and dai with soc core * s3c_i2sv2_register_component - register component and dai with soc core
* @dev: DAI device * @dev: DAI device
......
...@@ -65,26 +65,33 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) ...@@ -65,26 +65,33 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk"); s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk");
if (IS_ERR(s3c2412_i2s.iis_cclk)) { if (IS_ERR(s3c2412_i2s.iis_cclk)) {
pr_err("failed to get i2sclk clock\n"); pr_err("failed to get i2sclk clock\n");
return PTR_ERR(s3c2412_i2s.iis_cclk); ret = PTR_ERR(s3c2412_i2s.iis_cclk);
goto err;
} }
/* Set MPLL as the source for IIS CLK */ /* Set MPLL as the source for IIS CLK */
clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
clk_prepare_enable(s3c2412_i2s.iis_cclk); ret = clk_prepare_enable(s3c2412_i2s.iis_cclk);
if (ret)
s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; goto err;
/* Configure the I2S pins (GPE0...GPE4) in correct mode */ /* Configure the I2S pins (GPE0...GPE4) in correct mode */
s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
S3C_GPIO_PULL_NONE); S3C_GPIO_PULL_NONE);
return 0; return 0;
err:
s3c_i2sv2_cleanup(dai, &s3c2412_i2s);
return ret;
} }
static int s3c2412_i2s_remove(struct snd_soc_dai *dai) static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
{ {
clk_disable_unprepare(s3c2412_i2s.iis_cclk); clk_disable_unprepare(s3c2412_i2s.iis_cclk);
s3c_i2sv2_cleanup(dai, &s3c2412_i2s);
return 0; return 0;
} }
......
...@@ -340,6 +340,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); ...@@ -340,6 +340,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
{ {
int ret;
snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out, snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out,
&s3c24xx_i2s_pcm_stereo_in); &s3c24xx_i2s_pcm_stereo_in);
...@@ -348,7 +349,9 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai) ...@@ -348,7 +349,9 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
pr_err("failed to get iis_clock\n"); pr_err("failed to get iis_clock\n");
return PTR_ERR(s3c24xx_i2s.iis_clk); return PTR_ERR(s3c24xx_i2s.iis_clk);
} }
clk_prepare_enable(s3c24xx_i2s.iis_clk); ret = clk_prepare_enable(s3c24xx_i2s.iis_clk);
if (ret)
return ret;
/* Configure the I2S pins (GPE0...GPE4) in correct mode */ /* Configure the I2S pins (GPE0...GPE4) in correct mode */
s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
...@@ -377,7 +380,11 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) ...@@ -377,7 +380,11 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
{ {
clk_prepare_enable(s3c24xx_i2s.iis_clk); int ret;
ret = clk_prepare_enable(s3c24xx_i2s.iis_clk);
if (ret)
return ret;
writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); writel(s3c24xx_i2s.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
......
...@@ -211,7 +211,7 @@ static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd) ...@@ -211,7 +211,7 @@ static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd)
return 0; return 0;
} }
static struct snd_soc_ops simtec_snd_ops = { static const struct snd_soc_ops simtec_snd_ops = {
.hw_params = simtec_hw_params, .hw_params = simtec_hw_params,
}; };
......
...@@ -199,7 +199,7 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, ...@@ -199,7 +199,7 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static struct snd_soc_ops s3c24xx_uda134x_ops = { static const struct snd_soc_ops s3c24xx_uda134x_ops = {
.startup = s3c24xx_uda134x_startup, .startup = s3c24xx_uda134x_startup,
.shutdown = s3c24xx_uda134x_shutdown, .shutdown = s3c24xx_uda134x_shutdown,
.hw_params = s3c24xx_uda134x_hw_params, .hw_params = s3c24xx_uda134x_hw_params,
...@@ -237,7 +237,6 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev) ...@@ -237,7 +237,6 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)
mutex_init(&priv->clk_lock); mutex_init(&priv->clk_lock);
card->dev = &pdev->dev; card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, priv); snd_soc_card_set_drvdata(card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, card); ret = devm_snd_soc_register_card(&pdev->dev, card);
......
...@@ -144,7 +144,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream, ...@@ -144,7 +144,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
return ret; return ret;
} }
static struct snd_soc_ops smdk_spdif_ops = { static const struct snd_soc_ops smdk_spdif_ops = {
.hw_params = smdk_hw_params, .hw_params = smdk_hw_params,
}; };
......
...@@ -391,7 +391,9 @@ static int spdif_probe(struct platform_device *pdev) ...@@ -391,7 +391,9 @@ static int spdif_probe(struct platform_device *pdev)
ret = -ENOENT; ret = -ENOENT;
goto err0; goto err0;
} }
clk_prepare_enable(spdif->pclk); ret = clk_prepare_enable(spdif->pclk);
if (ret)
goto err0;
spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif"); spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif");
if (IS_ERR(spdif->sclk)) { if (IS_ERR(spdif->sclk)) {
...@@ -399,7 +401,9 @@ static int spdif_probe(struct platform_device *pdev) ...@@ -399,7 +401,9 @@ static int spdif_probe(struct platform_device *pdev)
ret = -ENOENT; ret = -ENOENT;
goto err1; goto err1;
} }
clk_prepare_enable(spdif->sclk); ret = clk_prepare_enable(spdif->sclk);
if (ret)
goto err1;
/* Request S/PDIF Register's memory region */ /* Request S/PDIF Register's memory region */
if (!request_mem_region(mem_res->start, if (!request_mem_region(mem_res->start,
......
...@@ -318,7 +318,7 @@ static const struct snd_kcontrol_new tm2_controls[] = { ...@@ -318,7 +318,7 @@ static const struct snd_kcontrol_new tm2_controls[] = {
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
}; };
const struct snd_soc_dapm_widget tm2_dapm_widgets[] = { static const struct snd_soc_dapm_widget tm2_dapm_widgets[] = {
SND_SOC_DAPM_HP("HP", NULL), SND_SOC_DAPM_HP("HP", NULL),
SND_SOC_DAPM_SPK("SPK", NULL), SND_SOC_DAPM_SPK("SPK", NULL),
SND_SOC_DAPM_SPK("RCV", NULL), SND_SOC_DAPM_SPK("RCV", NULL),
...@@ -521,7 +521,7 @@ static void tm2_pm_complete(struct device *dev) ...@@ -521,7 +521,7 @@ static void tm2_pm_complete(struct device *dev)
tm2_start_sysclk(card); tm2_start_sysclk(card);
} }
const struct dev_pm_ops tm2_pm_ops = { static const struct dev_pm_ops tm2_pm_ops = {
.prepare = tm2_pm_prepare, .prepare = tm2_pm_prepare,
.suspend = snd_soc_suspend, .suspend = snd_soc_suspend,
.resume = snd_soc_resume, .resume = snd_soc_resume,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment