Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
0004  *
0005  * Copyright (C) 2010 Texas Instruments, Inc
0006  *
0007  * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
0008  */
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/init.h>
0012 #include <linux/io.h>
0013 #include <linux/delay.h>
0014 #include <linux/pm.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/device.h>
0017 #include <linux/slab.h>
0018 #include <linux/clk.h>
0019 #include <linux/mfd/davinci_voicecodec.h>
0020 #include <linux/spi/spi.h>
0021 
0022 #include <sound/core.h>
0023 #include <sound/pcm.h>
0024 #include <sound/pcm_params.h>
0025 #include <sound/soc.h>
0026 #include <sound/initval.h>
0027 
0028 static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
0029     SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
0030     SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
0031 };
0032 
0033 static int cq93vc_mute(struct snd_soc_dai *dai, int mute, int direction)
0034 {
0035     struct snd_soc_component *component = dai->component;
0036     u8 reg;
0037 
0038     if (mute)
0039         reg = DAVINCI_VC_REG09_MUTE;
0040     else
0041         reg = 0;
0042 
0043     snd_soc_component_update_bits(component, DAVINCI_VC_REG09, DAVINCI_VC_REG09_MUTE,
0044                 reg);
0045 
0046     return 0;
0047 }
0048 
0049 static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0050                  int clk_id, unsigned int freq, int dir)
0051 {
0052     switch (freq) {
0053     case 22579200:
0054     case 27000000:
0055     case 33868800:
0056         return 0;
0057     }
0058 
0059     return -EINVAL;
0060 }
0061 
0062 static int cq93vc_set_bias_level(struct snd_soc_component *component,
0063                 enum snd_soc_bias_level level)
0064 {
0065     switch (level) {
0066     case SND_SOC_BIAS_ON:
0067         snd_soc_component_write(component, DAVINCI_VC_REG12,
0068                  DAVINCI_VC_REG12_POWER_ALL_ON);
0069         break;
0070     case SND_SOC_BIAS_PREPARE:
0071         break;
0072     case SND_SOC_BIAS_STANDBY:
0073         snd_soc_component_write(component, DAVINCI_VC_REG12,
0074                  DAVINCI_VC_REG12_POWER_ALL_OFF);
0075         break;
0076     case SND_SOC_BIAS_OFF:
0077         /* force all power off */
0078         snd_soc_component_write(component, DAVINCI_VC_REG12,
0079                  DAVINCI_VC_REG12_POWER_ALL_OFF);
0080         break;
0081     }
0082 
0083     return 0;
0084 }
0085 
0086 #define CQ93VC_RATES    (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
0087 #define CQ93VC_FORMATS  (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
0088 
0089 static const struct snd_soc_dai_ops cq93vc_dai_ops = {
0090     .mute_stream    = cq93vc_mute,
0091     .set_sysclk = cq93vc_set_dai_sysclk,
0092     .no_capture_mute = 1,
0093 };
0094 
0095 static struct snd_soc_dai_driver cq93vc_dai = {
0096     .name = "cq93vc-hifi",
0097     .playback = {
0098         .stream_name = "Playback",
0099         .channels_min = 1,
0100         .channels_max = 2,
0101         .rates = CQ93VC_RATES,
0102         .formats = CQ93VC_FORMATS,},
0103     .capture = {
0104         .stream_name = "Capture",
0105         .channels_min = 1,
0106         .channels_max = 2,
0107         .rates = CQ93VC_RATES,
0108         .formats = CQ93VC_FORMATS,},
0109     .ops = &cq93vc_dai_ops,
0110 };
0111 
0112 static int cq93vc_probe(struct snd_soc_component *component)
0113 {
0114     struct davinci_vc *davinci_vc = component->dev->platform_data;
0115 
0116     snd_soc_component_init_regmap(component, davinci_vc->regmap);
0117 
0118     return 0;
0119 }
0120 
0121 static const struct snd_soc_component_driver soc_component_dev_cq93vc = {
0122     .set_bias_level     = cq93vc_set_bias_level,
0123     .probe          = cq93vc_probe,
0124     .controls       = cq93vc_snd_controls,
0125     .num_controls       = ARRAY_SIZE(cq93vc_snd_controls),
0126     .idle_bias_on       = 1,
0127     .use_pmdown_time    = 1,
0128     .endianness     = 1,
0129 };
0130 
0131 static int cq93vc_platform_probe(struct platform_device *pdev)
0132 {
0133     return devm_snd_soc_register_component(&pdev->dev,
0134             &soc_component_dev_cq93vc, &cq93vc_dai, 1);
0135 }
0136 
0137 static int cq93vc_platform_remove(struct platform_device *pdev)
0138 {
0139     return 0;
0140 }
0141 
0142 static struct platform_driver cq93vc_codec_driver = {
0143     .driver = {
0144             .name = "cq93vc-codec",
0145     },
0146 
0147     .probe = cq93vc_platform_probe,
0148     .remove = cq93vc_platform_remove,
0149 };
0150 
0151 module_platform_driver(cq93vc_codec_driver);
0152 
0153 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
0154 MODULE_AUTHOR("Miguel Aguilar");
0155 MODULE_LICENSE("GPL");