linux/drivers/gpu/drm/msm/dp/dp_audio.c
<<
>>
Prefs
   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
  14#include "dp_catalog.h"
  15#include "dp_audio.h"
  16#include "dp_panel.h"
  17#include "dp_display.h"
  18
  19#define HEADER_BYTE_2_BIT        0
  20#define PARITY_BYTE_2_BIT        8
  21#define HEADER_BYTE_1_BIT       16
  22#define PARITY_BYTE_1_BIT       24
  23#define HEADER_BYTE_3_BIT       16
  24#define PARITY_BYTE_3_BIT       24
  25
  26struct dp_audio_private {
  27        struct platform_device *audio_pdev;
  28        struct platform_device *pdev;
  29        struct dp_catalog *catalog;
  30        struct dp_panel *panel;
  31
  32        bool engine_on;
  33        u32 channels;
  34
  35        struct dp_audio dp_audio;
  36};
  37
  38static u8 dp_audio_get_g0_value(u8 data)
  39{
  40        u8 c[4];
  41        u8 g[4];
  42        u8 ret_data = 0;
  43        u8 i;
  44
  45        for (i = 0; i < 4; i++)
  46                c[i] = (data >> i) & 0x01;
  47
  48        g[0] = c[3];
  49        g[1] = c[0] ^ c[3];
  50        g[2] = c[1];
  51        g[3] = c[2];
  52
  53        for (i = 0; i < 4; i++)
  54                ret_data = ((g[i] & 0x01) << i) | ret_data;
  55
  56        return ret_data;
  57}
  58
  59static u8 dp_audio_get_g1_value(u8 data)
  60{
  61        u8 c[4];
  62        u8 g[4];
  63        u8 ret_data = 0;
  64        u8 i;
  65
  66        for (i = 0; i < 4; i++)
  67                c[i] = (data >> i) & 0x01;
  68
  69        g[0] = c[0] ^ c[3];
  70        g[1] = c[0] ^ c[1] ^ c[3];
  71        g[2] = c[1] ^ c[2];
  72        g[3] = c[2] ^ c[3];
  73
  74        for (i = 0; i < 4; i++)
  75                ret_data = ((g[i] & 0x01) << i) | ret_data;
  76
  77        return ret_data;
  78}
  79
  80static u8 dp_audio_calculate_parity(u32 data)
  81{
  82        u8 x0 = 0;
  83        u8 x1 = 0;
  84        u8 ci = 0;
  85        u8 iData = 0;
  86        u8 i = 0;
  87        u8 parity_byte;
  88        u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
  89
  90        for (i = 0; i < num_byte; i++) {
  91                iData = (data >> i*4) & 0xF;
  92
  93                ci = iData ^ x1;
  94                x1 = x0 ^ dp_audio_get_g1_value(ci);
  95                x0 = dp_audio_get_g0_value(ci);
  96        }
  97
  98        parity_byte = x1 | (x0 << 4);
  99
 100        return parity_byte;
 101}
 102
 103static u32 dp_audio_get_header(struct dp_catalog *catalog,
 104                enum dp_catalog_audio_sdp_type sdp,
 105                enum dp_catalog_audio_header_type header)
 106{
 107        catalog->sdp_type = sdp;
 108        catalog->sdp_header = header;
 109        dp_catalog_audio_get_header(catalog);
 110
 111        return catalog->audio_data;
 112}
 113
 114static void dp_audio_set_header(struct dp_catalog *catalog,
 115                u32 data,
 116                enum dp_catalog_audio_sdp_type sdp,
 117                enum dp_catalog_audio_header_type header)
 118{
 119        catalog->sdp_type = sdp;
 120        catalog->sdp_header = header;
 121        catalog->audio_data = data;
 122        dp_catalog_audio_set_header(catalog);
 123}
 124
 125static void dp_audio_stream_sdp(struct dp_audio_private *audio)
 126{
 127        struct dp_catalog *catalog = audio->catalog;
 128        u32 value, new_value;
 129        u8 parity_byte;
 130
 131        /* Config header and parity byte 1 */
 132        value = dp_audio_get_header(catalog,
 133                        DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
 134
 135        new_value = 0x02;
 136        parity_byte = dp_audio_calculate_parity(new_value);
 137        value |= ((new_value << HEADER_BYTE_1_BIT)
 138                        | (parity_byte << PARITY_BYTE_1_BIT));
 139        DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
 140                        value, parity_byte);
 141        dp_audio_set_header(catalog, value,
 142                DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
 143
 144        /* Config header and parity byte 2 */
 145        value = dp_audio_get_header(catalog,
 146                        DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
 147        new_value = value;
 148        parity_byte = dp_audio_calculate_parity(new_value);
 149        value |= ((new_value << HEADER_BYTE_2_BIT)
 150                        | (parity_byte << PARITY_BYTE_2_BIT));
 151        DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
 152                        value, parity_byte);
 153
 154        dp_audio_set_header(catalog, value,
 155                DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
 156
 157        /* Config header and parity byte 3 */
 158        value = dp_audio_get_header(catalog,
 159                        DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
 160
 161        new_value = audio->channels - 1;
 162        parity_byte = dp_audio_calculate_parity(new_value);
 163        value |= ((new_value << HEADER_BYTE_3_BIT)
 164                        | (parity_byte << PARITY_BYTE_3_BIT));
 165        DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
 166                value, parity_byte);
 167
 168        dp_audio_set_header(catalog, value,
 169                DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
 170}
 171
 172static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
 173{
 174        struct dp_catalog *catalog = audio->catalog;
 175        u32 value, new_value;
 176        u8 parity_byte;
 177
 178        /* Config header and parity byte 1 */
 179        value = dp_audio_get_header(catalog,
 180                        DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
 181
 182        new_value = 0x1;
 183        parity_byte = dp_audio_calculate_parity(new_value);
 184        value |= ((new_value << HEADER_BYTE_1_BIT)
 185                        | (parity_byte << PARITY_BYTE_1_BIT));
 186        DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
 187                value, parity_byte);
 188        dp_audio_set_header(catalog, value,
 189                DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
 190
 191        /* Config header and parity byte 2 */
 192        value = dp_audio_get_header(catalog,
 193                        DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
 194
 195        new_value = 0x17;
 196        parity_byte = dp_audio_calculate_parity(new_value);
 197        value |= ((new_value << HEADER_BYTE_2_BIT)
 198                        | (parity_byte << PARITY_BYTE_2_BIT));
 199        DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
 200                        value, parity_byte);
 201        dp_audio_set_header(catalog, value,
 202                DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
 203
 204        /* Config header and parity byte 3 */
 205        value = dp_audio_get_header(catalog,
 206                        DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
 207
 208        new_value = (0x0 | (0x11 << 2));
 209        parity_byte = dp_audio_calculate_parity(new_value);
 210        value |= ((new_value << HEADER_BYTE_3_BIT)
 211                        | (parity_byte << PARITY_BYTE_3_BIT));
 212        DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
 213                        value, parity_byte);
 214        dp_audio_set_header(catalog, value,
 215                DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
 216}
 217
 218static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
 219{
 220        struct dp_catalog *catalog = audio->catalog;
 221        u32 value, new_value;
 222        u8 parity_byte;
 223
 224        /* Config header and parity byte 1 */
 225        value = dp_audio_get_header(catalog,
 226                        DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
 227
 228        new_value = 0x84;
 229        parity_byte = dp_audio_calculate_parity(new_value);
 230        value |= ((new_value << HEADER_BYTE_1_BIT)
 231                        | (parity_byte << PARITY_BYTE_1_BIT));
 232        DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
 233                        value, parity_byte);
 234        dp_audio_set_header(catalog, value,
 235                DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
 236
 237        /* Config header and parity byte 2 */
 238        value = dp_audio_get_header(catalog,
 239                        DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
 240
 241        new_value = 0x1b;
 242        parity_byte = dp_audio_calculate_parity(new_value);
 243        value |= ((new_value << HEADER_BYTE_2_BIT)
 244                        | (parity_byte << PARITY_BYTE_2_BIT));
 245        DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
 246                        value, parity_byte);
 247        dp_audio_set_header(catalog, value,
 248                DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
 249
 250        /* Config header and parity byte 3 */
 251        value = dp_audio_get_header(catalog,
 252                        DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
 253
 254        new_value = (0x0 | (0x11 << 2));
 255        parity_byte = dp_audio_calculate_parity(new_value);
 256        value |= ((new_value << HEADER_BYTE_3_BIT)
 257                        | (parity_byte << PARITY_BYTE_3_BIT));
 258        DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
 259                        new_value, parity_byte);
 260        dp_audio_set_header(catalog, value,
 261                DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
 262}
 263
 264static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
 265{
 266        struct dp_catalog *catalog = audio->catalog;
 267        u32 value, new_value;
 268        u8 parity_byte;
 269
 270        /* Config header and parity byte 1 */
 271        value = dp_audio_get_header(catalog,
 272                        DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
 273
 274        new_value = 0x05;
 275        parity_byte = dp_audio_calculate_parity(new_value);
 276        value |= ((new_value << HEADER_BYTE_1_BIT)
 277                        | (parity_byte << PARITY_BYTE_1_BIT));
 278        DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
 279                        value, parity_byte);
 280        dp_audio_set_header(catalog, value,
 281                DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
 282
 283        /* Config header and parity byte 2 */
 284        value = dp_audio_get_header(catalog,
 285                        DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
 286
 287        new_value = 0x0F;
 288        parity_byte = dp_audio_calculate_parity(new_value);
 289        value |= ((new_value << HEADER_BYTE_2_BIT)
 290                        | (parity_byte << PARITY_BYTE_2_BIT));
 291        DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
 292                        value, parity_byte);
 293        dp_audio_set_header(catalog, value,
 294                DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
 295
 296        /* Config header and parity byte 3 */
 297        value = dp_audio_get_header(catalog,
 298                        DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
 299
 300        new_value = 0x0;
 301        parity_byte = dp_audio_calculate_parity(new_value);
 302        value |= ((new_value << HEADER_BYTE_3_BIT)
 303                        | (parity_byte << PARITY_BYTE_3_BIT));
 304        DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
 305                        value, parity_byte);
 306        dp_audio_set_header(catalog, value,
 307                DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
 308}
 309
 310static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
 311{
 312        struct dp_catalog *catalog = audio->catalog;
 313        u32 value, new_value;
 314        u8 parity_byte;
 315
 316        /* Config header and parity byte 1 */
 317        value = dp_audio_get_header(catalog,
 318                        DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
 319
 320        new_value = 0x06;
 321        parity_byte = dp_audio_calculate_parity(new_value);
 322        value |= ((new_value << HEADER_BYTE_1_BIT)
 323                        | (parity_byte << PARITY_BYTE_1_BIT));
 324        DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
 325                        value, parity_byte);
 326        dp_audio_set_header(catalog, value,
 327                DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
 328
 329        /* Config header and parity byte 2 */
 330        value = dp_audio_get_header(catalog,
 331                        DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
 332
 333        new_value = 0x0F;
 334        parity_byte = dp_audio_calculate_parity(new_value);
 335        value |= ((new_value << HEADER_BYTE_2_BIT)
 336                        | (parity_byte << PARITY_BYTE_2_BIT));
 337        DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
 338                        value, parity_byte);
 339        dp_audio_set_header(catalog, value,
 340                DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
 341}
 342
 343static void dp_audio_setup_sdp(struct dp_audio_private *audio)
 344{
 345        dp_catalog_audio_config_sdp(audio->catalog);
 346
 347        dp_audio_stream_sdp(audio);
 348        dp_audio_timestamp_sdp(audio);
 349        dp_audio_infoframe_sdp(audio);
 350        dp_audio_copy_management_sdp(audio);
 351        dp_audio_isrc_sdp(audio);
 352}
 353
 354static void dp_audio_setup_acr(struct dp_audio_private *audio)
 355{
 356        u32 select = 0;
 357        struct dp_catalog *catalog = audio->catalog;
 358
 359        switch (audio->dp_audio.bw_code) {
 360        case DP_LINK_BW_1_62:
 361                select = 0;
 362                break;
 363        case DP_LINK_BW_2_7:
 364                select = 1;
 365                break;
 366        case DP_LINK_BW_5_4:
 367                select = 2;
 368                break;
 369        case DP_LINK_BW_8_1:
 370                select = 3;
 371                break;
 372        default:
 373                DRM_DEBUG_DP("Unknown link rate\n");
 374                select = 0;
 375                break;
 376        }
 377
 378        catalog->audio_data = select;
 379        dp_catalog_audio_config_acr(catalog);
 380}
 381
 382static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio)
 383{
 384        struct dp_catalog *catalog = audio->catalog;
 385        u32 safe_to_exit_level = 0;
 386
 387        switch (audio->dp_audio.lane_count) {
 388        case 1:
 389                safe_to_exit_level = 14;
 390                break;
 391        case 2:
 392                safe_to_exit_level = 8;
 393                break;
 394        case 4:
 395                safe_to_exit_level = 5;
 396                break;
 397        default:
 398                DRM_DEBUG_DP("setting the default safe_to_exit_level = %u\n",
 399                                safe_to_exit_level);
 400                safe_to_exit_level = 14;
 401                break;
 402        }
 403
 404        catalog->audio_data = safe_to_exit_level;
 405        dp_catalog_audio_sfe_level(catalog);
 406}
 407
 408static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
 409{
 410        struct dp_catalog *catalog = audio->catalog;
 411
 412        catalog->audio_data = enable;
 413        dp_catalog_audio_enable(catalog);
 414
 415        audio->engine_on = enable;
 416}
 417
 418static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev)
 419{
 420        struct dp_audio *dp_audio;
 421        struct msm_dp *dp_display;
 422
 423        if (!pdev) {
 424                DRM_ERROR("invalid input\n");
 425                return ERR_PTR(-ENODEV);
 426        }
 427
 428        dp_display = platform_get_drvdata(pdev);
 429        if (!dp_display) {
 430                DRM_ERROR("invalid input\n");
 431                return ERR_PTR(-ENODEV);
 432        }
 433
 434        dp_audio = dp_display->dp_audio;
 435
 436        if (!dp_audio) {
 437                DRM_ERROR("invalid dp_audio data\n");
 438                return ERR_PTR(-EINVAL);
 439        }
 440
 441        return container_of(dp_audio, struct dp_audio_private, dp_audio);
 442}
 443
 444static int dp_audio_hook_plugged_cb(struct device *dev, void *data,
 445                hdmi_codec_plugged_cb fn,
 446                struct device *codec_dev)
 447{
 448
 449        struct platform_device *pdev;
 450        struct msm_dp *dp_display;
 451
 452        pdev = to_platform_device(dev);
 453        if (!pdev) {
 454                pr_err("invalid input\n");
 455                return -ENODEV;
 456        }
 457
 458        dp_display = platform_get_drvdata(pdev);
 459        if (!dp_display) {
 460                pr_err("invalid input\n");
 461                return -ENODEV;
 462        }
 463
 464        return dp_display_set_plugged_cb(dp_display, fn, codec_dev);
 465}
 466
 467static int dp_audio_get_eld(struct device *dev,
 468        void *data, uint8_t *buf, size_t len)
 469{
 470        struct platform_device *pdev;
 471        struct msm_dp *dp_display;
 472
 473        pdev = to_platform_device(dev);
 474
 475        if (!pdev) {
 476                DRM_ERROR("invalid input\n");
 477                return -ENODEV;
 478        }
 479
 480        dp_display = platform_get_drvdata(pdev);
 481        if (!dp_display) {
 482                DRM_ERROR("invalid input\n");
 483                return -ENODEV;
 484        }
 485
 486        memcpy(buf, dp_display->connector->eld,
 487                min(sizeof(dp_display->connector->eld), len));
 488
 489        return 0;
 490}
 491
 492int dp_audio_hw_params(struct device *dev,
 493        void *data,
 494        struct hdmi_codec_daifmt *daifmt,
 495        struct hdmi_codec_params *params)
 496{
 497        int rc = 0;
 498        struct dp_audio_private *audio;
 499        struct platform_device *pdev;
 500        struct msm_dp *dp_display;
 501
 502        pdev = to_platform_device(dev);
 503        dp_display = platform_get_drvdata(pdev);
 504
 505        /*
 506         * there could be cases where sound card can be opened even
 507         * before OR even when DP is not connected . This can cause
 508         * unclocked access as the audio subsystem relies on the DP
 509         * driver to maintain the correct state of clocks. To protect
 510         * such cases check for connection status and bail out if not
 511         * connected.
 512         */
 513        if (!dp_display->power_on) {
 514                rc = -EINVAL;
 515                goto end;
 516        }
 517
 518        audio = dp_audio_get_data(pdev);
 519        if (IS_ERR(audio)) {
 520                rc = PTR_ERR(audio);
 521                goto end;
 522        }
 523
 524        audio->channels = params->channels;
 525
 526        dp_audio_setup_sdp(audio);
 527        dp_audio_setup_acr(audio);
 528        dp_audio_safe_to_exit_level(audio);
 529        dp_audio_enable(audio, true);
 530        dp_display->audio_enabled = true;
 531
 532end:
 533        return rc;
 534}
 535
 536static void dp_audio_shutdown(struct device *dev, void *data)
 537{
 538        struct dp_audio_private *audio;
 539        struct platform_device *pdev;
 540        struct msm_dp *dp_display;
 541
 542        pdev = to_platform_device(dev);
 543        dp_display = platform_get_drvdata(pdev);
 544        audio = dp_audio_get_data(pdev);
 545        if (IS_ERR(audio)) {
 546                DRM_ERROR("failed to get audio data\n");
 547                return;
 548        }
 549
 550        /*
 551         * if audio was not enabled there is no need
 552         * to execute the shutdown and we can bail out early.
 553         * This also makes sure that we dont cause an unclocked
 554         * access when audio subsystem calls this without DP being
 555         * connected. is_connected cannot be used here as its set
 556         * to false earlier than this call
 557         */
 558        if (!dp_display->audio_enabled)
 559                return;
 560
 561        dp_audio_enable(audio, false);
 562        /* signal the dp display to safely shutdown clocks */
 563        dp_display_signal_audio_complete(dp_display);
 564}
 565
 566static const struct hdmi_codec_ops dp_audio_codec_ops = {
 567        .hw_params = dp_audio_hw_params,
 568        .audio_shutdown = dp_audio_shutdown,
 569        .get_eld = dp_audio_get_eld,
 570        .hook_plugged_cb = dp_audio_hook_plugged_cb,
 571};
 572
 573static struct hdmi_codec_pdata codec_data = {
 574        .ops = &dp_audio_codec_ops,
 575        .max_i2s_channels = 8,
 576        .i2s = 1,
 577};
 578
 579int dp_register_audio_driver(struct device *dev,
 580                struct dp_audio *dp_audio)
 581{
 582        struct dp_audio_private *audio_priv;
 583
 584        audio_priv = container_of(dp_audio,
 585                        struct dp_audio_private, dp_audio);
 586
 587        audio_priv->audio_pdev = platform_device_register_data(dev,
 588                                                HDMI_CODEC_DRV_NAME,
 589                                                PLATFORM_DEVID_AUTO,
 590                                                &codec_data,
 591                                                sizeof(codec_data));
 592        return PTR_ERR_OR_ZERO(audio_priv->audio_pdev);
 593}
 594
 595struct dp_audio *dp_audio_get(struct platform_device *pdev,
 596                        struct dp_panel *panel,
 597                        struct dp_catalog *catalog)
 598{
 599        int rc = 0;
 600        struct dp_audio_private *audio;
 601        struct dp_audio *dp_audio;
 602
 603        if (!pdev || !panel || !catalog) {
 604                DRM_ERROR("invalid input\n");
 605                rc = -EINVAL;
 606                goto error;
 607        }
 608
 609        audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
 610        if (!audio) {
 611                rc = -ENOMEM;
 612                goto error;
 613        }
 614
 615        audio->pdev = pdev;
 616        audio->panel = panel;
 617        audio->catalog = catalog;
 618
 619        dp_audio = &audio->dp_audio;
 620
 621        dp_catalog_audio_init(catalog);
 622
 623        return dp_audio;
 624error:
 625        return ERR_PTR(rc);
 626}
 627
 628void dp_audio_put(struct dp_audio *dp_audio)
 629{
 630        struct dp_audio_private *audio;
 631
 632        if (!dp_audio)
 633                return;
 634
 635        audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
 636
 637        devm_kfree(&audio->pdev->dev, audio);
 638}
 639