blob: 8ab1c03d26bd5b616d31303f2076753b3464089b [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
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050031#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
32 SNDRV_PCM_RATE_48000)
33
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000034static struct snd_soc_dai_driver pcm3008_dai = {
35 .name = "pcm3008-hifi",
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050036 .playback = {
37 .stream_name = "PCM3008 Playback",
38 .channels_min = 1,
39 .channels_max = 2,
40 .rates = PCM3008_RATES,
41 .formats = SNDRV_PCM_FMTBIT_S16_LE,
42 },
43 .capture = {
44 .stream_name = "PCM3008 Capture",
45 .channels_min = 1,
46 .channels_max = 2,
47 .rates = PCM3008_RATES,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE,
49 },
50};
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050051
52static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
53{
54 gpio_free(setup->dem0_pin);
55 gpio_free(setup->dem1_pin);
56 gpio_free(setup->pdad_pin);
57 gpio_free(setup->pdda_pin);
58}
59
Mark Brownd7f18492013-07-10 16:48:24 +010060#ifdef CONFIG_PM
61static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050062{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000063 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Mark Brownd7f18492013-07-10 16:48:24 +010064
65 gpio_set_value(setup->pdad_pin, 0);
66 gpio_set_value(setup->pdda_pin, 0);
67
68 return 0;
69}
70
71static int pcm3008_soc_resume(struct snd_soc_codec *codec)
72{
73 struct pcm3008_setup_data *setup = codec->dev->platform_data;
74
75 gpio_set_value(setup->pdad_pin, 1);
76 gpio_set_value(setup->pdda_pin, 1);
77
78 return 0;
79}
80#else
81#define pcm3008_soc_suspend NULL
82#define pcm3008_soc_resume NULL
83#endif
84
85static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
86 .suspend = pcm3008_soc_suspend,
87 .resume = pcm3008_soc_resume,
88};
89
90static int pcm3008_codec_probe(struct platform_device *pdev)
91{
92 struct pcm3008_setup_data *setup = pdev->dev.platform_data;
93 int ret;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050094
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050095 /* DEM1 DEM0 DE-EMPHASIS_MODE
96 * Low Low De-emphasis 44.1 kHz ON
97 * Low High De-emphasis OFF
98 * High Low De-emphasis 48 kHz ON
99 * High High De-emphasis 32 kHz ON
100 */
101
102 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
103 ret = gpio_request(setup->dem0_pin, "codec_dem0");
104 if (ret == 0)
105 ret = gpio_direction_output(setup->dem0_pin, 1);
106 if (ret != 0)
107 goto gpio_err;
108
109 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
110 ret = gpio_request(setup->dem1_pin, "codec_dem1");
111 if (ret == 0)
112 ret = gpio_direction_output(setup->dem1_pin, 0);
113 if (ret != 0)
114 goto gpio_err;
115
116 /* Configure PDAD GPIO. */
117 ret = gpio_request(setup->pdad_pin, "codec_pdad");
118 if (ret == 0)
119 ret = gpio_direction_output(setup->pdad_pin, 1);
120 if (ret != 0)
121 goto gpio_err;
122
123 /* Configure PDDA GPIO. */
124 ret = gpio_request(setup->pdda_pin, "codec_pdda");
125 if (ret == 0)
126 ret = gpio_direction_output(setup->pdda_pin, 1);
127 if (ret != 0)
128 goto gpio_err;
129
Mark Brownd7f18492013-07-10 16:48:24 +0100130 return snd_soc_register_codec(&pdev->dev,
131 &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500132
133gpio_err:
134 pcm3008_gpio_free(setup);
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500135 return ret;
136}
137
Bill Pemberton7a79e942012-12-07 09:26:37 -0500138static int pcm3008_codec_remove(struct platform_device *pdev)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000139{
Mark Brownd7f18492013-07-10 16:48:24 +0100140 struct pcm3008_setup_data *setup = pdev->dev.platform_data;
141
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000142 snd_soc_unregister_codec(&pdev->dev);
Mark Brownd7f18492013-07-10 16:48:24 +0100143
144 pcm3008_gpio_free(setup);
145
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000146 return 0;
147}
148
149MODULE_ALIAS("platform:pcm3008-codec");
150
151static struct platform_driver pcm3008_codec_driver = {
152 .probe = pcm3008_codec_probe,
Bill Pemberton7a79e942012-12-07 09:26:37 -0500153 .remove = pcm3008_codec_remove,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000154 .driver = {
155 .name = "pcm3008-codec",
156 .owner = THIS_MODULE,
157 },
158};
159
Mark Brown5bbcc3c2011-11-23 22:52:08 +0000160module_platform_driver(pcm3008_codec_driver);
Mark Brown64089b82008-12-08 19:17:58 +0000161
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500162MODULE_DESCRIPTION("Soc PCM3008 driver");
163MODULE_AUTHOR("Hugo Villeneuve");
164MODULE_LICENSE("GPL");