1 /* sound/soc/samsung/hdmi_audio.c
3 * ALSA SoC Audio Layer - Samsung Hdmi Audio Plugin
5 * Copyright (c) 2012 Samsung Electronics Co. Ltd.
6 * Rahul Sharma <rahul.sharma@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
20 #include <linux/slab.h>
21 #include <linux/irq.h>
23 #include <linux/of_gpio.h>
24 #include <plat/gpio-cfg.h>
26 #include "codec_plugin.h"
27 #include "hdmi_audio.h"
29 #define DRV_NAME "exynos-hdmi-audio"
31 struct hdmi_audio_params {
38 struct hdmi_audio_params audio_params[] = {
39 { 32000, 27000, 4096, 0x3 },
40 { 44100, 30000, 6272, 0x0 },
41 { 88200, 30000, 12544, 0x8 },
42 { 176400, 30000, 25088, 0xc },
43 { 48000, 27000, 6144, 0x2 },
44 { 96000, 27000, 12288, 0xa },
45 { 192000, 27000, 24576, 0xe },
48 static inline u32 hdmi_reg_read(struct hdmi_audio_context *ctx, u32 reg_id)
50 return readl(ctx->regs + reg_id);
53 static inline void hdmi_reg_writeb(struct hdmi_audio_context *ctx,
56 writeb(value, ctx->regs + reg_id);
59 static inline void hdmi_reg_writemask(struct hdmi_audio_context *ctx,
60 u32 reg_id, u32 value, u32 mask)
62 u32 old = readl(ctx->regs + reg_id);
63 value = (value & mask) | (old & ~mask);
64 writel(value, ctx->regs + reg_id);
67 static int hdmi_get_audio_params(u32 freq)
71 for (i = 0; i < ARRAY_SIZE(audio_params); ++i)
72 if (freq == audio_params[i].sample_rate)
78 static void hdmi_set_acr(struct hdmi_audio_context *ctx, u8 *acr)
83 cts = ctx->params.cts;
86 acr[2] = cts >> 8 & 0xff;
90 acr[5] = n >> 8 & 0xff;
94 static void hdmi_reg_acr(struct hdmi_audio_context *ctx, u8 *acr)
96 hdmi_reg_writeb(ctx, HDMI_ACR_N0, acr[6]);
97 hdmi_reg_writeb(ctx, HDMI_ACR_N1, acr[5]);
98 hdmi_reg_writeb(ctx, HDMI_ACR_N2, acr[4]);
99 hdmi_reg_writeb(ctx, HDMI_ACR_MCTS0, acr[3]);
100 hdmi_reg_writeb(ctx, HDMI_ACR_MCTS1, acr[2]);
101 hdmi_reg_writeb(ctx, HDMI_ACR_MCTS2, acr[1]);
102 hdmi_reg_writeb(ctx, HDMI_ACR_CTS0, acr[3]);
103 hdmi_reg_writeb(ctx, HDMI_ACR_CTS1, acr[2]);
104 hdmi_reg_writeb(ctx, HDMI_ACR_CTS2, acr[1]);
105 hdmi_reg_writeb(ctx, HDMI_ACR_CON, 4);
108 static void hdmi_audio_i2s_init(struct hdmi_audio_context *ctx)
110 u32 sample_rate, bits_per_sample, frame_size_code;
111 u32 data_num, bit_ch, sample_frq;
115 sample_rate = ctx->params.sample_rate;
116 bits_per_sample = ctx->params.bits_per_sample;
119 switch (bits_per_sample) {
142 hdmi_set_acr(ctx, acr);
143 hdmi_reg_acr(ctx, acr);
145 hdmi_reg_writeb(ctx, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
146 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
147 | HDMI_I2S_MUX_ENABLE);
149 hdmi_reg_writeb(ctx, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
150 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
152 hdmi_reg_writeb(ctx, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
154 sample_frq = ctx->params.sample_frq;
156 hdmi_reg_writeb(ctx, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
157 hdmi_reg_writeb(ctx, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
159 val = hdmi_reg_read(ctx, HDMI_I2S_DSD_CON) | 0x01;
160 hdmi_reg_writeb(ctx, HDMI_I2S_DSD_CON, val);
162 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
163 hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
164 | HDMI_I2S_SEL_LRCK(6));
165 hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
166 | HDMI_I2S_SEL_SDATA2(4));
167 hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
168 | HDMI_I2S_SEL_SDATA2(2));
169 hdmi_reg_writeb(ctx, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
172 hdmi_reg_writeb(ctx, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
173 | HDMI_I2S_L_CH_LOW_POL);
174 hdmi_reg_writeb(ctx, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
175 | HDMI_I2S_SET_BIT_CH(bit_ch)
176 | HDMI_I2S_SET_SDATA_BIT(data_num)
177 | HDMI_I2S_BASIC_FORMAT);
179 /* Configure register related to CUV information */
180 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
181 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
183 | HDMI_I2S_LINEAR_PCM
184 | HDMI_I2S_CONSUMER_FORMAT);
185 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
186 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
187 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
188 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
189 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_4,
190 HDMI_I2S_ORG_SMP_FREQ_44_1
191 | HDMI_I2S_WORD_LEN_MAX24_24BITS
192 | HDMI_I2S_WORD_LEN_MAX_24BITS);
194 hdmi_reg_writeb(ctx, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
197 static void hdmi_audio_init(struct hdmi_audio_context *ctx)
199 hdmi_audio_i2s_init(ctx);
202 static int hdmi_audio_control(struct hdmi_audio_context *ctx,
207 snd_printdd("[%d] %s on %d\n", __LINE__,
210 mod = hdmi_reg_read(ctx, HDMI_MODE_SEL);
211 if (mod & HDMI_DVI_MODE_EN && onoff) {
212 snd_printdd("dvi mode on\n");
216 hdmi_reg_writeb(ctx, HDMI_AUI_CON, onoff ? 2 : 0);
217 hdmi_reg_writemask(ctx, HDMI_CON_0, onoff ?
218 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
222 static u8 hdmi_chksum(struct hdmi_audio_context *ctx,
223 u32 start, u8 len, u32 hdr_sum)
226 /* hdr_sum : header0 + header1 + header2
227 * start : start address of packet byte1
228 * len : packet bytes - 1 */
229 for (i = 0; i < len; ++i)
230 hdr_sum += 0xff & hdmi_reg_read(ctx, start + i * 4);
232 return (u8)(0x100 - (hdr_sum & 0xff));
235 static void hdmi_reg_infoframe(struct hdmi_audio_context *ctx,
236 struct hdmi_infoframe *infoframe)
240 hdmi_reg_writeb(ctx, HDMI_AUI_CON, 0x02);
241 hdmi_reg_writeb(ctx, HDMI_AUI_HEADER0, infoframe->type);
242 hdmi_reg_writeb(ctx, HDMI_AUI_HEADER1, infoframe->ver);
243 hdmi_reg_writeb(ctx, HDMI_AUI_HEADER2, infoframe->len);
244 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
245 chksum = hdmi_chksum(ctx, HDMI_AUI_BYTE(1),
246 infoframe->len, hdr_sum);
247 hdmi_reg_writeb(ctx, HDMI_AUI_CHECK_SUM, chksum);
250 static void hdmi_conf_init(struct hdmi_audio_context *ctx)
252 struct hdmi_infoframe infoframe;
254 snd_printdd("[%d] %s\n", __LINE__, __func__);
256 /* enable AVI packet every vsync, fixes purple line problem */
257 hdmi_reg_writemask(ctx, HDMI_CON_1, 2, 3 << 5);
259 infoframe.type = HDMI_PACKET_TYPE_AUI;
260 infoframe.ver = HDMI_AUI_VERSION;
261 infoframe.len = HDMI_AUI_LENGTH;
262 hdmi_reg_infoframe(ctx, &infoframe);
265 static int hdmi_audio_hw_params(struct device *dev,
266 struct snd_pcm_substream *substream,
267 struct snd_pcm_hw_params *params,
268 struct snd_soc_dai *dai)
270 struct hdmi_audio_context *ctx = NULL;
271 struct audio_codec_plugin *plugin;
275 dev_err(dev, "invalid device.\n");
280 snd_printdd("[%d] %s\n", __LINE__, __func__);
282 plugin = dev_get_drvdata(dev);
283 ctx = container_of(plugin, struct hdmi_audio_context, plugin);
285 switch (params_channels(params)) {
290 ctx->params.chan_count = params_channels(params);
293 dev_err(dev, "%d channels not supported\n",
294 params_channels(params));
299 switch (params_format(params)) {
300 case SNDRV_PCM_FORMAT_S8:
301 ctx->params.bits_per_sample = 8;
303 case SNDRV_PCM_FORMAT_S16_LE:
304 ctx->params.bits_per_sample = 12;
306 case SNDRV_PCM_FORMAT_S24_LE:
307 ctx->params.bits_per_sample = 16;
310 dev_err(dev, "Format(%d) not supported\n",
311 params_format(params));
316 index = hdmi_get_audio_params(params_rate(params));
318 ctx->params.sample_rate = audio_params[index].sample_rate;
319 ctx->params.sample_frq = audio_params[index].sample_frq;
320 ctx->params.cts = audio_params[index].cts;
321 ctx->params.n = audio_params[index].n;
323 dev_err(dev, "Sampling Rate (%d) not supported\n",
324 params_rate(params));
329 snd_printdd("chan cnt [%d]\n", ctx->params.chan_count);
330 snd_printdd("bps [%d]\n", ctx->params.bits_per_sample);
331 snd_printdd("sample_rate [%d]\n", ctx->params.sample_rate);
333 /* checking here to cache audioparms for hpd plug handling */
334 if (!atomic_read(&ctx->plugged))
337 hdmi_audio_control(ctx, false);
339 hdmi_audio_init(ctx);
343 hdmi_audio_control(ctx, false);
347 static int hdmi_audio_trigger(struct device *dev,
348 struct snd_pcm_substream *substream, int cmd,
349 struct snd_soc_dai *dai)
351 struct hdmi_audio_context *ctx = NULL;
352 struct audio_codec_plugin *plugin;
356 dev_err(dev, "invalid device.\n");
360 snd_printdd("[%d] %s\n", __LINE__, __func__);
362 plugin = dev_get_drvdata(dev);
363 ctx = container_of(plugin, struct hdmi_audio_context, plugin);
365 if (!atomic_read(&ctx->plugged))
369 case SNDRV_PCM_TRIGGER_START:
372 ret = hdmi_audio_control(ctx, true);
374 dev_err(dev, "audio enable failed.\n");
378 case SNDRV_PCM_TRIGGER_STOP:
379 hdmi_audio_control(ctx, false);
385 static int hdmi_set_state(struct device *dev, int enable)
387 struct hdmi_audio_context *ctx = NULL;
388 struct audio_codec_plugin *plugin;
391 dev_err(dev, "invalid device.\n");
395 snd_printdd("[%d] %s en %d\n", __LINE__, __func__, enable);
397 plugin = dev_get_drvdata(dev);
398 ctx = container_of(plugin, struct hdmi_audio_context, plugin);
399 ctx->enabled = !!enable;
401 if (!atomic_read(&ctx->plugged))
404 hdmi_audio_control(ctx, !!enable);
409 static int hdmi_get_state(struct device *dev, int *is_enabled)
411 struct hdmi_audio_context *ctx = NULL;
412 struct audio_codec_plugin *plugin;
415 dev_err(dev, "invalid device.\n");
419 snd_printdd("[%d] %s\n", __LINE__, __func__);
421 plugin = dev_get_drvdata(dev);
422 ctx = container_of(plugin, struct hdmi_audio_context, plugin);
424 if (is_enabled && ctx)
425 *is_enabled = ctx->enabled;
431 static void hdmi_audio_hotplug_func(struct work_struct *work)
433 struct hdmi_audio_context *ctx = container_of(work,
434 struct hdmi_audio_context, hotplug_work.work);
437 snd_printdd("[%d] %s plugged %d\n",
438 __LINE__, __func__, atomic_read(&ctx->plugged));
440 plugged = atomic_read(&ctx->plugged);
442 if (hdmi_reg_read(ctx, HDMI_MODE_SEL) & HDMI_DVI_MODE_EN) {
443 /* If HDMI operates in DVI mode,
444 * for audio purposes it is the same as nothing plugged.
445 * Unfortunately, hotplug interrupt is received multiple times,
446 * and HDMI_DVI_MODE_EN is set only in the last one.
447 * So, we have already reported that HDMI audio was plugged.
448 * So, update ctx, report now that it was unplugged and return.
450 atomic_set(&ctx->plugged, 0);
451 if (plugged && ctx->plugin.jack_cb)
452 ctx->plugin.jack_cb(false);
457 hdmi_audio_control(ctx, false);
459 hdmi_audio_init(ctx);
461 hdmi_audio_control(ctx, true);
464 if (ctx->plugin.jack_cb)
465 ctx->plugin.jack_cb(plugged);
468 static irqreturn_t hdmi_audio_irq_handler(int irq, void *arg)
470 struct hdmi_audio_context *ctx = arg;
471 u32 val = gpio_get_value(ctx->hpd_gpio);
473 atomic_set(&ctx->plugged, !!val);
474 snd_printdd("%s %s\n", __func__,
475 atomic_read(&ctx->plugged) ? "plugged" : "unplugged");
477 /* should set audio regs after ip, phy got stable. 5ms suff */
478 queue_delayed_work(ctx->hpd_wq, &ctx->hotplug_work,
479 msecs_to_jiffies(5));
484 static __devinit int hdmi_audio_probe(struct platform_device *pdev)
487 struct hdmi_audio_context *ctx;
488 struct resource *res;
489 struct device_node *parent_node;
491 snd_printdd(&pdev->dev, "[%d] %s\n", __LINE__, __func__);
493 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
495 dev_err(&pdev->dev, "failed to alloc common hdmi audio context.\n");
502 atomic_set(&ctx->plugged, 0);
503 ctx->plugin.dev = &pdev->dev;
504 ctx->plugin.ops.hw_params = hdmi_audio_hw_params;
505 ctx->plugin.ops.trigger = hdmi_audio_trigger;
506 ctx->plugin.ops.get_state = hdmi_get_state;
507 ctx->plugin.ops.set_state = hdmi_set_state;
508 ctx->params.sample_rate = DEFAULT_RATE;
509 ctx->params.bits_per_sample = DEFAULT_BPS;
511 dev_set_drvdata(&pdev->dev, &ctx->plugin);
513 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
515 dev_err(&pdev->dev, "failed to find registers.\n");
520 ctx->regs = ioremap(res->start, resource_size(res));
522 dev_err(&pdev->dev, "failed to map registers\n");
527 /* create workqueue and hotplug work */
528 ctx->hpd_wq = alloc_workqueue("exynos-hdmi-audio",
529 WQ_UNBOUND | WQ_NON_REENTRANT, 1);
530 if (ctx->hpd_wq == NULL) {
531 dev_err(&pdev->dev, "failed to create workqueue\n");
535 INIT_DELAYED_WORK(&ctx->hotplug_work, hdmi_audio_hotplug_func);
537 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
539 dev_err(&pdev->dev, "get interrupt res failed.\n");
544 parent_node = of_get_parent(pdev->dev.of_node);
546 dev_err(&pdev->dev, "no parent node found.\n");
551 ctx->hpd_gpio = (int)pdev->dev.platform_data;
553 if (!gpio_is_valid(ctx->hpd_gpio)) {
554 dev_err(&pdev->dev, "failed to get hpd gpio.");
559 ctx->ext_irq = gpio_to_irq(ctx->hpd_gpio);
561 ret = request_irq(res->start, hdmi_audio_irq_handler,
562 IRQF_SHARED, "int_hdmi_audio", ctx);
564 dev_err(&pdev->dev, "request interrupt failed.\n");
567 ctx->int_irq = res->start;
569 ret = request_irq(ctx->ext_irq, hdmi_audio_irq_handler,
570 IRQ_TYPE_EDGE_BOTH | IRQF_SHARED, "ext_hdmi_audio", ctx);
572 dev_err(&pdev->dev, "request interrupt failed.\n");
579 disable_irq(ctx->int_irq);
580 free_irq(ctx->int_irq, ctx);
582 destroy_workqueue(ctx->hpd_wq);
591 static int __devexit hdmi_audio_remove(struct platform_device *pdev)
593 struct hdmi_audio_context *ctx = NULL;
596 ctx = dev_get_drvdata(&pdev->dev);
598 disable_irq(ctx->int_irq);
599 free_irq(ctx->int_irq, ctx);
600 disable_irq(ctx->ext_irq);
601 free_irq(ctx->ext_irq, ctx);
602 destroy_workqueue(ctx->hpd_wq);
609 static struct platform_driver hdmi_audio_driver = {
612 .owner = THIS_MODULE,
614 .probe = hdmi_audio_probe,
615 .remove = __devexit_p(hdmi_audio_remove),
618 module_platform_driver(hdmi_audio_driver);
620 MODULE_AUTHOR("Rahul Sharma <rahul.sharma@samsung.com>");
621 MODULE_DESCRIPTION("HDMI Audio Codec Plugin");
622 MODULE_VERSION("1:1.0");
623 MODULE_LICENSE("GPL");
624 MODULE_ALIAS("platform:" DRV_NAME);