diff options
Diffstat (limited to 'sound/soc/omap/rx51.c')
-rw-r--r-- | sound/soc/omap/rx51.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 47d831ef2dbb..88052d29617f 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include <sound/jack.h> | ||
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | #include <sound/soc-dapm.h> | 33 | #include <sound/soc-dapm.h> |
@@ -37,14 +38,22 @@ | |||
37 | #include "omap-pcm.h" | 38 | #include "omap-pcm.h" |
38 | #include "../codecs/tlv320aic3x.h" | 39 | #include "../codecs/tlv320aic3x.h" |
39 | 40 | ||
41 | #define RX51_TVOUT_SEL_GPIO 40 | ||
42 | #define RX51_JACK_DETECT_GPIO 177 | ||
40 | /* | 43 | /* |
41 | * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This | 44 | * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This |
42 | * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c | 45 | * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c |
43 | */ | 46 | */ |
44 | #define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) | 47 | #define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) |
45 | 48 | ||
49 | enum { | ||
50 | RX51_JACK_DISABLED, | ||
51 | RX51_JACK_TVOUT, /* tv-out */ | ||
52 | }; | ||
53 | |||
46 | static int rx51_spk_func; | 54 | static int rx51_spk_func; |
47 | static int rx51_dmic_func; | 55 | static int rx51_dmic_func; |
56 | static int rx51_jack_func; | ||
48 | 57 | ||
49 | static void rx51_ext_control(struct snd_soc_codec *codec) | 58 | static void rx51_ext_control(struct snd_soc_codec *codec) |
50 | { | 59 | { |
@@ -57,6 +66,9 @@ static void rx51_ext_control(struct snd_soc_codec *codec) | |||
57 | else | 66 | else |
58 | snd_soc_dapm_disable_pin(codec, "DMic"); | 67 | snd_soc_dapm_disable_pin(codec, "DMic"); |
59 | 68 | ||
69 | gpio_set_value(RX51_TVOUT_SEL_GPIO, | ||
70 | rx51_jack_func == RX51_JACK_TVOUT); | ||
71 | |||
60 | snd_soc_dapm_sync(codec); | 72 | snd_soc_dapm_sync(codec); |
61 | } | 73 | } |
62 | 74 | ||
@@ -162,6 +174,40 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol, | |||
162 | return 1; | 174 | return 1; |
163 | } | 175 | } |
164 | 176 | ||
177 | static int rx51_get_jack(struct snd_kcontrol *kcontrol, | ||
178 | struct snd_ctl_elem_value *ucontrol) | ||
179 | { | ||
180 | ucontrol->value.integer.value[0] = rx51_jack_func; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int rx51_set_jack(struct snd_kcontrol *kcontrol, | ||
186 | struct snd_ctl_elem_value *ucontrol) | ||
187 | { | ||
188 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
189 | |||
190 | if (rx51_jack_func == ucontrol->value.integer.value[0]) | ||
191 | return 0; | ||
192 | |||
193 | rx51_jack_func = ucontrol->value.integer.value[0]; | ||
194 | rx51_ext_control(codec); | ||
195 | |||
196 | return 1; | ||
197 | } | ||
198 | |||
199 | static struct snd_soc_jack rx51_av_jack; | ||
200 | |||
201 | static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { | ||
202 | { | ||
203 | .gpio = RX51_JACK_DETECT_GPIO, | ||
204 | .name = "avdet-gpio", | ||
205 | .report = SND_JACK_VIDEOOUT, | ||
206 | .invert = 1, | ||
207 | .debounce_time = 200, | ||
208 | }, | ||
209 | }; | ||
210 | |||
165 | static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { | 211 | static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { |
166 | SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), | 212 | SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), |
167 | SND_SOC_DAPM_MIC("DMic", NULL), | 213 | SND_SOC_DAPM_MIC("DMic", NULL), |
@@ -177,10 +223,12 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
177 | 223 | ||
178 | static const char *spk_function[] = {"Off", "On"}; | 224 | static const char *spk_function[] = {"Off", "On"}; |
179 | static const char *input_function[] = {"ADC", "Digital Mic"}; | 225 | static const char *input_function[] = {"ADC", "Digital Mic"}; |
226 | static const char *jack_function[] = {"Off", "TV-OUT"}; | ||
180 | 227 | ||
181 | static const struct soc_enum rx51_enum[] = { | 228 | static const struct soc_enum rx51_enum[] = { |
182 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), | 229 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), |
183 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), | 230 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), |
231 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), | ||
184 | }; | 232 | }; |
185 | 233 | ||
186 | static const struct snd_kcontrol_new aic34_rx51_controls[] = { | 234 | static const struct snd_kcontrol_new aic34_rx51_controls[] = { |
@@ -188,10 +236,13 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { | |||
188 | rx51_get_spk, rx51_set_spk), | 236 | rx51_get_spk, rx51_set_spk), |
189 | SOC_ENUM_EXT("Input Select", rx51_enum[1], | 237 | SOC_ENUM_EXT("Input Select", rx51_enum[1], |
190 | rx51_get_input, rx51_set_input), | 238 | rx51_get_input, rx51_set_input), |
239 | SOC_ENUM_EXT("Jack Function", rx51_enum[2], | ||
240 | rx51_get_jack, rx51_set_jack), | ||
191 | }; | 241 | }; |
192 | 242 | ||
193 | static int rx51_aic34_init(struct snd_soc_codec *codec) | 243 | static int rx51_aic34_init(struct snd_soc_codec *codec) |
194 | { | 244 | { |
245 | struct snd_soc_card *card = codec->socdev->card; | ||
195 | int err; | 246 | int err; |
196 | 247 | ||
197 | /* Set up NC codec pins */ | 248 | /* Set up NC codec pins */ |
@@ -214,7 +265,16 @@ static int rx51_aic34_init(struct snd_soc_codec *codec) | |||
214 | 265 | ||
215 | snd_soc_dapm_sync(codec); | 266 | snd_soc_dapm_sync(codec); |
216 | 267 | ||
217 | return 0; | 268 | /* AV jack detection */ |
269 | err = snd_soc_jack_new(card, "AV Jack", | ||
270 | SND_JACK_VIDEOOUT, &rx51_av_jack); | ||
271 | if (err) | ||
272 | return err; | ||
273 | err = snd_soc_jack_add_gpios(&rx51_av_jack, | ||
274 | ARRAY_SIZE(rx51_av_jack_gpios), | ||
275 | rx51_av_jack_gpios); | ||
276 | |||
277 | return err; | ||
218 | } | 278 | } |
219 | 279 | ||
220 | /* Digital audio interface glue - connects codec <--> CPU */ | 280 | /* Digital audio interface glue - connects codec <--> CPU */ |
@@ -259,6 +319,11 @@ static int __init rx51_soc_init(void) | |||
259 | if (!machine_is_nokia_rx51()) | 319 | if (!machine_is_nokia_rx51()) |
260 | return -ENODEV; | 320 | return -ENODEV; |
261 | 321 | ||
322 | err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel"); | ||
323 | if (err) | ||
324 | goto err_gpio_tvout_sel; | ||
325 | gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0); | ||
326 | |||
262 | rx51_snd_device = platform_device_alloc("soc-audio", -1); | 327 | rx51_snd_device = platform_device_alloc("soc-audio", -1); |
263 | if (!rx51_snd_device) { | 328 | if (!rx51_snd_device) { |
264 | err = -ENOMEM; | 329 | err = -ENOMEM; |
@@ -277,13 +342,19 @@ static int __init rx51_soc_init(void) | |||
277 | err2: | 342 | err2: |
278 | platform_device_put(rx51_snd_device); | 343 | platform_device_put(rx51_snd_device); |
279 | err1: | 344 | err1: |
345 | gpio_free(RX51_TVOUT_SEL_GPIO); | ||
346 | err_gpio_tvout_sel: | ||
280 | 347 | ||
281 | return err; | 348 | return err; |
282 | } | 349 | } |
283 | 350 | ||
284 | static void __exit rx51_soc_exit(void) | 351 | static void __exit rx51_soc_exit(void) |
285 | { | 352 | { |
353 | snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios), | ||
354 | rx51_av_jack_gpios); | ||
355 | |||
286 | platform_device_unregister(rx51_snd_device); | 356 | platform_device_unregister(rx51_snd_device); |
357 | gpio_free(RX51_TVOUT_SEL_GPIO); | ||
287 | } | 358 | } |
288 | 359 | ||
289 | module_init(rx51_soc_init); | 360 | module_init(rx51_soc_init); |