blob: 446e8b4921b61df728da1481adaa54f991c67762 [file] [log] [blame]
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301/* Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/slab.h>
16#include <linux/bitops.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
20#include <linux/iopoll.h>
21#include <linux/types.h>
Sachin Bhayare3d3767e2018-01-02 21:10:57 +053022#include <linux/extcon.h>
Sachin Bhayareeeb88892018-01-02 16:36:01 +053023#include <linux/gcd.h>
24
25#include "mdss_hdmi_audio.h"
26#include "mdss_hdmi_util.h"
27
28#define HDMI_AUDIO_INFO_FRAME_PACKET_HEADER 0x84
29#define HDMI_AUDIO_INFO_FRAME_PACKET_VERSION 0x1
30#define HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH 0x0A
31
32#define HDMI_KHZ_TO_HZ 1000
33#define HDMI_MHZ_TO_HZ 1000000
34#define HDMI_ACR_N_MULTIPLIER 128
35#define DEFAULT_AUDIO_SAMPLE_RATE_HZ 48000
36
37/* Supported HDMI Audio channels */
38enum hdmi_audio_channels {
39 AUDIO_CHANNEL_2 = 2,
40 AUDIO_CHANNEL_3,
41 AUDIO_CHANNEL_4,
42 AUDIO_CHANNEL_5,
43 AUDIO_CHANNEL_6,
44 AUDIO_CHANNEL_7,
45 AUDIO_CHANNEL_8,
46};
47
48/* parameters for clock regeneration */
49struct hdmi_audio_acr {
50 u32 n;
51 u32 cts;
52};
53
54enum hdmi_audio_sample_rates {
55 AUDIO_SAMPLE_RATE_32KHZ,
56 AUDIO_SAMPLE_RATE_44_1KHZ,
57 AUDIO_SAMPLE_RATE_48KHZ,
58 AUDIO_SAMPLE_RATE_88_2KHZ,
59 AUDIO_SAMPLE_RATE_96KHZ,
60 AUDIO_SAMPLE_RATE_176_4KHZ,
61 AUDIO_SAMPLE_RATE_192KHZ,
62 AUDIO_SAMPLE_RATE_MAX
63};
64
65struct hdmi_audio {
Sachin Bhayare5076e252018-01-18 14:56:45 +053066 struct mdss_io_data *io;
Sachin Bhayareeeb88892018-01-02 16:36:01 +053067 struct msm_hdmi_audio_setup_params params;
Sachin Bhayare3d3767e2018-01-02 21:10:57 +053068 struct extcon_dev sdev;
Sachin Bhayareeeb88892018-01-02 16:36:01 +053069 u32 pclk;
70 bool ack_enabled;
71 bool audio_ack_enabled;
72 atomic_t ack_pending;
73};
74
75static void hdmi_audio_get_audio_sample_rate(u32 *sample_rate_hz)
76{
77 u32 rate = *sample_rate_hz;
78
79 switch (rate) {
80 case 32000:
81 *sample_rate_hz = AUDIO_SAMPLE_RATE_32KHZ;
82 break;
83 case 44100:
84 *sample_rate_hz = AUDIO_SAMPLE_RATE_44_1KHZ;
85 break;
86 case 48000:
87 *sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ;
88 break;
89 case 88200:
90 *sample_rate_hz = AUDIO_SAMPLE_RATE_88_2KHZ;
91 break;
92 case 96000:
93 *sample_rate_hz = AUDIO_SAMPLE_RATE_96KHZ;
94 break;
95 case 176400:
96 *sample_rate_hz = AUDIO_SAMPLE_RATE_176_4KHZ;
97 break;
98 case 192000:
99 *sample_rate_hz = AUDIO_SAMPLE_RATE_192KHZ;
100 break;
101 default:
102 pr_debug("%d unchanged\n", rate);
103 break;
104 }
105}
106
107static void hdmi_audio_get_acr_param(u32 pclk, u32 fs,
108 struct hdmi_audio_acr *acr)
109{
110 u32 div, mul;
111
112 if (!acr) {
113 pr_err("invalid data\n");
114 return;
115 }
116
117 /*
118 * as per HDMI specification, N/CTS = (128*fs)/pclk.
119 * get the ratio using this formula.
120 */
121 acr->n = HDMI_ACR_N_MULTIPLIER * fs;
122 acr->cts = pclk;
123
124 /* get the greatest common divisor for the ratio */
125 div = gcd(acr->n, acr->cts);
126
127 /* get the n and cts values wrt N/CTS formula */
128 acr->n /= div;
129 acr->cts /= div;
130
131 /*
132 * as per HDMI specification, 300 <= 128*fs/N <= 1500
133 * with a target of 128*fs/N = 1000. To get closest
134 * value without truncating fractional values, find
135 * the corresponding multiplier
136 */
137 mul = ((HDMI_ACR_N_MULTIPLIER * fs / HDMI_KHZ_TO_HZ)
138 + (acr->n - 1)) / acr->n;
139
140 acr->n *= mul;
141 acr->cts *= mul;
142}
143
144static void hdmi_audio_acr_enable(struct hdmi_audio *audio)
145{
Sachin Bhayare5076e252018-01-18 14:56:45 +0530146 struct mdss_io_data *io;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530147 struct hdmi_audio_acr acr;
148 struct msm_hdmi_audio_setup_params *params;
149 u32 pclk, layout, multiplier = 1, sample_rate;
150 u32 acr_pkt_ctl, aud_pkt_ctl2, acr_reg_cts, acr_reg_n;
151
152 if (!audio) {
153 pr_err("invalid input\n");
154 return;
155 }
156
157 io = audio->io;
158 params = &audio->params;
159 pclk = audio->pclk;
160 sample_rate = params->sample_rate_hz;
161
162 hdmi_audio_get_acr_param(pclk * HDMI_KHZ_TO_HZ, sample_rate, &acr);
163 hdmi_audio_get_audio_sample_rate(&sample_rate);
164
165 layout = params->num_of_channels == AUDIO_CHANNEL_2 ? 0 : 1;
166
167 pr_debug("n=%u, cts=%u, layout=%u\n", acr.n, acr.cts, layout);
168
169 /* AUDIO_PRIORITY | SOURCE */
170 acr_pkt_ctl = BIT(31) | BIT(8);
171
172 switch (sample_rate) {
173 case AUDIO_SAMPLE_RATE_44_1KHZ:
174 acr_pkt_ctl |= 0x2 << 4;
175 acr.cts <<= 12;
176
177 acr_reg_cts = HDMI_ACR_44_0;
178 acr_reg_n = HDMI_ACR_44_1;
179 break;
180 case AUDIO_SAMPLE_RATE_48KHZ:
181 acr_pkt_ctl |= 0x3 << 4;
182 acr.cts <<= 12;
183
184 acr_reg_cts = HDMI_ACR_48_0;
185 acr_reg_n = HDMI_ACR_48_1;
186 break;
187 case AUDIO_SAMPLE_RATE_192KHZ:
188 multiplier = 4;
189 acr.n >>= 2;
190
191 acr_pkt_ctl |= 0x3 << 4;
192 acr.cts <<= 12;
193
194 acr_reg_cts = HDMI_ACR_48_0;
195 acr_reg_n = HDMI_ACR_48_1;
196 break;
197 case AUDIO_SAMPLE_RATE_176_4KHZ:
198 multiplier = 4;
199 acr.n >>= 2;
200
201 acr_pkt_ctl |= 0x2 << 4;
202 acr.cts <<= 12;
203
204 acr_reg_cts = HDMI_ACR_44_0;
205 acr_reg_n = HDMI_ACR_44_1;
206 break;
207 case AUDIO_SAMPLE_RATE_96KHZ:
208 multiplier = 2;
209 acr.n >>= 1;
210
211 acr_pkt_ctl |= 0x3 << 4;
212 acr.cts <<= 12;
213
214 acr_reg_cts = HDMI_ACR_48_0;
215 acr_reg_n = HDMI_ACR_48_1;
216 break;
217 case AUDIO_SAMPLE_RATE_88_2KHZ:
218 multiplier = 2;
219 acr.n >>= 1;
220
221 acr_pkt_ctl |= 0x2 << 4;
222 acr.cts <<= 12;
223
224 acr_reg_cts = HDMI_ACR_44_0;
225 acr_reg_n = HDMI_ACR_44_1;
226 break;
227 default:
228 multiplier = 1;
229
230 acr_pkt_ctl |= 0x1 << 4;
231 acr.cts <<= 12;
232
233 acr_reg_cts = HDMI_ACR_32_0;
234 acr_reg_n = HDMI_ACR_32_1;
235 break;
236 }
237
238 aud_pkt_ctl2 = BIT(0) | (layout << 1);
239
240 /* N_MULTIPLE(multiplier) */
241 acr_pkt_ctl &= ~(7 << 16);
242 acr_pkt_ctl |= (multiplier & 0x7) << 16;
243
244 /* SEND | CONT */
245 acr_pkt_ctl |= BIT(0) | BIT(1);
246
247 DSS_REG_W(io, acr_reg_cts, acr.cts);
248 DSS_REG_W(io, acr_reg_n, acr.n);
249 DSS_REG_W(io, HDMI_ACR_PKT_CTRL, acr_pkt_ctl);
250 DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pkt_ctl2);
251}
252
253static void hdmi_audio_acr_setup(struct hdmi_audio *audio, bool on)
254{
255 if (on)
256 hdmi_audio_acr_enable(audio);
257 else
258 DSS_REG_W(audio->io, HDMI_ACR_PKT_CTRL, 0);
259}
260
261static void hdmi_audio_infoframe_setup(struct hdmi_audio *audio, bool enabled)
262{
Sachin Bhayare5076e252018-01-18 14:56:45 +0530263 struct mdss_io_data *io = NULL;
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530264 u32 channels, channel_allocation, level_shift, down_mix, layout;
265 u32 hdmi_debug_reg = 0, audio_info_0_reg = 0, audio_info_1_reg = 0;
266 u32 audio_info_ctrl_reg, aud_pck_ctrl_2_reg;
267 u32 check_sum, sample_present;
268
269 if (!audio) {
270 pr_err("invalid input\n");
271 return;
272 }
273
274 io = audio->io;
275 if (!io->base) {
276 pr_err("core io not inititalized\n");
277 return;
278 }
279
280 audio_info_ctrl_reg = DSS_REG_R(io, HDMI_INFOFRAME_CTRL0);
281 audio_info_ctrl_reg &= ~0xF0;
282
283 if (!enabled)
284 goto end;
285
286 channels = audio->params.num_of_channels - 1;
287 channel_allocation = audio->params.channel_allocation;
288 level_shift = audio->params.level_shift;
289 down_mix = audio->params.down_mix;
290 sample_present = audio->params.sample_present;
291
292 layout = audio->params.num_of_channels == AUDIO_CHANNEL_2 ? 0 : 1;
293 aud_pck_ctrl_2_reg = BIT(0) | (layout << 1);
294 DSS_REG_W(io, HDMI_AUDIO_PKT_CTRL2, aud_pck_ctrl_2_reg);
295
296 audio_info_1_reg |= channel_allocation & 0xFF;
297 audio_info_1_reg |= ((level_shift & 0xF) << 11);
298 audio_info_1_reg |= ((down_mix & 0x1) << 15);
299
300 check_sum = 0;
301 check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_HEADER;
302 check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_VERSION;
303 check_sum += HDMI_AUDIO_INFO_FRAME_PACKET_LENGTH;
304 check_sum += channels;
305 check_sum += channel_allocation;
306 check_sum += (level_shift & 0xF) << 3 | (down_mix & 0x1) << 7;
307 check_sum &= 0xFF;
308 check_sum = (u8) (256 - check_sum);
309
310 audio_info_0_reg |= check_sum & 0xFF;
311 audio_info_0_reg |= ((channels & 0x7) << 8);
312
313 /* Enable Audio InfoFrame Transmission */
314 audio_info_ctrl_reg |= 0xF0;
315
316 if (layout) {
317 /* Set the Layout bit */
318 hdmi_debug_reg |= BIT(4);
319
320 /* Set the Sample Present bits */
321 hdmi_debug_reg |= sample_present & 0xF;
322 }
323end:
324 DSS_REG_W(io, HDMI_DEBUG, hdmi_debug_reg);
325 DSS_REG_W(io, HDMI_AUDIO_INFO0, audio_info_0_reg);
326 DSS_REG_W(io, HDMI_AUDIO_INFO1, audio_info_1_reg);
327 DSS_REG_W(io, HDMI_INFOFRAME_CTRL0, audio_info_ctrl_reg);
328}
329
330static int hdmi_audio_on(void *ctx, u32 pclk,
331 struct msm_hdmi_audio_setup_params *params)
332{
333 struct hdmi_audio *audio = ctx;
334 int rc = 0;
335
336 if (!audio) {
337 pr_err("invalid input\n");
338 rc = -EINVAL;
339 goto end;
340 }
341
342 audio->pclk = pclk;
343 audio->params = *params;
344
345 if (!audio->params.num_of_channels) {
346 audio->params.sample_rate_hz = DEFAULT_AUDIO_SAMPLE_RATE_HZ;
347 audio->params.num_of_channels = AUDIO_CHANNEL_2;
348 }
349
350 hdmi_audio_acr_setup(audio, true);
351 hdmi_audio_infoframe_setup(audio, true);
352
353 pr_debug("HDMI Audio: Enabled\n");
354end:
355 return rc;
356}
357
358static void hdmi_audio_off(void *ctx)
359{
360 struct hdmi_audio *audio = ctx;
361
362 if (!audio) {
363 pr_err("invalid input\n");
364 return;
365 }
366
367 hdmi_audio_infoframe_setup(audio, false);
368 hdmi_audio_acr_setup(audio, false);
369
370 pr_debug("HDMI Audio: Disabled\n");
371}
372
373static void hdmi_audio_notify(void *ctx, int val)
374{
375 struct hdmi_audio *audio = ctx;
376 int state = 0;
377 bool switched;
378
379 if (!audio) {
380 pr_err("invalid input\n");
381 return;
382 }
383
384 state = audio->sdev.state;
385 if (state == val)
386 return;
387
388 if (audio->ack_enabled &&
389 atomic_read(&audio->ack_pending)) {
390 pr_err("%s ack pending, not notifying %s\n",
391 state ? "connect" : "disconnect",
392 val ? "connect" : "disconnect");
393 return;
394 }
395
Sachin Bhayare3d3767e2018-01-02 21:10:57 +0530396 extcon_set_state_sync(&audio->sdev, 0, val);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530397 switched = audio->sdev.state != state;
398
399 if (audio->ack_enabled && switched)
400 atomic_set(&audio->ack_pending, 1);
401
402 pr_debug("audio %s %s\n", switched ? "switched to" : "same as",
403 audio->sdev.state ? "HDMI" : "SPKR");
404}
405
406static void hdmi_audio_ack(void *ctx, u32 ack, u32 hpd)
407{
408 struct hdmi_audio *audio = ctx;
409 u32 ack_hpd;
410
411 if (!audio) {
412 pr_err("invalid input\n");
413 return;
414 }
415
416 if (ack & AUDIO_ACK_SET_ENABLE) {
417 audio->ack_enabled = ack & AUDIO_ACK_ENABLE ?
418 true : false;
419
420 pr_debug("audio ack feature %s\n",
421 audio->ack_enabled ? "enabled" : "disabled");
422 return;
423 }
424
425 if (!audio->ack_enabled)
426 return;
427
428 atomic_set(&audio->ack_pending, 0);
429
430 ack_hpd = ack & AUDIO_ACK_CONNECT;
431
432 pr_debug("acknowledging %s\n",
433 ack_hpd ? "connect" : "disconnect");
434
435 if (ack_hpd != hpd) {
436 pr_debug("unbalanced audio state, ack %d, hpd %d\n",
437 ack_hpd, hpd);
438
439 hdmi_audio_notify(ctx, hpd);
440 }
441}
442
443static void hdmi_audio_reset(void *ctx)
444{
445 struct hdmi_audio *audio = ctx;
446
447 if (!audio) {
448 pr_err("invalid input\n");
449 return;
450 }
451
452 atomic_set(&audio->ack_pending, 0);
453}
454
455static void hdmi_audio_status(void *ctx, struct hdmi_audio_status *status)
456{
457 struct hdmi_audio *audio = ctx;
458
459 if (!audio || !status) {
460 pr_err("invalid input\n");
461 return;
462 }
463
464 status->ack_enabled = audio->ack_enabled;
465 status->ack_pending = atomic_read(&audio->ack_pending);
466 status->switched = audio->sdev.state;
467}
468
469/**
470 * hdmi_audio_register() - audio registeration function
471 * @data: registeration initialization data
472 *
473 * This API configures audio module for client to use HDMI audio.
474 * Provides audio functionalities which client can call.
475 * Initializes internal data structures.
476 *
477 * Return: pointer to audio data that client needs to pass on
478 * calling audio functions.
479 */
480void *hdmi_audio_register(struct hdmi_audio_init_data *data)
481{
482 struct hdmi_audio *audio = NULL;
483 int rc = 0;
484
485 if (!data)
486 goto end;
487
488 audio = kzalloc(sizeof(*audio), GFP_KERNEL);
489 if (!audio)
490 goto end;
491
492 audio->sdev.name = "hdmi_audio";
Sachin Bhayare3d3767e2018-01-02 21:10:57 +0530493 rc = extcon_dev_register(&audio->sdev);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530494 if (rc) {
495 pr_err("audio switch registration failed\n");
496 kzfree(audio);
497 goto end;
498 }
499
500 audio->io = data->io;
501
502 data->ops->on = hdmi_audio_on;
503 data->ops->off = hdmi_audio_off;
504 data->ops->notify = hdmi_audio_notify;
505 data->ops->ack = hdmi_audio_ack;
506 data->ops->reset = hdmi_audio_reset;
507 data->ops->status = hdmi_audio_status;
508end:
509 return audio;
510}
511
512/**
513 * hdmi_audio_unregister() - unregister audio module
514 * @ctx: audio module's data
515 *
516 * Delete audio module's instance and allocated resources
517 */
518void hdmi_audio_unregister(void *ctx)
519{
520 struct hdmi_audio *audio = ctx;
521
522 if (audio) {
Sachin Bhayare3d3767e2018-01-02 21:10:57 +0530523 extcon_dev_unregister(&audio->sdev);
Sachin Bhayareeeb88892018-01-02 16:36:01 +0530524 kfree(ctx);
525 }
526}