blob: 19f5028354f667ea600b36a5a2ff700f1b919f6a [file] [log] [blame]
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -05001/*
2 * ALSA Soc PCM3008 codec support
3 *
4 * Author: Hugo Villeneuve
5 * Copyright (C) 2008 Lyrtech inc
6 *
7 * Based on AC97 Soc codec, original copyright follow:
8 * Copyright 2005 Wolfson Microelectronics PLC.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * Generic PCM3008 support.
16 */
17
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <linux/device.h>
21#include <linux/gpio.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Paul Gortmakerda155d52011-07-15 12:38:28 -040023#include <linux/module.h>
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050024#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include "pcm3008.h"
30
Mark Brownfaaf36f2013-08-15 12:01:40 +010031static const struct snd_soc_dapm_widget pcm3008_dapm_widgets[] = {
32SND_SOC_DAPM_INPUT("VINL"),
33SND_SOC_DAPM_INPUT("VINR"),
34
35SND_SOC_DAPM_OUTPUT("VOUTL"),
36SND_SOC_DAPM_OUTPUT("VOUTR"),
37};
38
39static const struct snd_soc_dapm_route pcm3008_dapm_routes[] = {
40 { "PCM3008 Capture", NULL, "VINL" },
41 { "PCM3008 Capture", NULL, "VINR" },
42
43 { "VOUTL", NULL, "PCM3008 Playback" },
44 { "VOUTR", NULL, "PCM3008 Playback" },
45};
46
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050047#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
48 SNDRV_PCM_RATE_48000)
49
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000050static struct snd_soc_dai_driver pcm3008_dai = {
51 .name = "pcm3008-hifi",
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050052 .playback = {
53 .stream_name = "PCM3008 Playback",
54 .channels_min = 1,
55 .channels_max = 2,
56 .rates = PCM3008_RATES,
57 .formats = SNDRV_PCM_FMTBIT_S16_LE,
58 },
59 .capture = {
60 .stream_name = "PCM3008 Capture",
61 .channels_min = 1,
62 .channels_max = 2,
63 .rates = PCM3008_RATES,
64 .formats = SNDRV_PCM_FMTBIT_S16_LE,
65 },
66};
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050067
Mark Brownd7f18492013-07-10 16:48:24 +010068#ifdef CONFIG_PM
69static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050070{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000071 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Mark Brownd7f18492013-07-10 16:48:24 +010072
Mark Brownea67afc2013-08-15 11:53:28 +010073 gpio_set_value_cansleep(setup->pdad_pin, 0);
74 gpio_set_value_cansleep(setup->pdda_pin, 0);
Mark Brownd7f18492013-07-10 16:48:24 +010075
76 return 0;
77}
78
79static int pcm3008_soc_resume(struct snd_soc_codec *codec)
80{
81 struct pcm3008_setup_data *setup = codec->dev->platform_data;
82
Mark Brownea67afc2013-08-15 11:53:28 +010083 gpio_set_value_cansleep(setup->pdad_pin, 1);
84 gpio_set_value_cansleep(setup->pdda_pin, 1);
Mark Brownd7f18492013-07-10 16:48:24 +010085
86 return 0;
87}
88#else
89#define pcm3008_soc_suspend NULL
90#define pcm3008_soc_resume NULL
91#endif
92
93static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
94 .suspend = pcm3008_soc_suspend,
95 .resume = pcm3008_soc_resume,
Mark Brownfaaf36f2013-08-15 12:01:40 +010096 .dapm_widgets = pcm3008_dapm_widgets,
97 .num_dapm_widgets = ARRAY_SIZE(pcm3008_dapm_widgets),
98 .dapm_routes = pcm3008_dapm_routes,
99 .num_dapm_routes = ARRAY_SIZE(pcm3008_dapm_routes),
Mark Brownd7f18492013-07-10 16:48:24 +0100100};
101
102static int pcm3008_codec_probe(struct platform_device *pdev)
103{
104 struct pcm3008_setup_data *setup = pdev->dev.platform_data;
105 int ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500106
Mark Brown33319a22013-07-10 16:49:16 +0100107 if (!setup)
108 return -EINVAL;
109
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500110 /* DEM1 DEM0 DE-EMPHASIS_MODE
111 * Low Low De-emphasis 44.1 kHz ON
112 * Low High De-emphasis OFF
113 * High Low De-emphasis 48 kHz ON
114 * High High De-emphasis 32 kHz ON
115 */
116
117 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
Mark Brownd57a79a2013-07-10 16:53:55 +0100118 ret = devm_gpio_request_one(&pdev->dev, setup->dem0_pin,
119 GPIOF_OUT_INIT_HIGH, "codec_dem0");
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500120 if (ret != 0)
Mark Brownd57a79a2013-07-10 16:53:55 +0100121 return ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500122
123 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
Mark Brownd57a79a2013-07-10 16:53:55 +0100124 ret = devm_gpio_request_one(&pdev->dev, setup->dem1_pin,
125 GPIOF_OUT_INIT_LOW, "codec_dem1");
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500126 if (ret != 0)
Mark Brownd57a79a2013-07-10 16:53:55 +0100127 return ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500128
129 /* Configure PDAD GPIO. */
Mark Brownd57a79a2013-07-10 16:53:55 +0100130 ret = devm_gpio_request_one(&pdev->dev, setup->pdad_pin,
131 GPIOF_OUT_INIT_HIGH, "codec_pdad");
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500132 if (ret != 0)
Mark Brownd57a79a2013-07-10 16:53:55 +0100133 return ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500134
135 /* Configure PDDA GPIO. */
Mark Brownd57a79a2013-07-10 16:53:55 +0100136 ret = devm_gpio_request_one(&pdev->dev, setup->pdda_pin,
137 GPIOF_OUT_INIT_HIGH, "codec_pdda");
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500138 if (ret != 0)
Mark Brownd57a79a2013-07-10 16:53:55 +0100139 return ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500140
Mark Brownd7f18492013-07-10 16:48:24 +0100141 return snd_soc_register_codec(&pdev->dev,
142 &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500143}
144
Bill Pemberton7a79e942012-12-07 09:26:37 -0500145static int pcm3008_codec_remove(struct platform_device *pdev)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000146{
147 snd_soc_unregister_codec(&pdev->dev);
Mark Brownd7f18492013-07-10 16:48:24 +0100148
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000149 return 0;
150}
151
152MODULE_ALIAS("platform:pcm3008-codec");
153
154static struct platform_driver pcm3008_codec_driver = {
155 .probe = pcm3008_codec_probe,
Bill Pemberton7a79e942012-12-07 09:26:37 -0500156 .remove = pcm3008_codec_remove,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000157 .driver = {
158 .name = "pcm3008-codec",
159 .owner = THIS_MODULE,
160 },
161};
162
Mark Brown5bbcc3c2011-11-23 22:52:08 +0000163module_platform_driver(pcm3008_codec_driver);
Mark Brown64089b82008-12-08 19:17:58 +0000164
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500165MODULE_DESCRIPTION("Soc PCM3008 driver");
166MODULE_AUTHOR("Hugo Villeneuve");
167MODULE_LICENSE("GPL");