diff options
author | Simon Glass | 2018-12-10 10:37:42 -0700 |
---|---|---|
committer | Simon Glass | 2018-12-13 16:36:30 -0700 |
commit | 0ab6f0b358195b26096806f3002c8d153e5334dd (patch) | |
tree | 8e8793d4db2fb5ab7c352108a27e28ad3a88c5fc /drivers/sound | |
parent | 482e585bdf4a9eb1374d525ec4e57c671038d239 (diff) |
dm: sound: Move common code out of maxim98095
The register-access code is useful for any maxim codec. Move it out into
its own file.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/sound')
-rw-r--r-- | drivers/sound/Makefile | 2 | ||||
-rw-r--r-- | drivers/sound/max98095.c | 181 | ||||
-rw-r--r-- | drivers/sound/max98095.h | 2 | ||||
-rw-r--r-- | drivers/sound/maxim_codec.c | 87 | ||||
-rw-r--r-- | drivers/sound/maxim_codec.h | 67 |
5 files changed, 204 insertions, 135 deletions
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 75fa31ec534..b08845599f9 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -15,4 +15,4 @@ else obj-$(CONFIG_I2S) += sound-i2s.o endif obj-$(CONFIG_SOUND_WM8994) += wm8994.o -obj-$(CONFIG_SOUND_MAX98095) += max98095.o +obj-$(CONFIG_SOUND_MAX98095) += max98095.o maxim_codec.o diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c index d6710dfaa7a..e9bf64f82f8 100644 --- a/drivers/sound/max98095.c +++ b/drivers/sound/max98095.c @@ -25,97 +25,11 @@ #include "i2s.h" #include "max98095.h" -struct max98095_priv { - unsigned int sysclk; - unsigned int rate; - unsigned int fmt; - int i2c_addr; - struct udevice *dev; -}; - /* Index 0 is reserved. */ int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 88200, 96000}; /* - * Writes value to a device register through i2c - * - * @param priv Private data for driver - * @param reg reg number to be write - * @param data data to be writen to the above registor - * - * @return int value 1 for change, 0 for no change or negative error code. - */ -static int max98095_i2c_write(struct max98095_priv *priv, unsigned int reg, - unsigned char data) -{ - debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n", - __func__, reg, data); -#ifdef CONFIG_DM_SOUND - debug("dev = %s\n", priv->dev->name); - return dm_i2c_write(priv->dev, reg, &data, 1); -#else - return i2c_write(priv->i2c_addr, reg, 1, &data, 1); -#endif -} - -/* - * Read a value from a device register through i2c - * - * @param priv Private data for driver - * @param reg reg number to be read - * @param data address of read data to be stored - * - * @return int value 0 for success, -1 in case of error. - */ -static unsigned int max98095_i2c_read(struct max98095_priv *priv, - unsigned int reg, unsigned char *data) -{ - int ret; - -#ifdef CONFIG_DM_SOUND - return dm_i2c_read(priv->dev, reg, data, 1); -#else - ret = i2c_read(priv->i2c_addr, reg, 1, data, 1); -#endif - if (ret != 0) { - debug("%s: Error while reading register %#04x\n", - __func__, reg); - return -1; - } - - return 0; -} - -/* - * update device register bits through i2c - * - * @param priv Private data for driver - * @param reg codec register - * @param mask register mask - * @param value new value - * - * @return int value 0 for success, non-zero error code. - */ -static int max98095_bic_or(struct max98095_priv *priv, unsigned int reg, - unsigned char mask, unsigned char value) -{ - int change, ret = 0; - unsigned char old, new; - - if (max98095_i2c_read(priv, reg, &old) != 0) - return -1; - new = (old & ~mask) | (value & mask); - change = (old != new) ? 1 : 0; - if (change) - ret = max98095_i2c_write(priv, reg, new); - if (ret < 0) - return ret; - - return change; -} - -/* * codec mclk clock divider coefficients based on sampling rate * * @param rate sampling rate @@ -147,7 +61,7 @@ static int rate_value(int rate, u8 *value) * * @return -1 for error and 0 Success. */ -static int max98095_hw_params(struct max98095_priv *priv, +static int max98095_hw_params(struct maxim_priv *priv, enum en_max_audio_interface aif_id, unsigned int rate, unsigned int bits_per_sample) { @@ -169,12 +83,11 @@ static int max98095_hw_params(struct max98095_priv *priv, switch (bits_per_sample) { case 16: - error = max98095_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, - 0); + error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, 0); break; case 24: - error = max98095_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, - M98095_DAI_WS); + error = maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_WS, + M98095_DAI_WS); break; default: debug("%s: Illegal bits per sample %d.\n", @@ -189,15 +102,15 @@ static int max98095_hw_params(struct max98095_priv *priv, } priv->rate = rate; - error |= max98095_bic_or(priv, M98095_DAI_CLKMODE, M98095_CLKMODE_MASK, + error |= maxim_bic_or(priv, M98095_DAI_CLKMODE, M98095_CLKMODE_MASK, regval); /* Update sample rate mode */ if (rate < 50000) - error |= max98095_bic_or(priv, M98095_DAI_FILTERS, + error |= maxim_bic_or(priv, M98095_DAI_FILTERS, M98095_DAI_DHF, 0); else - error |= max98095_bic_or(priv, M98095_DAI_FILTERS, + error |= maxim_bic_or(priv, M98095_DAI_FILTERS, M98095_DAI_DHF, M98095_DAI_DHF); if (error < 0) { @@ -216,7 +129,7 @@ static int max98095_hw_params(struct max98095_priv *priv, * * @return -1 for error and 0 success. */ -static int max98095_set_sysclk(struct max98095_priv *priv, unsigned int freq) +static int max98095_set_sysclk(struct maxim_priv *priv, unsigned int freq) { int error = 0; @@ -230,11 +143,11 @@ static int max98095_set_sysclk(struct max98095_priv *priv, unsigned int freq) * 0x03 (when master clk is 40MHz to 60MHz).. */ if ((freq >= 10000000) && (freq < 20000000)) { - error = max98095_i2c_write(priv, M98095_026_SYS_CLK, 0x10); + error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x10); } else if ((freq >= 20000000) && (freq < 40000000)) { - error = max98095_i2c_write(priv, M98095_026_SYS_CLK, 0x20); + error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x20); } else if ((freq >= 40000000) && (freq < 60000000)) { - error = max98095_i2c_write(priv, M98095_026_SYS_CLK, 0x30); + error = maxim_i2c_write(priv, M98095_026_SYS_CLK, 0x30); } else { debug("%s: Invalid master clock frequency\n", __func__); return -1; @@ -258,7 +171,7 @@ static int max98095_set_sysclk(struct max98095_priv *priv, unsigned int freq) * * @return -1 for error and 0 Success. */ -static int max98095_set_fmt(struct max98095_priv *priv, int fmt, +static int max98095_set_fmt(struct maxim_priv *priv, int fmt, enum en_max_audio_interface aif_id) { u8 regval = 0; @@ -288,8 +201,8 @@ static int max98095_set_fmt(struct max98095_priv *priv, int fmt, switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Slave mode PLL */ - error |= max98095_i2c_write(priv, M98095_DAI_CLKCFG_HI, 0x80); - error |= max98095_i2c_write(priv, M98095_DAI_CLKCFG_LO, 0x00); + error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_HI, 0x80); + error |= maxim_i2c_write(priv, M98095_DAI_CLKCFG_LO, 0x00); break; case SND_SOC_DAIFMT_CBM_CFM: /* Set to master mode */ @@ -330,11 +243,11 @@ static int max98095_set_fmt(struct max98095_priv *priv, int fmt, return -1; } - error |= max98095_bic_or(priv, M98095_DAI_FORMAT, + error |= maxim_bic_or(priv, M98095_DAI_FORMAT, M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI | M98095_DAI_WCI, regval); - error |= max98095_i2c_write(priv, M98095_DAI_CLOCK, M98095_DAI_BSEL64); + error |= maxim_i2c_write(priv, M98095_DAI_CLOCK, M98095_DAI_BSEL64); if (error < 0) { debug("%s: Error setting i2s format.\n", __func__); @@ -350,7 +263,7 @@ static int max98095_set_fmt(struct max98095_priv *priv, int fmt, * @param priv Private data for driver * @return -1 for error and 0 success. */ -static int max98095_reset(struct max98095_priv *priv) +static int max98095_reset(struct maxim_priv *priv) { int i, ret; @@ -358,13 +271,13 @@ static int max98095_reset(struct max98095_priv *priv) * Gracefully reset the DSP core and the codec hardware in a proper * sequence. */ - ret = max98095_i2c_write(priv, M98095_00F_HOST_CFG, 0); + ret = maxim_i2c_write(priv, M98095_00F_HOST_CFG, 0); if (ret != 0) { debug("%s: Failed to reset DSP: %d\n", __func__, ret); return ret; } - ret = max98095_i2c_write(priv, M98095_097_PWR_SYS, 0); + ret = maxim_i2c_write(priv, M98095_097_PWR_SYS, 0); if (ret != 0) { debug("%s: Failed to reset codec: %d\n", __func__, ret); return ret; @@ -375,7 +288,7 @@ static int max98095_reset(struct max98095_priv *priv) * reset hardware control register. */ for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) { - ret = max98095_i2c_write(priv, i, 0); + ret = maxim_i2c_write(priv, i, 0); if (ret < 0) { debug("%s: Failed to reset: %d\n", __func__, ret); return ret; @@ -392,7 +305,7 @@ static int max98095_reset(struct max98095_priv *priv) * * @returns -1 for error and 0 Success. */ -static int max98095_device_init(struct max98095_priv *priv) +static int max98095_device_init(struct maxim_priv *priv) { unsigned char id; int error = 0; @@ -412,7 +325,7 @@ static int max98095_device_init(struct max98095_priv *priv) priv->rate = -1U; priv->fmt = -1U; - error = max98095_i2c_read(priv, M98095_0FF_REV_ID, &id); + error = maxim_i2c_read(priv, M98095_0FF_REV_ID, &id); if (error < 0) { debug("%s: Failure reading hardware revision: %d\n", __func__, id); @@ -423,63 +336,63 @@ static int max98095_device_init(struct max98095_priv *priv) return 0; } -static int max98095_setup_interface(struct max98095_priv *priv, +static int max98095_setup_interface(struct maxim_priv *priv, enum en_max_audio_interface aif_id) { int error; - error = max98095_i2c_write(priv, M98095_097_PWR_SYS, M98095_PWRSV); + error = maxim_i2c_write(priv, M98095_097_PWR_SYS, M98095_PWRSV); /* * initialize registers to hardware default configuring audio * interface2 to DAC */ if (aif_id == AIF1) - error |= max98095_i2c_write(priv, M98095_048_MIX_DAC_LR, + error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR, M98095_DAI1L_TO_DACL | M98095_DAI1R_TO_DACR); else - error |= max98095_i2c_write(priv, M98095_048_MIX_DAC_LR, + error |= maxim_i2c_write(priv, M98095_048_MIX_DAC_LR, M98095_DAI2M_TO_DACL | M98095_DAI2M_TO_DACR); - error |= max98095_i2c_write(priv, M98095_092_PWR_EN_OUT, + error |= maxim_i2c_write(priv, M98095_092_PWR_EN_OUT, M98095_SPK_SPREADSPECTRUM); - error |= max98095_i2c_write(priv, M98095_04E_CFG_HP, M98095_HPNORMAL); + error |= maxim_i2c_write(priv, M98095_04E_CFG_HP, M98095_HPNORMAL); if (aif_id == AIF1) - error |= max98095_i2c_write(priv, M98095_02C_DAI1_IOCFG, + error |= maxim_i2c_write(priv, M98095_02C_DAI1_IOCFG, M98095_S1NORMAL | M98095_SDATA); else - error |= max98095_i2c_write(priv, M98095_036_DAI2_IOCFG, + error |= maxim_i2c_write(priv, M98095_036_DAI2_IOCFG, M98095_S2NORMAL | M98095_SDATA); /* take the codec out of the shut down */ - error |= max98095_bic_or(priv, M98095_097_PWR_SYS, M98095_SHDNRUN, + error |= maxim_bic_or(priv, M98095_097_PWR_SYS, M98095_SHDNRUN, M98095_SHDNRUN); /* * route DACL and DACR output to HO and Speakers * Ordering: DACL, DACR, DACL, DACR */ - error |= max98095_i2c_write(priv, M98095_050_MIX_SPK_LEFT, 0x01); - error |= max98095_i2c_write(priv, M98095_051_MIX_SPK_RIGHT, 0x01); - error |= max98095_i2c_write(priv, M98095_04C_MIX_HP_LEFT, 0x01); - error |= max98095_i2c_write(priv, M98095_04D_MIX_HP_RIGHT, 0x01); + error |= maxim_i2c_write(priv, M98095_050_MIX_SPK_LEFT, 0x01); + error |= maxim_i2c_write(priv, M98095_051_MIX_SPK_RIGHT, 0x01); + error |= maxim_i2c_write(priv, M98095_04C_MIX_HP_LEFT, 0x01); + error |= maxim_i2c_write(priv, M98095_04D_MIX_HP_RIGHT, 0x01); /* power Enable */ - error |= max98095_i2c_write(priv, M98095_091_PWR_EN_OUT, 0xF3); + error |= maxim_i2c_write(priv, M98095_091_PWR_EN_OUT, 0xF3); /* set Volume */ - error |= max98095_i2c_write(priv, M98095_064_LVL_HP_L, 15); - error |= max98095_i2c_write(priv, M98095_065_LVL_HP_R, 15); - error |= max98095_i2c_write(priv, M98095_067_LVL_SPK_L, 16); - error |= max98095_i2c_write(priv, M98095_068_LVL_SPK_R, 16); + error |= maxim_i2c_write(priv, M98095_064_LVL_HP_L, 15); + error |= maxim_i2c_write(priv, M98095_065_LVL_HP_R, 15); + error |= maxim_i2c_write(priv, M98095_067_LVL_SPK_L, 16); + error |= maxim_i2c_write(priv, M98095_068_LVL_SPK_R, 16); /* Enable DAIs */ - error |= max98095_i2c_write(priv, M98095_093_BIAS_CTRL, 0x30); + error |= maxim_i2c_write(priv, M98095_093_BIAS_CTRL, 0x30); if (aif_id == AIF1) - error |= max98095_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x01); + error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x01); else - error |= max98095_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x07); + error |= maxim_i2c_write(priv, M98095_096_PWR_DAC_CK, 0x07); if (error < 0) return -1; @@ -487,7 +400,7 @@ static int max98095_setup_interface(struct max98095_priv *priv, return 0; } -static int max98095_do_init(struct max98095_priv *priv, +static int max98095_do_init(struct maxim_priv *priv, enum en_max_audio_interface aif_id, int sampling_rate, int mclk_freq, int bits_per_sample) @@ -601,7 +514,7 @@ static int max98095_set_params(struct udevice *dev, int interface, int rate, int mclk_freq, int bits_per_sample, uint channels) { - struct max98095_priv *priv = dev_get_priv(dev); + struct maxim_priv *priv = dev_get_priv(dev); return max98095_do_init(priv, interface, rate, mclk_freq, bits_per_sample); @@ -609,7 +522,7 @@ static int max98095_set_params(struct udevice *dev, int interface, int rate, static int max98095_probe(struct udevice *dev) { - struct max98095_priv *priv = dev_get_priv(dev); + struct maxim_priv *priv = dev_get_priv(dev); int ret; priv->dev = dev; @@ -637,5 +550,5 @@ U_BOOT_DRIVER(max98095) = { .of_match = max98095_ids, .probe = max98095_probe, .ops = &max98095_ops, - .priv_auto_alloc_size = sizeof(struct max98095_priv), + .priv_auto_alloc_size = sizeof(struct maxim_priv), }; diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h index 13ae177a86b..f189db728d1 100644 --- a/drivers/sound/max98095.h +++ b/drivers/sound/max98095.h @@ -11,6 +11,8 @@ #ifndef _MAX98095_H #define _MAX98095_H +#include "maxim_codec.h" + /* Available audio interface ports in wm8994 codec */ enum en_max_audio_interface { AIF1, diff --git a/drivers/sound/maxim_codec.c b/drivers/sound/maxim_codec.c new file mode 100644 index 00000000000..dcaf081988b --- /dev/null +++ b/drivers/sound/maxim_codec.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * maxim_codec.c -- MAXIM CODEC Common driver + * + * Copyright 2011 Maxim Integrated Products + */ + +#include <common.h> +#include <div64.h> +#include <i2c.h> +#include <i2s.h> +#include <sound.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/cpu.h> +#include <asm/arch/power.h> +#include "maxim_codec.h" + +/* + * Writes value to a device register through i2c + * + * @param priv Private data for driver + * @param reg reg number to be write + * @param data data to be writen to the above registor + * + * @return int value 1 for change, 0 for no change or negative error code. + */ +int maxim_i2c_write(struct maxim_priv *priv, unsigned int reg, + unsigned char data) +{ + debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n", + __func__, reg, data); + return dm_i2c_write(priv->dev, reg, &data, 1); +} + +/* + * Read a value from a device register through i2c + * + * @param priv Private data for driver + * @param reg reg number to be read + * @param data address of read data to be stored + * + * @return int value 0 for success, -1 in case of error. + */ +unsigned int maxim_i2c_read(struct maxim_priv *priv, unsigned int reg, + unsigned char *data) +{ + int ret; + + return dm_i2c_read(priv->dev, reg, data, 1); + if (ret != 0) { + debug("%s: Error while reading register %#04x\n", + __func__, reg); + return -1; + } + + return 0; +} + +/* + * update device register bits through i2c + * + * @param priv Private data for driver + * @param reg codec register + * @param mask register mask + * @param value new value + * + * @return int value 0 for success, non-zero error code. + */ +int maxim_bic_or(struct maxim_priv *priv, unsigned int reg, unsigned char mask, + unsigned char value) +{ + int change, ret = 0; + unsigned char old, new; + + if (maxim_i2c_read(priv, reg, &old) != 0) + return -1; + new = (old & ~mask) | (value & mask); + change = (old != new) ? 1 : 0; + if (change) + ret = maxim_i2c_write(priv, reg, new); + if (ret < 0) + return ret; + + return change; +} diff --git a/drivers/sound/maxim_codec.h b/drivers/sound/maxim_codec.h new file mode 100644 index 00000000000..a3128e0bb73 --- /dev/null +++ b/drivers/sound/maxim_codec.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * maxim_codec.h -- MAXIM codec common interface file + * + * Copyright (C) 2013 Samsung Electronics + * D Krishna Mohan <krishna.md@samsung.com> + */ + +#ifndef __MAXIM_COMMON_H__ +#define __MAXIM_COMMON_H__ + +enum maxim_codec_type { + MAX98095, + MAX98090, +}; + +struct maxim_priv { + enum maxim_codec_type devtype; + unsigned int sysclk; + unsigned int rate; + unsigned int fmt; + struct udevice *dev; +}; + +#define MAXIM_AUDIO_I2C_BUS 7 +#define MAXIM_AUDIO_I2C_REG_98095 0x22 + +#define MAXIM_AUDIO_I2C_REG MAXIM_AUDIO_I2C_REG_98095 + +/* + * Writes value to a device register through i2c + * + * @param priv Private data for driver + * @param reg reg number to be write + * @param data data to be writen to the above registor + * + * @return int value 1 for change, 0 for no change or negative error code. + */ +int maxim_i2c_write(struct maxim_priv *priv, unsigned int reg, + unsigned char data); + +/* + * Read a value from a device register through i2c + * + * @param priv Private data for driver + * @param reg reg number to be read + * @param data address of read data to be stored + * + * @return int value 0 for success, -1 in case of error. + */ +unsigned int maxim_i2c_read(struct maxim_priv *priv, unsigned int reg, + unsigned char *data); + +/* + * update device register bits through i2c + * + * @param priv Private data for driver + * @param reg codec register + * @param mask register mask + * @param value new value + * + * @return int value 0 for success, non-zero error code. + */ +int maxim_bic_or(struct maxim_priv *priv, unsigned int reg, unsigned char mask, + unsigned char value); + +#endif /* __MAXIM_COMMON_H__ */ |