mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![Lars-Peter Clausen](/assets/img/avatar_default.png)
The devices from the ADAU17X1 family all have a MCLK clock input which supplies the master clock for the device. The master clock is used as the input clock for the PLL. Currently the MCLK rate as well as the desired PLL output frequency need to be supplied by calling snd_soc_dai_set_pll() form a machine driver. Add support for specifying the MCLK using the common clock framework. In addition to that also automatically configure the PLL to a suitable rate if the master clock was provided using the CCW. This allows to use the CODEC driver without any special configuration requirements from the machine driver. While the PLL output frequency can be configured over a (more or less) continuous range the narrowness of the range and the other constraints of the clocking tree usually only result in two output frequencies that will actually be chosen. One for 44.1kHz based rates and one for 48kHz based rates, these are the rates that the automatic PLL configuration will use. For the rare case where a non-standard setup is required a machine driver can disable the auto-configuration and configure a custom frequency using the existing mechanisms. If the common clock framework is not enabled clk_get() will return NULL and the driver will function as before and the clock rate needs to be configured manually. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
88 lines
2 KiB
C
88 lines
2 KiB
C
/*
|
|
* Driver for ADAU1361/ADAU1461/ADAU1761/ADAU1961 codec
|
|
*
|
|
* Copyright 2014 Analog Devices Inc.
|
|
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
|
*
|
|
* Licensed under the GPL-2.
|
|
*/
|
|
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/module.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <sound/soc.h>
|
|
|
|
#include "adau1761.h"
|
|
|
|
static void adau1761_spi_switch_mode(struct device *dev)
|
|
{
|
|
struct spi_device *spi = to_spi_device(dev);
|
|
|
|
/*
|
|
* To get the device into SPI mode CLATCH has to be pulled low three
|
|
* times. Do this by issuing three dummy reads.
|
|
*/
|
|
spi_w8r8(spi, 0x00);
|
|
spi_w8r8(spi, 0x00);
|
|
spi_w8r8(spi, 0x00);
|
|
}
|
|
|
|
static int adau1761_spi_probe(struct spi_device *spi)
|
|
{
|
|
const struct spi_device_id *id = spi_get_device_id(spi);
|
|
struct regmap_config config;
|
|
|
|
if (!id)
|
|
return -EINVAL;
|
|
|
|
config = adau1761_regmap_config;
|
|
config.val_bits = 8;
|
|
config.reg_bits = 24;
|
|
config.read_flag_mask = 0x1;
|
|
|
|
return adau1761_probe(&spi->dev,
|
|
devm_regmap_init_spi(spi, &config),
|
|
id->driver_data, adau1761_spi_switch_mode);
|
|
}
|
|
|
|
static int adau1761_spi_remove(struct spi_device *spi)
|
|
{
|
|
adau17x1_remove(&spi->dev);
|
|
return 0;
|
|
}
|
|
|
|
static const struct spi_device_id adau1761_spi_id[] = {
|
|
{ "adau1361", ADAU1361 },
|
|
{ "adau1461", ADAU1761 },
|
|
{ "adau1761", ADAU1761 },
|
|
{ "adau1961", ADAU1361 },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(spi, adau1761_spi_id);
|
|
|
|
#if defined(CONFIG_OF)
|
|
static const struct of_device_id adau1761_spi_dt_ids[] = {
|
|
{ .compatible = "adi,adau1361", },
|
|
{ .compatible = "adi,adau1461", },
|
|
{ .compatible = "adi,adau1761", },
|
|
{ .compatible = "adi,adau1961", },
|
|
{ },
|
|
};
|
|
MODULE_DEVICE_TABLE(of, adau1761_spi_dt_ids);
|
|
#endif
|
|
|
|
static struct spi_driver adau1761_spi_driver = {
|
|
.driver = {
|
|
.name = "adau1761",
|
|
.of_match_table = of_match_ptr(adau1761_spi_dt_ids),
|
|
},
|
|
.probe = adau1761_spi_probe,
|
|
.remove = adau1761_spi_remove,
|
|
.id_table = adau1761_spi_id,
|
|
};
|
|
module_spi_driver(adau1761_spi_driver);
|
|
|
|
MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC SPI driver");
|
|
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
|
MODULE_LICENSE("GPL");
|