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:
- model - the user-visible name of this sound complex
- clocks - should contain entries matching clock names in the clock-names
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
like headphones or speakers, for details see widgets.txt
- samsung,audio-routing - a list of the connections between audio
......@@ -46,9 +43,6 @@ sound {
"IN1", "Mic Jack",
"Mic Jack", "MICBIAS";
clocks = <&clock CLK_FOUT_EPLL>, <&i2s0 CLK_I2S_RCLK_SRC>;
clock-names = "epll", "sclk_i2s";
cpu {
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)
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[] = {
/* Headphone Output Volume */
SOC_DOUBLE_R_EXT_TLV("Headphone Playback Volume", RT5665_HPL_GAIN,
......@@ -1392,6 +1402,9 @@ static const struct snd_kcontrol_new rt5665_snd_controls[] = {
RT5665_L_VOL_SFT, 15, 1, snd_soc_get_volsw,
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 */
SOC_DOUBLE_TLV("OUT Playback Volume", RT5665_LOUT, RT5665_L_VOL_SFT,
RT5665_R_VOL_SFT, 39, 1, out_vol_tlv),
......@@ -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,
RT5665_STO2_ADC_L_BST_SFT, RT5665_STO2_ADC_R_BST_SFT,
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,
rt5665->lrck[dai->id] = params_rate(params);
pre_div = rl6231_get_clk_info(rt5665->sysclk, rt5665->lrck[dai->id]);
if (pre_div < 0) {
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
rt5665->lrck[dai->id], dai->id);
return -EINVAL;
dev_warn(codec->dev, "Force using PLL");
snd_soc_codec_set_pll(codec, 0, RT5665_PLL1_S_MCLK,
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);
if (frame_size < 0) {
......@@ -4183,6 +4204,15 @@ static int rt5665_hw_params(struct snd_pcm_substream *substream,
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;
}
......@@ -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)
{
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)
return 0;
......@@ -4267,12 +4297,15 @@ static int rt5665_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id,
switch (clk_id) {
case RT5665_SCLK_S_MCLK:
reg_val |= RT5665_SCLK_SRC_MCLK;
src = RT5665_CLK_SRC_MCLK;
break;
case RT5665_SCLK_S_PLL1:
reg_val |= RT5665_SCLK_SRC_PLL1;
src = RT5665_CLK_SRC_PLL1;
break;
case RT5665_SCLK_S_RCCLK:
reg_val |= RT5665_SCLK_SRC_RCCLK;
src = RT5665_CLK_SRC_RCCLK;
break;
default:
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,
}
snd_soc_update_bits(codec, RT5665_GLB_CLK,
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_src = clk_id;
......@@ -4927,7 +4970,7 @@ MODULE_DEVICE_TABLE(of, rt5665_of_match);
#endif
#ifdef CONFIG_ACPI
static struct acpi_device_id rt5665_acpi_match[] = {
static const struct acpi_device_id rt5665_acpi_match[] = {
{"10EC5665", 0,},
{"10EC5666", 0,},
{"10EC5668", 0,},
......
......@@ -1628,6 +1628,27 @@
#define RT5665_PWR_CLK1M_PD (0x0 << 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) */
#define RT5665_EQ_SRC_DAC (0x0 << 15)
......
......@@ -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,
RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
static const struct snd_kcontrol_new rt5670_sto_adc_l1_mux =
SOC_DAPM_ENUM("Stereo1 ADC L1 source", 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 const struct snd_kcontrol_new rt5670_sto_adc_1_mux =
SOC_DAPM_ENUM("Stereo1 ADC 1 Mux", rt5670_stereo1_adc1_enum);
static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc1_enum, RT5670_STO2_ADC_MIXER,
RT5670_ADC_1_SRC_SFT, rt5670_stereo_adc1_src);
static const struct snd_kcontrol_new rt5670_sto2_adc_l1_mux =
SOC_DAPM_ENUM("Stereo2 ADC L1 source", rt5670_stereo2_adc1_enum);
static const struct snd_kcontrol_new rt5670_sto2_adc_1_mux =
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] */
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,
RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
static const struct snd_kcontrol_new rt5670_sto_adc_l2_mux =
SOC_DAPM_ENUM("Stereo1 ADC L2 source", 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 const struct snd_kcontrol_new rt5670_sto_adc_2_mux =
SOC_DAPM_ENUM("Stereo1 ADC 2 Mux", rt5670_stereo1_adc2_enum);
static SOC_ENUM_SINGLE_DECL(rt5670_stereo2_adc2_enum, RT5670_STO2_ADC_MIXER,
RT5670_ADC_2_SRC_SFT, rt5670_stereo_adc2_src);
static const struct snd_kcontrol_new rt5670_sto2_adc_l2_mux =
SOC_DAPM_ENUM("Stereo2 ADC L2 source", rt5670_stereo2_adc2_enum);
static const struct snd_kcontrol_new rt5670_sto2_adc_2_mux =
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] */
static const char * const rt5670_stereo_adc_src[] = {
......@@ -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,
&rt5670_sto1_dmic_mux),
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,
&rt5670_sto_adc_r2_mux),
&rt5670_sto_adc_2_mux),
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,
&rt5670_sto_adc_r1_mux),
&rt5670_sto_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_dmic_mux),
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,
&rt5670_sto2_adc_r2_mux),
&rt5670_sto2_adc_2_mux),
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,
&rt5670_sto2_adc_r1_mux),
&rt5670_sto2_adc_1_mux),
SND_SOC_DAPM_MUX("Stereo2 ADC LR Mux", SND_SOC_NOPM, 0, 0,
&rt5670_sto2_adc_lr_mux),
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[] = {
.formats = RT5670_FORMATS,
},
.ops = &rt5670_aif_dai_ops,
.symmetric_rates = 1,
},
{
.name = "rt5670-aif2",
......@@ -2762,6 +2753,7 @@ static struct snd_soc_dai_driver rt5670_dai[] = {
.formats = RT5670_FORMATS,
},
.ops = &rt5670_aif_dai_ops,
.symmetric_rates = 1,
},
};
......@@ -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,
const struct i2c_device_id *id)
{
......@@ -2888,6 +2891,11 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true;
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);
......
......@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/firmware.h>
#include <linux/of_device.h>
#include <linux/property.h>
#include <sound/core.h>
#include <sound/pcm.h>
......@@ -779,9 +780,7 @@ static int rt5677_set_dsp_vad(struct snd_soc_codec *codec, bool on)
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(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_bst_tlv, 0, 1200, 0);
static const DECLARE_TLV_DB_SCALE(st_vol_tlv, -4650, 150, 0);
......@@ -4624,20 +4623,13 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
struct regmap_irq_chip_data *data = rt5677->irq_data;
int irq;
if (offset >= RT5677_GPIO1 && offset <= RT5677_GPIO3) {
if ((rt5677->pdata.jd1_gpio == 1 && offset == RT5677_GPIO1) ||
(rt5677->pdata.jd1_gpio == 2 &&
offset == RT5677_GPIO2) ||
(rt5677->pdata.jd1_gpio == 3 &&
offset == RT5677_GPIO3)) {
irq = RT5677_IRQ_JD1;
} else {
return -ENXIO;
}
}
if (offset >= RT5677_GPIO4 && offset <= RT5677_GPIO6) {
if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) ||
} else if ((rt5677->pdata.jd2_gpio == 1 && offset == RT5677_GPIO4) ||
(rt5677->pdata.jd2_gpio == 2 &&
offset == RT5677_GPIO5) ||
(rt5677->pdata.jd2_gpio == 3 &&
......@@ -4653,7 +4645,6 @@ static int rt5677_to_irq(struct gpio_chip *chip, unsigned offset)
} else {
return -ENXIO;
}
}
return regmap_irq_get_virq(data, irq);
}
......@@ -5021,24 +5012,21 @@ static const struct regmap_config rt5677_regmap = {
static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", RT5677 },
{ "rt5676", RT5676 },
{ "RT5677CE:00", RT5677 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
static const struct of_device_id rt5677_of_match[] = {
{ .compatible = "realtek,rt5677", },
{ .compatible = "realtek,rt5677", RT5677 },
{ }
};
MODULE_DEVICE_TABLE(of, rt5677_of_match);
#ifdef CONFIG_ACPI
static const struct acpi_device_id rt5677_acpi_match[] = {
{ "RT5677CE", RT5677 },
{ }
};
MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match);
#endif
static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
struct device *dev)
......@@ -5148,7 +5136,6 @@ static void rt5677_free_irq(struct i2c_client *i2c)
static int rt5677_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt5677_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5677_priv *rt5677;
int ret;
unsigned int val;
......@@ -5160,16 +5147,25 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
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);
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);
else
} else {
return -EINVAL;
}
/* pow-ldo2 and reset are optional. The codec pins may be statically
* connected on the board without gpios. If the gpio device property
......
......@@ -12,7 +12,6 @@
#ifndef __RT5677_H__
#define __RT5677_H__
#include <sound/rt5677.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
......@@ -1761,6 +1760,35 @@ enum {
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 snd_soc_codec *codec;
struct rt5677_platform_data pdata;
......
......@@ -50,6 +50,7 @@ struct samsung_i2s_variant_regs {
struct samsung_i2s_dai_data {
u32 quirks;
unsigned int pcm_rates;
const struct samsung_i2s_variant_regs *i2s_variant_regs;
};
......@@ -550,7 +551,9 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
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);
/* Over-ride the other's */
......@@ -1076,13 +1079,13 @@ static const struct snd_soc_component_driver samsung_i2s_component = {
.name = "samsung-i2s",
};
#define SAMSUNG_I2S_RATES SNDRV_PCM_RATE_8000_96000
#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_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;
......@@ -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.playback.channels_min = 1;
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;
if (!sec) {
i2s->i2s_dai_drv.capture.channels_min = 1;
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;
}
return i2s;
......@@ -1132,10 +1135,19 @@ static int i2s_runtime_suspend(struct device *dev)
static int i2s_runtime_resume(struct device *dev)
{
struct i2s_dai *i2s = dev_get_drvdata(dev);
int ret;
clk_prepare_enable(i2s->clk);
if (i2s->op_clk)
clk_prepare_enable(i2s->op_clk);
ret = clk_prepare_enable(i2s->clk);
if (ret)
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_i2smod, i2s->addr + I2SMOD);
......@@ -1242,7 +1254,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
i2s_dai_data = (struct samsung_i2s_dai_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) {
dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
return -ENOMEM;
......@@ -1316,7 +1328,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
goto err_disable_clk;
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) {
dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
ret = -ENOMEM;
......@@ -1376,13 +1388,9 @@ static int samsung_i2s_probe(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);
sec_dai = pri_dai->sec_dai;
pri_dai->sec_dai = NULL;
sec_dai->pri_dai = NULL;
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
......@@ -1452,29 +1460,34 @@ static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = {
static const struct samsung_i2s_dai_data i2sv3_dai_type = {
.quirks = QUIRK_NO_MUXPSR,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv3_regs,
};
static const struct samsung_i2s_dai_data i2sv5_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_IDMA,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv3_regs,
};
static const struct samsung_i2s_dai_data i2sv6_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv6_regs,
};
static const struct samsung_i2s_dai_data i2sv7_dai_type = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
QUIRK_SUPPORTS_TDM,
.pcm_rates = SNDRV_PCM_RATE_8000_192000,
.i2s_variant_regs = &i2sv7_regs,
};
static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = {
.quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,
.pcm_rates = SNDRV_PCM_RATE_8000_96000,
.i2s_variant_regs = &i2sv5_i2s1_regs,
};
......
......@@ -325,7 +325,7 @@ static int idma_close(struct snd_pcm_substream *substream)
return 0;
}
static struct snd_pcm_ops idma_ops = {
static const struct snd_pcm_ops idma_ops = {
.open = idma_open,
.close = idma_close,
.ioctl = snd_pcm_lib_ioctl,
......@@ -399,7 +399,7 @@ void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
}
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,
.pcm_new = idma_new,
.pcm_free = idma_free,
......
......@@ -79,7 +79,7 @@ static int jive_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_soc_ops jive_ops = {
static const struct snd_soc_ops jive_ops = {
.hw_params = jive_hw_params,
};
......
......@@ -19,8 +19,8 @@ struct odroid_priv {
struct snd_soc_card card;
struct snd_soc_dai_link dai_link;
struct clk *pll;
struct clk *rclk;
struct clk *clk_i2s_bus;
struct clk *sclk_i2s;
};
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,
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)
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)
return ret;
......@@ -118,14 +123,6 @@ static int odroid_audio_probe(struct platform_device *pdev)
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");
if (ret < 0)
return ret;
......@@ -171,14 +168,31 @@ static int odroid_audio_probe(struct platform_device *pdev)
link->name = "Primary";
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);
if (ret < 0) {
dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
goto err_put_i2s_n;
goto err_put_clk_i2s;
}
return 0;
err_put_clk_i2s:
clk_put(priv->clk_i2s_bus);
err_put_sclk:
clk_put(priv->sclk_i2s);
err_put_i2s_n:
of_node_put(link->cpu_of_node);
err_put_codec_n:
......@@ -192,6 +206,8 @@ static int odroid_audio_remove(struct platform_device *pdev)
of_node_put(priv->dai_link.cpu_of_node);
odroid_put_codec_of_nodes(&priv->dai_link);
clk_put(priv->sclk_i2s);
clk_put(priv->clk_i2s_bus);
return 0;
}
......
......@@ -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");
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 */
dev_set_drvdata(&pdev->dev, pcm);
......@@ -533,7 +535,9 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
ret = PTR_ERR(pcm->pclk);
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_out[pdev->id].addr = mem_res->start + S3C_PCM_TXFIFO;
......
......@@ -27,7 +27,7 @@
#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)
#define S3C_IIS_V2_SUPPORTED
#endif
......@@ -634,11 +634,10 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai,
i2s->iis_pclk = clk_get(dev, "iis");
if (IS_ERR(i2s->iis_pclk)) {
dev_err(dev, "failed to get iis_clock\n");
iounmap(i2s->regs);
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
* process without warnings. */
......@@ -652,6 +651,15 @@ int s3c_i2sv2_probe(struct snd_soc_dai *dai,
}
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
static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
{
......
......@@ -91,6 +91,13 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s,
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
* @dev: DAI device
......
......@@ -65,26 +65,33 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
s3c2412_i2s.iis_cclk = devm_clk_get(dai->dev, "i2sclk");
if (IS_ERR(s3c2412_i2s.iis_cclk)) {
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 */
clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
clk_prepare_enable(s3c2412_i2s.iis_cclk);
s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
ret = clk_prepare_enable(s3c2412_i2s.iis_cclk);
if (ret)
goto err;
/* Configure the I2S pins (GPE0...GPE4) in correct mode */
s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
S3C_GPIO_PULL_NONE);
return 0;
err:
s3c_i2sv2_cleanup(dai, &s3c2412_i2s);
return ret;
}
static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
{
clk_disable_unprepare(s3c2412_i2s.iis_cclk);
s3c_i2sv2_cleanup(dai, &s3c2412_i2s);
return 0;
}
......
......@@ -340,6 +340,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
{
int ret;
snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out,
&s3c24xx_i2s_pcm_stereo_in);
......@@ -348,7 +349,9 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
pr_err("failed to get iis_clock\n");
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 */
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)
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.iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
......
......@@ -211,7 +211,7 @@ static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd)
return 0;
}
static struct snd_soc_ops simtec_snd_ops = {
static const struct snd_soc_ops simtec_snd_ops = {
.hw_params = simtec_hw_params,
};
......
......@@ -199,7 +199,7 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_soc_ops s3c24xx_uda134x_ops = {
static const struct snd_soc_ops s3c24xx_uda134x_ops = {
.startup = s3c24xx_uda134x_startup,
.shutdown = s3c24xx_uda134x_shutdown,
.hw_params = s3c24xx_uda134x_hw_params,
......@@ -237,7 +237,6 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)
mutex_init(&priv->clk_lock);
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, card);
......
......@@ -144,7 +144,7 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
return ret;
}
static struct snd_soc_ops smdk_spdif_ops = {
static const struct snd_soc_ops smdk_spdif_ops = {
.hw_params = smdk_hw_params,
};
......
......@@ -391,7 +391,9 @@ static int spdif_probe(struct platform_device *pdev)
ret = -ENOENT;
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");
if (IS_ERR(spdif->sclk)) {
......@@ -399,7 +401,9 @@ static int spdif_probe(struct platform_device *pdev)
ret = -ENOENT;
goto err1;
}
clk_prepare_enable(spdif->sclk);
ret = clk_prepare_enable(spdif->sclk);
if (ret)
goto err1;
/* Request S/PDIF Register's memory region */
if (!request_mem_region(mem_res->start,
......
......@@ -318,7 +318,7 @@ static const struct snd_kcontrol_new tm2_controls[] = {
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_SPK("SPK", NULL),
SND_SOC_DAPM_SPK("RCV", NULL),
......@@ -521,7 +521,7 @@ static void tm2_pm_complete(struct device *dev)
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,
.suspend = snd_soc_suspend,
.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