linux/drivers/gpu/drm/i915/display/intel_lspcon.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2016 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21 * DEALINGS IN THE SOFTWARE.
  22 *
  23 *
  24 */
  25
  26#include <drm/drm_atomic_helper.h>
  27#include <drm/dp/drm_dp_dual_mode_helper.h>
  28#include <drm/drm_edid.h>
  29
  30#include "intel_de.h"
  31#include "intel_display_types.h"
  32#include "intel_dp.h"
  33#include "intel_lspcon.h"
  34#include "intel_hdmi.h"
  35
  36/* LSPCON OUI Vendor ID(signatures) */
  37#define LSPCON_VENDOR_PARADE_OUI 0x001CF8
  38#define LSPCON_VENDOR_MCA_OUI 0x0060AD
  39
  40#define DPCD_MCA_LSPCON_HDR_STATUS      0x70003
  41#define DPCD_PARADE_LSPCON_HDR_STATUS   0x00511
  42
  43/* AUX addresses to write MCA AVI IF */
  44#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
  45#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
  46#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
  47#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
  48
  49/* AUX addresses to write Parade AVI IF */
  50#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
  51#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
  52#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
  53#define LSPCON_PARADE_AVI_IF_DATA_SIZE 32
  54
  55static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
  56{
  57        struct intel_digital_port *dig_port =
  58                container_of(lspcon, struct intel_digital_port, lspcon);
  59
  60        return &dig_port->dp;
  61}
  62
  63static const char *lspcon_mode_name(enum drm_lspcon_mode mode)
  64{
  65        switch (mode) {
  66        case DRM_LSPCON_MODE_PCON:
  67                return "PCON";
  68        case DRM_LSPCON_MODE_LS:
  69                return "LS";
  70        case DRM_LSPCON_MODE_INVALID:
  71                return "INVALID";
  72        default:
  73                MISSING_CASE(mode);
  74                return "INVALID";
  75        }
  76}
  77
  78static bool lspcon_detect_vendor(struct intel_lspcon *lspcon)
  79{
  80        struct intel_dp *dp = lspcon_to_intel_dp(lspcon);
  81        struct drm_i915_private *i915 = dp_to_i915(dp);
  82        struct drm_dp_dpcd_ident *ident;
  83        u32 vendor_oui;
  84
  85        if (drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd))) {
  86                drm_err(&i915->drm, "Can't read description\n");
  87                return false;
  88        }
  89
  90        ident = &dp->desc.ident;
  91        vendor_oui = (ident->oui[0] << 16) | (ident->oui[1] << 8) |
  92                      ident->oui[2];
  93
  94        switch (vendor_oui) {
  95        case LSPCON_VENDOR_MCA_OUI:
  96                lspcon->vendor = LSPCON_VENDOR_MCA;
  97                drm_dbg_kms(&i915->drm, "Vendor: Mega Chips\n");
  98                break;
  99
 100        case LSPCON_VENDOR_PARADE_OUI:
 101                lspcon->vendor = LSPCON_VENDOR_PARADE;
 102                drm_dbg_kms(&i915->drm, "Vendor: Parade Tech\n");
 103                break;
 104
 105        default:
 106                drm_err(&i915->drm, "Invalid/Unknown vendor OUI\n");
 107                return false;
 108        }
 109
 110        return true;
 111}
 112
 113static u32 get_hdr_status_reg(struct intel_lspcon *lspcon)
 114{
 115        if (lspcon->vendor == LSPCON_VENDOR_MCA)
 116                return DPCD_MCA_LSPCON_HDR_STATUS;
 117        else
 118                return DPCD_PARADE_LSPCON_HDR_STATUS;
 119}
 120
 121void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon)
 122{
 123        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 124        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 125        u8 hdr_caps;
 126        int ret;
 127
 128        ret = drm_dp_dpcd_read(&intel_dp->aux, get_hdr_status_reg(lspcon),
 129                               &hdr_caps, 1);
 130
 131        if (ret < 0) {
 132                drm_dbg_kms(&i915->drm, "HDR capability detection failed\n");
 133                lspcon->hdr_supported = false;
 134        } else if (hdr_caps & 0x1) {
 135                drm_dbg_kms(&i915->drm, "LSPCON capable of HDR\n");
 136                lspcon->hdr_supported = true;
 137        }
 138}
 139
 140static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
 141{
 142        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 143        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 144        enum drm_lspcon_mode current_mode;
 145        struct i2c_adapter *adapter = &intel_dp->aux.ddc;
 146
 147        if (drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode)) {
 148                drm_dbg_kms(&i915->drm, "Error reading LSPCON mode\n");
 149                return DRM_LSPCON_MODE_INVALID;
 150        }
 151        return current_mode;
 152}
 153
 154static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon,
 155                                             enum drm_lspcon_mode mode)
 156{
 157        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 158        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 159        enum drm_lspcon_mode current_mode;
 160
 161        current_mode = lspcon_get_current_mode(lspcon);
 162        if (current_mode == mode)
 163                goto out;
 164
 165        drm_dbg_kms(&i915->drm, "Waiting for LSPCON mode %s to settle\n",
 166                    lspcon_mode_name(mode));
 167
 168        wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 400);
 169        if (current_mode != mode)
 170                drm_err(&i915->drm, "LSPCON mode hasn't settled\n");
 171
 172out:
 173        drm_dbg_kms(&i915->drm, "Current LSPCON mode %s\n",
 174                    lspcon_mode_name(current_mode));
 175
 176        return current_mode;
 177}
 178
 179static int lspcon_change_mode(struct intel_lspcon *lspcon,
 180                              enum drm_lspcon_mode mode)
 181{
 182        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 183        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 184        int err;
 185        enum drm_lspcon_mode current_mode;
 186        struct i2c_adapter *adapter = &intel_dp->aux.ddc;
 187
 188        err = drm_lspcon_get_mode(intel_dp->aux.drm_dev, adapter, &current_mode);
 189        if (err) {
 190                drm_err(&i915->drm, "Error reading LSPCON mode\n");
 191                return err;
 192        }
 193
 194        if (current_mode == mode) {
 195                drm_dbg_kms(&i915->drm, "Current mode = desired LSPCON mode\n");
 196                return 0;
 197        }
 198
 199        err = drm_lspcon_set_mode(intel_dp->aux.drm_dev, adapter, mode);
 200        if (err < 0) {
 201                drm_err(&i915->drm, "LSPCON mode change failed\n");
 202                return err;
 203        }
 204
 205        lspcon->mode = mode;
 206        drm_dbg_kms(&i915->drm, "LSPCON mode changed done\n");
 207        return 0;
 208}
 209
 210static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon)
 211{
 212        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 213        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 214        u8 rev;
 215
 216        if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV,
 217                              &rev) != 1) {
 218                drm_dbg_kms(&i915->drm, "Native AUX CH down\n");
 219                return false;
 220        }
 221
 222        drm_dbg_kms(&i915->drm, "Native AUX CH up, DPCD version: %d.%d\n",
 223                    rev >> 4, rev & 0xf);
 224
 225        return true;
 226}
 227
 228static bool lspcon_probe(struct intel_lspcon *lspcon)
 229{
 230        int retry;
 231        enum drm_dp_dual_mode_type adaptor_type;
 232        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 233        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 234        struct i2c_adapter *adapter = &intel_dp->aux.ddc;
 235        enum drm_lspcon_mode expected_mode;
 236
 237        expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
 238                        DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS;
 239
 240        /* Lets probe the adaptor and check its type */
 241        for (retry = 0; retry < 6; retry++) {
 242                if (retry)
 243                        usleep_range(500, 1000);
 244
 245                adaptor_type = drm_dp_dual_mode_detect(intel_dp->aux.drm_dev, adapter);
 246                if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON)
 247                        break;
 248        }
 249
 250        if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) {
 251                drm_dbg_kms(&i915->drm, "No LSPCON detected, found %s\n",
 252                            drm_dp_get_dual_mode_type_name(adaptor_type));
 253                return false;
 254        }
 255
 256        /* Yay ... got a LSPCON device */
 257        drm_dbg_kms(&i915->drm, "LSPCON detected\n");
 258        lspcon->mode = lspcon_wait_mode(lspcon, expected_mode);
 259
 260        /*
 261         * In the SW state machine, lets Put LSPCON in PCON mode only.
 262         * In this way, it will work with both HDMI 1.4 sinks as well as HDMI
 263         * 2.0 sinks.
 264         */
 265        if (lspcon->mode != DRM_LSPCON_MODE_PCON) {
 266                if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON) < 0) {
 267                        drm_err(&i915->drm, "LSPCON mode change to PCON failed\n");
 268                        return false;
 269                }
 270        }
 271        return true;
 272}
 273
 274static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
 275{
 276        struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
 277        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 278        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 279        unsigned long start = jiffies;
 280
 281        while (1) {
 282                if (intel_digital_port_connected(&dig_port->base)) {
 283                        drm_dbg_kms(&i915->drm, "LSPCON recovering in PCON mode after %u ms\n",
 284                                    jiffies_to_msecs(jiffies - start));
 285                        return;
 286                }
 287
 288                if (time_after(jiffies, start + msecs_to_jiffies(1000)))
 289                        break;
 290
 291                usleep_range(10000, 15000);
 292        }
 293
 294        drm_dbg_kms(&i915->drm, "LSPCON DP descriptor mismatch after resume\n");
 295}
 296
 297static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux)
 298{
 299        u8 avi_if_ctrl;
 300        u8 retry;
 301        ssize_t ret;
 302
 303        /* Check if LSPCON FW is ready for data */
 304        for (retry = 0; retry < 5; retry++) {
 305                if (retry)
 306                        usleep_range(200, 300);
 307
 308                ret = drm_dp_dpcd_read(aux, LSPCON_PARADE_AVI_IF_CTRL,
 309                                       &avi_if_ctrl, 1);
 310                if (ret < 0) {
 311                        drm_err(aux->drm_dev, "Failed to read AVI IF control\n");
 312                        return false;
 313                }
 314
 315                if ((avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF) == 0)
 316                        return true;
 317        }
 318
 319        drm_err(aux->drm_dev, "Parade FW not ready to accept AVI IF\n");
 320        return false;
 321}
 322
 323static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux,
 324                                                  u8 *avi_buf)
 325{
 326        u8 avi_if_ctrl;
 327        u8 block_count = 0;
 328        u8 *data;
 329        u16 reg;
 330        ssize_t ret;
 331
 332        while (block_count < 4) {
 333                if (!lspcon_parade_fw_ready(aux)) {
 334                        drm_dbg_kms(aux->drm_dev, "LSPCON FW not ready, block %d\n",
 335                                    block_count);
 336                        return false;
 337                }
 338
 339                reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
 340                data = avi_buf + block_count * 8;
 341                ret = drm_dp_dpcd_write(aux, reg, data, 8);
 342                if (ret < 0) {
 343                        drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n",
 344                                block_count);
 345                        return false;
 346                }
 347
 348                /*
 349                 * Once a block of data is written, we have to inform the FW
 350                 * about this by writing into avi infoframe control register:
 351                 * - set the kickoff bit[7] to 1
 352                 * - write the block no. to bits[1:0]
 353                 */
 354                reg = LSPCON_PARADE_AVI_IF_CTRL;
 355                avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF | block_count;
 356                ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
 357                if (ret < 0) {
 358                        drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n",
 359                                reg, block_count);
 360                        return false;
 361                }
 362
 363                block_count++;
 364        }
 365
 366        drm_dbg_kms(aux->drm_dev, "Wrote AVI IF blocks successfully\n");
 367        return true;
 368}
 369
 370static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux,
 371                                               const u8 *frame,
 372                                               ssize_t len)
 373{
 374        u8 avi_if[LSPCON_PARADE_AVI_IF_DATA_SIZE] = {1, };
 375
 376        /*
 377         * Parade's frames contains 32 bytes of data, divided
 378         * into 4 frames:
 379         *      Token byte (first byte of first frame, must be non-zero)
 380         *      HB0 to HB2       from AVI IF (3 bytes header)
 381         *      PB0 to PB27 from AVI IF (28 bytes data)
 382         * So it should look like this
 383         *      first block: | <token> <HB0-HB2> <DB0-DB3> |
 384         *      next 3 blocks: |<DB4-DB11>|<DB12-DB19>|<DB20-DB28>|
 385         */
 386
 387        if (len > LSPCON_PARADE_AVI_IF_DATA_SIZE - 1) {
 388                drm_err(aux->drm_dev, "Invalid length of infoframes\n");
 389                return false;
 390        }
 391
 392        memcpy(&avi_if[1], frame, len);
 393
 394        if (!_lspcon_parade_write_infoframe_blocks(aux, avi_if)) {
 395                drm_dbg_kms(aux->drm_dev, "Failed to write infoframe blocks\n");
 396                return false;
 397        }
 398
 399        return true;
 400}
 401
 402static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux,
 403                                            const u8 *buffer, ssize_t len)
 404{
 405        int ret;
 406        u32 val = 0;
 407        u32 retry;
 408        u16 reg;
 409        const u8 *data = buffer;
 410
 411        reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
 412        while (val < len) {
 413                /* DPCD write for AVI IF can fail on a slow FW day, so retry */
 414                for (retry = 0; retry < 5; retry++) {
 415                        ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1);
 416                        if (ret == 1) {
 417                                break;
 418                        } else if (retry < 4) {
 419                                mdelay(50);
 420                                continue;
 421                        } else {
 422                                drm_err(aux->drm_dev, "DPCD write failed at:0x%x\n", reg);
 423                                return false;
 424                        }
 425                }
 426                val++; reg++; data++;
 427        }
 428
 429        val = 0;
 430        reg = LSPCON_MCA_AVI_IF_CTRL;
 431        ret = drm_dp_dpcd_read(aux, reg, &val, 1);
 432        if (ret < 0) {
 433                drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg);
 434                return false;
 435        }
 436
 437        /* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
 438        val &= ~LSPCON_MCA_AVI_IF_HANDLED;
 439        val |= LSPCON_MCA_AVI_IF_KICKOFF;
 440
 441        ret = drm_dp_dpcd_write(aux, reg, &val, 1);
 442        if (ret < 0) {
 443                drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg);
 444                return false;
 445        }
 446
 447        val = 0;
 448        ret = drm_dp_dpcd_read(aux, reg, &val, 1);
 449        if (ret < 0) {
 450                drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg);
 451                return false;
 452        }
 453
 454        if (val == LSPCON_MCA_AVI_IF_HANDLED)
 455                drm_dbg_kms(aux->drm_dev, "AVI IF handled by FW\n");
 456
 457        return true;
 458}
 459
 460void lspcon_write_infoframe(struct intel_encoder *encoder,
 461                            const struct intel_crtc_state *crtc_state,
 462                            unsigned int type,
 463                            const void *frame, ssize_t len)
 464{
 465        bool ret = true;
 466        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 467        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 468        struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
 469
 470        switch (type) {
 471        case HDMI_INFOFRAME_TYPE_AVI:
 472                if (lspcon->vendor == LSPCON_VENDOR_MCA)
 473                        ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
 474                                                              frame, len);
 475                else
 476                        ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
 477                                                                 frame, len);
 478                break;
 479        case HDMI_PACKET_TYPE_GAMUT_METADATA:
 480                drm_dbg_kms(&i915->drm, "Update HDR metadata for lspcon\n");
 481                /* It uses the legacy hsw implementation for the same */
 482                hsw_write_infoframe(encoder, crtc_state, type, frame, len);
 483                break;
 484        default:
 485                return;
 486        }
 487
 488        if (!ret) {
 489                drm_err(&i915->drm, "Failed to write infoframes\n");
 490                return;
 491        }
 492}
 493
 494void lspcon_read_infoframe(struct intel_encoder *encoder,
 495                           const struct intel_crtc_state *crtc_state,
 496                           unsigned int type,
 497                           void *frame, ssize_t len)
 498{
 499        /* FIXME implement for AVI Infoframe as well */
 500        if (type == HDMI_PACKET_TYPE_GAMUT_METADATA)
 501                hsw_read_infoframe(encoder, crtc_state, type,
 502                                   frame, len);
 503}
 504
 505void lspcon_set_infoframes(struct intel_encoder *encoder,
 506                           bool enable,
 507                           const struct intel_crtc_state *crtc_state,
 508                           const struct drm_connector_state *conn_state)
 509{
 510        ssize_t ret;
 511        union hdmi_infoframe frame;
 512        u8 buf[VIDEO_DIP_DATA_SIZE];
 513        struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 514        struct intel_lspcon *lspcon = &dig_port->lspcon;
 515        struct drm_i915_private *i915 = to_i915(encoder->base.dev);
 516        const struct drm_display_mode *adjusted_mode =
 517                &crtc_state->hw.adjusted_mode;
 518
 519        if (!lspcon->active) {
 520                drm_err(&i915->drm, "Writing infoframes while LSPCON disabled ?\n");
 521                return;
 522        }
 523
 524        /* FIXME precompute infoframes */
 525
 526        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
 527                                                       conn_state->connector,
 528                                                       adjusted_mode);
 529        if (ret < 0) {
 530                drm_err(&i915->drm, "couldn't fill AVI infoframe\n");
 531                return;
 532        }
 533
 534        /*
 535         * Currently there is no interface defined to
 536         * check user preference between RGB/YCBCR444
 537         * or YCBCR420. So the only possible case for
 538         * YCBCR444 usage is driving YCBCR420 output
 539         * with LSPCON, when pipe is configured for
 540         * YCBCR444 output and LSPCON takes care of
 541         * downsampling it.
 542         */
 543        if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
 544                frame.avi.colorspace = HDMI_COLORSPACE_YUV420;
 545        else
 546                frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 547
 548        /* Set the Colorspace as per the HDMI spec */
 549        drm_hdmi_avi_infoframe_colorimetry(&frame.avi, conn_state);
 550
 551        /* nonsense combination */
 552        drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&
 553                    crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
 554
 555        if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) {
 556                drm_hdmi_avi_infoframe_quant_range(&frame.avi,
 557                                                   conn_state->connector,
 558                                                   adjusted_mode,
 559                                                   crtc_state->limited_color_range ?
 560                                                   HDMI_QUANTIZATION_RANGE_LIMITED :
 561                                                   HDMI_QUANTIZATION_RANGE_FULL);
 562        } else {
 563                frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
 564                frame.avi.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
 565        }
 566
 567        drm_hdmi_avi_infoframe_content_type(&frame.avi, conn_state);
 568
 569        ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf));
 570        if (ret < 0) {
 571                drm_err(&i915->drm, "Failed to pack AVI IF\n");
 572                return;
 573        }
 574
 575        dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI,
 576                                  buf, ret);
 577}
 578
 579static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux)
 580{
 581        int ret;
 582        u32 val = 0;
 583        u16 reg = LSPCON_MCA_AVI_IF_CTRL;
 584
 585        ret = drm_dp_dpcd_read(aux, reg, &val, 1);
 586        if (ret < 0) {
 587                drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg);
 588                return false;
 589        }
 590
 591        return val & LSPCON_MCA_AVI_IF_KICKOFF;
 592}
 593
 594static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux)
 595{
 596        int ret;
 597        u32 val = 0;
 598        u16 reg = LSPCON_PARADE_AVI_IF_CTRL;
 599
 600        ret = drm_dp_dpcd_read(aux, reg, &val, 1);
 601        if (ret < 0) {
 602                drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg);
 603                return false;
 604        }
 605
 606        return val & LSPCON_PARADE_AVI_IF_KICKOFF;
 607}
 608
 609u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
 610                              const struct intel_crtc_state *pipe_config)
 611{
 612        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 613        struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
 614        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 615        bool infoframes_enabled;
 616        u32 val = 0;
 617        u32 mask, tmp;
 618
 619        if (lspcon->vendor == LSPCON_VENDOR_MCA)
 620                infoframes_enabled = _lspcon_read_avi_infoframe_enabled_mca(&intel_dp->aux);
 621        else
 622                infoframes_enabled = _lspcon_read_avi_infoframe_enabled_parade(&intel_dp->aux);
 623
 624        if (infoframes_enabled)
 625                val |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI);
 626
 627        if (lspcon->hdr_supported) {
 628                tmp = intel_de_read(dev_priv,
 629                                    HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder));
 630                mask = VIDEO_DIP_ENABLE_GMP_HSW;
 631
 632                if (tmp & mask)
 633                        val |= intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
 634        }
 635
 636        return val;
 637}
 638
 639void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon)
 640{
 641        lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON);
 642}
 643
 644bool lspcon_init(struct intel_digital_port *dig_port)
 645{
 646        struct intel_dp *intel_dp = &dig_port->dp;
 647        struct intel_lspcon *lspcon = &dig_port->lspcon;
 648        struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 649        struct drm_connector *connector = &intel_dp->attached_connector->base;
 650
 651        lspcon->active = false;
 652        lspcon->mode = DRM_LSPCON_MODE_INVALID;
 653
 654        if (!lspcon_probe(lspcon)) {
 655                drm_err(&i915->drm, "Failed to probe lspcon\n");
 656                return false;
 657        }
 658
 659        if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) {
 660                drm_err(&i915->drm, "LSPCON DPCD read failed\n");
 661                return false;
 662        }
 663
 664        if (!lspcon_detect_vendor(lspcon)) {
 665                drm_err(&i915->drm, "LSPCON vendor detection failed\n");
 666                return false;
 667        }
 668
 669        connector->ycbcr_420_allowed = true;
 670        lspcon->active = true;
 671        drm_dbg_kms(&i915->drm, "Success: LSPCON init\n");
 672        return true;
 673}
 674
 675u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder,
 676                                    const struct intel_crtc_state *pipe_config)
 677{
 678        struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 679
 680        return dig_port->infoframes_enabled(encoder, pipe_config);
 681}
 682
 683void lspcon_resume(struct intel_digital_port *dig_port)
 684{
 685        struct intel_lspcon *lspcon = &dig_port->lspcon;
 686        struct drm_device *dev = dig_port->base.base.dev;
 687        struct drm_i915_private *i915 = to_i915(dev);
 688        enum drm_lspcon_mode expected_mode;
 689
 690        if (!intel_bios_is_lspcon_present(i915, dig_port->base.port))
 691                return;
 692
 693        if (!lspcon->active) {
 694                if (!lspcon_init(dig_port)) {
 695                        drm_err(&i915->drm, "LSPCON init failed on port %c\n",
 696                                port_name(dig_port->base.port));
 697                        return;
 698                }
 699        }
 700
 701        if (lspcon_wake_native_aux_ch(lspcon)) {
 702                expected_mode = DRM_LSPCON_MODE_PCON;
 703                lspcon_resume_in_pcon_wa(lspcon);
 704        } else {
 705                expected_mode = DRM_LSPCON_MODE_LS;
 706        }
 707
 708        if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON)
 709                return;
 710
 711        if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON))
 712                drm_err(&i915->drm, "LSPCON resume failed\n");
 713        else
 714                drm_dbg_kms(&i915->drm, "LSPCON resume success\n");
 715}
 716