Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/dp: add audio support for Display Port on MSM

Introduce audio support for Display Port on MSM chipsets.
This change integrates DP audio sub-module with the main
Display Port platform driver.

In addition, this change leverages hdmi_codec_ops to expose
the operations to the audio driver.

Changes in v2: fix up a compilation issue on drm-next branch
Changes in v3: none
Changes in v4: none
Changes in v5: none
Changes in v6: rebase on top of latest patchset of dependency

Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>

authored by

Abhinav Kumar and committed by
Rob Clark
d13e36d7 061eb621

+935 -1
+2 -1
drivers/gpu/drm/msm/Makefile
··· 111 111 dp/dp_parser.o \ 112 112 dp/dp_power.o \ 113 113 dp/dp_pll.o \ 114 - dp/dp_pll_10nm.o 114 + dp/dp_pll_10nm.o \ 115 + dp/dp_audio.o 115 116 116 117 msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o 117 118 msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o
+7
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
··· 1112 1112 return; 1113 1113 } 1114 1114 1115 + 1116 + if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort && 1117 + dpu_enc->cur_master->hw_mdptop && 1118 + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) 1119 + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( 1120 + dpu_enc->cur_master->hw_mdptop); 1121 + 1115 1122 _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info); 1116 1123 1117 1124 if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
+583
drivers/gpu/drm/msm/dp/dp_audio.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + 7 + #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ 8 + 9 + #include <linux/of_platform.h> 10 + 11 + #include <drm/drm_dp_helper.h> 12 + #include <drm/drm_edid.h> 13 + #include <sound/hdmi-codec.h> 14 + 15 + #include "dp_catalog.h" 16 + #include "dp_audio.h" 17 + #include "dp_panel.h" 18 + #include "dp_display.h" 19 + 20 + #define HEADER_BYTE_2_BIT 0 21 + #define PARITY_BYTE_2_BIT 8 22 + #define HEADER_BYTE_1_BIT 16 23 + #define PARITY_BYTE_1_BIT 24 24 + #define HEADER_BYTE_3_BIT 16 25 + #define PARITY_BYTE_3_BIT 24 26 + 27 + struct dp_audio_private { 28 + struct platform_device *audio_pdev; 29 + struct platform_device *pdev; 30 + struct dp_catalog *catalog; 31 + struct dp_panel *panel; 32 + 33 + bool engine_on; 34 + u32 channels; 35 + 36 + struct dp_audio dp_audio; 37 + }; 38 + 39 + static u8 dp_audio_get_g0_value(u8 data) 40 + { 41 + u8 c[4]; 42 + u8 g[4]; 43 + u8 ret_data = 0; 44 + u8 i; 45 + 46 + for (i = 0; i < 4; i++) 47 + c[i] = (data >> i) & 0x01; 48 + 49 + g[0] = c[3]; 50 + g[1] = c[0] ^ c[3]; 51 + g[2] = c[1]; 52 + g[3] = c[2]; 53 + 54 + for (i = 0; i < 4; i++) 55 + ret_data = ((g[i] & 0x01) << i) | ret_data; 56 + 57 + return ret_data; 58 + } 59 + 60 + static u8 dp_audio_get_g1_value(u8 data) 61 + { 62 + u8 c[4]; 63 + u8 g[4]; 64 + u8 ret_data = 0; 65 + u8 i; 66 + 67 + for (i = 0; i < 4; i++) 68 + c[i] = (data >> i) & 0x01; 69 + 70 + g[0] = c[0] ^ c[3]; 71 + g[1] = c[0] ^ c[1] ^ c[3]; 72 + g[2] = c[1] ^ c[2]; 73 + g[3] = c[2] ^ c[3]; 74 + 75 + for (i = 0; i < 4; i++) 76 + ret_data = ((g[i] & 0x01) << i) | ret_data; 77 + 78 + return ret_data; 79 + } 80 + 81 + static u8 dp_audio_calculate_parity(u32 data) 82 + { 83 + u8 x0 = 0; 84 + u8 x1 = 0; 85 + u8 ci = 0; 86 + u8 iData = 0; 87 + u8 i = 0; 88 + u8 parity_byte; 89 + u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2; 90 + 91 + for (i = 0; i < num_byte; i++) { 92 + iData = (data >> i*4) & 0xF; 93 + 94 + ci = iData ^ x1; 95 + x1 = x0 ^ dp_audio_get_g1_value(ci); 96 + x0 = dp_audio_get_g0_value(ci); 97 + } 98 + 99 + parity_byte = x1 | (x0 << 4); 100 + 101 + return parity_byte; 102 + } 103 + 104 + static u32 dp_audio_get_header(struct dp_catalog *catalog, 105 + enum dp_catalog_audio_sdp_type sdp, 106 + enum dp_catalog_audio_header_type header) 107 + { 108 + catalog->sdp_type = sdp; 109 + catalog->sdp_header = header; 110 + dp_catalog_audio_get_header(catalog); 111 + 112 + return catalog->audio_data; 113 + } 114 + 115 + static void dp_audio_set_header(struct dp_catalog *catalog, 116 + u32 data, 117 + enum dp_catalog_audio_sdp_type sdp, 118 + enum dp_catalog_audio_header_type header) 119 + { 120 + catalog->sdp_type = sdp; 121 + catalog->sdp_header = header; 122 + catalog->audio_data = data; 123 + dp_catalog_audio_set_header(catalog); 124 + } 125 + 126 + static void dp_audio_stream_sdp(struct dp_audio_private *audio) 127 + { 128 + struct dp_catalog *catalog = audio->catalog; 129 + u32 value, new_value; 130 + u8 parity_byte; 131 + 132 + /* Config header and parity byte 1 */ 133 + value = dp_audio_get_header(catalog, 134 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); 135 + 136 + new_value = 0x02; 137 + parity_byte = dp_audio_calculate_parity(new_value); 138 + value |= ((new_value << HEADER_BYTE_1_BIT) 139 + | (parity_byte << PARITY_BYTE_1_BIT)); 140 + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 141 + value, parity_byte); 142 + dp_audio_set_header(catalog, value, 143 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); 144 + 145 + /* Config header and parity byte 2 */ 146 + value = dp_audio_get_header(catalog, 147 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); 148 + new_value = value; 149 + parity_byte = dp_audio_calculate_parity(new_value); 150 + value |= ((new_value << HEADER_BYTE_2_BIT) 151 + | (parity_byte << PARITY_BYTE_2_BIT)); 152 + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 153 + value, parity_byte); 154 + 155 + dp_audio_set_header(catalog, value, 156 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); 157 + 158 + /* Config header and parity byte 3 */ 159 + value = dp_audio_get_header(catalog, 160 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); 161 + 162 + new_value = audio->channels - 1; 163 + parity_byte = dp_audio_calculate_parity(new_value); 164 + value |= ((new_value << HEADER_BYTE_3_BIT) 165 + | (parity_byte << PARITY_BYTE_3_BIT)); 166 + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 167 + value, parity_byte); 168 + 169 + dp_audio_set_header(catalog, value, 170 + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); 171 + } 172 + 173 + static void dp_audio_timestamp_sdp(struct dp_audio_private *audio) 174 + { 175 + struct dp_catalog *catalog = audio->catalog; 176 + u32 value, new_value; 177 + u8 parity_byte; 178 + 179 + /* Config header and parity byte 1 */ 180 + value = dp_audio_get_header(catalog, 181 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); 182 + 183 + new_value = 0x1; 184 + parity_byte = dp_audio_calculate_parity(new_value); 185 + value |= ((new_value << HEADER_BYTE_1_BIT) 186 + | (parity_byte << PARITY_BYTE_1_BIT)); 187 + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 188 + value, parity_byte); 189 + dp_audio_set_header(catalog, value, 190 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); 191 + 192 + /* Config header and parity byte 2 */ 193 + value = dp_audio_get_header(catalog, 194 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); 195 + 196 + new_value = 0x17; 197 + parity_byte = dp_audio_calculate_parity(new_value); 198 + value |= ((new_value << HEADER_BYTE_2_BIT) 199 + | (parity_byte << PARITY_BYTE_2_BIT)); 200 + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 201 + value, parity_byte); 202 + dp_audio_set_header(catalog, value, 203 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); 204 + 205 + /* Config header and parity byte 3 */ 206 + value = dp_audio_get_header(catalog, 207 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); 208 + 209 + new_value = (0x0 | (0x11 << 2)); 210 + parity_byte = dp_audio_calculate_parity(new_value); 211 + value |= ((new_value << HEADER_BYTE_3_BIT) 212 + | (parity_byte << PARITY_BYTE_3_BIT)); 213 + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 214 + value, parity_byte); 215 + dp_audio_set_header(catalog, value, 216 + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); 217 + } 218 + 219 + static void dp_audio_infoframe_sdp(struct dp_audio_private *audio) 220 + { 221 + struct dp_catalog *catalog = audio->catalog; 222 + u32 value, new_value; 223 + u8 parity_byte; 224 + 225 + /* Config header and parity byte 1 */ 226 + value = dp_audio_get_header(catalog, 227 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); 228 + 229 + new_value = 0x84; 230 + parity_byte = dp_audio_calculate_parity(new_value); 231 + value |= ((new_value << HEADER_BYTE_1_BIT) 232 + | (parity_byte << PARITY_BYTE_1_BIT)); 233 + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 234 + value, parity_byte); 235 + dp_audio_set_header(catalog, value, 236 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); 237 + 238 + /* Config header and parity byte 2 */ 239 + value = dp_audio_get_header(catalog, 240 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); 241 + 242 + new_value = 0x1b; 243 + parity_byte = dp_audio_calculate_parity(new_value); 244 + value |= ((new_value << HEADER_BYTE_2_BIT) 245 + | (parity_byte << PARITY_BYTE_2_BIT)); 246 + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 247 + value, parity_byte); 248 + dp_audio_set_header(catalog, value, 249 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); 250 + 251 + /* Config header and parity byte 3 */ 252 + value = dp_audio_get_header(catalog, 253 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); 254 + 255 + new_value = (0x0 | (0x11 << 2)); 256 + parity_byte = dp_audio_calculate_parity(new_value); 257 + value |= ((new_value << HEADER_BYTE_3_BIT) 258 + | (parity_byte << PARITY_BYTE_3_BIT)); 259 + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 260 + new_value, parity_byte); 261 + dp_audio_set_header(catalog, value, 262 + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); 263 + } 264 + 265 + static void dp_audio_copy_management_sdp(struct dp_audio_private *audio) 266 + { 267 + struct dp_catalog *catalog = audio->catalog; 268 + u32 value, new_value; 269 + u8 parity_byte; 270 + 271 + /* Config header and parity byte 1 */ 272 + value = dp_audio_get_header(catalog, 273 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); 274 + 275 + new_value = 0x05; 276 + parity_byte = dp_audio_calculate_parity(new_value); 277 + value |= ((new_value << HEADER_BYTE_1_BIT) 278 + | (parity_byte << PARITY_BYTE_1_BIT)); 279 + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 280 + value, parity_byte); 281 + dp_audio_set_header(catalog, value, 282 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); 283 + 284 + /* Config header and parity byte 2 */ 285 + value = dp_audio_get_header(catalog, 286 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); 287 + 288 + new_value = 0x0F; 289 + parity_byte = dp_audio_calculate_parity(new_value); 290 + value |= ((new_value << HEADER_BYTE_2_BIT) 291 + | (parity_byte << PARITY_BYTE_2_BIT)); 292 + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 293 + value, parity_byte); 294 + dp_audio_set_header(catalog, value, 295 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); 296 + 297 + /* Config header and parity byte 3 */ 298 + value = dp_audio_get_header(catalog, 299 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); 300 + 301 + new_value = 0x0; 302 + parity_byte = dp_audio_calculate_parity(new_value); 303 + value |= ((new_value << HEADER_BYTE_3_BIT) 304 + | (parity_byte << PARITY_BYTE_3_BIT)); 305 + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", 306 + value, parity_byte); 307 + dp_audio_set_header(catalog, value, 308 + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); 309 + } 310 + 311 + static void dp_audio_isrc_sdp(struct dp_audio_private *audio) 312 + { 313 + struct dp_catalog *catalog = audio->catalog; 314 + u32 value, new_value; 315 + u8 parity_byte; 316 + 317 + /* Config header and parity byte 1 */ 318 + value = dp_audio_get_header(catalog, 319 + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); 320 + 321 + new_value = 0x06; 322 + parity_byte = dp_audio_calculate_parity(new_value); 323 + value |= ((new_value << HEADER_BYTE_1_BIT) 324 + | (parity_byte << PARITY_BYTE_1_BIT)); 325 + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", 326 + value, parity_byte); 327 + dp_audio_set_header(catalog, value, 328 + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); 329 + 330 + /* Config header and parity byte 2 */ 331 + value = dp_audio_get_header(catalog, 332 + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); 333 + 334 + new_value = 0x0F; 335 + parity_byte = dp_audio_calculate_parity(new_value); 336 + value |= ((new_value << HEADER_BYTE_2_BIT) 337 + | (parity_byte << PARITY_BYTE_2_BIT)); 338 + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", 339 + value, parity_byte); 340 + dp_audio_set_header(catalog, value, 341 + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); 342 + } 343 + 344 + static void dp_audio_setup_sdp(struct dp_audio_private *audio) 345 + { 346 + dp_catalog_audio_config_sdp(audio->catalog); 347 + 348 + dp_audio_stream_sdp(audio); 349 + dp_audio_timestamp_sdp(audio); 350 + dp_audio_infoframe_sdp(audio); 351 + dp_audio_copy_management_sdp(audio); 352 + dp_audio_isrc_sdp(audio); 353 + } 354 + 355 + static void dp_audio_setup_acr(struct dp_audio_private *audio) 356 + { 357 + u32 select = 0; 358 + struct dp_catalog *catalog = audio->catalog; 359 + 360 + switch (audio->dp_audio.bw_code) { 361 + case DP_LINK_BW_1_62: 362 + select = 0; 363 + break; 364 + case DP_LINK_BW_2_7: 365 + select = 1; 366 + break; 367 + case DP_LINK_BW_5_4: 368 + select = 2; 369 + break; 370 + case DP_LINK_BW_8_1: 371 + select = 3; 372 + break; 373 + default: 374 + DRM_DEBUG_DP("Unknown link rate\n"); 375 + select = 0; 376 + break; 377 + } 378 + 379 + catalog->audio_data = select; 380 + dp_catalog_audio_config_acr(catalog); 381 + } 382 + 383 + static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio) 384 + { 385 + struct dp_catalog *catalog = audio->catalog; 386 + u32 safe_to_exit_level = 0; 387 + 388 + switch (audio->dp_audio.lane_count) { 389 + case 1: 390 + safe_to_exit_level = 14; 391 + break; 392 + case 2: 393 + safe_to_exit_level = 8; 394 + break; 395 + case 4: 396 + safe_to_exit_level = 5; 397 + break; 398 + default: 399 + DRM_DEBUG_DP("setting the default safe_to_exit_level = %u\n", 400 + safe_to_exit_level); 401 + safe_to_exit_level = 14; 402 + break; 403 + } 404 + 405 + catalog->audio_data = safe_to_exit_level; 406 + dp_catalog_audio_sfe_level(catalog); 407 + } 408 + 409 + static void dp_audio_enable(struct dp_audio_private *audio, bool enable) 410 + { 411 + struct dp_catalog *catalog = audio->catalog; 412 + 413 + catalog->audio_data = enable; 414 + dp_catalog_audio_enable(catalog); 415 + 416 + audio->engine_on = enable; 417 + } 418 + 419 + static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev) 420 + { 421 + struct dp_audio *dp_audio; 422 + struct msm_dp *dp_display; 423 + 424 + if (!pdev) { 425 + DRM_ERROR("invalid input\n"); 426 + return ERR_PTR(-ENODEV); 427 + } 428 + 429 + dp_display = platform_get_drvdata(pdev); 430 + if (!dp_display) { 431 + DRM_ERROR("invalid input\n"); 432 + return ERR_PTR(-ENODEV); 433 + } 434 + 435 + dp_audio = dp_display->dp_audio; 436 + 437 + if (!dp_audio) { 438 + DRM_ERROR("invalid dp_audio data\n"); 439 + return ERR_PTR(-EINVAL); 440 + } 441 + 442 + return container_of(dp_audio, struct dp_audio_private, dp_audio); 443 + } 444 + 445 + static int dp_audio_get_eld(struct device *dev, 446 + void *data, uint8_t *buf, size_t len) 447 + { 448 + struct platform_device *pdev; 449 + struct msm_dp *dp_display; 450 + 451 + pdev = to_platform_device(dev); 452 + 453 + if (!pdev) { 454 + DRM_ERROR("invalid input\n"); 455 + return -ENODEV; 456 + } 457 + 458 + dp_display = platform_get_drvdata(pdev); 459 + if (!dp_display) { 460 + DRM_ERROR("invalid input\n"); 461 + return -ENODEV; 462 + } 463 + 464 + memcpy(buf, dp_display->connector->eld, 465 + min(sizeof(dp_display->connector->eld), len)); 466 + 467 + return 0; 468 + } 469 + 470 + int dp_audio_hw_params(struct device *dev, 471 + void *data, 472 + struct hdmi_codec_daifmt *daifmt, 473 + struct hdmi_codec_params *params) 474 + { 475 + int rc = 0; 476 + struct dp_audio_private *audio; 477 + struct platform_device *pdev; 478 + 479 + pdev = to_platform_device(dev); 480 + 481 + audio = dp_audio_get_data(pdev); 482 + if (IS_ERR(audio)) { 483 + rc = PTR_ERR(audio); 484 + goto end; 485 + } 486 + 487 + audio->channels = params->channels; 488 + 489 + dp_audio_setup_sdp(audio); 490 + dp_audio_setup_acr(audio); 491 + dp_audio_safe_to_exit_level(audio); 492 + dp_audio_enable(audio, true); 493 + end: 494 + return rc; 495 + } 496 + 497 + static void dp_audio_shutdown(struct device *dev, void *data) 498 + { 499 + struct dp_audio_private *audio; 500 + struct platform_device *pdev; 501 + 502 + pdev = to_platform_device(dev); 503 + audio = dp_audio_get_data(pdev); 504 + if (IS_ERR(audio)) { 505 + DRM_ERROR("failed to get audio data\n"); 506 + return; 507 + } 508 + 509 + dp_audio_enable(audio, false); 510 + } 511 + 512 + static const struct hdmi_codec_ops dp_audio_codec_ops = { 513 + .hw_params = dp_audio_hw_params, 514 + .audio_shutdown = dp_audio_shutdown, 515 + .get_eld = dp_audio_get_eld, 516 + }; 517 + 518 + static struct hdmi_codec_pdata codec_data = { 519 + .ops = &dp_audio_codec_ops, 520 + .max_i2s_channels = 8, 521 + .i2s = 1, 522 + }; 523 + 524 + int dp_register_audio_driver(struct device *dev, 525 + struct dp_audio *dp_audio) 526 + { 527 + struct dp_audio_private *audio_priv; 528 + 529 + audio_priv = container_of(dp_audio, 530 + struct dp_audio_private, dp_audio); 531 + 532 + audio_priv->audio_pdev = platform_device_register_data(dev, 533 + HDMI_CODEC_DRV_NAME, 534 + PLATFORM_DEVID_AUTO, 535 + &codec_data, 536 + sizeof(codec_data)); 537 + return PTR_ERR_OR_ZERO(audio_priv->audio_pdev); 538 + } 539 + 540 + struct dp_audio *dp_audio_get(struct platform_device *pdev, 541 + struct dp_panel *panel, 542 + struct dp_catalog *catalog) 543 + { 544 + int rc = 0; 545 + struct dp_audio_private *audio; 546 + struct dp_audio *dp_audio; 547 + 548 + if (!pdev || !panel || !catalog) { 549 + DRM_ERROR("invalid input\n"); 550 + rc = -EINVAL; 551 + goto error; 552 + } 553 + 554 + audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL); 555 + if (!audio) { 556 + rc = -ENOMEM; 557 + goto error; 558 + } 559 + 560 + audio->pdev = pdev; 561 + audio->panel = panel; 562 + audio->catalog = catalog; 563 + 564 + dp_audio = &audio->dp_audio; 565 + 566 + dp_catalog_audio_init(catalog); 567 + 568 + return dp_audio; 569 + error: 570 + return ERR_PTR(rc); 571 + } 572 + 573 + void dp_audio_put(struct dp_audio *dp_audio) 574 + { 575 + struct dp_audio_private *audio; 576 + 577 + if (!dp_audio) 578 + return; 579 + 580 + audio = container_of(dp_audio, struct dp_audio_private, dp_audio); 581 + 582 + devm_kfree(&audio->pdev->dev, audio); 583 + }
+72
drivers/gpu/drm/msm/dp/dp_audio.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4 + */ 5 + 6 + #ifndef _DP_AUDIO_H_ 7 + #define _DP_AUDIO_H_ 8 + 9 + #include <linux/platform_device.h> 10 + 11 + #include "dp_panel.h" 12 + #include "dp_catalog.h" 13 + #include <sound/hdmi-codec.h> 14 + 15 + /** 16 + * struct dp_audio 17 + * @lane_count: number of lanes configured in current session 18 + * @bw_code: link rate's bandwidth code for current session 19 + */ 20 + struct dp_audio { 21 + u32 lane_count; 22 + u32 bw_code; 23 + }; 24 + 25 + /** 26 + * dp_audio_get() 27 + * 28 + * Creates and instance of dp audio. 29 + * 30 + * @pdev: caller's platform device instance. 31 + * @panel: an instance of dp_panel module. 32 + * @catalog: an instance of dp_catalog module. 33 + * 34 + * Returns the error code in case of failure, otherwize 35 + * an instance of newly created dp_module. 36 + */ 37 + struct dp_audio *dp_audio_get(struct platform_device *pdev, 38 + struct dp_panel *panel, 39 + struct dp_catalog *catalog); 40 + 41 + /** 42 + * dp_register_audio_driver() 43 + * 44 + * Registers DP device with hdmi_codec interface. 45 + * 46 + * @dev: DP device instance. 47 + * @dp_audio: an instance of dp_audio module. 48 + * 49 + * 50 + * Returns the error code in case of failure, otherwise 51 + * zero on success. 52 + */ 53 + int dp_register_audio_driver(struct device *dev, 54 + struct dp_audio *dp_audio); 55 + 56 + /** 57 + * dp_audio_put() 58 + * 59 + * Cleans the dp_audio instance. 60 + * 61 + * @dp_audio: an instance of dp_audio. 62 + */ 63 + void dp_audio_put(struct dp_audio *dp_audio); 64 + 65 + int dp_audio_hw_params(struct device *dev, 66 + void *data, 67 + struct hdmi_codec_daifmt *daifmt, 68 + struct hdmi_codec_params *params); 69 + 70 + #endif /* _DP_AUDIO_H_ */ 71 + 72 +
+192
drivers/gpu/drm/msm/dp/dp_catalog.c
··· 90 90 struct dp_catalog_private { 91 91 struct device *dev; 92 92 struct dp_io *io; 93 + u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; 93 94 struct dp_catalog dp_catalog; 94 95 u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; 95 96 }; ··· 1070 1069 catalog->io = io; 1071 1070 1072 1071 return &catalog->dp_catalog; 1072 + } 1073 + 1074 + void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog) 1075 + { 1076 + struct dp_catalog_private *catalog; 1077 + u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 1078 + enum dp_catalog_audio_sdp_type sdp; 1079 + enum dp_catalog_audio_header_type header; 1080 + 1081 + if (!dp_catalog) 1082 + return; 1083 + 1084 + catalog = container_of(dp_catalog, 1085 + struct dp_catalog_private, dp_catalog); 1086 + 1087 + sdp_map = catalog->audio_map; 1088 + sdp = dp_catalog->sdp_type; 1089 + header = dp_catalog->sdp_header; 1090 + 1091 + dp_catalog->audio_data = dp_read_link(catalog, 1092 + sdp_map[sdp][header]); 1093 + } 1094 + 1095 + void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog) 1096 + { 1097 + struct dp_catalog_private *catalog; 1098 + u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; 1099 + enum dp_catalog_audio_sdp_type sdp; 1100 + enum dp_catalog_audio_header_type header; 1101 + u32 data; 1102 + 1103 + if (!dp_catalog) 1104 + return; 1105 + 1106 + catalog = container_of(dp_catalog, 1107 + struct dp_catalog_private, dp_catalog); 1108 + 1109 + sdp_map = catalog->audio_map; 1110 + sdp = dp_catalog->sdp_type; 1111 + header = dp_catalog->sdp_header; 1112 + data = dp_catalog->audio_data; 1113 + 1114 + dp_write_link(catalog, sdp_map[sdp][header], data); 1115 + } 1116 + 1117 + void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog) 1118 + { 1119 + struct dp_catalog_private *catalog; 1120 + u32 acr_ctrl, select; 1121 + 1122 + if (!dp_catalog) 1123 + return; 1124 + 1125 + catalog = container_of(dp_catalog, 1126 + struct dp_catalog_private, dp_catalog); 1127 + 1128 + select = dp_catalog->audio_data; 1129 + acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); 1130 + 1131 + DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl); 1132 + 1133 + dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); 1134 + } 1135 + 1136 + void dp_catalog_audio_enable(struct dp_catalog *dp_catalog) 1137 + { 1138 + struct dp_catalog_private *catalog; 1139 + bool enable; 1140 + u32 audio_ctrl; 1141 + 1142 + if (!dp_catalog) 1143 + return; 1144 + 1145 + catalog = container_of(dp_catalog, 1146 + struct dp_catalog_private, dp_catalog); 1147 + 1148 + enable = !!dp_catalog->audio_data; 1149 + audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG); 1150 + 1151 + if (enable) 1152 + audio_ctrl |= BIT(0); 1153 + else 1154 + audio_ctrl &= ~BIT(0); 1155 + 1156 + DRM_DEBUG_DP("dp_audio_cfg = 0x%x\n", audio_ctrl); 1157 + 1158 + dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); 1159 + /* make sure audio engine is disabled */ 1160 + wmb(); 1161 + } 1162 + 1163 + void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog) 1164 + { 1165 + struct dp_catalog_private *catalog; 1166 + u32 sdp_cfg = 0; 1167 + u32 sdp_cfg2 = 0; 1168 + 1169 + if (!dp_catalog) 1170 + return; 1171 + 1172 + catalog = container_of(dp_catalog, 1173 + struct dp_catalog_private, dp_catalog); 1174 + 1175 + sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG); 1176 + /* AUDIO_TIMESTAMP_SDP_EN */ 1177 + sdp_cfg |= BIT(1); 1178 + /* AUDIO_STREAM_SDP_EN */ 1179 + sdp_cfg |= BIT(2); 1180 + /* AUDIO_COPY_MANAGEMENT_SDP_EN */ 1181 + sdp_cfg |= BIT(5); 1182 + /* AUDIO_ISRC_SDP_EN */ 1183 + sdp_cfg |= BIT(6); 1184 + /* AUDIO_INFOFRAME_SDP_EN */ 1185 + sdp_cfg |= BIT(20); 1186 + 1187 + DRM_DEBUG_DP("sdp_cfg = 0x%x\n", sdp_cfg); 1188 + 1189 + dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); 1190 + 1191 + sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2); 1192 + /* IFRM_REGSRC -> Do not use reg values */ 1193 + sdp_cfg2 &= ~BIT(0); 1194 + /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */ 1195 + sdp_cfg2 &= ~BIT(1); 1196 + 1197 + DRM_DEBUG_DP("sdp_cfg2 = 0x%x\n", sdp_cfg2); 1198 + 1199 + dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); 1200 + } 1201 + 1202 + void dp_catalog_audio_init(struct dp_catalog *dp_catalog) 1203 + { 1204 + struct dp_catalog_private *catalog; 1205 + 1206 + static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = { 1207 + { 1208 + MMSS_DP_AUDIO_STREAM_0, 1209 + MMSS_DP_AUDIO_STREAM_1, 1210 + MMSS_DP_AUDIO_STREAM_1, 1211 + }, 1212 + { 1213 + MMSS_DP_AUDIO_TIMESTAMP_0, 1214 + MMSS_DP_AUDIO_TIMESTAMP_1, 1215 + MMSS_DP_AUDIO_TIMESTAMP_1, 1216 + }, 1217 + { 1218 + MMSS_DP_AUDIO_INFOFRAME_0, 1219 + MMSS_DP_AUDIO_INFOFRAME_1, 1220 + MMSS_DP_AUDIO_INFOFRAME_1, 1221 + }, 1222 + { 1223 + MMSS_DP_AUDIO_COPYMANAGEMENT_0, 1224 + MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1225 + MMSS_DP_AUDIO_COPYMANAGEMENT_1, 1226 + }, 1227 + { 1228 + MMSS_DP_AUDIO_ISRC_0, 1229 + MMSS_DP_AUDIO_ISRC_1, 1230 + MMSS_DP_AUDIO_ISRC_1, 1231 + }, 1232 + }; 1233 + 1234 + if (!dp_catalog) 1235 + return; 1236 + 1237 + catalog = container_of(dp_catalog, 1238 + struct dp_catalog_private, dp_catalog); 1239 + 1240 + catalog->audio_map = sdp_map; 1241 + } 1242 + 1243 + void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) 1244 + { 1245 + struct dp_catalog_private *catalog; 1246 + u32 mainlink_levels, safe_to_exit_level; 1247 + 1248 + if (!dp_catalog) 1249 + return; 1250 + 1251 + catalog = container_of(dp_catalog, 1252 + struct dp_catalog_private, dp_catalog); 1253 + 1254 + safe_to_exit_level = dp_catalog->audio_data; 1255 + mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); 1256 + mainlink_levels &= 0xFE0; 1257 + mainlink_levels |= safe_to_exit_level; 1258 + 1259 + DRM_DEBUG_DP("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", 1260 + mainlink_levels, safe_to_exit_level); 1261 + 1262 + dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); 1073 1263 }
+29
drivers/gpu/drm/msm/dp/dp_catalog.h
··· 42 42 PHY_AUX_CFG_MAX, 43 43 }; 44 44 45 + enum dp_catalog_audio_sdp_type { 46 + DP_AUDIO_SDP_STREAM, 47 + DP_AUDIO_SDP_TIMESTAMP, 48 + DP_AUDIO_SDP_INFOFRAME, 49 + DP_AUDIO_SDP_COPYMANAGEMENT, 50 + DP_AUDIO_SDP_ISRC, 51 + DP_AUDIO_SDP_MAX, 52 + }; 53 + 54 + enum dp_catalog_audio_header_type { 55 + DP_AUDIO_SDP_HEADER_1, 56 + DP_AUDIO_SDP_HEADER_2, 57 + DP_AUDIO_SDP_HEADER_3, 58 + DP_AUDIO_SDP_HEADER_MAX, 59 + }; 60 + 45 61 struct dp_catalog { 46 62 u32 aux_data; 47 63 u32 total; 48 64 u32 sync_start; 49 65 u32 width_blanking; 50 66 u32 dp_active; 67 + enum dp_catalog_audio_sdp_type sdp_type; 68 + enum dp_catalog_audio_header_type sdp_header; 69 + u32 audio_data; 51 70 }; 52 71 53 72 /* AUX APIs */ ··· 120 101 void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog); 121 102 122 103 struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io); 104 + 105 + /* DP Audio APIs */ 106 + void dp_catalog_audio_get_header(struct dp_catalog *catalog); 107 + void dp_catalog_audio_set_header(struct dp_catalog *catalog); 108 + void dp_catalog_audio_config_acr(struct dp_catalog *catalog); 109 + void dp_catalog_audio_enable(struct dp_catalog *catalog); 110 + void dp_catalog_audio_enable(struct dp_catalog *catalog); 111 + void dp_catalog_audio_config_sdp(struct dp_catalog *catalog); 112 + void dp_catalog_audio_init(struct dp_catalog *catalog); 113 + void dp_catalog_audio_sfe_level(struct dp_catalog *catalog); 123 114 124 115 #endif /* _DP_CATALOG_H_ */
+48
drivers/gpu/drm/msm/dp/dp_display.c
··· 25 25 #include "dp_display.h" 26 26 #include "dp_drm.h" 27 27 #include "dp_pll.h" 28 + #include "dp_audio.h" 28 29 29 30 static struct msm_dp *g_dp_display; 30 31 #define HPD_STRING_SIZE 30 ··· 114 113 spinlock_t event_lock; 115 114 116 115 struct completion resume_comp; 116 + 117 + struct dp_audio *audio; 117 118 }; 118 119 119 120 static const struct of_device_id dp_dt_match[] = { ··· 215 212 DRM_ERROR("Power client create failed\n"); 216 213 goto end; 217 214 } 215 + 216 + rc = dp_register_audio_driver(dev, dp->audio); 217 + if (rc) { 218 + DRM_ERROR("Audio registration Dp failed\n"); 219 + goto end; 220 + } 221 + 218 222 end: 219 223 return rc; 220 224 } ··· 394 384 int rc = 0; 395 385 struct dp_display_private *dp; 396 386 387 + if (!dev) { 388 + DRM_ERROR("invalid dev\n"); 389 + rc = -EINVAL; 390 + return rc; 391 + } 392 + 397 393 dp = container_of(g_dp_display, 398 394 struct dp_display_private, dp_display); 395 + if (!dp) { 396 + DRM_ERROR("no driver data found\n"); 397 + rc = -ENODEV; 398 + return rc; 399 + } 399 400 400 401 dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); 401 402 ··· 641 620 dp_panel_put(dp->panel); 642 621 dp_aux_put(dp->aux); 643 622 dp_pll_put(dp->pll); 623 + dp_audio_put(dp->audio); 644 624 } 645 625 646 626 static int dp_init_sub_modules(struct dp_display_private *dp) ··· 741 719 goto error_ctrl; 742 720 } 743 721 722 + dp->audio = dp_audio_get(dp->pdev, dp->panel, dp->catalog); 723 + if (IS_ERR(dp->audio)) { 724 + rc = PTR_ERR(dp->audio); 725 + pr_err("failed to initialize audio, rc = %d\n", rc); 726 + dp->audio = NULL; 727 + goto error_audio; 728 + } 729 + 744 730 return rc; 731 + 732 + error_audio: 733 + dp_ctrl_put(dp->ctrl); 745 734 error_ctrl: 746 735 dp_panel_put(dp->panel); 747 736 error_link: ··· 800 767 801 768 static int dp_display_post_enable(struct msm_dp *dp_display) 802 769 { 770 + struct dp_display_private *dp; 771 + u32 rate; 772 + 773 + dp = container_of(dp_display, struct dp_display_private, dp_display); 774 + 775 + rate = dp->link->link_params.rate; 776 + 777 + if (dp->audio_supported) { 778 + dp->audio->bw_code = drm_dp_link_rate_to_bw_code(rate); 779 + dp->audio->lane_count = dp->link->link_params.num_lanes; 780 + } 781 + 803 782 return 0; 804 783 } 805 784 ··· 1123 1078 init_completion(&dp->resume_comp); 1124 1079 1125 1080 g_dp_display = &dp->dp_display; 1081 + 1082 + /* Store DP audio handle inside DP display */ 1083 + g_dp_display->dp_audio = dp->audio; 1126 1084 1127 1085 platform_set_drvdata(pdev, g_dp_display); 1128 1086
+2
drivers/gpu/drm/msm/dp/dp_display.h
··· 14 14 struct drm_encoder *encoder; 15 15 bool is_connected; 16 16 u32 max_pclk_khz; 17 + 17 18 u32 max_dp_lanes; 19 + struct dp_audio *dp_audio; 18 20 }; 19 21 20 22 int dp_display_validate_mode(struct msm_dp *dp_display, u32 mode_pclk_khz);