blob: 32e5a591f921411be49bb9e820c1be686065937b [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
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000060static int pcm3008_soc_probe(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050061{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +000062 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050063 int ret = 0;
64
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -050065 /* DEM1 DEM0 DE-EMPHASIS_MODE
66 * Low Low De-emphasis 44.1 kHz ON
67 * Low High De-emphasis OFF
68 * High Low De-emphasis 48 kHz ON
69 * High High De-emphasis 32 kHz ON
70 */
71
72 /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
73 ret = gpio_request(setup->dem0_pin, "codec_dem0");
74 if (ret == 0)
75 ret = gpio_direction_output(setup->dem0_pin, 1);
76 if (ret != 0)
77 goto gpio_err;
78
79 /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
80 ret = gpio_request(setup->dem1_pin, "codec_dem1");
81 if (ret == 0)
82 ret = gpio_direction_output(setup->dem1_pin, 0);
83 if (ret != 0)
84 goto gpio_err;
85
86 /* Configure PDAD GPIO. */
87 ret = gpio_request(setup->pdad_pin, "codec_pdad");
88 if (ret == 0)
89 ret = gpio_direction_output(setup->pdad_pin, 1);
90 if (ret != 0)
91 goto gpio_err;
92
93 /* Configure PDDA GPIO. */
94 ret = gpio_request(setup->pdda_pin, "codec_pdda");
95 if (ret == 0)
96 ret = gpio_direction_output(setup->pdda_pin, 1);
97 if (ret != 0)
98 goto gpio_err;
99
100 return ret;
101
102gpio_err:
103 pcm3008_gpio_free(setup);
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500104
105 return ret;
106}
107
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000108static int pcm3008_soc_remove(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500109{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000110 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500111
112 pcm3008_gpio_free(setup);
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500113 return 0;
114}
115
116#ifdef CONFIG_PM
Lars-Peter Clausen84b315e2011-12-02 10:18:28 +0100117static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500118{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000119 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500120
121 gpio_set_value(setup->pdad_pin, 0);
122 gpio_set_value(setup->pdda_pin, 0);
123
124 return 0;
125}
126
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000127static int pcm3008_soc_resume(struct snd_soc_codec *codec)
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500128{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000129 struct pcm3008_setup_data *setup = codec->dev->platform_data;
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500130
131 gpio_set_value(setup->pdad_pin, 1);
132 gpio_set_value(setup->pdda_pin, 1);
133
134 return 0;
135}
136#else
137#define pcm3008_soc_suspend NULL
138#define pcm3008_soc_resume NULL
139#endif
140
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000141static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500142 .probe = pcm3008_soc_probe,
143 .remove = pcm3008_soc_remove,
144 .suspend = pcm3008_soc_suspend,
145 .resume = pcm3008_soc_resume,
146};
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500147
Bill Pemberton7a79e942012-12-07 09:26:37 -0500148static int pcm3008_codec_probe(struct platform_device *pdev)
Mark Brown64089b82008-12-08 19:17:58 +0000149{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000150 return snd_soc_register_codec(&pdev->dev,
151 &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
Mark Brown64089b82008-12-08 19:17:58 +0000152}
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000153
Bill Pemberton7a79e942012-12-07 09:26:37 -0500154static int pcm3008_codec_remove(struct platform_device *pdev)
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000155{
156 snd_soc_unregister_codec(&pdev->dev);
157 return 0;
158}
159
160MODULE_ALIAS("platform:pcm3008-codec");
161
162static struct platform_driver pcm3008_codec_driver = {
163 .probe = pcm3008_codec_probe,
Bill Pemberton7a79e942012-12-07 09:26:37 -0500164 .remove = pcm3008_codec_remove,
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000165 .driver = {
166 .name = "pcm3008-codec",
167 .owner = THIS_MODULE,
168 },
169};
170
Mark Brown5bbcc3c2011-11-23 22:52:08 +0000171module_platform_driver(pcm3008_codec_driver);
Mark Brown64089b82008-12-08 19:17:58 +0000172
Hugo Villeneuve1c0090c2008-11-19 01:37:31 -0500173MODULE_DESCRIPTION("Soc PCM3008 driver");
174MODULE_AUTHOR("Hugo Villeneuve");
175MODULE_LICENSE("GPL");