cregit-Linux how code gets into the kernel

Release 4.11 sound/soc/codecs/si476x.c

Directory: sound/soc/codecs
/*
 * sound/soc/codecs/si476x.c -- Codec driver for SI476X chips
 *
 * Copyright (C) 2012 Innovative Converged Devices(ICD)
 * Copyright (C) 2013 Andrey Smirnov
 *
 * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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/module.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include <sound/initval.h>

#include <linux/i2c.h>

#include <linux/mfd/si476x-core.h>


enum si476x_audio_registers {
	
SI476X_DIGITAL_IO_OUTPUT_FORMAT		= 0x0203,
	
SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE	= 0x0202,
};


enum si476x_digital_io_output_format {
	
SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT	= 11,
	
SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT	= 8,
};


#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK	((0x7 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
                                                  (0x7 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))

#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK	(0x7e)


enum si476x_daudio_formats {
	
SI476X_DAUDIO_MODE_I2S		= (0x0 << 1),
	
SI476X_DAUDIO_MODE_DSP_A	= (0x6 << 1),
	
SI476X_DAUDIO_MODE_DSP_B	= (0x7 << 1),
	
SI476X_DAUDIO_MODE_LEFT_J	= (0x8 << 1),
	
SI476X_DAUDIO_MODE_RIGHT_J	= (0x9 << 1),

	
SI476X_DAUDIO_MODE_IB		= (1 << 5),
	
SI476X_DAUDIO_MODE_IF		= (1 << 6),
};


enum si476x_pcm_format {
	
SI476X_PCM_FORMAT_S8		= 2,
	
SI476X_PCM_FORMAT_S16_LE	= 4,
	
SI476X_PCM_FORMAT_S20_3LE	= 5,
	
SI476X_PCM_FORMAT_S24_LE	= 6,
};


static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("LOUT"),
SND_SOC_DAPM_OUTPUT("ROUT"),
};


static const struct snd_soc_dapm_route si476x_dapm_routes[] = {
	{ "Capture", NULL, "LOUT" },
	{ "Capture", NULL, "ROUT" },
};


static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev); int err; u16 format = 0; if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) return -EINVAL; switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: format |= SI476X_DAUDIO_MODE_DSP_A; break; case SND_SOC_DAIFMT_DSP_B: format |= SI476X_DAUDIO_MODE_DSP_B; break; case SND_SOC_DAIFMT_I2S: format |= SI476X_DAUDIO_MODE_I2S; break; case SND_SOC_DAIFMT_RIGHT_J: format |= SI476X_DAUDIO_MODE_RIGHT_J; break; case SND_SOC_DAIFMT_LEFT_J: format |= SI476X_DAUDIO_MODE_LEFT_J; break; default: return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_NF: format |= SI476X_DAUDIO_MODE_IB; break; default: return -EINVAL; } break; case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_LEFT_J: switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; case SND_SOC_DAIFMT_IB_IF: format |= SI476X_DAUDIO_MODE_IB | SI476X_DAUDIO_MODE_IF; break; case SND_SOC_DAIFMT_IB_NF: format |= SI476X_DAUDIO_MODE_IB; break; case SND_SOC_DAIFMT_NB_IF: format |= SI476X_DAUDIO_MODE_IF; break; default: return -EINVAL; } break; default: return -EINVAL; } si476x_core_lock(core); err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK, format); si476x_core_unlock(core); if (err < 0) { dev_err(codec_dai->codec->dev, "Failed to set output format\n"); return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andrey Smirnov22891.20%150.00%
Mark Brown228.80%150.00%
Total250100.00%2100.00%


static int si476x_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev); int rate, width, err; rate = params_rate(params); if (rate < 32000 || rate > 48000) { dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate); return -EINVAL; } switch (params_width(params)) { case 8: width = SI476X_PCM_FORMAT_S8; break; case 16: width = SI476X_PCM_FORMAT_S16_LE; break; case 20: width = SI476X_PCM_FORMAT_S20_3LE; break; case 24: width = SI476X_PCM_FORMAT_S24_LE; break; default: return -EINVAL; } si476x_core_lock(core); err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE, rate); if (err < 0) { dev_err(dai->codec->dev, "Failed to set sample rate\n"); goto out; } err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); if (err < 0) { dev_err(dai->codec->dev, "Failed to set output width\n"); goto out; } out: si476x_core_unlock(core); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Andrey Smirnov18283.11%125.00%
Mark Brown3616.44%250.00%
Axel Lin10.46%125.00%
Total219100.00%4100.00%

static const struct snd_soc_dai_ops si476x_dai_ops = { .hw_params = si476x_codec_hw_params, .set_fmt = si476x_codec_set_dai_fmt, }; static struct snd_soc_dai_driver si476x_dai = { .name = "si476x-codec", .capture = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE }, .ops = &si476x_dai_ops, };
static struct regmap *si476x_get_regmap(struct device *dev) { return dev_get_regmap(dev->parent, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Xiubo Li23100.00%2100.00%
Total23100.00%2100.00%

static struct snd_soc_codec_driver soc_codec_dev_si476x = { .get_regmap = si476x_get_regmap, .component_driver = { .dapm_widgets = si476x_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets), .dapm_routes = si476x_dapm_routes, .num_dapm_routes = ARRAY_SIZE(si476x_dapm_routes), }, };
static int si476x_platform_probe(struct platform_device *pdev) { return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x, &si476x_dai, 1); }

Contributors

PersonTokensPropCommitsCommitProp
Andrey Smirnov28100.00%1100.00%
Total28100.00%1100.00%


static int si476x_platform_remove(struct platform_device *pdev) { snd_soc_unregister_codec(&pdev->dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andrey Smirnov22100.00%1100.00%
Total22100.00%1100.00%

MODULE_ALIAS("platform:si476x-codec"); static struct platform_driver si476x_platform_driver = { .driver = { .name = "si476x-codec", }, .probe = si476x_platform_probe, .remove = si476x_platform_remove, }; module_platform_driver(si476x_platform_driver); MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>"); MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Andrey Smirnov73481.83%216.67%
Mark Brown12614.05%325.00%
Xiubo Li283.12%325.00%
Kuninori Morimoto50.56%18.33%
Axel Lin20.22%216.67%
Andrew Morton20.22%18.33%
Total897100.00%12100.00%
Directory: sound/soc/codecs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.