Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport of pcm5122 driver #24

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f87a620
ASoC: pcm512x: Add PCM512x driver
broonie Feb 6, 2014
d30d3f5
ASoC: pcm512x: More constification
broonie Feb 6, 2014
58d38d7
ASoC: pcm512x: Implement paging support
broonie Feb 7, 2014
01c6a19
ASoC: pcm512x: Implement analogue volume control
broonie Feb 7, 2014
62b4c6d
ASoC: pcm512x: Split out bus drivers
broonie Mar 7, 2014
1a49e6b
ASoC: pcm512x: Fix duplicate const warning
broonie Mar 7, 2014
cb5aea5
ASoC: pcm512x: Use CONFIG_PM_RUNTIME macro
Apr 4, 2014
a038ad6
ASoC: pcm512x: Replace usage deprecated SOC_VALUE_ENUM macro
larsclausen Apr 14, 2014
1ab994f
ASoC: pcm512x: Correct Digital Playback control names
broonie Aug 8, 2014
f0cf270
ASoC: pcm512x: Trigger auto-increment of register addresses on i2c
peda-r Dec 8, 2014
e24afa2
ASoC: pcm512x: Also support PCM514x devices
peda-r Dec 9, 2014
a1ad2a0
ASoC: pcm512x: Fix DSP program selection
peda-r Jan 8, 2015
818766a
ALSA: pcm: Add snd_interval_ranges() and snd_pcm_hw_constraint_ranges()
peda-r Jan 28, 2015
7f52815
ASoC: pcm512x: Fix spelling of register field names.
peda-r Jan 28, 2015
1cd4447
ASoC: pcm512x: Support mastering BCLK/LRCLK without using the PLL
peda-r Jan 28, 2015
45db890
ASoC: pcm512x: Support mastering BCLK/LRCLK using the PLL
peda-r Jan 28, 2015
68e26a9
ASoC: pcm512x: Avoid the PLL for the DAC clock, if possible
peda-r Jan 28, 2015
fcf1ba5
ASoC: pcm512x: Support SND_SOC_DAIFMT_CBM_CFS
peda-r Jan 28, 2015
d633162
ASoC: pcm512x: Fixup warning splat
peda-r Jan 29, 2015
74748da
ASoC: pcm512x: Use the correct range constraints for S24_LE
peda-r Jan 29, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Documentation/devicetree/bindings/sound/pcm512x.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
PCM512x audio CODECs

These devices support both I2C and SPI (configured with pin strapping
on the board).

Required properties:

- compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or
"ti,pcm5142"

- reg : the I2C address of the device for I2C, the chip select
number for SPI.

- AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the
device, as covered in bindings/regulator/regulator.txt

Optional properties:

- clocks : A clock specifier for the clock connected as SCLK. If this
is absent the device will be configured to clock from BCLK. If pll-in
and pll-out are specified in addition to a clock, the device is
configured to accept clock input on a specified gpio pin.

- pll-in, pll-out : gpio pins used to connect the pll using <1>
through <6>. The device will be configured for clock input on the
given pll-in pin and PLL output on the given pll-out pin. An
external connection from the pll-out pin to the SCLK pin is assumed.

Examples:

pcm5122: pcm5122@4c {
compatible = "ti,pcm5122";
reg = <0x4c>;

AVDD-supply = <&reg_3v3_analog>;
DVDD-supply = <&reg_1v8>;
CPVDD-supply = <&reg_3v3>;
};


pcm5142: pcm5142@4c {
compatible = "ti,pcm5142";
reg = <0x4c>;

AVDD-supply = <&reg_3v3_analog>;
DVDD-supply = <&reg_1v8>;
CPVDD-supply = <&reg_3v3>;

clocks = <&sck>;
pll-in = <3>;
pll-out = <6>;
};
12 changes: 12 additions & 0 deletions include/sound/pcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@ struct snd_pcm_hw_constraint_list {
unsigned int mask;
};

struct snd_pcm_hw_constraint_ranges {
unsigned int count;
const struct snd_interval *ranges;
unsigned int mask;
};

struct snd_pcm_hwptr_log;

struct snd_pcm_runtime {
Expand Down Expand Up @@ -791,6 +797,8 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
const struct snd_interval *b, struct snd_interval *c);
int snd_interval_list(struct snd_interval *i, unsigned int count,
const unsigned int *list, unsigned int mask);
int snd_interval_ranges(struct snd_interval *i, unsigned int count,
const struct snd_interval *list, unsigned int mask);
int snd_interval_ratnum(struct snd_interval *i,
unsigned int rats_count, struct snd_ratnum *rats,
unsigned int *nump, unsigned int *denp);
Expand All @@ -815,6 +823,10 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_list *l);
int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_ranges *r);
int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
Expand Down
85 changes: 85 additions & 0 deletions sound/core/pcm_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,60 @@ int snd_interval_list(struct snd_interval *i, unsigned int count,

EXPORT_SYMBOL(snd_interval_list);

/**
* snd_interval_ranges - refine the interval value from the list of ranges
* @i: the interval value to refine
* @count: the number of elements in the list of ranges
* @ranges: the ranges list
* @mask: the bit-mask to evaluate
*
* Refines the interval value from the list of ranges.
* When mask is non-zero, only the elements corresponding to bit 1 are
* evaluated.
*
* Return: Positive if the value is changed, zero if it's not changed, or a
* negative error code.
*/
int snd_interval_ranges(struct snd_interval *i, unsigned int count,
const struct snd_interval *ranges, unsigned int mask)
{
unsigned int k;
struct snd_interval range_union;
struct snd_interval range;

if (!count) {
snd_interval_none(i);
return -EINVAL;
}
snd_interval_any(&range_union);
range_union.min = UINT_MAX;
range_union.max = 0;
for (k = 0; k < count; k++) {
if (mask && !(mask & (1 << k)))
continue;
snd_interval_copy(&range, &ranges[k]);
if (snd_interval_refine(&range, i) < 0)
continue;
if (snd_interval_empty(&range))
continue;

if (range.min < range_union.min) {
range_union.min = range.min;
range_union.openmin = 1;
}
if (range.min == range_union.min && !range.openmin)
range_union.openmin = 0;
if (range.max > range_union.max) {
range_union.max = range.max;
range_union.openmax = 1;
}
if (range.max == range_union.max && !range.openmax)
range_union.openmax = 0;
}
return snd_interval_refine(i, &range_union);
}
EXPORT_SYMBOL(snd_interval_ranges);

static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
{
unsigned int n;
Expand Down Expand Up @@ -1301,6 +1355,37 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,

EXPORT_SYMBOL(snd_pcm_hw_constraint_list);

static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_hw_constraint_ranges *r = rule->private;
return snd_interval_ranges(hw_param_interval(params, rule->var),
r->count, r->ranges, r->mask);
}


/**
* snd_pcm_hw_constraint_ranges - apply list of range constraints to a parameter
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the list of range constraints
* @r: ranges
*
* Apply the list of range constraints to an interval parameter.
*
* Return: Zero if successful, or a negative error code on failure.
*/
int snd_pcm_hw_constraint_ranges(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
const struct snd_pcm_hw_constraint_ranges *r)
{
return snd_pcm_hw_rule_add(runtime, cond, var,
snd_pcm_hw_rule_ranges, (void *)r,
var, -1);
}
EXPORT_SYMBOL(snd_pcm_hw_constraint_ranges);

static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
Expand Down
17 changes: 17 additions & 0 deletions sound/soc/codecs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ML26124 if I2C
select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI
select SND_SOC_PCM3008
select SND_SOC_PCM512x_I2C if I2C
select SND_SOC_PCM512x_SPI if SPI_MASTER
select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SI476X if MFD_SI476X_CORE
Expand Down Expand Up @@ -283,6 +285,21 @@ config SND_SOC_OMAP_HDMI_CODEC
config SND_SOC_PCM3008
tristate

config SND_SOC_PCM512x
tristate

config SND_SOC_PCM512x_I2C
tristate "Texas Instruments PCM512x CODECs - I2C"
depends on I2C
select SND_SOC_PCM512x
select REGMAP_I2C

config SND_SOC_PCM512x_SPI
tristate "Texas Instruments PCM512x CODECs - SPI"
depends on SPI_MASTER
select SND_SOC_PCM512x
select REGMAP_SPI

config SND_SOC_RT5631
tristate

Expand Down
6 changes: 6 additions & 0 deletions sound/soc/codecs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ snd-soc-mc13783-objs := mc13783.o
snd-soc-ml26124-objs := ml26124.o
snd-soc-omap-hdmi-codec-objs := omap-hdmi.o
snd-soc-pcm3008-objs := pcm3008.o
snd-soc-pcm512x-objs := pcm512x.o
snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
snd-soc-pcm512x-spi-objs := pcm512x-spi.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
Expand Down Expand Up @@ -165,6 +168,9 @@ obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
obj-$(CONFIG_SND_SOC_OMAP_HDMI_CODEC) += snd-soc-omap-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o
obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
Expand Down
81 changes: 81 additions & 0 deletions sound/soc/codecs/pcm512x-i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>

#include "pcm512x.h"

static int pcm512x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regmap *regmap;
struct regmap_config config = pcm512x_regmap;

/* msb needs to be set to enable auto-increment of addresses */
config.read_flag_mask = 0x80;
config.write_flag_mask = 0x80;

regmap = devm_regmap_init_i2c(i2c, &config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);

return pcm512x_probe(&i2c->dev, regmap);
}

static int pcm512x_i2c_remove(struct i2c_client *i2c)
{
pcm512x_remove(&i2c->dev);
return 0;
}

static const struct i2c_device_id pcm512x_i2c_id[] = {
{ "pcm5121", },
{ "pcm5122", },
{ "pcm5141", },
{ "pcm5142", },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);

static const struct of_device_id pcm512x_of_match[] = {
{ .compatible = "ti,pcm5121", },
{ .compatible = "ti,pcm5122", },
{ .compatible = "ti,pcm5141", },
{ .compatible = "ti,pcm5142", },
{ }
};
MODULE_DEVICE_TABLE(of, pcm512x_of_match);

static struct i2c_driver pcm512x_i2c_driver = {
.probe = pcm512x_i2c_probe,
.remove = pcm512x_i2c_remove,
.id_table = pcm512x_i2c_id,
.driver = {
.name = "pcm512x",
.owner = THIS_MODULE,
.of_match_table = pcm512x_of_match,
.pm = &pcm512x_pm_ops,
},
};

module_i2c_driver(pcm512x_i2c_driver);

MODULE_DESCRIPTION("ASoC PCM512x codec driver - I2C");
MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
MODULE_LICENSE("GPL v2");
73 changes: 73 additions & 0 deletions sound/soc/codecs/pcm512x-spi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Driver for the PCM512x CODECs
*
* Author: Mark Brown <broonie@linaro.org>
* Copyright 2014 Linaro Ltd
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>

#include "pcm512x.h"

static int pcm512x_spi_probe(struct spi_device *spi)
{
struct regmap *regmap;
int ret;

regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
return ret;
}

return pcm512x_probe(&spi->dev, regmap);
}

static int pcm512x_spi_remove(struct spi_device *spi)
{
pcm512x_remove(&spi->dev);
return 0;
}

static const struct spi_device_id pcm512x_spi_id[] = {
{ "pcm5121", },
{ "pcm5122", },
{ "pcm5141", },
{ "pcm5142", },
{ },
};
MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);

static const struct of_device_id pcm512x_of_match[] = {
{ .compatible = "ti,pcm5121", },
{ .compatible = "ti,pcm5122", },
{ .compatible = "ti,pcm5141", },
{ .compatible = "ti,pcm5142", },
{ }
};
MODULE_DEVICE_TABLE(of, pcm512x_of_match);

static struct spi_driver pcm512x_spi_driver = {
.probe = pcm512x_spi_probe,
.remove = pcm512x_spi_remove,
.id_table = pcm512x_spi_id,
.driver = {
.name = "pcm512x",
.owner = THIS_MODULE,
.of_match_table = pcm512x_of_match,
.pm = &pcm512x_pm_ops,
},
};

module_spi_driver(pcm512x_spi_driver);
Loading