@@ -99,20 +99,6 @@ msm-y := \
msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o
-msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_usbpd.o \
- dp/dp_parser.o \
- dp/dp_power.o \
- dp/dp_catalog.o \
- dp/dp_aux.o \
- dp/dp_panel.o \
- dp/dp_link.o \
- dp/dp_ctrl.o \
- dp/dp_audio.o \
- dp/dp_debug.o \
- dp/dp_display.o \
- dp/dp_drm.o \
- dp/dp_hdcp2p2.o
-
msm_wb-$(CONFIG_DRM_MSM_WRITEBACK) += disp/dpu1/dpu_wb.o \
disp/dpu1/dpu_encoder_phys_wb.o
deleted file mode 100644
@@ -1,806 +0,0 @@
-/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/of_platform.h>
-#include <linux/msm_ext_display.h>
-
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_edid.h>
-
-#include "dp_catalog.h"
-#include "dp_audio.h"
-#include "dp_panel.h"
-
-#define HEADER_BYTE_2_BIT 0
-#define PARITY_BYTE_2_BIT 8
-#define HEADER_BYTE_1_BIT 16
-#define PARITY_BYTE_1_BIT 24
-#define HEADER_BYTE_3_BIT 16
-#define PARITY_BYTE_3_BIT 24
-
-struct dp_audio_private {
- struct platform_device *ext_pdev;
- struct platform_device *pdev;
- struct dp_catalog_audio *catalog;
- struct msm_ext_disp_init_data ext_audio_data;
- struct dp_panel *panel;
-
- bool ack_enabled;
- bool session_on;
- bool engine_on;
-
- u32 channels;
-
- struct completion hpd_comp;
-
- struct dp_audio dp_audio;
-};
-
-static u8 dp_audio_get_g0_value(u8 data)
-{
- u8 c[4];
- u8 g[4];
- u8 ret_data = 0;
- u8 i;
-
- for (i = 0; i < 4; i++)
- c[i] = (data >> i) & 0x01;
-
- g[0] = c[3];
- g[1] = c[0] ^ c[3];
- g[2] = c[1];
- g[3] = c[2];
-
- for (i = 0; i < 4; i++)
- ret_data = ((g[i] & 0x01) << i) | ret_data;
-
- return ret_data;
-}
-
-static u8 dp_audio_get_g1_value(u8 data)
-{
- u8 c[4];
- u8 g[4];
- u8 ret_data = 0;
- u8 i;
-
- for (i = 0; i < 4; i++)
- c[i] = (data >> i) & 0x01;
-
- g[0] = c[0] ^ c[3];
- g[1] = c[0] ^ c[1] ^ c[3];
- g[2] = c[1] ^ c[2];
- g[3] = c[2] ^ c[3];
-
- for (i = 0; i < 4; i++)
- ret_data = ((g[i] & 0x01) << i) | ret_data;
-
- return ret_data;
-}
-
-static u8 dp_audio_calculate_parity(u32 data)
-{
- u8 x0 = 0;
- u8 x1 = 0;
- u8 ci = 0;
- u8 iData = 0;
- u8 i = 0;
- u8 parity_byte;
- u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
-
- for (i = 0; i < num_byte; i++) {
- iData = (data >> i*4) & 0xF;
-
- ci = iData ^ x1;
- x1 = x0 ^ dp_audio_get_g1_value(ci);
- x0 = dp_audio_get_g0_value(ci);
- }
-
- parity_byte = x1 | (x0 << 4);
-
- return parity_byte;
-}
-
-static u32 dp_audio_get_header(struct dp_catalog_audio *catalog,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header)
-{
- catalog->sdp_type = sdp;
- catalog->sdp_header = header;
- catalog->get_header(catalog);
-
- return catalog->data;
-}
-
-static void dp_audio_set_header(struct dp_catalog_audio *catalog,
- u32 data,
- enum dp_catalog_audio_sdp_type sdp,
- enum dp_catalog_audio_header_type header)
-{
- catalog->sdp_type = sdp;
- catalog->sdp_header = header;
- catalog->data = data;
- catalog->set_header(catalog);
-}
-
-static void dp_audio_stream_sdp(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 value, new_value;
- u8 parity_byte;
-
- /* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
-
- new_value = 0x02;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_1_BIT)
- | (parity_byte << PARITY_BYTE_1_BIT));
- pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
-
- /* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
- new_value = value;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_2_BIT)
- | (parity_byte << PARITY_BYTE_2_BIT));
- pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
-
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
-
- /* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
-
- new_value = audio->channels - 1;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_3_BIT)
- | (parity_byte << PARITY_BYTE_3_BIT));
- pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
-
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
-}
-
-static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 value, new_value;
- u8 parity_byte;
-
- /* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
-
- new_value = 0x1;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_1_BIT)
- | (parity_byte << PARITY_BYTE_1_BIT));
- pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
-
- /* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
-
- new_value = 0x17;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_2_BIT)
- | (parity_byte << PARITY_BYTE_2_BIT));
- pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
-
- /* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
-
- new_value = (0x0 | (0x11 << 2));
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_3_BIT)
- | (parity_byte << PARITY_BYTE_3_BIT));
- pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
-}
-
-static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 value, new_value;
- u8 parity_byte;
-
- /* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
-
- new_value = 0x84;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_1_BIT)
- | (parity_byte << PARITY_BYTE_1_BIT));
- pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
-
- /* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
-
- new_value = 0x1b;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_2_BIT)
- | (parity_byte << PARITY_BYTE_2_BIT));
- pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
-
- /* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
-
- new_value = (0x0 | (0x11 << 2));
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_3_BIT)
- | (parity_byte << PARITY_BYTE_3_BIT));
- pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
- new_value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
-}
-
-static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 value, new_value;
- u8 parity_byte;
-
- /* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
-
- new_value = 0x05;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_1_BIT)
- | (parity_byte << PARITY_BYTE_1_BIT));
- pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
-
- /* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
-
- new_value = 0x0F;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_2_BIT)
- | (parity_byte << PARITY_BYTE_2_BIT));
- pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
-
- /* Config header and parity byte 3 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
-
- new_value = 0x0;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_3_BIT)
- | (parity_byte << PARITY_BYTE_3_BIT));
- pr_debug("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
-}
-
-static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 value, new_value;
- u8 parity_byte;
-
- /* Config header and parity byte 1 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
-
- new_value = 0x06;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_1_BIT)
- | (parity_byte << PARITY_BYTE_1_BIT));
- pr_debug("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
-
- /* Config header and parity byte 2 */
- value = dp_audio_get_header(catalog,
- DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
-
- new_value = 0x0F;
- parity_byte = dp_audio_calculate_parity(new_value);
- value |= ((new_value << HEADER_BYTE_2_BIT)
- | (parity_byte << PARITY_BYTE_2_BIT));
- pr_debug("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n",
- value, parity_byte);
- dp_audio_set_header(catalog, value,
- DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
-}
-
-static void dp_audio_setup_sdp(struct dp_audio_private *audio)
-{
- audio->catalog->config_sdp(audio->catalog);
-
- dp_audio_stream_sdp(audio);
- dp_audio_timestamp_sdp(audio);
- dp_audio_infoframe_sdp(audio);
- dp_audio_copy_management_sdp(audio);
- dp_audio_isrc_sdp(audio);
-}
-
-static void dp_audio_setup_acr(struct dp_audio_private *audio)
-{
- u32 select = 0;
- struct dp_catalog_audio *catalog = audio->catalog;
-
- switch (audio->dp_audio.bw_code) {
- case DP_LINK_BW_1_62:
- select = 0;
- break;
- case DP_LINK_BW_2_7:
- select = 1;
- break;
- case DP_LINK_BW_5_4:
- select = 2;
- break;
- case DP_LINK_BW_8_1:
- select = 3;
- break;
- default:
- pr_debug("Unknown link rate\n");
- select = 0;
- break;
- }
-
- catalog->data = select;
- catalog->config_acr(catalog);
-}
-
-static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
- u32 safe_to_exit_level = 0;
-
- switch (audio->dp_audio.lane_count) {
- case 1:
- safe_to_exit_level = 14;
- break;
- case 2:
- safe_to_exit_level = 8;
- break;
- case 4:
- safe_to_exit_level = 5;
- break;
- default:
- pr_debug("setting the default safe_to_exit_level = %u\n",
- safe_to_exit_level);
- safe_to_exit_level = 14;
- break;
- }
-
- catalog->data = safe_to_exit_level;
- catalog->safe_to_exit_level(catalog);
-}
-
-static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
-{
- struct dp_catalog_audio *catalog = audio->catalog;
-
- catalog->data = enable;
- catalog->enable(catalog);
-
- audio->engine_on = enable;
-}
-
-static struct dp_audio_private *get_audio_get_data(struct platform_device *pdev)
-{
- struct msm_ext_disp_data *ext_data;
- struct dp_audio *dp_audio;
-
- if (!pdev) {
- pr_err("invalid input\n");
- return ERR_PTR(-ENODEV);
- }
-
- ext_data = platform_get_drvdata(pdev);
- if (!ext_data) {
- pr_err("invalid ext disp data\n");
- return ERR_PTR(-EINVAL);
- }
-
- dp_audio = ext_data->intf_data;
- if (!ext_data) {
- pr_err("invalid intf data\n");
- return ERR_PTR(-EINVAL);
- }
-
- return container_of(dp_audio, struct dp_audio_private, dp_audio);
-}
-
-static int dp_audio_info_setup(struct platform_device *pdev,
- struct msm_ext_disp_audio_setup_params *params)
-{
- int rc = 0;
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio)) {
- rc = PTR_ERR(audio);
- goto end;
- }
-
- audio->channels = params->num_of_channels;
-
- dp_audio_setup_sdp(audio);
- dp_audio_setup_acr(audio);
- dp_audio_safe_to_exit_level(audio);
- dp_audio_enable(audio, true);
-end:
- return rc;
-}
-
-static int dp_audio_get_edid_blk(struct platform_device *pdev,
- struct msm_ext_disp_audio_edid_blk *blk)
-{
- int rc = 0;
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio)) {
- rc = PTR_ERR(audio);
- goto end;
- }
-
- if (!audio->panel || !audio->panel->edid) {
- pr_err("invalid panel data\n");
- rc = -EINVAL;
- goto end;
- }
-
-/*
- * TODO:
- * audio_data_blk should be changed to be a cea_sad array
- * audio_data_blk_size should be changed to contain a count of sads
- *
- * Once this is done, use drm_edid_to_sad() to extract this from
- * audio->panel->edid. I'd change this, but I don't have that code :/
- */
-#if 0
- blk->audio_data_blk = edid->audio_data_block;
- blk->audio_data_blk_size = edid->adb_size;
-#endif
-
- blk->spk_alloc_data_blk_size = drm_edid_to_speaker_allocation(
- audio->panel->edid,
- blk->spkr_alloc_data_block);
-
-end:
- return rc;
-}
-
-static int dp_audio_get_cable_status(struct platform_device *pdev, u32 vote)
-{
- int rc = 0;
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio)) {
- rc = PTR_ERR(audio);
- goto end;
- }
-
- if (!audio->panel) {
- pr_err("invalid panel data\n");
- rc = -EINVAL;
- goto end;
- }
-
- return audio->session_on;
-end:
- return rc;
-}
-
-static int dp_audio_get_intf_id(struct platform_device *pdev)
-{
- int rc = 0;
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio)) {
- rc = PTR_ERR(audio);
- goto end;
- }
-
- return EXT_DISPLAY_TYPE_DP;
-end:
- return rc;
-}
-
-static void dp_audio_teardown_done(struct platform_device *pdev)
-{
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio))
- return;
-
- if (!audio->panel) {
- pr_err("invalid panel data\n");
- return;
- }
-
- dp_audio_enable(audio, false);
-
- complete_all(&audio->hpd_comp);
-
- pr_debug("audio engine disabled\n");
-}
-
-static int dp_audio_ack_done(struct platform_device *pdev, u32 ack)
-{
- int rc = 0, ack_hpd;
- struct dp_audio_private *audio;
-
- audio = get_audio_get_data(pdev);
- if (IS_ERR(audio)) {
- rc = PTR_ERR(audio);
- goto end;
- }
-
- if (ack & AUDIO_ACK_SET_ENABLE) {
- audio->ack_enabled = ack & AUDIO_ACK_ENABLE ?
- true : false;
-
- pr_debug("audio ack feature %s\n",
- audio->ack_enabled ? "enabled" : "disabled");
- goto end;
- }
-
- if (!audio->ack_enabled)
- goto end;
-
- ack_hpd = ack & AUDIO_ACK_CONNECT;
-
- pr_debug("acknowledging audio (%d)\n", ack_hpd);
-
- if (!audio->engine_on)
- complete_all(&audio->hpd_comp);
-end:
- return rc;
-}
-
-static int dp_audio_init_ext_disp(struct dp_audio_private *audio)
-{
- int rc = 0;
- struct device_node *pd = NULL;
- const char *phandle = "qcom,ext-disp";
- struct msm_ext_disp_init_data *ext;
- struct msm_ext_disp_audio_codec_ops *ops;
-
- ext = &audio->ext_audio_data;
- ops = &ext->codec_ops;
-
- ext->type = EXT_DISPLAY_TYPE_DP;
- ext->pdev = audio->pdev;
- ext->intf_data = &audio->dp_audio;
-
- ops->audio_info_setup = dp_audio_info_setup;
- ops->get_audio_edid_blk = dp_audio_get_edid_blk;
- ops->cable_status = dp_audio_get_cable_status;
- ops->get_intf_id = dp_audio_get_intf_id;
- ops->teardown_done = dp_audio_teardown_done;
- ops->acknowledge = dp_audio_ack_done;
-
- if (!audio->pdev->dev.of_node) {
- pr_err("cannot find audio dev.of_node\n");
- rc = -ENODEV;
- goto end;
- }
-
- pd = of_parse_phandle(audio->pdev->dev.of_node, phandle, 0);
- if (!pd) {
- pr_err("cannot parse %s handle\n", phandle);
- rc = -ENODEV;
- goto end;
- }
-
- audio->ext_pdev = of_find_device_by_node(pd);
- if (!audio->ext_pdev) {
- pr_err("cannot find %s pdev\n", phandle);
- rc = -ENODEV;
- goto end;
- }
-
- rc = msm_ext_disp_register_intf(audio->ext_pdev, ext);
- if (rc)
- pr_err("failed to register disp\n");
-end:
- if (pd)
- of_node_put(pd);
-
- return rc;
-}
-
-static int dp_audio_on(struct dp_audio *dp_audio)
-{
- int rc = 0;
- struct dp_audio_private *audio;
- struct msm_ext_disp_init_data *ext;
-
- if (!dp_audio) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
-
- ext = &audio->ext_audio_data;
-
- audio->session_on = true;
-
- rc = ext->intf_ops.audio_config(audio->ext_pdev,
- EXT_DISPLAY_TYPE_DP,
- EXT_DISPLAY_CABLE_CONNECT);
- if (rc) {
- pr_err("failed to config audio, err=%d\n", rc);
- goto end;
- }
-
- rc = ext->intf_ops.audio_notify(audio->ext_pdev,
- EXT_DISPLAY_TYPE_DP,
- EXT_DISPLAY_CABLE_CONNECT);
- if (rc) {
- pr_err("failed to notify audio, err=%d\n", rc);
- goto end;
- }
-
- reinit_completion(&audio->hpd_comp);
- rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 5);
- if (!rc) {
- pr_err("timeout\n");
- rc = -ETIMEDOUT;
- goto end;
- }
-
- pr_debug("success\n");
-end:
- return rc;
-}
-
-static int dp_audio_off(struct dp_audio *dp_audio)
-{
- int rc = 0;
- struct dp_audio_private *audio;
- struct msm_ext_disp_init_data *ext;
-
- if (!dp_audio) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
- ext = &audio->ext_audio_data;
-
- rc = ext->intf_ops.audio_notify(audio->ext_pdev,
- EXT_DISPLAY_TYPE_DP,
- EXT_DISPLAY_CABLE_DISCONNECT);
- if (rc) {
- pr_err("failed to notify audio, err=%d\n", rc);
- goto end;
- }
-
- reinit_completion(&audio->hpd_comp);
- rc = wait_for_completion_timeout(&audio->hpd_comp, HZ * 5);
- if (!rc) {
- pr_err("timeout\n");
- rc = -ETIMEDOUT;
- goto end;
- }
-
- pr_debug("success\n");
-end:
- rc = ext->intf_ops.audio_config(audio->ext_pdev,
- EXT_DISPLAY_TYPE_DP,
- EXT_DISPLAY_CABLE_DISCONNECT);
- if (rc)
- pr_err("failed to config audio, err=%d\n", rc);
-
- audio->session_on = false;
- audio->engine_on = false;
-
- return rc;
-}
-
-struct dp_audio *dp_audio_get(struct platform_device *pdev,
- struct dp_panel *panel,
- struct dp_catalog_audio *catalog)
-{
- int rc = 0;
- struct dp_audio_private *audio;
- struct dp_audio *dp_audio;
-
- if (!pdev || !panel || !catalog) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
- if (!audio) {
- rc = -ENOMEM;
- goto error;
- }
-
- init_completion(&audio->hpd_comp);
-
- audio->pdev = pdev;
- audio->panel = panel;
- audio->catalog = catalog;
-
- dp_audio = &audio->dp_audio;
-
- dp_audio->on = dp_audio_on;
- dp_audio->off = dp_audio_off;
-
- rc = dp_audio_init_ext_disp(audio);
- if (rc) {
- devm_kfree(&pdev->dev, audio);
- goto error;
- }
-
- catalog->init(catalog);
-
- return dp_audio;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_audio_put(struct dp_audio *dp_audio)
-{
- struct dp_audio_private *audio;
-
- if (!dp_audio)
- return;
-
- audio = container_of(dp_audio, struct dp_audio_private, dp_audio);
-
- devm_kfree(&audio->pdev->dev, audio);
-}
deleted file mode 100644
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_AUDIO_H_
-#define _DP_AUDIO_H_
-
-#include <linux/platform_device.h>
-
-#include "dp_panel.h"
-#include "dp_catalog.h"
-
-/**
- * struct dp_audio
- * @lane_count: number of lanes configured in current session
- * @bw_code: link rate's bandwidth code for current session
- */
-struct dp_audio {
- u32 lane_count;
- u32 bw_code;
-
- /**
- * on()
- *
- * Enables the audio by notifying the user module.
- *
- * @dp_audio: an instance of struct dp_audio.
- *
- * Returns the error code in case of failure, 0 in success case.
- */
- int (*on)(struct dp_audio *dp_audio);
-
- /**
- * off()
- *
- * Disables the audio by notifying the user module.
- *
- * @dp_audio: an instance of struct dp_audio.
- *
- * Returns the error code in case of failure, 0 in success case.
- */
- int (*off)(struct dp_audio *dp_audio);
-};
-
-/**
- * dp_audio_get()
- *
- * Creates and instance of dp audio.
- *
- * @pdev: caller's platform device instance.
- * @panel: an instance of dp_panel module.
- * @catalog: an instance of dp_catalog_audio module.
- *
- * Returns the error code in case of failure, otherwize
- * an instance of newly created dp_module.
- */
-struct dp_audio *dp_audio_get(struct platform_device *pdev,
- struct dp_panel *panel,
- struct dp_catalog_audio *catalog);
-
-/**
- * dp_audio_put()
- *
- * Cleans the dp_audio instance.
- *
- * @dp_audio: an instance of dp_audio.
- */
-void dp_audio_put(struct dp_audio *dp_audio);
-#endif /* _DP_AUDIO_H_ */
-
-
deleted file mode 100644
@@ -1,570 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/delay.h>
-
-#include "dp_aux.h"
-
-#define DP_AUX_ENUM_STR(x) #x
-
-enum {
- DP_AUX_DATA_INDEX_WRITE = BIT(31),
-};
-
-struct dp_aux_private {
- struct device *dev;
- struct dp_aux dp_aux;
- struct dp_catalog_aux *catalog;
- struct dp_aux_cfg *cfg;
-
- struct mutex mutex;
- struct completion comp;
-
- u32 aux_error_num;
- u32 retry_cnt;
- bool cmd_busy;
- bool native;
- bool read;
- bool no_send_addr;
- bool no_send_stop;
- u32 offset;
- u32 segment;
-
- struct drm_dp_aux drm_aux;
-};
-
-static char *dp_aux_get_error(u32 aux_error)
-{
- switch (aux_error) {
- case DP_AUX_ERR_NONE:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE);
- case DP_AUX_ERR_ADDR:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR);
- case DP_AUX_ERR_TOUT:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT);
- case DP_AUX_ERR_NACK:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK);
- case DP_AUX_ERR_DEFER:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER);
- case DP_AUX_ERR_NACK_DEFER:
- return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER);
- default:
- return "unknown";
- }
-}
-
-static u32 dp_aux_write(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *msg)
-{
- u32 data[4], reg, len;
- u8 *msgdata = msg->buffer;
- int const aux_cmd_fifo_len = 128;
- int i = 0;
-
- if (aux->read)
- len = 4;
- else
- len = msg->size + 4;
-
- /*
- * cmd fifo only has depth of 144 bytes
- * limit buf length to 128 bytes here
- */
- if (len > aux_cmd_fifo_len) {
- pr_err("buf len error\n");
- return 0;
- }
-
- /* Pack cmd and write to HW */
- data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */
- if (aux->read)
- data[0] |= BIT(4); /* R/W */
-
- data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */
- data[2] = msg->address & 0xff; /* addr[7:0] */
- data[3] = (msg->size - 1) & 0xff; /* len[7:0] */
-
- for (i = 0; i < len; i++) {
- reg = (i < 4) ? data[i] : msgdata[i - 4];
- reg = ((reg) << 8) & 0x0000ff00; /* index = 0, write */
- if (i == 0)
- reg |= DP_AUX_DATA_INDEX_WRITE;
- aux->catalog->data = reg;
- aux->catalog->write_data(aux->catalog);
- }
-
- aux->catalog->clear_trans(aux->catalog, false);
-
- reg = 0; /* Transaction number == 1 */
- if (!aux->native) { /* i2c */
- reg |= BIT(8);
-
- if (aux->no_send_addr)
- reg |= BIT(10);
-
- if (aux->no_send_stop)
- reg |= BIT(11);
- }
-
- reg |= BIT(9);
- aux->catalog->data = reg;
- aux->catalog->write_trans(aux->catalog);
-
- return len;
-}
-
-static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *msg)
-{
- u32 ret = 0, len = 0, timeout;
- int const aux_timeout_ms = HZ/4;
-
- reinit_completion(&aux->comp);
-
- len = dp_aux_write(aux, msg);
- if (len == 0) {
- pr_err("DP AUX write failed\n");
- return -EINVAL;
- }
-
- timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms);
- if (!timeout) {
- pr_err("aux %s timeout\n", (aux->read ? "read" : "write"));
- return -ETIMEDOUT;
- }
-
- if (aux->aux_error_num == DP_AUX_ERR_NONE) {
- ret = len;
- } else {
- pr_err_ratelimited("aux err: %s\n",
- dp_aux_get_error(aux->aux_error_num));
-
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *msg)
-{
- u32 data;
- u8 *dp;
- u32 i, actual_i;
- u32 len = msg->size;
-
- aux->catalog->clear_trans(aux->catalog, true);
-
- data = 0;
- data |= DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */
- data |= BIT(0); /* read */
-
- aux->catalog->data = data;
- aux->catalog->write_data(aux->catalog);
-
- dp = msg->buffer;
-
- /* discard first byte */
- data = aux->catalog->read_data(aux->catalog);
-
- for (i = 0; i < len; i++) {
- data = aux->catalog->read_data(aux->catalog);
- *dp++ = (u8)((data >> 8) & 0xff);
-
- actual_i = (data >> 16) & 0xFF;
- if (i != actual_i)
- pr_warn("Index mismatch: expected %d, found %d\n",
- i, actual_i);
- }
-}
-
-static void dp_aux_native_handler(struct dp_aux_private *aux)
-{
- u32 isr = aux->catalog->isr;
-
- if (isr & DP_INTR_AUX_I2C_DONE)
- aux->aux_error_num = DP_AUX_ERR_NONE;
- else if (isr & DP_INTR_WRONG_ADDR)
- aux->aux_error_num = DP_AUX_ERR_ADDR;
- else if (isr & DP_INTR_TIMEOUT)
- aux->aux_error_num = DP_AUX_ERR_TOUT;
- if (isr & DP_INTR_NACK_DEFER)
- aux->aux_error_num = DP_AUX_ERR_NACK;
-
- complete(&aux->comp);
-}
-
-static void dp_aux_i2c_handler(struct dp_aux_private *aux)
-{
- u32 isr = aux->catalog->isr;
-
- if (isr & DP_INTR_AUX_I2C_DONE) {
- if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER))
- aux->aux_error_num = DP_AUX_ERR_NACK;
- else
- aux->aux_error_num = DP_AUX_ERR_NONE;
- } else {
- if (isr & DP_INTR_WRONG_ADDR)
- aux->aux_error_num = DP_AUX_ERR_ADDR;
- else if (isr & DP_INTR_TIMEOUT)
- aux->aux_error_num = DP_AUX_ERR_TOUT;
- if (isr & DP_INTR_NACK_DEFER)
- aux->aux_error_num = DP_AUX_ERR_NACK_DEFER;
- if (isr & DP_INTR_I2C_NACK)
- aux->aux_error_num = DP_AUX_ERR_NACK;
- if (isr & DP_INTR_I2C_DEFER)
- aux->aux_error_num = DP_AUX_ERR_DEFER;
- }
-
- complete(&aux->comp);
-}
-
-static void dp_aux_isr(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux) {
- pr_err("invalid input\n");
- return;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- aux->catalog->get_irq(aux->catalog, aux->cmd_busy);
-
- if (!aux->cmd_busy)
- return;
-
- if (aux->native)
- dp_aux_native_handler(aux);
- else
- dp_aux_i2c_handler(aux);
-}
-
-static void dp_aux_reconfig(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux) {
- pr_err("invalid input\n");
- return;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- aux->catalog->update_aux_cfg(aux->catalog,
- aux->cfg, PHY_AUX_CFG1);
- aux->catalog->reset(aux->catalog);
-}
-
-static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *input_msg)
-{
- u32 const edid_address = 0x50;
- u32 const segment_address = 0x30;
- bool i2c_read = input_msg->request &
- (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
- u8 *data = NULL;
-
- if (aux->native || i2c_read || ((input_msg->address != edid_address) &&
- (input_msg->address != segment_address)))
- return;
-
-
- data = input_msg->buffer;
- if (input_msg->address == segment_address)
- aux->segment = *data;
- else
- aux->offset = *data;
-}
-
-/**
- * dp_aux_transfer_helper() - helper function for EDID read transactions
- *
- * @aux: DP AUX private structure
- * @input_msg: input message from DRM upstream APIs
- *
- * return: void
- *
- * This helper function is used to fix EDID reads for non-compliant
- * sinks that do not handle the i2c middle-of-transaction flag correctly.
- */
-static void dp_aux_transfer_helper(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *input_msg)
-{
- struct drm_dp_aux_msg helper_msg;
- u32 const message_size = 0x10;
- u32 const segment_address = 0x30;
- bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT;
- bool i2c_read = input_msg->request &
- (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
-
- if (!i2c_mot || !i2c_read || (input_msg->size == 0))
- return;
-
- aux->read = false;
- aux->cmd_busy = true;
- aux->no_send_addr = true;
- aux->no_send_stop = true;
-
- /*
- * Send the segment address for every i2c read in which the
- * middle-of-tranaction flag is set. This is required to support EDID
- * reads of more than 2 blocks as the segment address is reset to 0
- * since we are overriding the middle-of-transaction flag for read
- * transactions.
- */
- memset(&helper_msg, 0, sizeof(helper_msg));
- helper_msg.address = segment_address;
- helper_msg.buffer = &aux->segment;
- helper_msg.size = 1;
- dp_aux_cmd_fifo_tx(aux, &helper_msg);
-
- /*
- * Send the offset address for every i2c read in which the
- * middle-of-transaction flag is set. This will ensure that the sink
- * will update its read pointer and return the correct portion of the
- * EDID buffer in the subsequent i2c read trasntion triggered in the
- * native AUX transfer function.
- */
- memset(&helper_msg, 0, sizeof(helper_msg));
- helper_msg.address = input_msg->address;
- helper_msg.buffer = &aux->offset;
- helper_msg.size = 1;
- dp_aux_cmd_fifo_tx(aux, &helper_msg);
- aux->offset += message_size;
-
- if (aux->offset == 0x80 || aux->offset == 0x100)
- aux->segment = 0x0; /* reset segment at end of block */
-}
-
-/*
- * This function does the real job to process an AUX transaction.
- * It will call aux_reset() function to reset the AUX channel,
- * if the waiting is timeout.
- */
-static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
- struct drm_dp_aux_msg *msg)
-{
- ssize_t ret;
- int const aux_cmd_native_max = 16;
- int const aux_cmd_i2c_max = 128;
- int const retry_count = 5;
- struct dp_aux_private *aux = container_of(drm_aux,
- struct dp_aux_private, drm_aux);
-
- mutex_lock(&aux->mutex);
-
- aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
-
- /* Ignore address only message */
- if ((msg->size == 0) || (msg->buffer == NULL)) {
- msg->reply = aux->native ?
- DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
- ret = msg->size;
- goto unlock_exit;
- }
-
- /* msg sanity check */
- if ((aux->native && (msg->size > aux_cmd_native_max)) ||
- (msg->size > aux_cmd_i2c_max)) {
- pr_err("%s: invalid msg: size(%zu), request(%x)\n",
- __func__, msg->size, msg->request);
- ret = -EINVAL;
- goto unlock_exit;
- }
-
- dp_aux_update_offset_and_segment(aux, msg);
- dp_aux_transfer_helper(aux, msg);
-
- aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
- aux->cmd_busy = true;
-
- if (aux->read) {
- aux->no_send_addr = true;
- aux->no_send_stop = false;
- } else {
- aux->no_send_addr = true;
- aux->no_send_stop = true;
- }
-
- ret = dp_aux_cmd_fifo_tx(aux, msg);
- if ((ret < 0) && aux->native) {
- aux->retry_cnt++;
- if (!(aux->retry_cnt % retry_count))
- aux->catalog->update_aux_cfg(aux->catalog,
- aux->cfg, PHY_AUX_CFG1);
- aux->catalog->reset(aux->catalog);
- goto unlock_exit;
- } else if (ret < 0) {
- goto unlock_exit;
- }
-
- if (aux->aux_error_num == DP_AUX_ERR_NONE) {
- if (aux->read)
- dp_aux_cmd_fifo_rx(aux, msg);
-
- msg->reply = aux->native ?
- DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
- } else {
- /* Reply defer to retry */
- msg->reply = aux->native ?
- DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
- }
-
- /* Return requested size for success or retry */
- ret = msg->size;
- aux->retry_cnt = 0;
-
-unlock_exit:
- aux->cmd_busy = false;
- mutex_unlock(&aux->mutex);
- return ret;
-}
-
-static void dp_aux_reset_phy_config_indices(struct dp_aux_cfg *aux_cfg)
-{
- int i = 0;
-
- for (i = 0; i < PHY_AUX_CFG_MAX; i++)
- aux_cfg[i].current_index = 0;
-}
-
-static void dp_aux_init(struct dp_aux *dp_aux, struct dp_aux_cfg *aux_cfg)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux || !aux_cfg) {
- pr_err("invalid input\n");
- return;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- aux->catalog->reset(aux->catalog);
- aux->catalog->enable(aux->catalog, true);
- aux->retry_cnt = 0;
- dp_aux_reset_phy_config_indices(aux_cfg);
- aux->catalog->setup(aux->catalog, aux_cfg);
-}
-
-static void dp_aux_deinit(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux) {
- pr_err("invalid input\n");
- return;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- aux->catalog->enable(aux->catalog, false);
-}
-
-static int dp_aux_register(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
- int ret = 0;
-
- if (!dp_aux) {
- pr_err("invalid input\n");
- ret = -EINVAL;
- goto exit;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- aux->drm_aux.name = "dpu_dp_aux";
- aux->drm_aux.dev = aux->dev;
- aux->drm_aux.transfer = dp_aux_transfer;
- ret = drm_dp_aux_register(&aux->drm_aux);
- if (ret) {
- pr_err("%s: failed to register drm aux: %d\n", __func__, ret);
- goto exit;
- }
- dp_aux->drm_aux = &aux->drm_aux;
-exit:
- return ret;
-}
-
-static void dp_aux_deregister(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux) {
- pr_err("invalid input\n");
- return;
- }
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
- drm_dp_aux_unregister(&aux->drm_aux);
-}
-
-struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
- struct dp_aux_cfg *aux_cfg)
-{
- int rc = 0;
- struct dp_aux_private *aux;
- struct dp_aux *dp_aux;
-
- if (!catalog || !aux_cfg) {
- pr_err("invalid input\n");
- rc = -ENODEV;
- goto error;
- }
-
- aux = devm_kzalloc(dev, sizeof(*aux), GFP_KERNEL);
- if (!aux) {
- rc = -ENOMEM;
- goto error;
- }
-
- init_completion(&aux->comp);
- aux->cmd_busy = false;
- mutex_init(&aux->mutex);
-
- aux->dev = dev;
- aux->catalog = catalog;
- aux->cfg = aux_cfg;
- dp_aux = &aux->dp_aux;
- aux->retry_cnt = 0;
-
- dp_aux->isr = dp_aux_isr;
- dp_aux->init = dp_aux_init;
- dp_aux->deinit = dp_aux_deinit;
- dp_aux->drm_aux_register = dp_aux_register;
- dp_aux->drm_aux_deregister = dp_aux_deregister;
- dp_aux->reconfig = dp_aux_reconfig;
-
- return dp_aux;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_aux_put(struct dp_aux *dp_aux)
-{
- struct dp_aux_private *aux;
-
- if (!dp_aux)
- return;
-
- aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
- mutex_destroy(&aux->mutex);
-
- devm_kfree(aux->dev, aux);
-}
deleted file mode 100644
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_AUX_H_
-#define _DP_AUX_H_
-
-#include "dp_catalog.h"
-#include <drm/drm_dp_helper.h>
-
-enum dp_aux_error {
- DP_AUX_ERR_NONE = 0,
- DP_AUX_ERR_ADDR = -1,
- DP_AUX_ERR_TOUT = -2,
- DP_AUX_ERR_NACK = -3,
- DP_AUX_ERR_DEFER = -4,
- DP_AUX_ERR_NACK_DEFER = -5,
-};
-
-struct dp_aux {
- struct drm_dp_aux *drm_aux;
- int (*drm_aux_register)(struct dp_aux *aux);
- void (*drm_aux_deregister)(struct dp_aux *aux);
- void (*isr)(struct dp_aux *aux);
- void (*init)(struct dp_aux *aux, struct dp_aux_cfg *aux_cfg);
- void (*deinit)(struct dp_aux *aux);
- void (*reconfig)(struct dp_aux *aux);
-};
-
-struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
- struct dp_aux_cfg *aux_cfg);
-void dp_aux_put(struct dp_aux *aux);
-
-#endif /*__DP_AUX_H_*/
deleted file mode 100644
@@ -1,1320 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/delay.h>
-#include <drm/drm_dp_helper.h>
-
-#include "dp_catalog.h"
-#include "dp_reg.h"
-
-#define DP_GET_MSB(x) (x >> 8)
-#define DP_GET_LSB(x) (x & 0xff)
-
-#define dp_read(offset) readl_relaxed((offset))
-#define dp_write(offset, data) writel_relaxed((data), (offset))
-
-#define dp_catalog_get_priv(x) { \
- struct dp_catalog *dp_catalog; \
- dp_catalog = container_of(x, struct dp_catalog, x); \
- catalog = container_of(dp_catalog, struct dp_catalog_private, \
- dp_catalog); \
-}
-
-#define DP_INTERRUPT_STATUS1 \
- (DP_INTR_AUX_I2C_DONE| \
- DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
- DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \
- DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \
- DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR)
-
-#define DP_INTR_MASK1 (DP_INTERRUPT_STATUS1 << 2)
-
-#define DP_INTERRUPT_STATUS2 \
- (DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \
- DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED)
-
-#define DP_INTR_MASK2 (DP_INTERRUPT_STATUS2 << 2)
-
-static u8 const vm_pre_emphasis[4][4] = {
- {0x00, 0x0B, 0x12, 0xFF}, /* pe0, 0 db */
- {0x00, 0x0A, 0x12, 0xFF}, /* pe1, 3.5 db */
- {0x00, 0x0C, 0xFF, 0xFF}, /* pe2, 6.0 db */
- {0xFF, 0xFF, 0xFF, 0xFF} /* pe3, 9.5 db */
-};
-
-/* voltage swing, 0.2v and 1.0v are not support */
-static u8 const vm_voltage_swing[4][4] = {
- {0x07, 0x0F, 0x14, 0xFF}, /* sw0, 0.4v */
- {0x11, 0x1D, 0x1F, 0xFF}, /* sw1, 0.6 v */
- {0x18, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
- {0xFF, 0xFF, 0xFF, 0xFF} /* sw1, 1.2 v, optional */
-};
-
-/* audio related catalog functions */
-struct dp_catalog_private {
- struct device *dev;
- struct dp_io *io;
-
- u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX];
- struct dp_catalog dp_catalog;
-};
-
-/* aux related catalog functions */
-static u32 dp_catalog_aux_read_data(struct dp_catalog_aux *aux)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- goto end;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- return dp_read(base + DP_AUX_DATA);
-end:
- return 0;
-}
-
-static int dp_catalog_aux_write_data(struct dp_catalog_aux *aux)
-{
- int rc = 0;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_AUX_DATA, aux->data);
-end:
- return rc;
-}
-
-static int dp_catalog_aux_write_trans(struct dp_catalog_aux *aux)
-{
- int rc = 0;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_AUX_TRANS_CTRL, aux->data);
-end:
- return rc;
-}
-
-static int dp_catalog_aux_clear_trans(struct dp_catalog_aux *aux, bool read)
-{
- int rc = 0;
- u32 data = 0;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- if (read) {
- data = dp_read(base + DP_AUX_TRANS_CTRL);
- data &= ~BIT(9);
- dp_write(base + DP_AUX_TRANS_CTRL, data);
- } else {
- dp_write(base + DP_AUX_TRANS_CTRL, 0);
- }
-end:
- return rc;
-}
-
-static void dp_catalog_aux_reset(struct dp_catalog_aux *aux)
-{
- u32 aux_ctrl;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- aux_ctrl = dp_read(base + DP_AUX_CTRL);
-
- aux_ctrl |= BIT(1);
- dp_write(base + DP_AUX_CTRL, aux_ctrl);
- usleep_range(1000, 1010); /* h/w recommended delay */
-
- aux_ctrl &= ~BIT(1);
- dp_write(base + DP_AUX_CTRL, aux_ctrl);
-}
-
-static void dp_catalog_aux_enable(struct dp_catalog_aux *aux, bool enable)
-{
- u32 aux_ctrl;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- aux_ctrl = dp_read(base + DP_AUX_CTRL);
-
- if (enable) {
- dp_write(base + DP_TIMEOUT_COUNT, 0xffff);
- dp_write(base + DP_AUX_LIMITS, 0xffff);
- aux_ctrl |= BIT(0);
- } else {
- aux_ctrl &= ~BIT(0);
- }
-
- dp_write(base + DP_AUX_CTRL, aux_ctrl);
-}
-
-static void dp_catalog_aux_update_cfg(struct dp_catalog_aux *aux,
- struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type)
-{
- struct dp_catalog_private *catalog;
- u32 new_index = 0, current_index = 0;
-
- if (!aux || !cfg || (type >= PHY_AUX_CFG_MAX)) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(aux);
-
- current_index = cfg[type].current_index;
- new_index = (current_index + 1) % cfg[type].cfg_cnt;
- pr_debug("Updating %s from 0x%08x to 0x%08x\n",
- dp_phy_aux_config_type_to_string(type),
- cfg[type].lut[current_index], cfg[type].lut[new_index]);
-
- dp_write(catalog->io->phy_io.base + cfg[type].offset,
- cfg[type].lut[new_index]);
- cfg[type].current_index = new_index;
-}
-
-static void dp_catalog_aux_setup(struct dp_catalog_aux *aux,
- struct dp_aux_cfg *cfg)
-{
- struct dp_catalog_private *catalog;
- int i = 0;
-
- if (!aux || !cfg) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(aux);
-
- dp_write(catalog->io->phy_io.base + DP_PHY_PD_CTL, 0x65);
- wmb(); /* make sure PD programming happened */
-
- /* Turn on BIAS current for PHY/PLL */
- dp_write(catalog->io->dp_pll_io.base +
- QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1b);
-
- /* DP AUX CFG register programming */
- for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
- pr_debug("%s: offset=0x%08x, value=0x%08x\n",
- dp_phy_aux_config_type_to_string(i),
- cfg[i].offset, cfg[i].lut[cfg[i].current_index]);
- dp_write(catalog->io->phy_io.base + cfg[i].offset,
- cfg[i].lut[cfg[i].current_index]);
- }
-
- dp_write(catalog->io->phy_io.base + DP_PHY_AUX_INTERRUPT_MASK, 0x1F);
-}
-
-static void dp_catalog_aux_get_irq(struct dp_catalog_aux *aux, bool cmd_busy)
-{
- u32 ack;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!aux) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(aux);
- base = catalog->io->ctrl_io.base;
-
- aux->isr = dp_read(base + DP_INTR_STATUS);
- aux->isr &= ~DP_INTR_MASK1;
- ack = aux->isr & DP_INTERRUPT_STATUS1;
- ack <<= 1;
- ack |= DP_INTR_MASK1;
- dp_write(base + DP_INTR_STATUS, ack);
-}
-
-/* controller related catalog functions */
-static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- return dp_read(base + DP_HDCP_STATUS);
-}
-
-static void dp_catalog_ctrl_setup_infoframe_sdp(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 header, data;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- header = dp_read(base + MMSS_DP_VSCEXT_0);
- header |= ctrl->hdr_data.vsc_hdr_byte1;
- dp_write(base + MMSS_DP_VSCEXT_0, header);
-
- header = dp_read(base + MMSS_DP_VSCEXT_1);
- header |= ctrl->hdr_data.vsc_hdr_byte1;
- dp_write(base + MMSS_DP_VSCEXT_1, header);
-
- header = dp_read(base + MMSS_DP_VSCEXT_1);
- header |= ctrl->hdr_data.vsc_hdr_byte1;
- dp_write(base + MMSS_DP_VSCEXT_1, header);
-
- header = ctrl->hdr_data.version;
- header |= ctrl->hdr_data.length << 8;
- header |= ctrl->hdr_data.eotf << 16;
- header |= (ctrl->hdr_data.descriptor_id << 24);
- dp_write(base + MMSS_DP_VSCEXT_2, header);
-
- data = (DP_GET_LSB(ctrl->hdr_data.display_primaries_x[0]) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_x[0]) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.display_primaries_y[0]) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_y[0]) << 24));
- dp_write(base + MMSS_DP_VSCEXT_3, data);
-
- data = (DP_GET_LSB(ctrl->hdr_data.display_primaries_x[1]) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_x[1]) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.display_primaries_y[1]) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_y[1]) << 24));
- dp_write(base + MMSS_DP_VSCEXT_4, data);
-
- data = (DP_GET_LSB(ctrl->hdr_data.display_primaries_x[2]) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_x[2]) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.display_primaries_y[2]) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.display_primaries_y[2]) << 24));
- dp_write(base + MMSS_DP_VSCEXT_5, data);
-
- data = (DP_GET_LSB(ctrl->hdr_data.white_point_x) |
- (DP_GET_MSB(ctrl->hdr_data.white_point_x) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.white_point_y) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.white_point_y) << 24));
- dp_write(base + MMSS_DP_VSCEXT_6, data);
-
- data = (DP_GET_LSB(ctrl->hdr_data.max_luminance) |
- (DP_GET_MSB(ctrl->hdr_data.max_luminance) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.min_luminance) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.min_luminance) << 24));
- dp_write(base + MMSS_DP_VSCEXT_7, data);
-
- data = (DP_GET_LSB(ctrl->hdr_data.max_content_light_level) |
- (DP_GET_MSB(ctrl->hdr_data.max_content_light_level) << 8) |
- (DP_GET_LSB(ctrl->hdr_data.max_average_light_level) << 16) |
- (DP_GET_MSB(ctrl->hdr_data.max_average_light_level) << 24));
- dp_write(base + MMSS_DP_VSCEXT_8, data);
-
- dp_write(base + MMSS_DP_VSCEXT_9, 0x00);
-}
-
-static void dp_catalog_ctrl_setup_vsc_sdp(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 value;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- value = dp_read(base + MMSS_DP_GENERIC0_0);
- value |= ctrl->hdr_data.vsc_hdr_byte1;
- dp_write(base + MMSS_DP_GENERIC0_0, value);
-
- value = dp_read(base + MMSS_DP_GENERIC0_1);
- value |= ctrl->hdr_data.vsc_hdr_byte2;
- dp_write(base + MMSS_DP_GENERIC0_1, value);
-
- value = dp_read(base + MMSS_DP_GENERIC0_1);
- value |= ctrl->hdr_data.vsc_hdr_byte3;
- dp_write(base + MMSS_DP_GENERIC0_1, value);
-
- dp_write(base + MMSS_DP_GENERIC0_2, 0x00);
- dp_write(base + MMSS_DP_GENERIC0_3, 0x00);
- dp_write(base + MMSS_DP_GENERIC0_4, 0x00);
- dp_write(base + MMSS_DP_GENERIC0_5, 0x00);
-
- dp_write(base + MMSS_DP_GENERIC0_6, ctrl->hdr_data.pkt_payload);
- dp_write(base + MMSS_DP_GENERIC0_7, 0x00);
- dp_write(base + MMSS_DP_GENERIC0_8, 0x00);
- dp_write(base + MMSS_DP_GENERIC0_9, 0x00);
-}
-
-static void dp_catalog_ctrl_config_hdr(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 cfg, cfg2;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- cfg = dp_read(base + MMSS_DP_SDP_CFG);
- /* VSCEXT_SDP_EN */
- cfg |= BIT(16);
-
- /* GEN0_SDP_EN */
- cfg |= BIT(17);
-
- dp_write(base + MMSS_DP_SDP_CFG, cfg);
-
- cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
- /* Generic0 SDP Payload is 19 bytes which is > 16, so Bit16 is 1 */
- cfg2 |= BIT(16);
- dp_write(base + MMSS_DP_SDP_CFG2, cfg2);
-
- dp_catalog_ctrl_setup_vsc_sdp(ctrl);
- dp_catalog_ctrl_setup_infoframe_sdp(ctrl);
-
- cfg = dp_read(base + DP_MISC1_MISC0);
- /* Indicates presence of VSC */
- cfg |= BIT(6) << 8;
-
- dp_write(base + DP_MISC1_MISC0, cfg);
-
- cfg = dp_read(base + DP_CONFIGURATION_CTRL);
- /* Send VSC */
- cfg |= BIT(7);
-
- switch (ctrl->hdr_data.bpc) {
- default:
- case 10:
- cfg |= BIT(9);
- break;
- case 8:
- cfg |= BIT(8);
- break;
- }
-
- dp_write(base + DP_CONFIGURATION_CTRL, cfg);
-
- cfg = dp_read(base + DP_COMPRESSION_MODE_CTRL);
-
- /* Trigger SDP values in registers */
- cfg |= BIT(8);
- dp_write(base + DP_COMPRESSION_MODE_CTRL, cfg);
-}
-
-static void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_VALID_BOUNDARY, ctrl->valid_boundary);
- dp_write(base + DP_TU, ctrl->dp_tu);
- dp_write(base + DP_VALID_BOUNDARY_2, ctrl->valid_boundary2);
-}
-
-static void dp_catalog_ctrl_state_ctrl(struct dp_catalog_ctrl *ctrl, u32 state)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_STATE_CTRL, state);
-}
-
-static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u32 cfg)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg);
-
- dp_write(base + DP_CONFIGURATION_CTRL, cfg);
- dp_write(base + DP_MAINLINK_LEVELS, 0xa08);
- dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1);
-}
-
-static void dp_catalog_ctrl_lane_mapping(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_LOGICAL2PHYSCIAL_LANE_MAPPING, 0xe4);
-}
-
-static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl,
- bool enable)
-{
- u32 mainlink_ctrl;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- if (enable) {
- dp_write(base + DP_MAINLINK_CTRL, 0x02000000);
- wmb(); /* make sure mainlink is turned off before reset */
- dp_write(base + DP_MAINLINK_CTRL, 0x02000002);
- wmb(); /* make sure mainlink entered reset */
- dp_write(base + DP_MAINLINK_CTRL, 0x02000000);
- wmb(); /* make sure mainlink reset done */
- dp_write(base + DP_MAINLINK_CTRL, 0x02000001);
- wmb(); /* make sure mainlink turned on */
- } else {
- mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
- mainlink_ctrl &= ~BIT(0);
- dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl);
- }
-}
-
-static void dp_catalog_ctrl_config_misc(struct dp_catalog_ctrl *ctrl,
- u32 cc, u32 tb)
-{
- u32 misc_val;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- misc_val = dp_read(base + DP_MISC1_MISC0);
- misc_val |= cc;
- misc_val |= (tb << 5);
- misc_val |= BIT(0); /* Configure clock to synchronous mode */
-
- pr_debug("misc settings = 0x%x\n", misc_val);
- dp_write(base + DP_MISC1_MISC0, misc_val);
-}
-
-static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
- u32 rate, u32 stream_rate_khz,
- bool fixed_nvid)
-{
- u32 pixel_m, pixel_n;
- u32 mvid, nvid;
- u64 mvid_calc;
- u32 const nvid_fixed = 0x8000;
- u32 const link_rate_hbr2 = 540000;
- u32 const link_rate_hbr3 = 810000;
- struct dp_catalog_private *catalog;
- void __iomem *base_cc, *base_ctrl;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- if (fixed_nvid) {
- pr_debug("use fixed NVID=0x%x\n", nvid_fixed);
- nvid = nvid_fixed;
-
- pr_debug("link rate=%dkbps, stream_rate_khz=%uKhz",
- rate, stream_rate_khz);
-
- /*
- * For intermediate results, use 64 bit arithmetic to avoid
- * loss of precision.
- */
- mvid_calc = (u64) stream_rate_khz * nvid;
- mvid_calc = div_u64(mvid_calc, rate);
-
- /*
- * truncate back to 32 bits as this final divided value will
- * always be within the range of a 32 bit unsigned int.
- */
- mvid = (u32) mvid_calc;
- } else {
- base_cc = catalog->io->dp_cc_io.base;
-
- pixel_m = dp_read(base_cc + MMSS_DP_PIXEL_M);
- pixel_n = dp_read(base_cc + MMSS_DP_PIXEL_N);
- pr_debug("pixel_m=0x%x, pixel_n=0x%x\n", pixel_m, pixel_n);
-
- mvid = (pixel_m & 0xFFFF) * 5;
- nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
-
- pr_debug("rate = %d\n", rate);
-
- if (link_rate_hbr2 == rate)
- nvid *= 2;
-
- if (link_rate_hbr3 == rate)
- nvid *= 3;
- }
-
- base_ctrl = catalog->io->ctrl_io.base;
- pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
- dp_write(base_ctrl + DP_SOFTWARE_MVID, mvid);
- dp_write(base_ctrl + DP_SOFTWARE_NVID, nvid);
-}
-
-static void dp_catalog_ctrl_set_pattern(struct dp_catalog_ctrl *ctrl,
- u32 pattern)
-{
- int bit, cnt = 10;
- u32 data;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- bit = 1;
- bit <<= (pattern - 1);
- pr_debug("hw: bit=%d train=%d\n", bit, pattern);
- dp_write(base + DP_STATE_CTRL, bit);
-
- bit = 8;
- bit <<= (pattern - 1);
-
- while (cnt--) {
- data = dp_read(base + DP_MAINLINK_READY);
- if (data & bit)
- break;
- }
-
- if (cnt == 0)
- pr_err("set link_train=%d failed\n", pattern);
-}
-
-static void dp_catalog_ctrl_usb_reset(struct dp_catalog_ctrl *ctrl, bool flip)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
-
- base = catalog->io->usb3_dp_com.base;
-
- dp_write(base + USB3_DP_COM_RESET_OVRD_CTRL, 0x0a);
- dp_write(base + USB3_DP_COM_PHY_MODE_CTRL, 0x02);
- dp_write(base + USB3_DP_COM_SW_RESET, 0x01);
- /* make sure usb3 com phy software reset is done */
- wmb();
-
- if (!flip) /* CC1 */
- dp_write(base + USB3_DP_COM_TYPEC_CTRL, 0x02);
- else /* CC2 */
- dp_write(base + USB3_DP_COM_TYPEC_CTRL, 0x03);
-
- dp_write(base + USB3_DP_COM_SWI_CTRL, 0x00);
- dp_write(base + USB3_DP_COM_SW_RESET, 0x00);
- /* make sure the software reset is done */
- wmb();
-
- dp_write(base + USB3_DP_COM_POWER_DOWN_CTRL, 0x01);
- dp_write(base + USB3_DP_COM_RESET_OVRD_CTRL, 0x00);
- /* make sure phy is brought out of reset */
- wmb();
-
-}
-
-static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl)
-{
- u32 sw_reset;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- sw_reset = dp_read(base + DP_SW_RESET);
-
- sw_reset |= BIT(0);
- dp_write(base + DP_SW_RESET, sw_reset);
- usleep_range(1000, 1010); /* h/w recommended delay */
-
- sw_reset &= ~BIT(0);
- dp_write(base + DP_SW_RESET, sw_reset);
-}
-
-static bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog_ctrl *ctrl)
-{
- u32 data;
- int cnt = 10;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- goto end;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- while (--cnt) {
- /* DP_MAINLINK_READY */
- data = dp_read(base + DP_MAINLINK_READY);
- if (data & BIT(0))
- return true;
-
- usleep_range(1000, 1010); /* 1ms wait before next reg read */
- }
- pr_err("mainlink not ready\n");
-end:
- return false;
-}
-
-static void dp_catalog_ctrl_enable_irq(struct dp_catalog_ctrl *ctrl,
- bool enable)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- if (enable) {
- dp_write(base + DP_INTR_STATUS, DP_INTR_MASK1);
- dp_write(base + DP_INTR_STATUS2, DP_INTR_MASK2);
- } else {
- dp_write(base + DP_INTR_STATUS, 0x00);
- dp_write(base + DP_INTR_STATUS2, 0x00);
- }
-}
-
-static void dp_catalog_ctrl_hpd_config(struct dp_catalog_ctrl *ctrl, bool en)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- if (en) {
- u32 reftimer = dp_read(base + DP_DP_HPD_REFTIMER);
-
- dp_write(base + DP_DP_HPD_INT_ACK, 0xF);
- dp_write(base + DP_DP_HPD_INT_MASK, 0xF);
-
- /* Enabling REFTIMER */
- reftimer |= BIT(16);
- dp_write(base + DP_DP_HPD_REFTIMER, 0xF);
- /* Enable HPD */
- dp_write(base + DP_DP_HPD_CTRL, 0x1);
- } else {
- /*Disable HPD */
- dp_write(base + DP_DP_HPD_CTRL, 0x0);
- }
-}
-
-static void dp_catalog_ctrl_get_interrupt(struct dp_catalog_ctrl *ctrl)
-{
- u32 ack = 0;
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- ctrl->isr = dp_read(base + DP_INTR_STATUS2);
- ctrl->isr &= ~DP_INTR_MASK2;
- ack = ctrl->isr & DP_INTERRUPT_STATUS2;
- ack <<= 1;
- ack |= DP_INTR_MASK2;
- dp_write(base + DP_INTR_STATUS2, ack);
-}
-
-static void dp_catalog_ctrl_phy_reset(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_PHY_CTRL, 0x5); /* bit 0 & 2 */
- usleep_range(1000, 1010); /* h/w recommended delay */
- dp_write(base + DP_PHY_CTRL, 0x0);
- wmb(); /* make sure PHY reset done */
-}
-
-static void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog_ctrl *ctrl,
- bool flipped, u8 ln_cnt)
-{
- u32 info = 0x0;
- struct dp_catalog_private *catalog;
- u8 orientation = BIT(!!flipped);
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
-
- info |= (ln_cnt & 0x0F);
- info |= ((orientation & 0x0F) << 4);
- pr_debug("Shared Info = 0x%x\n", info);
-
- dp_write(catalog->io->phy_io.base + DP_PHY_SPARE0, info);
-}
-
-static void dp_catalog_ctrl_update_vx_px(struct dp_catalog_ctrl *ctrl,
- u8 v_level, u8 p_level)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base0, *base1;
- u8 value0, value1;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
- base0 = catalog->io->ln_tx0_io.base;
- base1 = catalog->io->ln_tx1_io.base;
-
- pr_debug("hw: v=%d p=%d\n", v_level, p_level);
-
- value0 = vm_voltage_swing[v_level][p_level];
- value1 = vm_pre_emphasis[v_level][p_level];
-
- /* program default setting first */
- dp_write(base0 + TXn_TX_DRV_LVL, 0x2A);
- dp_write(base1 + TXn_TX_DRV_LVL, 0x2A);
- dp_write(base0 + TXn_TX_EMP_POST1_LVL, 0x20);
- dp_write(base1 + TXn_TX_EMP_POST1_LVL, 0x20);
-
- /* Enable MUX to use Cursor values from these registers */
- value0 |= BIT(5);
- value1 |= BIT(5);
-
- /* Configure host and panel only if both values are allowed */
- if (value0 != 0xFF && value1 != 0xFF) {
- dp_write(base0 + TXn_TX_DRV_LVL, value0);
- dp_write(base1 + TXn_TX_DRV_LVL, value0);
- dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1);
- dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1);
-
- pr_debug("hw: vx_value=0x%x px_value=0x%x\n",
- value0, value1);
- } else {
- pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n",
- v_level, value0, p_level, value1);
- }
-}
-
-static void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog_ctrl *ctrl,
- u32 pattern)
-{
- struct dp_catalog_private *catalog;
- u32 value = 0x0;
- void __iomem *base = NULL;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_catalog_get_priv(ctrl);
-
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_STATE_CTRL, 0x0);
-
- switch (pattern) {
- case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
- dp_write(base + DP_STATE_CTRL, 0x1);
- break;
- case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
- value &= ~(1 << 16);
- dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
- value |= 0xFC;
- dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
- dp_write(base + DP_MAINLINK_LEVELS, 0x2);
- dp_write(base + DP_STATE_CTRL, 0x10);
- break;
- case DP_TEST_PHY_PATTERN_PRBS7:
- dp_write(base + DP_STATE_CTRL, 0x20);
- break;
- case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
- dp_write(base + DP_STATE_CTRL, 0x40);
- /* 00111110000011111000001111100000 */
- dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 0x3E0F83E0);
- /* 00001111100000111110000011111000 */
- dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 0x0F83E0F8);
- /* 1111100000111110 */
- dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 0x0000F83E);
- break;
- case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
- value = BIT(16);
- dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
- value |= 0xFC;
- dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
- dp_write(base + DP_MAINLINK_LEVELS, 0x2);
- dp_write(base + DP_STATE_CTRL, 0x10);
- break;
- default:
- pr_debug("No valid test pattern requested: 0x%x\n", pattern);
- return;
- }
-
- /* Make sure the test pattern is programmed in the hardware */
- wmb();
-}
-
-static u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog_ctrl *ctrl)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base = NULL;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return 0;
- }
-
- dp_catalog_get_priv(ctrl);
-
- base = catalog->io->ctrl_io.base;
-
- return dp_read(base + DP_MAINLINK_READY);
-}
-
-/* panel related catalog functions */
-static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
-
- if (!panel) {
- pr_err("invalid input\n");
- goto end;
- }
-
- dp_catalog_get_priv(panel);
- base = catalog->io->ctrl_io.base;
-
- dp_write(base + DP_TOTAL_HOR_VER, panel->total);
- dp_write(base + DP_START_HOR_VER_FROM_SYNC, panel->sync_start);
- dp_write(base + DP_HSYNC_VSYNC_WIDTH_POLARITY, panel->width_blanking);
- dp_write(base + DP_ACTIVE_HOR_VER, panel->dp_active);
-end:
- return 0;
-}
-
-static void dp_catalog_audio_init(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = {
- {
- MMSS_DP_AUDIO_STREAM_0,
- MMSS_DP_AUDIO_STREAM_1,
- MMSS_DP_AUDIO_STREAM_1,
- },
- {
- MMSS_DP_AUDIO_TIMESTAMP_0,
- MMSS_DP_AUDIO_TIMESTAMP_1,
- MMSS_DP_AUDIO_TIMESTAMP_1,
- },
- {
- MMSS_DP_AUDIO_INFOFRAME_0,
- MMSS_DP_AUDIO_INFOFRAME_1,
- MMSS_DP_AUDIO_INFOFRAME_1,
- },
- {
- MMSS_DP_AUDIO_COPYMANAGEMENT_0,
- MMSS_DP_AUDIO_COPYMANAGEMENT_1,
- MMSS_DP_AUDIO_COPYMANAGEMENT_1,
- },
- {
- MMSS_DP_AUDIO_ISRC_0,
- MMSS_DP_AUDIO_ISRC_1,
- MMSS_DP_AUDIO_ISRC_1,
- },
- };
-
- if (!audio)
- return;
-
- dp_catalog_get_priv(audio);
-
- catalog->audio_map = sdp_map;
-}
-
-static void dp_catalog_audio_config_sdp(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 sdp_cfg = 0;
- u32 sdp_cfg2 = 0;
-
- if (!audio)
- return;
-
- dp_catalog_get_priv(audio);
- base = catalog->io->ctrl_io.base;
-
- /* AUDIO_TIMESTAMP_SDP_EN */
- sdp_cfg |= BIT(1);
- /* AUDIO_STREAM_SDP_EN */
- sdp_cfg |= BIT(2);
- /* AUDIO_COPY_MANAGEMENT_SDP_EN */
- sdp_cfg |= BIT(5);
- /* AUDIO_ISRC_SDP_EN */
- sdp_cfg |= BIT(6);
- /* AUDIO_INFOFRAME_SDP_EN */
- sdp_cfg |= BIT(20);
-
- pr_debug("sdp_cfg = 0x%x\n", sdp_cfg);
- dp_write(base + MMSS_DP_SDP_CFG, sdp_cfg);
-
- sdp_cfg2 = dp_read(base + MMSS_DP_SDP_CFG2);
- /* IFRM_REGSRC -> Do not use reg values */
- sdp_cfg2 &= ~BIT(0);
- /* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */
- sdp_cfg2 &= ~BIT(1);
-
- pr_debug("sdp_cfg2 = 0x%x\n", sdp_cfg2);
- dp_write(base + MMSS_DP_SDP_CFG2, sdp_cfg2);
-}
-
-static void dp_catalog_audio_get_header(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
- void __iomem *base;
- enum dp_catalog_audio_sdp_type sdp;
- enum dp_catalog_audio_header_type header;
-
- if (!audio)
- return;
-
- dp_catalog_get_priv(audio);
-
- base = catalog->io->ctrl_io.base;
- sdp_map = catalog->audio_map;
- sdp = audio->sdp_type;
- header = audio->sdp_header;
-
- audio->data = dp_read(base + sdp_map[sdp][header]);
-}
-
-static void dp_catalog_audio_set_header(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
- void __iomem *base;
- enum dp_catalog_audio_sdp_type sdp;
- enum dp_catalog_audio_header_type header;
- u32 data;
-
- if (!audio)
- return;
-
- dp_catalog_get_priv(audio);
-
- base = catalog->io->ctrl_io.base;
- sdp_map = catalog->audio_map;
- sdp = audio->sdp_type;
- header = audio->sdp_header;
- data = audio->data;
-
- dp_write(base + sdp_map[sdp][header], data);
-}
-
-static void dp_catalog_audio_config_acr(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 acr_ctrl, select;
-
- dp_catalog_get_priv(audio);
-
- select = audio->data;
- base = catalog->io->ctrl_io.base;
-
- acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14);
-
- pr_debug("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl);
-
- dp_write(base + MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
-}
-
-static void dp_catalog_audio_safe_to_exit_level(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- u32 mainlink_levels, safe_to_exit_level;
-
- dp_catalog_get_priv(audio);
-
- base = catalog->io->ctrl_io.base;
- safe_to_exit_level = audio->data;
-
- mainlink_levels = dp_read(base + DP_MAINLINK_LEVELS);
- mainlink_levels &= 0xFE0;
- mainlink_levels |= safe_to_exit_level;
-
- pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
- mainlink_levels, safe_to_exit_level);
-
- dp_write(base + DP_MAINLINK_LEVELS, mainlink_levels);
-}
-
-static void dp_catalog_audio_enable(struct dp_catalog_audio *audio)
-{
- struct dp_catalog_private *catalog;
- void __iomem *base;
- bool enable;
- u32 audio_ctrl;
-
- dp_catalog_get_priv(audio);
-
- base = catalog->io->ctrl_io.base;
- enable = !!audio->data;
-
- audio_ctrl = dp_read(base + MMSS_DP_AUDIO_CFG);
-
- if (enable)
- audio_ctrl |= BIT(0);
- else
- audio_ctrl &= ~BIT(0);
-
- pr_debug("dp_audio_cfg = 0x%x\n", audio_ctrl);
- dp_write(base + MMSS_DP_AUDIO_CFG, audio_ctrl);
-
- /* make sure audio engine is disabled */
- wmb();
-}
-
-struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io)
-{
- int rc = 0;
- struct dp_catalog *dp_catalog;
- struct dp_catalog_private *catalog;
- struct dp_catalog_aux aux = {
- .read_data = dp_catalog_aux_read_data,
- .write_data = dp_catalog_aux_write_data,
- .write_trans = dp_catalog_aux_write_trans,
- .clear_trans = dp_catalog_aux_clear_trans,
- .reset = dp_catalog_aux_reset,
- .update_aux_cfg = dp_catalog_aux_update_cfg,
- .enable = dp_catalog_aux_enable,
- .setup = dp_catalog_aux_setup,
- .get_irq = dp_catalog_aux_get_irq,
- };
- struct dp_catalog_ctrl ctrl = {
- .state_ctrl = dp_catalog_ctrl_state_ctrl,
- .config_ctrl = dp_catalog_ctrl_config_ctrl,
- .lane_mapping = dp_catalog_ctrl_lane_mapping,
- .mainlink_ctrl = dp_catalog_ctrl_mainlink_ctrl,
- .config_misc = dp_catalog_ctrl_config_misc,
- .config_msa = dp_catalog_ctrl_config_msa,
- .set_pattern = dp_catalog_ctrl_set_pattern,
- .reset = dp_catalog_ctrl_reset,
- .usb_reset = dp_catalog_ctrl_usb_reset,
- .mainlink_ready = dp_catalog_ctrl_mainlink_ready,
- .enable_irq = dp_catalog_ctrl_enable_irq,
- .hpd_config = dp_catalog_ctrl_hpd_config,
- .phy_reset = dp_catalog_ctrl_phy_reset,
- .phy_lane_cfg = dp_catalog_ctrl_phy_lane_cfg,
- .update_vx_px = dp_catalog_ctrl_update_vx_px,
- .get_interrupt = dp_catalog_ctrl_get_interrupt,
- .config_hdr = dp_catalog_ctrl_config_hdr,
- .update_transfer_unit = dp_catalog_ctrl_update_transfer_unit,
- .read_hdcp_status = dp_catalog_ctrl_read_hdcp_status,
- .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern,
- .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern,
- };
- struct dp_catalog_audio audio = {
- .init = dp_catalog_audio_init,
- .config_acr = dp_catalog_audio_config_acr,
- .enable = dp_catalog_audio_enable,
- .config_sdp = dp_catalog_audio_config_sdp,
- .set_header = dp_catalog_audio_set_header,
- .get_header = dp_catalog_audio_get_header,
- .safe_to_exit_level = dp_catalog_audio_safe_to_exit_level,
- };
- struct dp_catalog_panel panel = {
- .timing_cfg = dp_catalog_panel_timing_cfg,
- };
-
- if (!io) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL);
- if (!catalog) {
- rc = -ENOMEM;
- goto error;
- }
-
- catalog->dev = dev;
- catalog->io = io;
-
- dp_catalog = &catalog->dp_catalog;
-
- dp_catalog->aux = aux;
- dp_catalog->ctrl = ctrl;
- dp_catalog->audio = audio;
- dp_catalog->panel = panel;
-
- return dp_catalog;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_catalog_put(struct dp_catalog *dp_catalog)
-{
- struct dp_catalog_private *catalog;
-
- if (!dp_catalog)
- return;
-
- catalog = container_of(dp_catalog, struct dp_catalog_private,
- dp_catalog);
-
- devm_kfree(catalog->dev, catalog);
-}
deleted file mode 100644
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_CATALOG_H_
-#define _DP_CATALOG_H_
-
-#include "dp_parser.h"
-
-/* interrupts */
-#define DP_INTR_HPD BIT(0)
-#define DP_INTR_AUX_I2C_DONE BIT(3)
-#define DP_INTR_WRONG_ADDR BIT(6)
-#define DP_INTR_TIMEOUT BIT(9)
-#define DP_INTR_NACK_DEFER BIT(12)
-#define DP_INTR_WRONG_DATA_CNT BIT(15)
-#define DP_INTR_I2C_NACK BIT(18)
-#define DP_INTR_I2C_DEFER BIT(21)
-#define DP_INTR_PLL_UNLOCKED BIT(24)
-#define DP_INTR_AUX_ERROR BIT(27)
-
-#define DP_INTR_READY_FOR_VIDEO BIT(0)
-#define DP_INTR_IDLE_PATTERN_SENT BIT(3)
-#define DP_INTR_FRAME_END BIT(6)
-#define DP_INTR_CRC_UPDATED BIT(9)
-
-#define HDR_PRIMARIES_COUNT 3
-
-struct dp_catalog_hdr_data {
- u32 vsc_hdr_byte0;
- u32 vsc_hdr_byte1;
- u32 vsc_hdr_byte2;
- u32 vsc_hdr_byte3;
- u32 pkt_payload;
-
- u32 bpc;
-
- u32 version;
- u32 length;
- u32 eotf;
- u32 descriptor_id;
-
- u32 display_primaries_x[HDR_PRIMARIES_COUNT];
- u32 display_primaries_y[HDR_PRIMARIES_COUNT];
- u32 white_point_x;
- u32 white_point_y;
- u32 max_luminance;
- u32 min_luminance;
- u32 max_content_light_level;
- u32 max_average_light_level;
-};
-
-struct dp_catalog_aux {
- u32 data;
- u32 isr;
-
- u32 (*read_data)(struct dp_catalog_aux *aux);
- int (*write_data)(struct dp_catalog_aux *aux);
- int (*write_trans)(struct dp_catalog_aux *aux);
- int (*clear_trans)(struct dp_catalog_aux *aux, bool read);
- void (*reset)(struct dp_catalog_aux *aux);
- void (*enable)(struct dp_catalog_aux *aux, bool enable);
- void (*update_aux_cfg)(struct dp_catalog_aux *aux,
- struct dp_aux_cfg *cfg, enum dp_phy_aux_config_type type);
- void (*setup)(struct dp_catalog_aux *aux,
- struct dp_aux_cfg *aux_cfg);
- void (*get_irq)(struct dp_catalog_aux *aux, bool cmd_busy);
-};
-
-struct dp_catalog_ctrl {
- u32 dp_tu;
- u32 valid_boundary;
- u32 valid_boundary2;
- u32 isr;
- struct dp_catalog_hdr_data hdr_data;
-
- void (*state_ctrl)(struct dp_catalog_ctrl *ctrl, u32 state);
- void (*config_ctrl)(struct dp_catalog_ctrl *ctrl, u32 config);
- void (*lane_mapping)(struct dp_catalog_ctrl *ctrl);
- void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable);
- void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb);
- void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate,
- u32 stream_rate_khz, bool fixed_nvid);
- void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
- void (*reset)(struct dp_catalog_ctrl *ctrl);
- void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip);
- bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl);
- void (*enable_irq)(struct dp_catalog_ctrl *ctrl, bool enable);
- void (*hpd_config)(struct dp_catalog_ctrl *ctrl, bool enable);
- void (*phy_reset)(struct dp_catalog_ctrl *ctrl);
- void (*phy_lane_cfg)(struct dp_catalog_ctrl *ctrl, bool flipped,
- u8 lane_cnt);
- void (*update_vx_px)(struct dp_catalog_ctrl *ctrl, u8 v_level,
- u8 p_level);
- void (*get_interrupt)(struct dp_catalog_ctrl *ctrl);
- void (*config_hdr)(struct dp_catalog_ctrl *ctrl);
- void (*update_transfer_unit)(struct dp_catalog_ctrl *ctrl);
- u32 (*read_hdcp_status)(struct dp_catalog_ctrl *ctrl);
- void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl,
- u32 pattern);
- u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl);
-};
-
-enum dp_catalog_audio_sdp_type {
- DP_AUDIO_SDP_STREAM,
- DP_AUDIO_SDP_TIMESTAMP,
- DP_AUDIO_SDP_INFOFRAME,
- DP_AUDIO_SDP_COPYMANAGEMENT,
- DP_AUDIO_SDP_ISRC,
- DP_AUDIO_SDP_MAX,
-};
-
-enum dp_catalog_audio_header_type {
- DP_AUDIO_SDP_HEADER_1,
- DP_AUDIO_SDP_HEADER_2,
- DP_AUDIO_SDP_HEADER_3,
- DP_AUDIO_SDP_HEADER_MAX,
-};
-
-struct dp_catalog_audio {
- enum dp_catalog_audio_sdp_type sdp_type;
- enum dp_catalog_audio_header_type sdp_header;
- u32 data;
-
- void (*init)(struct dp_catalog_audio *audio);
- void (*enable)(struct dp_catalog_audio *audio);
- void (*config_acr)(struct dp_catalog_audio *audio);
- void (*config_sdp)(struct dp_catalog_audio *audio);
- void (*set_header)(struct dp_catalog_audio *audio);
- void (*get_header)(struct dp_catalog_audio *audio);
- void (*safe_to_exit_level)(struct dp_catalog_audio *audio);
-};
-
-struct dp_catalog_panel {
- u32 total;
- u32 sync_start;
- u32 width_blanking;
- u32 dp_active;
-
- int (*timing_cfg)(struct dp_catalog_panel *panel);
-};
-
-struct dp_catalog {
- struct dp_catalog_aux aux;
- struct dp_catalog_ctrl ctrl;
- struct dp_catalog_audio audio;
- struct dp_catalog_panel panel;
-};
-
-struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io);
-void dp_catalog_put(struct dp_catalog *catalog);
-
-#endif /* _DP_CATALOG_H_ */
deleted file mode 100644
@@ -1,1474 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/types.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-
-#include "dp_ctrl.h"
-
-#define DP_KHZ_TO_HZ 1000
-
-#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0)
-#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3)
-
-/* dp state ctrl */
-#define ST_TRAIN_PATTERN_1 BIT(0)
-#define ST_TRAIN_PATTERN_2 BIT(1)
-#define ST_TRAIN_PATTERN_3 BIT(2)
-#define ST_TRAIN_PATTERN_4 BIT(3)
-#define ST_SYMBOL_ERR_RATE_MEASUREMENT BIT(4)
-#define ST_PRBS7 BIT(5)
-#define ST_CUSTOM_80_BIT_PATTERN BIT(6)
-#define ST_SEND_VIDEO BIT(7)
-#define ST_PUSH_IDLE BIT(8)
-
-#define MR_LINK_TRAINING1 0x8
-#define MR_LINK_SYMBOL_ERM 0x80
-#define MR_LINK_PRBS7 0x100
-#define MR_LINK_CUSTOM80 0x200
-
-struct dp_vc_tu_mapping_table {
- u32 vic;
- u8 lanes;
- u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */
- u8 bpp;
- u8 valid_boundary_link;
- u16 delay_start_link;
- bool boundary_moderation_en;
- u8 valid_lower_boundary_link;
- u8 upper_boundary_count;
- u8 lower_boundary_count;
- u8 tu_size_minus1;
-};
-
-struct dp_ctrl_private {
- struct dp_ctrl dp_ctrl;
-
- struct device *dev;
- struct dp_aux *aux;
- struct dp_panel *panel;
- struct dp_link *link;
- struct dp_power *power;
- struct dp_parser *parser;
- struct dp_catalog_ctrl *catalog;
-
- struct completion idle_comp;
- struct completion video_comp;
-
- bool orientation;
- atomic_t aborted;
-
- u32 pixel_rate;
- u32 vic;
-};
-
-enum notification_status {
- NOTIFY_UNKNOWN,
- NOTIFY_CONNECT,
- NOTIFY_DISCONNECT,
- NOTIFY_CONNECT_IRQ_HPD,
- NOTIFY_DISCONNECT_IRQ_HPD,
-};
-
-static void dp_ctrl_idle_patterns_sent(struct dp_ctrl_private *ctrl)
-{
- pr_debug("idle_patterns_sent\n");
- complete(&ctrl->idle_comp);
-}
-
-static void dp_ctrl_video_ready(struct dp_ctrl_private *ctrl)
-{
- pr_debug("dp_video_ready\n");
- complete(&ctrl->video_comp);
-}
-
-static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl) {
- pr_err("Invalid input data\n");
- return;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- atomic_set(&ctrl->aborted, 1);
-}
-
-static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state)
-{
- ctrl->catalog->state_ctrl(ctrl->catalog, state);
-}
-
-static void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)
-{
- int const idle_pattern_completion_timeout_ms = 3 * HZ / 100;
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl) {
- pr_err("Invalid input data\n");
- return;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- reinit_completion(&ctrl->idle_comp);
- dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE);
-
- if (!wait_for_completion_timeout(&ctrl->idle_comp,
- idle_pattern_completion_timeout_ms))
- pr_warn("PUSH_IDLE pattern timedout\n");
-
- pr_debug("mainlink off done\n");
-}
-
-static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
-{
- u32 config = 0, tbd;
- u8 *dpcd = ctrl->panel->dpcd;
-
- config |= (2 << 13); /* Default-> LSCLK DIV: 1/4 LCLK */
- config |= (0 << 11); /* RGB */
-
- /* Scrambler reset enable */
- if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP)
- config |= (1 << 10);
-
- tbd = ctrl->link->get_test_bits_depth(ctrl->link,
- ctrl->panel->pinfo.bpp);
-
- if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN)
- tbd = DP_TEST_BIT_DEPTH_8;
-
- config |= tbd << 8;
-
- /* Num of Lanes */
- config |= ((ctrl->link->link_params.lane_count - 1) << 4);
-
- if (drm_dp_enhanced_frame_cap(dpcd))
- config |= 0x40;
-
- config |= 0x04; /* progressive video */
-
- config |= 0x03; /* sycn clock & static Mvid */
-
- ctrl->catalog->config_ctrl(ctrl->catalog, config);
-}
-
-/**
- * dp_ctrl_configure_source_params() - configures DP transmitter source params
- * @ctrl: Display Port Driver data
- *
- * Configures the DP transmitter source params including details such as lane
- * configuration, output format and sink/panel timing information.
- */
-static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
-{
- u32 cc, tb;
-
- ctrl->catalog->lane_mapping(ctrl->catalog);
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, true);
-
- dp_ctrl_config_ctrl(ctrl);
-
- tb = ctrl->link->get_test_bits_depth(ctrl->link,
- ctrl->panel->pinfo.bpp);
- cc = ctrl->link->get_colorimetry_config(ctrl->link);
- ctrl->catalog->config_misc(ctrl->catalog, cc, tb);
- ctrl->panel->timing_cfg(ctrl->panel);
-}
-
-static void dp_ctrl_get_extra_req_bytes(u64 result_valid,
- int valid_bdary_link,
- u64 value1, u64 value2,
- bool *negative, u64 *result,
- u64 compare)
-{
- *negative = false;
- if (result_valid >= compare) {
- if (valid_bdary_link
- >= compare)
- *result = value1 + value2;
- else {
- if (value1 < value2)
- *negative = true;
- *result = (value1 >= value2) ?
- (value1 - value2) : (value2 - value1);
- }
- } else {
- if (valid_bdary_link
- >= compare) {
- if (value1 >= value2)
- *negative = true;
- *result = (value1 >= value2) ?
- (value1 - value2) : (value2 - value1);
- } else {
- *result = value1 + value2;
- *negative = true;
- }
- }
-}
-
-static u64 roundup_u64(u64 x, u64 y)
-{
- x += (y - 1);
- return (div64_ul(x, y) * y);
-}
-
-static u64 rounddown_u64(u64 x, u64 y)
-{
- u64 rem;
-
- div64_u64_rem(x, y, &rem);
- return (x - rem);
-}
-
-static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
- struct dp_vc_tu_mapping_table *tu_table)
-{
- u32 multiplier = 1000000;
- u64 pclk, lclk;
- u8 bpp, ln_cnt;
- int run_idx = 0;
- u32 lwidth, h_blank;
- u32 fifo_empty = 0;
- u32 ratio_scale = 1001;
- u64 temp, ratio, original_ratio;
- u64 temp2, reminder;
- u64 temp3, temp4, result = 0;
-
- u64 err = multiplier;
- u64 n_err = 0, n_n_err = 0;
- bool n_err_neg, nn_err_neg;
- u8 hblank_margin = 16;
-
- u8 tu_size, tu_size_desired = 0, tu_size_minus1;
- int valid_boundary_link;
- u64 resulting_valid;
- u64 total_valid;
- u64 effective_valid;
- u64 effective_valid_recorded;
- int n_tus;
- int n_tus_per_lane;
- int paired_tus;
- int remainder_tus;
- int remainder_tus_upper, remainder_tus_lower;
- int extra_bytes;
- int filler_size;
- int delay_start_link;
- int boundary_moderation_en = 0;
- int upper_bdry_cnt = 0;
- int lower_bdry_cnt = 0;
- int i_upper_bdry_cnt = 0;
- int i_lower_bdry_cnt = 0;
- int valid_lower_boundary_link = 0;
- int even_distribution_bf = 0;
- int even_distribution_legacy = 0;
- int even_distribution = 0;
- int min_hblank = 0;
- int extra_pclk_cycles;
- u8 extra_pclk_cycle_delay = 4;
- int extra_pclk_cycles_in_link_clk;
- u64 ratio_by_tu;
- u64 average_valid2;
- u64 extra_buffer_margin;
- int new_valid_boundary_link;
-
- u64 resulting_valid_tmp;
- u64 ratio_by_tu_tmp;
- int n_tus_tmp;
- int extra_pclk_cycles_tmp;
- int extra_pclk_cycles_in_lclk_tmp;
- int extra_req_bytes_new_tmp;
- int filler_size_tmp;
- int lower_filler_size_tmp;
- int delay_start_link_tmp;
- int min_hblank_tmp = 0;
- bool extra_req_bytes_is_neg = false;
- struct dp_panel_info *pinfo = &ctrl->panel->pinfo;
-
- u8 dp_brute_force = 1;
- u64 brute_force_threshold = 10;
- u64 diff_abs;
-
- ln_cnt = ctrl->link->link_params.lane_count;
-
- bpp = pinfo->bpp;
- lwidth = pinfo->h_active;
- h_blank = pinfo->h_back_porch + pinfo->h_front_porch +
- pinfo->h_sync_width;
- pclk = pinfo->pixel_clk_khz * 1000;
-
- boundary_moderation_en = 0;
- upper_bdry_cnt = 0;
- lower_bdry_cnt = 0;
- i_upper_bdry_cnt = 0;
- i_lower_bdry_cnt = 0;
- valid_lower_boundary_link = 0;
- even_distribution_bf = 0;
- even_distribution_legacy = 0;
- even_distribution = 0;
- min_hblank = 0;
-
- lclk = drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code) * DP_KHZ_TO_HZ;
-
- pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n",
- pclk, lwidth, h_blank);
- pr_debug("lclk = %lld, ln_cnt = %d\n", lclk, ln_cnt);
- ratio = div64_u64_rem(pclk * bpp * multiplier,
- 8 * ln_cnt * lclk, &reminder);
- ratio = div64_u64((pclk * bpp * multiplier), (8 * ln_cnt * lclk));
- original_ratio = ratio;
-
- extra_buffer_margin = roundup_u64(div64_u64(extra_pclk_cycle_delay
- * lclk * multiplier, pclk), multiplier);
- extra_buffer_margin = div64_u64(extra_buffer_margin, multiplier);
-
- /* To deal with cases where lines are not distributable */
- if (((lwidth % ln_cnt) != 0) && ratio < multiplier) {
- ratio = ratio * ratio_scale;
- ratio = ratio < (1000 * multiplier)
- ? ratio : (1000 * multiplier);
- }
- pr_debug("ratio = %lld\n", ratio);
-
- for (tu_size = 32; tu_size <= 64; tu_size++) {
- temp = ratio * tu_size;
- temp2 = (div_u64(temp / multiplier) + 1) * multiplier;
- n_err = roundup_u64(temp, multiplier) - temp;
-
- if (n_err < err) {
- err = n_err;
- tu_size_desired = tu_size;
- }
- }
- pr_debug("Info: tu_size_desired = %d\n", tu_size_desired);
-
- tu_size_minus1 = tu_size_desired - 1;
-
- valid_boundary_link = roundup_u64(ratio * tu_size_desired, multiplier);
- valid_boundary_link /= multiplier;
- n_tus = rounddown((lwidth * bpp * multiplier)
- / (8 * valid_boundary_link), multiplier) / multiplier;
- even_distribution_legacy = n_tus % ln_cnt == 0 ? 1 : 0;
- pr_debug("Info: n_symbol_per_tu=%d, number_of_tus=%d\n",
- valid_boundary_link, n_tus);
-
- extra_bytes = roundup_u64((n_tus + 1)
- * ((valid_boundary_link * multiplier)
- - (original_ratio * tu_size_desired)), multiplier);
- extra_bytes /= multiplier;
- extra_pclk_cycles = roundup(extra_bytes * 8 * multiplier / bpp,
- multiplier);
- extra_pclk_cycles /= multiplier;
- extra_pclk_cycles_in_link_clk = roundup_u64(div64_u64(extra_pclk_cycles
- * lclk * multiplier, pclk), multiplier);
- extra_pclk_cycles_in_link_clk /= multiplier;
- filler_size = roundup_u64((tu_size_desired - valid_boundary_link)
- * multiplier, multiplier);
- filler_size /= multiplier;
- ratio_by_tu = div64_u64(ratio * tu_size_desired, multiplier);
-
- pr_debug("extra_pclk_cycles_in_link_clk=%d, extra_bytes=%d\n",
- extra_pclk_cycles_in_link_clk, extra_bytes);
- pr_debug("extra_pclk_cycles_in_link_clk=%d\n",
- extra_pclk_cycles_in_link_clk);
- pr_debug("filler_size=%d, extra_buffer_margin=%lld\n",
- filler_size, extra_buffer_margin);
-
- delay_start_link = ((extra_bytes > extra_pclk_cycles_in_link_clk)
- ? extra_bytes
- : extra_pclk_cycles_in_link_clk)
- + filler_size + extra_buffer_margin;
- resulting_valid = valid_boundary_link;
- pr_debug("Info: delay_start_link=%d, filler_size=%d\n",
- delay_start_link, filler_size);
- pr_debug("valid_boundary_link=%d ratio_by_tu=%lld\n",
- valid_boundary_link, ratio_by_tu);
-
- diff_abs = (resulting_valid >= ratio_by_tu)
- ? (resulting_valid - ratio_by_tu)
- : (ratio_by_tu - resulting_valid);
-
- if (err != 0 && ((diff_abs > brute_force_threshold)
- || (even_distribution_legacy == 0)
- || (dp_brute_force == 1))) {
- err = multiplier;
- for (tu_size = 32; tu_size <= 64; tu_size++) {
- for (i_upper_bdry_cnt = 1; i_upper_bdry_cnt <= 15;
- i_upper_bdry_cnt++) {
- for (i_lower_bdry_cnt = 1;
- i_lower_bdry_cnt <= 15;
- i_lower_bdry_cnt++) {
- new_valid_boundary_link =
- roundup_u64(ratio
- * tu_size, multiplier);
- average_valid2 = (i_upper_bdry_cnt
- * new_valid_boundary_link
- + i_lower_bdry_cnt
- * (new_valid_boundary_link
- - multiplier))
- / (i_upper_bdry_cnt
- + i_lower_bdry_cnt);
- n_tus = rounddown_u64(div64_u64(lwidth
- * multiplier * multiplier
- * (bpp / 8), average_valid2),
- multiplier);
- n_tus /= multiplier;
- n_tus_per_lane
- = rounddown(n_tus
- * multiplier
- / ln_cnt, multiplier);
- n_tus_per_lane /= multiplier;
- paired_tus =
- rounddown((n_tus_per_lane)
- * multiplier
- / (i_upper_bdry_cnt
- + i_lower_bdry_cnt),
- multiplier);
- paired_tus /= multiplier;
- remainder_tus = n_tus_per_lane
- - paired_tus
- * (i_upper_bdry_cnt
- + i_lower_bdry_cnt);
- if ((remainder_tus
- - i_upper_bdry_cnt) > 0) {
- remainder_tus_upper
- = i_upper_bdry_cnt;
- remainder_tus_lower =
- remainder_tus
- - i_upper_bdry_cnt;
- } else {
- remainder_tus_upper
- = remainder_tus;
- remainder_tus_lower = 0;
- }
- total_valid = paired_tus
- * (i_upper_bdry_cnt
- * new_valid_boundary_link
- + i_lower_bdry_cnt
- * (new_valid_boundary_link
- - multiplier))
- + (remainder_tus_upper
- * new_valid_boundary_link)
- + (remainder_tus_lower
- * (new_valid_boundary_link
- - multiplier));
- n_err_neg = nn_err_neg = false;
- effective_valid
- = div_u64(total_valid,
- n_tus_per_lane);
- n_n_err = (effective_valid
- >= (ratio * tu_size))
- ? (effective_valid
- - (ratio * tu_size))
- : ((ratio * tu_size)
- - effective_valid);
- if (effective_valid < (ratio * tu_size))
- nn_err_neg = true;
- n_err = (average_valid2
- >= (ratio * tu_size))
- ? (average_valid2
- - (ratio * tu_size))
- : ((ratio * tu_size)
- - average_valid2);
- if (average_valid2 < (ratio * tu_size))
- n_err_neg = true;
- even_distribution =
- n_tus % ln_cnt == 0 ? 1 : 0;
- diff_abs =
- resulting_valid >= ratio_by_tu
- ? (resulting_valid
- - ratio_by_tu)
- : (ratio_by_tu
- - resulting_valid);
-
- resulting_valid_tmp = div64_u64(
- (i_upper_bdry_cnt
- * new_valid_boundary_link
- + i_lower_bdry_cnt
- * (new_valid_boundary_link
- - multiplier)),
- (i_upper_bdry_cnt
- + i_lower_bdry_cnt));
- ratio_by_tu_tmp =
- original_ratio * tu_size;
- ratio_by_tu_tmp /= multiplier;
- n_tus_tmp = rounddown_u64(
- div64_u64(lwidth
- * multiplier * multiplier
- * bpp / 8,
- resulting_valid_tmp),
- multiplier);
- n_tus_tmp /= multiplier;
-
- temp3 = (resulting_valid_tmp
- >= (original_ratio * tu_size))
- ? (resulting_valid_tmp
- - original_ratio * tu_size)
- : (original_ratio * tu_size)
- - resulting_valid_tmp;
- temp3 = (n_tus_tmp + 1) * temp3;
- temp4 = (new_valid_boundary_link
- >= (original_ratio * tu_size))
- ? (new_valid_boundary_link
- - original_ratio
- * tu_size)
- : (original_ratio * tu_size)
- - new_valid_boundary_link;
- temp4 = (i_upper_bdry_cnt
- * ln_cnt * temp4);
-
- temp3 = roundup_u64(temp3, multiplier);
- temp4 = roundup_u64(temp4, multiplier);
- dp_ctrl_get_extra_req_bytes
- (resulting_valid_tmp,
- new_valid_boundary_link,
- temp3, temp4,
- &extra_req_bytes_is_neg,
- &result,
- (original_ratio * tu_size));
- extra_req_bytes_new_tmp
- = div64_ul(result, multiplier);
- if ((extra_req_bytes_is_neg)
- && (extra_req_bytes_new_tmp
- > 1))
- extra_req_bytes_new_tmp
- = extra_req_bytes_new_tmp - 1;
- if (extra_req_bytes_new_tmp == 0)
- extra_req_bytes_new_tmp = 1;
- extra_pclk_cycles_tmp =
- (u64)(extra_req_bytes_new_tmp
- * 8 * multiplier) / bpp;
- extra_pclk_cycles_tmp /= multiplier;
-
- if (extra_pclk_cycles_tmp <= 0)
- extra_pclk_cycles_tmp = 1;
- extra_pclk_cycles_in_lclk_tmp =
- roundup_u64(div64_u64(
- extra_pclk_cycles_tmp
- * lclk * multiplier,
- pclk), multiplier);
- extra_pclk_cycles_in_lclk_tmp
- /= multiplier;
- filler_size_tmp = roundup_u64(
- (tu_size * multiplier *
- new_valid_boundary_link),
- multiplier);
- filler_size_tmp /= multiplier;
- lower_filler_size_tmp =
- filler_size_tmp + 1;
- if (extra_req_bytes_is_neg)
- temp3 = (extra_req_bytes_new_tmp
- > extra_pclk_cycles_in_lclk_tmp
- ? extra_pclk_cycles_in_lclk_tmp
- : extra_req_bytes_new_tmp);
- else
- temp3 = (extra_req_bytes_new_tmp
- > extra_pclk_cycles_in_lclk_tmp
- ? extra_req_bytes_new_tmp :
- extra_pclk_cycles_in_lclk_tmp);
-
- temp4 = lower_filler_size_tmp
- + extra_buffer_margin;
- if (extra_req_bytes_is_neg)
- delay_start_link_tmp
- = (temp3 >= temp4)
- ? (temp3 - temp4)
- : (temp4 - temp3);
- else
- delay_start_link_tmp
- = temp3 + temp4;
-
- min_hblank_tmp = (int)div64_u64(
- roundup_u64(
- div64_u64(delay_start_link_tmp
- * pclk * multiplier, lclk),
- multiplier), multiplier)
- + hblank_margin;
-
- if (((even_distribution == 1)
- || ((even_distribution_bf == 0)
- && (even_distribution_legacy
- == 0)))
- && !n_err_neg && !nn_err_neg
- && n_n_err < err
- && (n_n_err < diff_abs
- || (dp_brute_force == 1))
- && (new_valid_boundary_link
- - 1) > 0
- && (h_blank >=
- (u32)min_hblank_tmp)) {
- upper_bdry_cnt =
- i_upper_bdry_cnt;
- lower_bdry_cnt =
- i_lower_bdry_cnt;
- err = n_n_err;
- boundary_moderation_en = 1;
- tu_size_desired = tu_size;
- valid_boundary_link =
- new_valid_boundary_link;
- effective_valid_recorded
- = effective_valid;
- delay_start_link
- = delay_start_link_tmp;
- filler_size = filler_size_tmp;
- min_hblank = min_hblank_tmp;
- n_tus = n_tus_tmp;
- even_distribution_bf = 1;
-
- pr_debug("upper_bdry_cnt=%d, lower_boundary_cnt=%d, err=%lld, tu_size_desired=%d, valid_boundary_link=%d, effective_valid=%lld\n",
- upper_bdry_cnt,
- lower_bdry_cnt, err,
- tu_size_desired,
- valid_boundary_link,
- effective_valid);
- }
- }
- }
- }
-
- if (boundary_moderation_en == 1) {
- resulting_valid = (u64)(upper_bdry_cnt
- *valid_boundary_link + lower_bdry_cnt
- * (valid_boundary_link - 1))
- / (upper_bdry_cnt + lower_bdry_cnt);
- ratio_by_tu = original_ratio * tu_size_desired;
- valid_lower_boundary_link =
- (valid_boundary_link / multiplier) - 1;
-
- tu_size_minus1 = tu_size_desired - 1;
- even_distribution_bf = 1;
- valid_boundary_link /= multiplier;
- pr_debug("Info: Boundary_moderation enabled\n");
- }
- }
-
- min_hblank = ((int) roundup_u64(div64_u64(delay_start_link * pclk
- * multiplier, lclk), multiplier))
- / multiplier + hblank_margin;
- if (h_blank < (u32)min_hblank) {
- pr_debug(" WARNING: run_idx=%d Programmed h_blank %d is smaller than the min_hblank %d supported.\n",
- run_idx, h_blank, min_hblank);
- }
-
- if (fifo_empty) {
- tu_size_minus1 = 31;
- valid_boundary_link = 32;
- delay_start_link = 0;
- boundary_moderation_en = 0;
- }
-
- pr_debug("tu_size_minus1=%d valid_boundary_link=%d delay_start_link=%d boundary_moderation_en=%d\n upper_boundary_cnt=%d lower_boundary_cnt=%d valid_lower_boundary_link=%d min_hblank=%d\n",
- tu_size_minus1, valid_boundary_link, delay_start_link,
- boundary_moderation_en, upper_bdry_cnt, lower_bdry_cnt,
- valid_lower_boundary_link, min_hblank);
-
- tu_table->valid_boundary_link = valid_boundary_link;
- tu_table->delay_start_link = delay_start_link;
- tu_table->boundary_moderation_en = boundary_moderation_en;
- tu_table->valid_lower_boundary_link = valid_lower_boundary_link;
- tu_table->upper_boundary_count = upper_bdry_cnt;
- tu_table->lower_boundary_count = lower_bdry_cnt;
- tu_table->tu_size_minus1 = tu_size_minus1;
-}
-
-static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl)
-{
- u32 dp_tu = 0x0;
- u32 valid_boundary = 0x0;
- u32 valid_boundary2 = 0x0;
- struct dp_vc_tu_mapping_table tu_calc_table;
-
- dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);
-
- dp_tu |= tu_calc_table.tu_size_minus1;
- valid_boundary |= tu_calc_table.valid_boundary_link;
- valid_boundary |= (tu_calc_table.delay_start_link << 16);
-
- valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1);
- valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16);
- valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20);
-
- if (tu_calc_table.boundary_moderation_en)
- valid_boundary2 |= BIT(0);
-
- pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",
- dp_tu, valid_boundary, valid_boundary2);
-
- ctrl->catalog->dp_tu = dp_tu;
- ctrl->catalog->valid_boundary = valid_boundary;
- ctrl->catalog->valid_boundary2 = valid_boundary2;
-
- ctrl->catalog->update_transfer_unit(ctrl->catalog);
-}
-
-static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
-
- ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2);
- if (ret <= 0) {
- pr_err("Link Train timedout\n");
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int dp_ctrl_update_sink_vx_px(struct dp_ctrl_private *ctrl,
- u32 voltage_level, u32 pre_emphasis_level)
-{
- int i;
- u8 buf[4];
- u32 max_level_reached = 0;
-
- if (voltage_level == DP_LINK_VOLTAGE_MAX) {
- pr_debug("max. voltage swing level reached %d\n",
- voltage_level);
- max_level_reached |= BIT(2);
- }
-
- if (pre_emphasis_level == DP_LINK_PRE_EMPHASIS_MAX) {
- pr_debug("max. pre-emphasis level reached %d\n",
- pre_emphasis_level);
- max_level_reached |= BIT(5);
- }
-
- pre_emphasis_level <<= 3;
-
- for (i = 0; i < 4; i++)
- buf[i] = voltage_level | pre_emphasis_level | max_level_reached;
-
- pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level);
- return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4);
-}
-
-static void dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
-{
- struct dp_link *link = ctrl->link;
-
- ctrl->catalog->update_vx_px(ctrl->catalog,
- link->phy_params.v_level, link->phy_params.p_level);
-
- dp_ctrl_update_sink_vx_px(ctrl, link->phy_params.v_level,
- link->phy_params.p_level);
-}
-
-static void dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
- u8 pattern)
-{
- u8 buf[4];
-
- pr_debug("sink: pattern=%x\n", pattern);
-
- buf[0] = pattern;
- drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1);
-}
-
-static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
- u8 *link_status)
-{
- int ret = 0, len;
- u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS;
- u32 link_status_read_max_retries = 100;
-
- while (--link_status_read_max_retries) {
- len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
- link_status);
- if (len != DP_LINK_STATUS_SIZE) {
- pr_err("DP link status read failed, err: %d\n", len);
- ret = len;
- break;
- }
-
- if (!(link_status[offset] & DP_LINK_STATUS_UPDATED))
- break;
- }
-
- return ret;
-}
-
-static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)
-{
- int tries, old_v_level, ret = 0;
- u8 link_status[DP_LINK_STATUS_SIZE];
- int const maximum_retries = 5;
-
- dp_ctrl_state_ctrl(ctrl, 0);
- /* Make sure to clear the current pattern before starting a new one */
- wmb();
-
- ctrl->catalog->set_pattern(ctrl->catalog, 0x01);
- dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE); /* train_1 */
- dp_ctrl_update_vx_px(ctrl);
-
- tries = 0;
- old_v_level = ctrl->link->phy_params.v_level;
- while (1) {
- drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);
-
- ret = dp_ctrl_read_link_status(ctrl, link_status);
- if (ret)
- break;
-
- if (drm_dp_clock_recovery_ok(link_status,
- ctrl->link->link_params.lane_count)) {
- break;
- }
-
- if (ctrl->link->phy_params.v_level == DP_LINK_VOLTAGE_MAX) {
- pr_err_ratelimited("max v_level reached\n");
- ret = -EAGAIN;
- break;
- }
-
- if (old_v_level == ctrl->link->phy_params.v_level) {
- tries++;
- if (tries >= maximum_retries) {
- pr_err("max tries reached\n");
- ret = -ETIMEDOUT;
- break;
- }
- } else {
- tries = 0;
- old_v_level = ctrl->link->phy_params.v_level;
- }
-
- pr_debug("clock recovery not done, adjusting vx px\n");
-
- ctrl->link->adjust_levels(ctrl->link, link_status);
- dp_ctrl_update_vx_px(ctrl);
- }
-
- return ret;
-}
-
-static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
-
- if (!ctrl)
- return -EINVAL;
-
- switch (ctrl->link->link_params.bw_code) {
- case DP_LINK_BW_8_1:
- ctrl->link->link_params.bw_code = DP_LINK_BW_5_4;
- break;
- case DP_LINK_BW_5_4:
- ctrl->link->link_params.bw_code = DP_LINK_BW_2_7;
- break;
- case DP_LINK_BW_2_7:
- case DP_LINK_BW_1_62:
- default:
- ctrl->link->link_params.bw_code = DP_LINK_BW_1_62;
- break;
- };
-
- pr_debug("new bw code=0x%x\n", ctrl->link->link_params.bw_code);
-
- return ret;
-}
-
-static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl)
-{
- dp_ctrl_train_pattern_set(ctrl, 0);
- drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
-}
-
-static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
-{
- int tries = 0, ret = 0;
- char pattern;
- int const maximum_retries = 5;
- u8 link_status[DP_LINK_STATUS_SIZE];
-
- dp_ctrl_state_ctrl(ctrl, 0);
- /* Make sure to clear the current pattern before starting a new one */
- wmb();
-
- if (drm_dp_tps3_supported(ctrl->panel->dpcd))
- pattern = DP_TRAINING_PATTERN_3;
- else
- pattern = DP_TRAINING_PATTERN_2;
-
- dp_ctrl_update_vx_px(ctrl);
- ctrl->catalog->set_pattern(ctrl->catalog, pattern);
- dp_ctrl_train_pattern_set(ctrl, pattern | DP_RECOVERED_CLOCK_OUT_EN);
-
- do {
- drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
-
- ret = dp_ctrl_read_link_status(ctrl, link_status);
- if (ret)
- break;
-
- if (drm_dp_channel_eq_ok(link_status,
- ctrl->link->link_params.lane_count))
- break;
-
- if (tries > maximum_retries) {
- ret = -ETIMEDOUT;
- break;
- }
- tries++;
-
- ctrl->link->adjust_levels(ctrl->link, link_status);
- dp_ctrl_update_vx_px(ctrl);
- } while (1);
-
- return ret;
-}
-
-static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
- u8 encoding = 0x1;
- struct drm_dp_link link_info = {0};
-
- ctrl->link->phy_params.p_level = 0;
- ctrl->link->phy_params.v_level = 0;
-
- dp_ctrl_config_ctrl(ctrl);
-
- link_info.num_lanes = ctrl->link->link_params.lane_count;
- link_info.rate = drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code);
- link_info.capabilities = ctrl->panel->link_info.capabilities;
-
- drm_dp_link_configure(ctrl->aux->drm_aux, &link_info);
- drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
- &encoding, 1);
-
- ret = dp_ctrl_link_train_1(ctrl);
- if (ret) {
- pr_err("link training #1 failed\n");
- goto end;
- }
-
- /* print success info as this is a result of user initiated action */
- pr_info("link training #1 successful\n");
-
- ret = dp_ctrl_link_training_2(ctrl);
- if (ret) {
- pr_err("link training #2 failed\n");
- goto end;
- }
-
- /* print success info as this is a result of user initiated action */
- pr_debug("link training #2 successful\n");
-
-end:
- dp_ctrl_state_ctrl(ctrl, 0);
- /* Make sure to clear the current pattern before starting a new one */
- wmb();
-
- dp_ctrl_clear_training_pattern(ctrl);
- return ret;
-}
-
-static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train)
-{
- bool mainlink_ready = false;
- int ret = 0;
-
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, true);
-
- ret = ctrl->link->psm_config(ctrl->link,
- &ctrl->panel->link_info, false);
- if (ret)
- goto end;
-
- if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
- goto end;
-
- if (!train)
- goto send_video;
-
- /*
- * As part of previous calls, DP controller state might have
- * transitioned to PUSH_IDLE. In order to start transmitting a link
- * training pattern, we have to first to a DP software reset.
- */
- ctrl->catalog->reset(ctrl->catalog);
-
- ret = dp_ctrl_link_train(ctrl);
- if (ret)
- goto end;
-
-send_video:
- /*
- * Set up transfer unit values and set controller state to send
- * video.
- */
- dp_ctrl_setup_tr_unit(ctrl);
- ctrl->catalog->state_ctrl(ctrl->catalog, ST_SEND_VIDEO);
-
- dp_ctrl_wait4video_ready(ctrl);
- mainlink_ready = ctrl->catalog->mainlink_ready(ctrl->catalog);
- pr_debug("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
-end:
- return ret;
-}
-
-static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl,
- char *name, u32 rate)
-{
- u32 num = ctrl->parser->mp[DP_CTRL_PM].num_clk;
- struct dss_clk *cfg = ctrl->parser->mp[DP_CTRL_PM].clk_config;
-
- while (num && strcmp(cfg->clk_name, name)) {
- num--;
- cfg++;
- }
-
- pr_debug("setting rate=%d on clk=%s\n", rate, name);
-
- if (num)
- cfg->rate = rate;
- else
- pr_err("%s clock could not be set with rate %d\n", name, rate);
-}
-
-static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
-
- ctrl->power->set_pixel_clk_parent(ctrl->power);
-
- dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk",
- drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code));
-
- dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate);
-
- ret = ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, true);
- if (ret) {
- pr_err("Unabled to start link clocks\n");
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int dp_ctrl_disable_mainlink_clocks(struct dp_ctrl_private *ctrl)
-{
- return ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, false);
-}
-
-static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip)
-{
- struct dp_ctrl_private *ctrl;
- struct dp_catalog_ctrl *catalog;
-
- if (!dp_ctrl) {
- pr_err("Invalid input data\n");
- return -EINVAL;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- ctrl->orientation = flip;
- catalog = ctrl->catalog;
-
- catalog->usb_reset(ctrl->catalog, flip);
- catalog->phy_reset(ctrl->catalog);
- catalog->enable_irq(ctrl->catalog, true);
-
- return 0;
-}
-
-/**
- * dp_ctrl_host_deinit() - Uninitialize DP controller
- * @ctrl: Display Port Driver data
- *
- * Perform required steps to uninitialize DP controller
- * and its resources.
- */
-static void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl) {
- pr_err("Invalid input data\n");
- return;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- ctrl->catalog->enable_irq(ctrl->catalog, false);
-
- pr_debug("Host deinitialized successfully\n");
-}
-
-static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
-{
- u8 *dpcd = ctrl->panel->dpcd;
-
- /*
- * For better interop experience, used a fixed NVID=0x8000
- * whenever connected to a VGA dongle downstream.
- */
- if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT) {
- u8 type = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_TYPE_MASK;
- if (type == DP_DWN_STRM_PORT_TYPE_ANALOG)
- return true;
- }
-
- return false;
-}
-
-static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
-
- ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
- ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
-
- ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
-
- do {
- if (ret == -EAGAIN) {
- /* try with lower link rate */
- dp_ctrl_link_rate_down_shift(ctrl);
-
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
- }
-
- ctrl->catalog->phy_lane_cfg(ctrl->catalog,
- ctrl->orientation, ctrl->link->link_params.lane_count);
-
- /*
- * Disable and re-enable the mainlink clock since the
- * link clock might have been adjusted as part of the
- * link maintenance.
- */
- dp_ctrl_disable_mainlink_clocks(ctrl);
-
- ret = dp_ctrl_enable_mainlink_clocks(ctrl);
- if (ret)
- continue;
-
- dp_ctrl_configure_source_params(ctrl);
-
- ctrl->catalog->config_msa(ctrl->catalog,
- drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code),
- ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
-
- reinit_completion(&ctrl->idle_comp);
-
- ret = dp_ctrl_setup_main_link(ctrl, true);
- } while (ret == -EAGAIN);
-
- return ret;
-}
-
-static void dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
-{
- int ret = 0;
-
- if (!ctrl->link->phy_params.phy_test_pattern_sel) {
- pr_debug("no test pattern selected by sink\n");
- return;
- }
-
- pr_debug("start\n");
-
- ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
- /*
- * The global reset will need DP link ralated clocks to be
- * running. Add the global reset just before disabling the
- * link clocks and core clocks.
- */
- ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
- ctrl->dp_ctrl.off(&ctrl->dp_ctrl);
-
- ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl);
- if (ret)
- pr_err("failed to enable DP controller\n");
-
- pr_debug("end\n");
-}
-
-static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
-{
- bool success = false;
- u32 pattern_sent = 0x0;
- u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
-
- pr_debug("request: %s\n",
- dp_link_get_phy_test_pattern(pattern_requested));
-
- ctrl->catalog->update_vx_px(ctrl->catalog,
- ctrl->link->phy_params.v_level,
- ctrl->link->phy_params.p_level);
- ctrl->catalog->send_phy_pattern(ctrl->catalog, pattern_requested);
- ctrl->link->send_test_response(ctrl->link);
-
- pattern_sent = ctrl->catalog->read_phy_pattern(ctrl->catalog);
-
- switch (pattern_sent) {
- case MR_LINK_TRAINING1:
- if (pattern_requested ==
- DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING)
- success = true;
- break;
- case MR_LINK_SYMBOL_ERM:
- if ((pattern_requested ==
- DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT)
- || (pattern_requested ==
- DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN))
- success = true;
- break;
- case MR_LINK_PRBS7:
- if (pattern_requested == DP_TEST_PHY_PATTERN_PRBS7)
- success = true;
- break;
- case MR_LINK_CUSTOM80:
- if (pattern_requested ==
- DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN)
- success = true;
- break;
- default:
- success = false;
- return;
- }
-
- pr_debug("%s: %s\n", success ? "success" : "failed",
- dp_link_get_phy_test_pattern(pattern_requested));
-}
-
-static void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
- u32 sink_request = 0x0;
-
- if (!dp_ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- sink_request = ctrl->link->sink_request;
-
- if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
- pr_info("PHY_TEST_PATTERN request\n");
- dp_ctrl_process_phy_test_request(ctrl);
- }
-
- if (sink_request & DP_LINK_STATUS_UPDATED)
- dp_ctrl_link_maintenance(ctrl);
-
- if (sink_request & DP_TEST_LINK_TRAINING) {
- ctrl->link->send_test_response(ctrl->link);
- dp_ctrl_link_maintenance(ctrl);
- }
-}
-
-static void dp_ctrl_reset(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl) {
- pr_err("invalid params\n");
- return;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- ctrl->catalog->reset(ctrl->catalog);
-}
-
-static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
-{
- int rc = 0;
- struct dp_ctrl_private *ctrl;
- u32 rate = 0;
- u32 link_train_max_retries = 100;
- u32 const phy_cts_pixel_clk_khz = 148500;
-
- if (!dp_ctrl) {
- rc = -EINVAL;
- goto end;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- atomic_set(&ctrl->aborted, 0);
- rate = ctrl->panel->link_info.rate;
-
- ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
- ctrl->catalog->hpd_config(ctrl->catalog, true);
-
- if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
- pr_debug("using phy test link parameters\n");
- if (!ctrl->panel->pinfo.pixel_clk_khz)
- ctrl->pixel_rate = phy_cts_pixel_clk_khz;
- } else {
- ctrl->link->link_params.bw_code =
- drm_dp_link_rate_to_bw_code(rate);
- ctrl->link->link_params.lane_count =
- ctrl->panel->link_info.num_lanes;
- ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
- }
-
- pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n",
- ctrl->link->link_params.bw_code,
- ctrl->link->link_params.lane_count, ctrl->pixel_rate);
-
- ctrl->catalog->phy_lane_cfg(ctrl->catalog,
- ctrl->orientation, ctrl->link->link_params.lane_count);
-
- rc = dp_ctrl_enable_mainlink_clocks(ctrl);
- if (rc)
- goto end;
-
- reinit_completion(&ctrl->idle_comp);
-
- dp_ctrl_configure_source_params(ctrl);
-
- while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
- ctrl->catalog->config_msa(ctrl->catalog,
- drm_dp_bw_code_to_link_rate(
- ctrl->link->link_params.bw_code),
- ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
-
- rc = dp_ctrl_setup_main_link(ctrl, true);
- if (!rc)
- break;
-
- /* try with lower link rate */
- dp_ctrl_link_rate_down_shift(ctrl);
-
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
-
- dp_ctrl_disable_mainlink_clocks(ctrl);
- /* hw recommended delay before re-enabling clocks */
- msleep(20);
-
- dp_ctrl_enable_mainlink_clocks(ctrl);
- }
-
- if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
- dp_ctrl_send_phy_test_pattern(ctrl);
-
- pr_debug("End-\n");
-
-end:
- return rc;
-}
-
-static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl)
- return;
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
- ctrl->catalog->reset(ctrl->catalog);
-
- /* Make sure DP is disabled before clk disable */
- wmb();
-
- dp_ctrl_disable_mainlink_clocks(ctrl);
-
- pr_debug("DP off done\n");
-}
-
-static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl)
- return;
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- ctrl->catalog->get_interrupt(ctrl->catalog);
-
- if (ctrl->catalog->isr & DP_CTRL_INTR_READY_FOR_VIDEO)
- dp_ctrl_video_ready(ctrl);
-
- if (ctrl->catalog->isr & DP_CTRL_INTR_IDLE_PATTERN_SENT)
- dp_ctrl_idle_patterns_sent(ctrl);
-}
-
-struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in)
-{
- int rc = 0;
- struct dp_ctrl_private *ctrl;
- struct dp_ctrl *dp_ctrl;
-
- if (!in->dev || !in->panel || !in->aux ||
- !in->link || !in->catalog) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- ctrl = devm_kzalloc(in->dev, sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl) {
- rc = -ENOMEM;
- goto error;
- }
-
- init_completion(&ctrl->idle_comp);
- init_completion(&ctrl->video_comp);
-
- /* in parameters */
- ctrl->parser = in->parser;
- ctrl->panel = in->panel;
- ctrl->power = in->power;
- ctrl->aux = in->aux;
- ctrl->link = in->link;
- ctrl->catalog = in->catalog;
-
- dp_ctrl = &ctrl->dp_ctrl;
-
- /* out parameters */
- dp_ctrl->init = dp_ctrl_host_init;
- dp_ctrl->deinit = dp_ctrl_host_deinit;
- dp_ctrl->on = dp_ctrl_on;
- dp_ctrl->off = dp_ctrl_off;
- dp_ctrl->push_idle = dp_ctrl_push_idle;
- dp_ctrl->abort = dp_ctrl_abort;
- dp_ctrl->isr = dp_ctrl_isr;
- dp_ctrl->reset = dp_ctrl_reset;
- dp_ctrl->handle_sink_request = dp_ctrl_handle_sink_request;
-
- return dp_ctrl;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_ctrl_put(struct dp_ctrl *dp_ctrl)
-{
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl)
- return;
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- devm_kfree(ctrl->dev, ctrl);
-}
deleted file mode 100644
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_CTRL_H_
-#define _DP_CTRL_H_
-
-#include "dp_aux.h"
-#include "dp_panel.h"
-#include "dp_link.h"
-#include "dp_parser.h"
-#include "dp_power.h"
-#include "dp_catalog.h"
-
-struct dp_ctrl {
- int (*init)(struct dp_ctrl *dp_ctrl, bool flip);
- void (*deinit)(struct dp_ctrl *dp_ctrl);
- int (*on)(struct dp_ctrl *dp_ctrl);
- void (*off)(struct dp_ctrl *dp_ctrl);
- void (*reset)(struct dp_ctrl *dp_ctrl);
- void (*push_idle)(struct dp_ctrl *dp_ctrl);
- void (*abort)(struct dp_ctrl *dp_ctrl);
- void (*isr)(struct dp_ctrl *dp_ctrl);
- void (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
-};
-
-struct dp_ctrl_in {
- struct device *dev;
- struct dp_panel *panel;
- struct dp_aux *aux;
- struct dp_link *link;
- struct dp_parser *parser;
- struct dp_power *power;
- struct dp_catalog_ctrl *catalog;
-};
-
-struct dp_ctrl *dp_ctrl_get(struct dp_ctrl_in *in);
-void dp_ctrl_put(struct dp_ctrl *dp_ctrl);
-
-#endif /* _DP_CTRL_H_ */
deleted file mode 100644
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/debugfs.h>
-
-#include "dp_parser.h"
-#include "dp_power.h"
-#include "dp_catalog.h"
-#include "dp_aux.h"
-#include "dp_ctrl.h"
-#include "dp_debug.h"
-#include "drm_connector.h"
-#include "dp_display.h"
-
-#define DEBUG_NAME "drm_dp"
-
-struct dp_debug_private {
- struct dentry *root;
-
- struct dp_usbpd *usbpd;
- struct dp_link *link;
- struct dp_panel *panel;
- struct drm_connector **connector;
- struct device *dev;
-
- struct dp_debug dp_debug;
-};
-
-static ssize_t dp_debug_write_hpd(struct file *file,
- const char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dp_debug_private *debug = file->private_data;
- char buf[SZ_8];
- size_t len = 0;
- int hpd;
-
- if (!debug)
- return -ENODEV;
-
- if (*ppos)
- return 0;
-
- /* Leave room for termination char */
- len = min_t(size_t, count, SZ_8 - 1);
- if (copy_from_user(buf, user_buff, len))
- goto end;
-
- buf[len] = '\0';
-
- if (kstrtoint(buf, 10, &hpd) != 0)
- goto end;
-
- debug->usbpd->connect(debug->usbpd, hpd);
-end:
- return -len;
-}
-
-static ssize_t dp_debug_write_edid_modes(struct file *file,
- const char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dp_debug_private *debug = file->private_data;
- char buf[SZ_32];
- size_t len = 0;
- int hdisplay = 0, vdisplay = 0, vrefresh = 0;
-
- if (!debug)
- return -ENODEV;
-
- if (*ppos)
- goto end;
-
- /* Leave room for termination char */
- len = min_t(size_t, count, SZ_32 - 1);
- if (copy_from_user(buf, user_buff, len))
- goto clear;
-
- buf[len] = '\0';
-
- if (sscanf(buf, "%d %d %d", &hdisplay, &vdisplay, &vrefresh) != 3)
- goto clear;
-
- if (!hdisplay || !vdisplay || !vrefresh)
- goto clear;
-
- debug->dp_debug.debug_en = true;
- debug->dp_debug.hdisplay = hdisplay;
- debug->dp_debug.vdisplay = vdisplay;
- debug->dp_debug.vrefresh = vrefresh;
- goto end;
-clear:
- pr_debug("clearing debug modes\n");
- debug->dp_debug.debug_en = false;
-end:
- return len;
-}
-
-static ssize_t dp_debug_read_connected(struct file *file,
- char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dp_debug_private *debug = file->private_data;
- char buf[SZ_8];
- u32 len = 0;
-
- if (!debug)
- return -ENODEV;
-
- if (*ppos)
- return 0;
-
- len += snprintf(buf, SZ_8, "%d\n", debug->usbpd->hpd_high);
-
- if (copy_to_user(user_buff, buf, len))
- return -EFAULT;
-
- *ppos += len;
- return len;
-}
-
-static ssize_t dp_debug_read_edid_modes(struct file *file,
- char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dp_debug_private *debug = file->private_data;
- char *buf;
- u32 len = 0;
- int rc = 0;
- struct drm_connector *connector;
- struct drm_display_mode *mode;
-
- if (!debug) {
- pr_err("invalid data\n");
- rc = -ENODEV;
- goto error;
- }
-
- connector = *debug->connector;
-
- if (!connector) {
- pr_err("connector is NULL\n");
- rc = -EINVAL;
- goto error;
- }
-
- if (*ppos)
- goto error;
-
- buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf) {
- rc = -ENOMEM;
- goto error;
- }
-
- list_for_each_entry(mode, &connector->modes, head) {
- len += snprintf(buf + len, SZ_4K - len,
- "%s %d %d %d %d %d %d %d %d %d 0x%x\n",
- mode->name, mode->vrefresh, mode->hdisplay,
- mode->hsync_start, mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start, mode->vsync_end,
- mode->vtotal, mode->flags);
- }
-
- if (copy_to_user(user_buff, buf, len)) {
- kfree(buf);
- rc = -EFAULT;
- goto error;
- }
-
- *ppos += len;
- kfree(buf);
-
- return len;
-error:
- return rc;
-}
-
-static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len)
-{
- if (rc >= *max_size) {
- pr_err("buffer overflow\n");
- return -EINVAL;
- }
- *len += rc;
- *max_size = SZ_4K - *len;
-
- return 0;
-}
-
-static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff,
- size_t count, loff_t *ppos)
-{
- struct dp_debug_private *debug = file->private_data;
- char *buf;
- u32 len = 0, rc = 0;
- u64 lclk = 0;
- u32 max_size = SZ_4K;
-
- if (!debug)
- return -ENODEV;
-
- if (*ppos)
- return 0;
-
- buf = kzalloc(SZ_4K, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\tdp_panel\n\t\tmax_pclk_khz = %d\n",
- debug->panel->max_pclk_khz);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\tdrm_dp_link\n\t\trate = %u\n",
- debug->panel->link_info.rate);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tnum_lanes = %u\n",
- debug->panel->link_info.num_lanes);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tcapabilities = %lu\n",
- debug->panel->link_info.capabilities);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\tdp_panel_info:\n\t\tactive = %dx%d\n",
- debug->panel->pinfo.h_active,
- debug->panel->pinfo.v_active);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tback_porch = %dx%d\n",
- debug->panel->pinfo.h_back_porch,
- debug->panel->pinfo.v_back_porch);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tfront_porch = %dx%d\n",
- debug->panel->pinfo.h_front_porch,
- debug->panel->pinfo.v_front_porch);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tsync_width = %dx%d\n",
- debug->panel->pinfo.h_sync_width,
- debug->panel->pinfo.v_sync_width);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tactive_low = %dx%d\n",
- debug->panel->pinfo.h_active_low,
- debug->panel->pinfo.v_active_low);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\th_skew = %d\n",
- debug->panel->pinfo.h_skew);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\trefresh rate = %d\n",
- debug->panel->pinfo.refresh_rate);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tpixel clock khz = %d\n",
- debug->panel->pinfo.pixel_clk_khz);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tbpp = %d\n",
- debug->panel->pinfo.bpp);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- /* Link Information */
- rc = snprintf(buf + len, max_size,
- "\tdp_link:\n\t\ttest_requested = %d\n",
- debug->link->sink_request);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tlane_count = %d\n", debug->link->link_params.lane_count);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tbw_code = %d\n", debug->link->link_params.bw_code);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- lclk = drm_dp_bw_code_to_link_rate(
- debug->link->link_params.bw_code) * 1000;
- rc = snprintf(buf + len, max_size,
- "\t\tlclk = %lld\n", lclk);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tv_level = %d\n", debug->link->phy_params.v_level);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tp_level = %d\n", debug->link->phy_params.p_level);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- if (copy_to_user(user_buff, buf, len))
- goto error;
-
- *ppos += len;
-
- kfree(buf);
- return len;
-error:
- kfree(buf);
- return -EINVAL;
-}
-
-static const struct file_operations dp_debug_fops = {
- .open = simple_open,
- .read = dp_debug_read_info,
-};
-
-static const struct file_operations edid_modes_fops = {
- .open = simple_open,
- .read = dp_debug_read_edid_modes,
- .write = dp_debug_write_edid_modes,
-};
-
-static const struct file_operations hpd_fops = {
- .open = simple_open,
- .write = dp_debug_write_hpd,
-};
-
-static const struct file_operations connected_fops = {
- .open = simple_open,
- .read = dp_debug_read_connected,
-};
-
-static int dp_debug_init(struct dp_debug *dp_debug)
-{
- int rc = 0;
- struct dp_debug_private *debug = container_of(dp_debug,
- struct dp_debug_private, dp_debug);
- struct dentry *dir, *file, *edid_modes;
- struct dentry *hpd, *connected;
- struct dentry *root = debug->root;
-
- dir = debugfs_create_dir(DEBUG_NAME, NULL);
- if (IS_ERR_OR_NULL(dir)) {
- rc = PTR_ERR(dir);
- pr_err("[%s] debugfs create dir failed, rc = %d\n",
- DEBUG_NAME, rc);
- goto error;
- }
-
- file = debugfs_create_file("dp_debug", 0444, dir,
- debug, &dp_debug_fops);
- if (IS_ERR_OR_NULL(file)) {
- rc = PTR_ERR(file);
- pr_err("[%s] debugfs create file failed, rc=%d\n",
- DEBUG_NAME, rc);
- goto error_remove_dir;
- }
-
- edid_modes = debugfs_create_file("edid_modes", 0644, dir,
- debug, &edid_modes_fops);
- if (IS_ERR_OR_NULL(edid_modes)) {
- rc = PTR_ERR(edid_modes);
- pr_err("[%s] debugfs create edid_modes failed, rc=%d\n",
- DEBUG_NAME, rc);
- goto error_remove_dir;
- }
-
- hpd = debugfs_create_file("hpd", 0644, dir,
- debug, &hpd_fops);
- if (IS_ERR_OR_NULL(hpd)) {
- rc = PTR_ERR(hpd);
- pr_err("[%s] debugfs hpd failed, rc=%d\n",
- DEBUG_NAME, rc);
- goto error_remove_dir;
- }
-
- connected = debugfs_create_file("connected", 0444, dir,
- debug, &connected_fops);
- if (IS_ERR_OR_NULL(connected)) {
- rc = PTR_ERR(connected);
- pr_err("[%s] debugfs connected failed, rc=%d\n",
- DEBUG_NAME, rc);
- goto error_remove_dir;
- }
-
- root = dir;
- return rc;
-error_remove_dir:
- debugfs_remove(dir);
-error:
- return rc;
-}
-
-struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
- struct dp_usbpd *usbpd, struct dp_link *link,
- struct drm_connector **connector)
-{
- int rc = 0;
- struct dp_debug_private *debug;
- struct dp_debug *dp_debug;
-
- if (!dev || !panel || !usbpd || !link) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL);
- if (!debug) {
- rc = -ENOMEM;
- goto error;
- }
-
- debug->dp_debug.debug_en = false;
- debug->usbpd = usbpd;
- debug->link = link;
- debug->panel = panel;
- debug->dev = dev;
- debug->connector = connector;
-
- dp_debug = &debug->dp_debug;
- dp_debug->vdisplay = 0;
- dp_debug->hdisplay = 0;
- dp_debug->vrefresh = 0;
-
- rc = dp_debug_init(dp_debug);
- if (rc) {
- devm_kfree(dev, debug);
- goto error;
- }
-
- return dp_debug;
-error:
- return ERR_PTR(rc);
-}
-
-static int dp_debug_deinit(struct dp_debug *dp_debug)
-{
- struct dp_debug_private *debug;
-
- if (!dp_debug)
- return -EINVAL;
-
- debug = container_of(dp_debug, struct dp_debug_private, dp_debug);
-
- debugfs_remove(debug->root);
-
- return 0;
-}
-
-void dp_debug_put(struct dp_debug *dp_debug)
-{
- struct dp_debug_private *debug;
-
- if (!dp_debug)
- return;
-
- debug = container_of(dp_debug, struct dp_debug_private, dp_debug);
-
- dp_debug_deinit(dp_debug);
-
- devm_kfree(debug->dev, debug);
-}
deleted file mode 100644
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_DEBUG_H_
-#define _DP_DEBUG_H_
-
-#include "dp_panel.h"
-#include "dp_link.h"
-#include "dp_usbpd.h"
-
-/**
- * struct dp_debug
- * @debug_en: specifies whether debug mode enabled
- * @vdisplay: used to filter out vdisplay value
- * @hdisplay: used to filter out hdisplay value
- * @vrefresh: used to filter out vrefresh value
- */
-struct dp_debug {
- bool debug_en;
- int vdisplay;
- int hdisplay;
- int vrefresh;
-};
-
-/**
- * dp_debug_get() - configure and get the DisplayPlot debug module data
- *
- * @dev: device instance of the caller
- * @panel: instance of panel module
- * @usbpd: instance of usbpd module
- * @link: instance of link module
- * @connector: double pointer to display connector
- * return: pointer to allocated debug module data
- *
- * This function sets up the debug module and provides a way
- * for debugfs input to be communicated with existing modules
- */
-struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
- struct dp_usbpd *usbpd, struct dp_link *link,
- struct drm_connector **connector);
-/**
- * dp_debug_put()
- *
- * Cleans up dp_debug instance
- *
- * @dp_debug: instance of dp_debug
- */
-void dp_debug_put(struct dp_debug *dp_debug);
-#endif /* _DP_DEBUG_H_ */
deleted file mode 100644
@@ -1,1255 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/debugfs.h>
-#include <linux/component.h>
-#include <linux/of_irq.h>
-#include <linux/hdcp_qseecom.h>
-
-#include "msm_drv.h"
-#include "dp_usbpd.h"
-#include "dp_parser.h"
-#include "dp_power.h"
-#include "dp_catalog.h"
-#include "dp_aux.h"
-#include "dp_link.h"
-#include "dp_panel.h"
-#include "dp_ctrl.h"
-#include "dp_audio.h"
-#include "dp_display.h"
-#include "dpu_hdcp.h"
-#include "dp_debug.h"
-
-static struct dp_display *g_dp_display;
-#define HPD_STRING_SIZE 30
-
-struct dp_hdcp {
- void *data;
- struct dpu_hdcp_ops *ops;
-
- void *hdcp1;
- void *hdcp2;
-
- int enc_lvl;
-
- bool auth_state;
- bool hdcp1_present;
- bool hdcp2_present;
- bool feature_enabled;
-};
-
-struct dp_display_private {
- char *name;
- int irq;
-
- /* state variables */
- bool core_initialized;
- bool power_on;
- bool hpd_irq_on;
- bool audio_supported;
-
- struct platform_device *pdev;
- struct dentry *root;
- struct completion notification_comp;
-
- struct dp_usbpd *usbpd;
- struct dp_parser *parser;
- struct dp_power *power;
- struct dp_catalog *catalog;
- struct dp_aux *aux;
- struct dp_link *link;
- struct dp_panel *panel;
- struct dp_ctrl *ctrl;
- struct dp_audio *audio;
- struct dp_debug *debug;
-
- struct dp_hdcp hdcp;
-
- struct dp_usbpd_cb usbpd_cb;
- struct dp_display_mode mode;
- struct dp_display dp_display;
-
- struct workqueue_struct *hdcp_workqueue;
- struct delayed_work hdcp_cb_work;
- struct mutex hdcp_mutex;
- int hdcp_status;
-};
-
-static const struct of_device_id dp_dt_match[] = {
- {.compatible = "qcom,dp-display"},
- {}
-};
-
-static inline bool dp_display_is_hdcp_enabled(struct dp_display_private *dp)
-{
- return dp->hdcp.feature_enabled &&
- (dp->hdcp.hdcp1_present || dp->hdcp.hdcp2_present) &&
- dp->hdcp.ops;
-}
-
-static irqreturn_t dp_display_irq(int irq, void *dev_id)
-{
- struct dp_display_private *dp = dev_id;
-
- if (!dp) {
- pr_err("invalid data\n");
- return IRQ_NONE;
- }
-
- /* DP controller isr */
- dp->ctrl->isr(dp->ctrl);
-
- /* DP aux isr */
- dp->aux->isr(dp->aux);
-
- /* HDCP isr */
- if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->isr) {
- if (dp->hdcp.ops->isr(dp->hdcp.data))
- pr_err("dp_hdcp_isr failed\n");
- }
-
- return IRQ_HANDLED;
-}
-
-static void dp_display_hdcp_cb_work(struct work_struct *work)
-{
- struct dp_display_private *dp;
- struct delayed_work *dw = to_delayed_work(work);
- struct dpu_hdcp_ops *ops;
- int rc = 0;
- u32 hdcp_auth_state;
-
- dp = container_of(dw, struct dp_display_private, hdcp_cb_work);
-
- rc = dp->catalog->ctrl.read_hdcp_status(&dp->catalog->ctrl);
- if (rc >= 0) {
- hdcp_auth_state = (rc >> 20) & 0x3;
- pr_debug("hdcp auth state %d\n", hdcp_auth_state);
- }
-
- ops = dp->hdcp.ops;
-
- switch (dp->hdcp_status) {
- case HDCP_STATE_AUTHENTICATING:
- pr_debug("start authenticaton\n");
-
- if (dp->hdcp.ops && dp->hdcp.ops->authenticate)
- rc = dp->hdcp.ops->authenticate(dp->hdcp.data);
-
- break;
- case HDCP_STATE_AUTHENTICATED:
- pr_debug("hdcp authenticated\n");
- dp->hdcp.auth_state = true;
- break;
- case HDCP_STATE_AUTH_FAIL:
- dp->hdcp.auth_state = false;
-
- if (dp->power_on) {
- pr_debug("Reauthenticating\n");
- if (ops && ops->reauthenticate) {
- rc = ops->reauthenticate(dp->hdcp.data);
- if (rc)
- pr_err("reauth failed rc=%d\n", rc);
- }
- } else {
- pr_debug("not reauthenticating, cable disconnected\n");
- }
-
- break;
- default:
- break;
- }
-}
-
-static void dp_display_notify_hdcp_status_cb(void *ptr,
- enum dpu_hdcp_states status)
-{
- struct dp_display_private *dp = ptr;
-
- if (!dp) {
- pr_err("invalid input\n");
- return;
- }
-
- dp->hdcp_status = status;
-
- if (dp->dp_display.is_connected)
- queue_delayed_work(dp->hdcp_workqueue, &dp->hdcp_cb_work, HZ/4);
-}
-
-static int dp_display_create_hdcp_workqueue(struct dp_display_private *dp)
-{
- dp->hdcp_workqueue = create_workqueue("sdm_dp_hdcp");
- if (IS_ERR_OR_NULL(dp->hdcp_workqueue)) {
- pr_err("Error creating hdcp_workqueue\n");
- return -EPERM;
- }
-
- INIT_DELAYED_WORK(&dp->hdcp_cb_work, dp_display_hdcp_cb_work);
-
- return 0;
-}
-
-static void dp_display_destroy_hdcp_workqueue(struct dp_display_private *dp)
-{
- if (dp->hdcp_workqueue)
- destroy_workqueue(dp->hdcp_workqueue);
-}
-
-static void dp_display_update_hdcp_info(struct dp_display_private *dp)
-{
- void *fd = NULL;
- struct dpu_hdcp_ops *ops = NULL;
-
- if (!dp) {
- pr_err("invalid input\n");
- return;
- }
-
- if (!dp->hdcp.feature_enabled) {
- pr_debug("feature not enabled\n");
- return;
- }
-
- fd = dp->hdcp.hdcp2;
- if (fd)
- ops = dpu_dp_hdcp2p2_start(fd);
-
- if (ops && ops->feature_supported)
- dp->hdcp.hdcp2_present = ops->feature_supported(fd);
- else
- dp->hdcp.hdcp2_present = false;
-
- pr_debug("hdcp2p2: %s\n",
- dp->hdcp.hdcp2_present ? "supported" : "not supported");
-
- if (!dp->hdcp.hdcp2_present) {
- dp->hdcp.hdcp1_present = hdcp1_check_if_supported_load_app();
-
- if (dp->hdcp.hdcp1_present) {
- fd = dp->hdcp.hdcp1;
- ops = dpu_hdcp_1x_start(fd);
- }
- }
-
- pr_debug("hdcp1x: %s\n",
- dp->hdcp.hdcp1_present ? "supported" : "not supported");
-
- if (dp->hdcp.hdcp2_present || dp->hdcp.hdcp1_present) {
- dp->hdcp.data = fd;
- dp->hdcp.ops = ops;
- } else {
- dp->hdcp.data = NULL;
- dp->hdcp.ops = NULL;
- }
-}
-
-static void dp_display_deinitialize_hdcp(struct dp_display_private *dp)
-{
- if (!dp) {
- pr_err("invalid input\n");
- return;
- }
-
- dpu_dp_hdcp2p2_deinit(dp->hdcp.data);
- dp_display_destroy_hdcp_workqueue(dp);
- mutex_destroy(&dp->hdcp_mutex);
-}
-
-static int dp_display_initialize_hdcp(struct dp_display_private *dp)
-{
- struct dpu_hdcp_init_data hdcp_init_data;
- struct resource *res;
- int rc = 0;
-
- if (!dp) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- mutex_init(&dp->hdcp_mutex);
-
- rc = dp_display_create_hdcp_workqueue(dp);
- if (rc) {
- pr_err("Failed to create HDCP workqueue\n");
- goto error;
- }
-
- res = platform_get_resource_byname(dp->pdev,
- IORESOURCE_MEM, "dp_ctrl");
- if (!res) {
- pr_err("Error getting dp ctrl resource\n");
- rc = -EINVAL;
- goto error;
- }
-
- hdcp_init_data.phy_addr = res->start;
- hdcp_init_data.client_id = HDCP_CLIENT_DP;
- hdcp_init_data.drm_aux = dp->aux->drm_aux;
- hdcp_init_data.cb_data = (void *)dp;
- hdcp_init_data.workq = dp->hdcp_workqueue;
- hdcp_init_data.mutex = &dp->hdcp_mutex;
- hdcp_init_data.sec_access = true;
- hdcp_init_data.notify_status = dp_display_notify_hdcp_status_cb;
- hdcp_init_data.core_io = &dp->parser->io.ctrl_io;
- hdcp_init_data.qfprom_io = &dp->parser->io.qfprom_io;
- hdcp_init_data.hdcp_io = &dp->parser->io.hdcp_io;
- hdcp_init_data.revision = &dp->panel->link_info.revision;
-
- dp->hdcp.hdcp1 = dpu_hdcp_1x_init(&hdcp_init_data);
- if (IS_ERR_OR_NULL(dp->hdcp.hdcp1)) {
- pr_err("Error initializing HDCP 1.x\n");
- rc = -EINVAL;
- goto error;
- }
-
- pr_debug("HDCP 1.3 initialized\n");
-
- dp->hdcp.hdcp2 = dpu_dp_hdcp2p2_init(&hdcp_init_data);
- if (!IS_ERR_OR_NULL(dp->hdcp.hdcp2))
- pr_debug("HDCP 2.2 initialized\n");
-
- dp->hdcp.feature_enabled = true;
-
- return 0;
-error:
- dp_display_deinitialize_hdcp(dp);
- return rc;
-}
-
-static int dp_display_bind(struct device *dev, struct device *master,
- void *data)
-{
- int rc = 0;
- struct dp_display_private *dp;
- struct drm_device *drm;
- struct msm_drm_private *priv;
- struct platform_device *pdev = to_platform_device(dev);
-
- if (!dev || !pdev || !master) {
- pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n",
- dev, pdev, master);
- rc = -EINVAL;
- goto end;
- }
-
- drm = dev_get_drvdata(master);
- dp = platform_get_drvdata(pdev);
- if (!drm || !dp) {
- pr_err("invalid param(s), drm %pK, dp %pK\n",
- drm, dp);
- rc = -EINVAL;
- goto end;
- }
-
- dp->dp_display.drm_dev = drm;
- priv = drm->dev_private;
-
- rc = dp->parser->parse(dp->parser);
- if (rc) {
- pr_err("device tree parsing failed\n");
- goto end;
- }
-
- rc = dp->aux->drm_aux_register(dp->aux);
- if (rc) {
- pr_err("DRM DP AUX register failed\n");
- goto end;
- }
-
- rc = dp->power->power_client_init(dp->power, &priv->phandle);
- if (rc) {
- pr_err("Power client create failed\n");
- goto end;
- }
-
- rc = dp_display_initialize_hdcp(dp);
- if (rc) {
- pr_err("HDCP initialization failed\n");
- goto end;
- }
-end:
- return rc;
-}
-
-static void dp_display_unbind(struct device *dev, struct device *master,
- void *data)
-{
- struct dp_display_private *dp;
- struct platform_device *pdev = to_platform_device(dev);
-
- if (!dev || !pdev) {
- pr_err("invalid param(s)\n");
- return;
- }
-
- dp = platform_get_drvdata(pdev);
- if (!dp) {
- pr_err("Invalid params\n");
- return;
- }
-
- (void)dp->power->power_client_deinit(dp->power);
- (void)dp->aux->drm_aux_deregister(dp->aux);
- dp_display_deinitialize_hdcp(dp);
-}
-
-static const struct component_ops dp_display_comp_ops = {
- .bind = dp_display_bind,
- .unbind = dp_display_unbind,
-};
-
-static bool dp_display_is_ds_bridge(struct dp_panel *panel)
-{
- return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
- DP_DWN_STRM_PORT_PRESENT);
-}
-
-static bool dp_display_is_sink_count_zero(struct dp_display_private *dp)
-{
- return dp_display_is_ds_bridge(dp->panel) &&
- (dp->link->sink_count.count == 0);
-}
-
-static void dp_display_send_hpd_event(struct dp_display *dp_display)
-{
- struct drm_device *dev = NULL;
- struct dp_display_private *dp;
- struct drm_connector *connector;
- char name[HPD_STRING_SIZE], status[HPD_STRING_SIZE],
- bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE];
- char *envp[5];
-
- if (!dp_display) {
- pr_err("invalid input\n");
- return;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
- if (!dp) {
- pr_err("invalid params\n");
- return;
- }
- connector = dp->dp_display.connector;
- dev = dp_display->connector->dev;
-
- connector->status = connector->funcs->detect(connector, false);
- pr_debug("[%s] status updated to %s\n",
- connector->name,
- drm_get_connector_status_name(connector->status));
- snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name);
- snprintf(status, HPD_STRING_SIZE, "status=%s",
- drm_get_connector_status_name(connector->status));
- snprintf(bpp, HPD_STRING_SIZE, "bpp=%d",
- dp_link_bit_depth_to_bpp(
- dp->link->test_video.test_bit_depth));
- snprintf(pattern, HPD_STRING_SIZE, "pattern=%d",
- dp->link->test_video.test_video_pattern);
-
- pr_debug("generating hotplug event [%s]:[%s] [%s] [%s]\n",
- name, status, bpp, pattern);
- envp[0] = name;
- envp[1] = status;
- envp[2] = bpp;
- envp[3] = pattern;
- envp[4] = NULL;
- kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
- envp);
-}
-
-static int dp_display_send_hpd_notification(struct dp_display_private *dp,
- bool hpd)
-{
- if ((hpd && dp->dp_display.is_connected) ||
- (!hpd && !dp->dp_display.is_connected)) {
- pr_info("HPD already %s\n", (hpd ? "on" : "off"));
- return 0;
- }
-
- /* reset video pattern flag on disconnect */
- if (!hpd)
- dp->panel->video_test = false;
-
- dp->dp_display.is_connected = hpd;
- reinit_completion(&dp->notification_comp);
- dp_display_send_hpd_event(&dp->dp_display);
-
- if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) {
- pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int dp_display_process_hpd_high(struct dp_display_private *dp)
-{
- int rc = 0;
- u32 max_pclk_from_edid = 0;
- struct edid *edid;
-
- dp->aux->init(dp->aux, dp->parser->aux_cfg);
-
- if (dp->link->psm_enabled)
- goto notify;
-
- rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector);
- if (rc)
- goto notify;
-
- dp->link->process_request(dp->link);
-
- if (dp_display_is_sink_count_zero(dp)) {
- pr_debug("no downstream devices connected\n");
- rc = -EINVAL;
- goto end;
- }
-
- edid = dp->panel->edid_ctrl->edid;
-
- dp->audio_supported = drm_detect_monitor_audio(edid);
-
- dp->panel->handle_sink_request(dp->panel);
-
- max_pclk_from_edid = dp->panel->get_max_pclk(dp->panel);
-
- dp->dp_display.max_pclk_khz = min(max_pclk_from_edid,
- dp->parser->max_pclk_khz);
-
-notify:
- dp_display_send_hpd_notification(dp, true);
-
-end:
- return rc;
-}
-
-static void dp_display_host_init(struct dp_display_private *dp)
-{
- bool flip = false;
-
- if (dp->core_initialized) {
- pr_debug("DP core already initialized\n");
- return;
- }
-
- if (dp->usbpd->orientation == ORIENTATION_CC2)
- flip = true;
-
- dp->power->init(dp->power, flip);
- dp->ctrl->init(dp->ctrl, flip);
- enable_irq(dp->irq);
- dp->core_initialized = true;
-}
-
-static void dp_display_host_deinit(struct dp_display_private *dp)
-{
- if (!dp->core_initialized) {
- pr_debug("DP core already off\n");
- return;
- }
-
- dp->ctrl->deinit(dp->ctrl);
- dp->power->deinit(dp->power);
- disable_irq(dp->irq);
- dp->core_initialized = false;
-}
-
-static void dp_display_process_hpd_low(struct dp_display_private *dp)
-{
- /* cancel any pending request */
- dp->ctrl->abort(dp->ctrl);
-
- if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->off) {
- cancel_delayed_work_sync(&dp->hdcp_cb_work);
- dp->hdcp.ops->off(dp->hdcp.data);
- }
-
- if (dp->audio_supported)
- dp->audio->off(dp->audio);
-
- dp_display_send_hpd_notification(dp, false);
-
- dp->aux->deinit(dp->aux);
-}
-
-static int dp_display_usbpd_configure_cb(struct device *dev)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dev) {
- pr_err("invalid dev\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp = dev_get_drvdata(dev);
- if (!dp) {
- pr_err("no driver data found\n");
- rc = -ENODEV;
- goto end;
- }
-
- dp_display_host_init(dp);
-
- if (dp->usbpd->hpd_high)
- dp_display_process_hpd_high(dp);
-end:
- return rc;
-}
-
-static void dp_display_clean(struct dp_display_private *dp)
-{
- if (dp_display_is_hdcp_enabled(dp)) {
- dp->hdcp_status = HDCP_STATE_INACTIVE;
-
- cancel_delayed_work_sync(&dp->hdcp_cb_work);
- if (dp->hdcp.ops->off)
- dp->hdcp.ops->off(dp->hdcp.data);
- }
-
- dp->ctrl->push_idle(dp->ctrl);
- dp->ctrl->off(dp->ctrl);
-}
-
-static int dp_display_usbpd_disconnect_cb(struct device *dev)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dev) {
- pr_err("invalid dev\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp = dev_get_drvdata(dev);
- if (!dp) {
- pr_err("no driver data found\n");
- rc = -ENODEV;
- goto end;
- }
-
- /* cancel any pending request */
- dp->ctrl->abort(dp->ctrl);
-
- if (dp->audio_supported)
- dp->audio->off(dp->audio);
-
- rc = dp_display_send_hpd_notification(dp, false);
-
- /* if cable is disconnected, reset psm_enabled flag */
- if (!dp->usbpd->alt_mode_cfg_done)
- dp->link->psm_enabled = false;
-
- if ((rc < 0) && dp->power_on)
- dp_display_clean(dp);
-
- dp_display_host_deinit(dp);
-end:
- return rc;
-}
-
-static void dp_display_handle_video_request(struct dp_display_private *dp)
-{
- if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) {
- /* force disconnect followed by connect */
- dp->usbpd->connect(dp->usbpd, false);
- dp->panel->video_test = true;
- dp->usbpd->connect(dp->usbpd, true);
- dp->link->send_test_response(dp->link);
- }
-}
-
-static int dp_display_handle_hpd_irq(struct dp_display_private *dp)
-{
- if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) {
- dp_display_send_hpd_notification(dp, false);
-
- if (dp_display_is_sink_count_zero(dp)) {
- pr_debug("sink count is zero, nothing to do\n");
- return 0;
- }
-
- return dp_display_process_hpd_high(dp);
- }
-
- dp->ctrl->handle_sink_request(dp->ctrl);
-
- dp_display_handle_video_request(dp);
-
- return 0;
-}
-
-static int dp_display_usbpd_attention_cb(struct device *dev)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dev) {
- pr_err("invalid dev\n");
- return -EINVAL;
- }
-
- dp = dev_get_drvdata(dev);
- if (!dp) {
- pr_err("no driver data found\n");
- return -ENODEV;
- }
-
- if (dp->usbpd->hpd_irq) {
- dp->hpd_irq_on = true;
-
- if (dp_display_is_hdcp_enabled(dp) && dp->hdcp.ops->cp_irq) {
- if (!dp->hdcp.ops->cp_irq(dp->hdcp.data))
- goto end;
- }
-
- rc = dp->link->process_request(dp->link);
- /* check for any test request issued by sink */
- if (!rc)
- dp_display_handle_hpd_irq(dp);
-
- dp->hpd_irq_on = false;
- goto end;
- }
-
- if (!dp->usbpd->hpd_high) {
- dp_display_process_hpd_low(dp);
- goto end;
- }
-
- if (dp->usbpd->alt_mode_cfg_done)
- dp_display_process_hpd_high(dp);
-end:
- return rc;
-}
-
-static void dp_display_deinit_sub_modules(struct dp_display_private *dp)
-{
- dp_audio_put(dp->audio);
- dp_ctrl_put(dp->ctrl);
- dp_link_put(dp->link);
- dp_panel_put(dp->panel);
- dp_aux_put(dp->aux);
- dp_power_put(dp->power);
- dp_catalog_put(dp->catalog);
- dp_parser_put(dp->parser);
- dp_usbpd_put(dp->usbpd);
- dp_debug_put(dp->debug);
-}
-
-static int dp_init_sub_modules(struct dp_display_private *dp)
-{
- int rc = 0;
- struct device *dev = &dp->pdev->dev;
- struct dp_usbpd_cb *cb = &dp->usbpd_cb;
- struct dp_ctrl_in ctrl_in = {
- .dev = dev,
- };
- struct dp_panel_in panel_in = {
- .dev = dev,
- };
-
- cb->configure = dp_display_usbpd_configure_cb;
- cb->disconnect = dp_display_usbpd_disconnect_cb;
- cb->attention = dp_display_usbpd_attention_cb;
-
- dp->usbpd = dp_usbpd_get(dev, cb);
- if (IS_ERR(dp->usbpd)) {
- rc = PTR_ERR(dp->usbpd);
- pr_err("failed to initialize usbpd, rc = %d\n", rc);
- dp->usbpd = NULL;
- goto error;
- }
-
- dp->parser = dp_parser_get(dp->pdev);
- if (IS_ERR(dp->parser)) {
- rc = PTR_ERR(dp->parser);
- pr_err("failed to initialize parser, rc = %d\n", rc);
- dp->parser = NULL;
- goto error_parser;
- }
-
- dp->catalog = dp_catalog_get(dev, &dp->parser->io);
- if (IS_ERR(dp->catalog)) {
- rc = PTR_ERR(dp->catalog);
- pr_err("failed to initialize catalog, rc = %d\n", rc);
- dp->catalog = NULL;
- goto error_catalog;
- }
-
- dp->power = dp_power_get(dp->parser);
- if (IS_ERR(dp->power)) {
- rc = PTR_ERR(dp->power);
- pr_err("failed to initialize power, rc = %d\n", rc);
- dp->power = NULL;
- goto error_power;
- }
-
- dp->aux = dp_aux_get(dev, &dp->catalog->aux, dp->parser->aux_cfg);
- if (IS_ERR(dp->aux)) {
- rc = PTR_ERR(dp->aux);
- pr_err("failed to initialize aux, rc = %d\n", rc);
- dp->aux = NULL;
- goto error_aux;
- }
-
- dp->link = dp_link_get(dev, dp->aux);
- if (IS_ERR(dp->link)) {
- rc = PTR_ERR(dp->link);
- pr_err("failed to initialize link, rc = %d\n", rc);
- dp->link = NULL;
- goto error_link;
- }
-
- panel_in.aux = dp->aux;
- panel_in.catalog = &dp->catalog->panel;
- panel_in.link = dp->link;
-
- dp->panel = dp_panel_get(&panel_in);
- if (IS_ERR(dp->panel)) {
- rc = PTR_ERR(dp->panel);
- pr_err("failed to initialize panel, rc = %d\n", rc);
- dp->panel = NULL;
- goto error_panel;
- }
-
- ctrl_in.link = dp->link;
- ctrl_in.panel = dp->panel;
- ctrl_in.aux = dp->aux;
- ctrl_in.power = dp->power;
- ctrl_in.catalog = &dp->catalog->ctrl;
- ctrl_in.parser = dp->parser;
-
- dp->ctrl = dp_ctrl_get(&ctrl_in);
- if (IS_ERR(dp->ctrl)) {
- rc = PTR_ERR(dp->ctrl);
- pr_err("failed to initialize ctrl, rc = %d\n", rc);
- dp->ctrl = NULL;
- goto error_ctrl;
- }
-
- dp->audio = dp_audio_get(dp->pdev, dp->panel, &dp->catalog->audio);
- if (IS_ERR(dp->audio)) {
- rc = PTR_ERR(dp->audio);
- pr_err("failed to initialize audio, rc = %d\n", rc);
- dp->audio = NULL;
- goto error_audio;
- }
-
- dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
- dp->link, &dp->dp_display.connector);
- if (IS_ERR(dp->debug)) {
- rc = PTR_ERR(dp->debug);
- pr_err("failed to initialize debug, rc = %d\n", rc);
- dp->debug = NULL;
- goto error_debug;
- }
-
- return rc;
-error_debug:
- dp_audio_put(dp->audio);
-error_audio:
- dp_ctrl_put(dp->ctrl);
-error_ctrl:
- dp_panel_put(dp->panel);
-error_panel:
- dp_link_put(dp->link);
-error_link:
- dp_aux_put(dp->aux);
-error_aux:
- dp_power_put(dp->power);
-error_power:
- dp_catalog_put(dp->catalog);
-error_catalog:
- dp_parser_put(dp->parser);
-error_parser:
- dp_usbpd_put(dp->usbpd);
-error:
- return rc;
-}
-
-static int dp_display_set_mode(struct dp_display *dp_display,
- struct dp_display_mode *mode)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- dp->panel->pinfo = mode->timing;
- dp->panel->init_info(dp->panel);
-error:
- return rc;
-}
-
-static int dp_display_prepare(struct dp_display *dp)
-{
- return 0;
-}
-
-static int dp_display_enable(struct dp_display *dp_display)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- if (dp->power_on) {
- pr_debug("Link already setup, return\n");
- return 0;
- }
-
- rc = dp->ctrl->on(dp->ctrl);
- if (!rc)
- dp->power_on = true;
-error:
- return rc;
-}
-
-static int dp_display_post_enable(struct dp_display *dp_display)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- if (dp->audio_supported) {
- dp->audio->bw_code = dp->link->link_params.bw_code;
- dp->audio->lane_count = dp->link->link_params.lane_count;
- dp->audio->on(dp->audio);
- }
-
- complete_all(&dp->notification_comp);
-
- dp_display_update_hdcp_info(dp);
-
- if (dp_display_is_hdcp_enabled(dp)) {
- cancel_delayed_work_sync(&dp->hdcp_cb_work);
-
- dp->hdcp_status = HDCP_STATE_AUTHENTICATING;
- queue_delayed_work(dp->hdcp_workqueue,
- &dp->hdcp_cb_work, HZ / 2);
- }
-end:
- return rc;
-}
-
-static int dp_display_pre_disable(struct dp_display *dp_display)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- if (dp_display_is_hdcp_enabled(dp)) {
- dp->hdcp_status = HDCP_STATE_INACTIVE;
-
- cancel_delayed_work_sync(&dp->hdcp_cb_work);
- if (dp->hdcp.ops->off)
- dp->hdcp.ops->off(dp->hdcp.data);
- }
-
- if (dp->usbpd->alt_mode_cfg_done && (dp->usbpd->hpd_high ||
- dp->usbpd->forced_disconnect))
- dp->link->psm_config(dp->link, &dp->panel->link_info, true);
-
- dp->ctrl->push_idle(dp->ctrl);
-error:
- return rc;
-}
-
-static int dp_display_disable(struct dp_display *dp_display)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- if (!dp->power_on || !dp->core_initialized)
- goto error;
-
- dp->ctrl->off(dp->ctrl);
-
- dp->power_on = false;
-
- complete_all(&dp->notification_comp);
-error:
- return rc;
-}
-
-static int dp_request_irq(struct dp_display *dp_display)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);
- if (dp->irq < 0) {
- rc = dp->irq;
- pr_err("failed to get irq: %d\n", rc);
- return rc;
- }
-
- rc = devm_request_irq(&dp->pdev->dev, dp->irq, dp_display_irq,
- IRQF_TRIGGER_HIGH, "dp_display_isr", dp);
- if (rc < 0) {
- pr_err("failed to request IRQ%u: %d\n",
- dp->irq, rc);
- return rc;
- }
- disable_irq(dp->irq);
-
- return 0;
-}
-
-static struct dp_debug *dp_get_debug(struct dp_display *dp_display)
-{
- struct dp_display_private *dp;
-
- if (!dp_display) {
- pr_err("invalid input\n");
- return ERR_PTR(-EINVAL);
- }
-
- dp = container_of(dp_display, struct dp_display_private, dp_display);
-
- return dp->debug;
-}
-
-static int dp_display_unprepare(struct dp_display *dp)
-{
- return 0;
-}
-
-static int dp_display_validate_mode(struct dp_display *dp,
- struct dp_display_mode *mode)
-{
- return 0;
-}
-
-static int dp_display_get_modes(struct dp_display *dp,
- struct dp_display_mode *dp_mode)
-{
- struct dp_display_private *dp_display;
- int ret = 0;
-
- if (!dp) {
- pr_err("invalid params\n");
- return 0;
- }
-
- dp_display = container_of(dp, struct dp_display_private, dp_display);
-
- ret = dp_display->panel->get_modes(dp_display->panel,
- dp->connector, dp_mode);
- if (dp_mode->timing.pixel_clk_khz)
- dp->max_pclk_khz = dp_mode->timing.pixel_clk_khz;
- return ret;
-}
-
-static bool dp_display_check_video_test(struct dp_display *dp)
-{
- struct dp_display_private *dp_display;
-
- if (!dp) {
- pr_err("invalid params\n");
- return false;
- }
-
- dp_display = container_of(dp, struct dp_display_private, dp_display);
-
- if (dp_display->panel->video_test)
- return true;
-
- return false;
-}
-
-static int dp_display_get_test_bpp(struct dp_display *dp)
-{
- struct dp_display_private *dp_display;
-
- if (!dp) {
- pr_err("invalid params\n");
- return 0;
- }
-
- dp_display = container_of(dp, struct dp_display_private, dp_display);
-
- return dp_link_bit_depth_to_bpp(
- dp_display->link->test_video.test_bit_depth);
-}
-
-static int dp_display_probe(struct platform_device *pdev)
-{
- int rc = 0;
- struct dp_display_private *dp;
-
- if (!pdev || !pdev->dev.of_node) {
- pr_err("pdev not found\n");
- return -ENODEV;
- }
-
- dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
- if (!dp)
- return -ENOMEM;
-
- init_completion(&dp->notification_comp);
-
- dp->pdev = pdev;
- dp->name = "drm_dp";
-
- rc = dp_init_sub_modules(dp);
- if (rc) {
- devm_kfree(&pdev->dev, dp);
- return -EPROBE_DEFER;
- }
-
- platform_set_drvdata(pdev, dp);
-
- g_dp_display = &dp->dp_display;
-
- g_dp_display->enable = dp_display_enable;
- g_dp_display->post_enable = dp_display_post_enable;
- g_dp_display->pre_disable = dp_display_pre_disable;
- g_dp_display->disable = dp_display_disable;
- g_dp_display->set_mode = dp_display_set_mode;
- g_dp_display->validate_mode = dp_display_validate_mode;
- g_dp_display->get_modes = dp_display_get_modes;
- g_dp_display->prepare = dp_display_prepare;
- g_dp_display->unprepare = dp_display_unprepare;
- g_dp_display->request_irq = dp_request_irq;
- g_dp_display->get_debug = dp_get_debug;
- g_dp_display->send_hpd_event = dp_display_send_hpd_event;
- g_dp_display->is_video_test = dp_display_check_video_test;
- g_dp_display->get_test_bpp = dp_display_get_test_bpp;
-
- rc = component_add(&pdev->dev, &dp_display_comp_ops);
- if (rc) {
- pr_err("component add failed, rc=%d\n", rc);
- dp_display_deinit_sub_modules(dp);
- devm_kfree(&pdev->dev, dp);
- }
-
- return rc;
-}
-
-int dp_display_get_displays(void **displays, int count)
-{
- if (!displays) {
- pr_err("invalid data\n");
- return -EINVAL;
- }
-
- if (count != 1) {
- pr_err("invalid number of displays\n");
- return -EINVAL;
- }
-
- displays[0] = g_dp_display;
- return count;
-}
-
-int dp_display_get_num_of_displays(void)
-{
- return 1;
-}
-
-static int dp_display_remove(struct platform_device *pdev)
-{
- struct dp_display_private *dp;
-
- if (!pdev)
- return -EINVAL;
-
- dp = platform_get_drvdata(pdev);
-
- dp_display_deinit_sub_modules(dp);
-
- platform_set_drvdata(pdev, NULL);
- devm_kfree(&pdev->dev, dp);
-
- return 0;
-}
-
-static struct platform_driver dp_display_driver = {
- .probe = dp_display_probe,
- .remove = dp_display_remove,
- .driver = {
- .name = "msm-dp-display",
- .of_match_table = dp_dt_match,
- },
-};
-
-static int __init dp_display_init(void)
-{
- int ret;
-
- ret = platform_driver_register(&dp_display_driver);
- if (ret) {
- pr_err("driver register failed");
- return ret;
- }
-
- return ret;
-}
-module_init(dp_display_init);
-
-static void __exit dp_display_cleanup(void)
-{
- platform_driver_unregister(&dp_display_driver);
-}
-module_exit(dp_display_cleanup);
-
deleted file mode 100644
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_DISPLAY_H_
-#define _DP_DISPLAY_H_
-
-#include <drm/drmP.h>
-
-#include "dp_panel.h"
-
-struct dp_display {
- struct drm_device *drm_dev;
- struct dp_bridge *bridge;
- struct drm_connector *connector;
- bool is_connected;
- u32 max_pclk_khz;
-
- int (*enable)(struct dp_display *dp_display);
- int (*post_enable)(struct dp_display *dp_display);
-
- int (*pre_disable)(struct dp_display *dp_display);
- int (*disable)(struct dp_display *dp_display);
-
- int (*set_mode)(struct dp_display *dp_display,
- struct dp_display_mode *mode);
- int (*validate_mode)(struct dp_display *dp_display,
- struct dp_display_mode *mode);
- int (*get_modes)(struct dp_display *dp_display,
- struct dp_display_mode *dp_mode);
- int (*prepare)(struct dp_display *dp_display);
- int (*unprepare)(struct dp_display *dp_display);
- int (*request_irq)(struct dp_display *dp_display);
- struct dp_debug *(*get_debug)(struct dp_display *dp_display);
- void (*send_hpd_event)(struct dp_display *dp_display);
- bool (*is_video_test)(struct dp_display *dp_display);
- int (*get_test_bpp)(struct dp_display *dp_display);
-};
-
-int dp_display_get_num_of_displays(void);
-int dp_display_get_displays(void **displays, int count);
-#endif /* _DP_DISPLAY_H_ */
deleted file mode 100644
@@ -1,538 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp]: %s: " fmt, __func__
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_atomic.h>
-#include <drm/drm_crtc.h>
-
-#include "msm_drv.h"
-#include "msm_kms.h"
-#include "dpu_connector.h"
-#include "dp_drm.h"
-#include "dp_debug.h"
-
-#define to_dp_bridge(x) container_of((x), struct dp_bridge, base)
-
-static void convert_to_dp_mode(const struct drm_display_mode *drm_mode,
- struct dp_display_mode *dp_mode, struct dp_display *dp)
-{
- const u32 num_components = 3;
-
- memset(dp_mode, 0, sizeof(*dp_mode));
-
- dp_mode->timing.h_active = drm_mode->hdisplay;
- dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end;
- dp_mode->timing.h_sync_width = drm_mode->htotal -
- (drm_mode->hsync_start + dp_mode->timing.h_back_porch);
- dp_mode->timing.h_front_porch = drm_mode->hsync_start -
- drm_mode->hdisplay;
- dp_mode->timing.h_skew = drm_mode->hskew;
-
- dp_mode->timing.v_active = drm_mode->vdisplay;
- dp_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end;
- dp_mode->timing.v_sync_width = drm_mode->vtotal -
- (drm_mode->vsync_start + dp_mode->timing.v_back_porch);
-
- dp_mode->timing.v_front_porch = drm_mode->vsync_start -
- drm_mode->vdisplay;
-
- if (dp->is_video_test(dp))
- dp_mode->timing.bpp = dp->get_test_bpp(dp);
- else
- dp_mode->timing.bpp = dp->connector->display_info.bpc *
- num_components;
-
- if (!dp_mode->timing.bpp)
- dp_mode->timing.bpp = 24;
-
- dp_mode->timing.refresh_rate = drm_mode->vrefresh;
-
- dp_mode->timing.pixel_clk_khz = drm_mode->clock;
-
- dp_mode->timing.v_active_low =
- !!(drm_mode->flags & DRM_MODE_FLAG_NVSYNC);
-
- dp_mode->timing.h_active_low =
- !!(drm_mode->flags & DRM_MODE_FLAG_NHSYNC);
-}
-
-static void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
- struct drm_display_mode *drm_mode)
-{
- u32 flags = 0;
-
- memset(drm_mode, 0, sizeof(*drm_mode));
-
- drm_mode->hdisplay = dp_mode->timing.h_active;
- drm_mode->hsync_start = drm_mode->hdisplay +
- dp_mode->timing.h_front_porch;
- drm_mode->hsync_end = drm_mode->hsync_start +
- dp_mode->timing.h_sync_width;
- drm_mode->htotal = drm_mode->hsync_end + dp_mode->timing.h_back_porch;
- drm_mode->hskew = dp_mode->timing.h_skew;
-
- drm_mode->vdisplay = dp_mode->timing.v_active;
- drm_mode->vsync_start = drm_mode->vdisplay +
- dp_mode->timing.v_front_porch;
- drm_mode->vsync_end = drm_mode->vsync_start +
- dp_mode->timing.v_sync_width;
- drm_mode->vtotal = drm_mode->vsync_end + dp_mode->timing.v_back_porch;
-
- drm_mode->vrefresh = dp_mode->timing.refresh_rate;
- drm_mode->clock = dp_mode->timing.pixel_clk_khz;
-
- if (dp_mode->timing.h_active_low)
- flags |= DRM_MODE_FLAG_NHSYNC;
- else
- flags |= DRM_MODE_FLAG_PHSYNC;
-
- if (dp_mode->timing.v_active_low)
- flags |= DRM_MODE_FLAG_NVSYNC;
- else
- flags |= DRM_MODE_FLAG_PVSYNC;
-
- drm_mode->flags = flags;
-
- drm_mode->type = 0x48;
- drm_mode_set_name(drm_mode);
-}
-
-static int dp_bridge_attach(struct drm_bridge *dp_bridge)
-{
- struct dp_bridge *bridge = to_dp_bridge(dp_bridge);
-
- if (!dp_bridge) {
- pr_err("Invalid params\n");
- return -EINVAL;
- }
-
- pr_debug("[%d] attached\n", bridge->id);
-
- return 0;
-}
-
-static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge)
-{
- int rc = 0;
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge) {
- pr_err("Invalid params\n");
- return;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- /* By this point mode should have been validated through mode_fixup */
- rc = dp->set_mode(dp, &bridge->dp_mode);
- if (rc) {
- pr_err("[%d] failed to perform a mode set, rc=%d\n",
- bridge->id, rc);
- return;
- }
-
- rc = dp->prepare(dp);
- if (rc) {
- pr_err("[%d] DP display prepare failed, rc=%d\n",
- bridge->id, rc);
- return;
- }
-
- rc = dp->enable(dp);
- if (rc) {
- pr_err("[%d] DP display enable failed, rc=%d\n",
- bridge->id, rc);
- dp->unprepare(dp);
- }
-}
-
-static void dp_bridge_enable(struct drm_bridge *drm_bridge)
-{
- int rc = 0;
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge) {
- pr_err("Invalid params\n");
- return;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- rc = dp->post_enable(dp);
- if (rc)
- pr_err("[%d] DP display post enable failed, rc=%d\n",
- bridge->id, rc);
-}
-
-static void dp_bridge_disable(struct drm_bridge *drm_bridge)
-{
- int rc = 0;
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge) {
- pr_err("Invalid params\n");
- return;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- rc = dp->pre_disable(dp);
- if (rc) {
- pr_err("[%d] DP display pre disable failed, rc=%d\n",
- bridge->id, rc);
- }
-}
-
-static void dp_bridge_post_disable(struct drm_bridge *drm_bridge)
-{
- int rc = 0;
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge) {
- pr_err("Invalid params\n");
- return;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- rc = dp->disable(dp);
- if (rc) {
- pr_err("[%d] DP display disable failed, rc=%d\n",
- bridge->id, rc);
- return;
- }
-
- rc = dp->unprepare(dp);
- if (rc) {
- pr_err("[%d] DP display unprepare failed, rc=%d\n",
- bridge->id, rc);
- return;
- }
-}
-
-static void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge || !mode || !adjusted_mode) {
- pr_err("Invalid params\n");
- return;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- memset(&bridge->dp_mode, 0x0, sizeof(struct dp_display_mode));
- convert_to_dp_mode(adjusted_mode, &bridge->dp_mode, dp);
-}
-
-static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- int rc = 0;
- bool ret = true;
- struct dp_display_mode dp_mode;
- struct dp_bridge *bridge;
- struct dp_display *dp;
-
- if (!drm_bridge || !mode || !adjusted_mode) {
- pr_err("Invalid params\n");
- ret = false;
- goto end;
- }
-
- bridge = to_dp_bridge(drm_bridge);
- dp = bridge->display;
-
- convert_to_dp_mode(mode, &dp_mode, dp);
-
- rc = dp->validate_mode(dp, &dp_mode);
- if (rc) {
- pr_err("[%d] mode is not valid, rc=%d\n", bridge->id, rc);
- ret = false;
- } else {
- convert_to_drm_mode(&dp_mode, adjusted_mode);
- }
-end:
- return ret;
-}
-
-static const struct drm_bridge_funcs dp_bridge_ops = {
- .attach = dp_bridge_attach,
- .mode_fixup = dp_bridge_mode_fixup,
- .pre_enable = dp_bridge_pre_enable,
- .enable = dp_bridge_enable,
- .disable = dp_bridge_disable,
- .post_disable = dp_bridge_post_disable,
- .mode_set = dp_bridge_mode_set,
-};
-
-int dp_connector_post_init(struct drm_connector *connector,
- void *info,
- void *display)
-{
- struct dp_display *dp_display = display;
-
- if (!info || !dp_display)
- return -EINVAL;
-
- dp_display->connector = connector;
- return 0;
-}
-
-int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,
- struct msm_mode_info *mode_info, u32 max_mixer_width)
-{
- const u32 dual_lm = 2;
- const u32 single_lm = 1;
- const u32 single_intf = 1;
- const u32 no_enc = 0;
- struct msm_display_topology *topology;
-
- if (!drm_mode || !mode_info || !max_mixer_width) {
- pr_err("invalid params\n");
- return -EINVAL;
- }
-
- topology = &mode_info->topology;
- topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ?
- dual_lm : single_lm;
- topology->num_enc = no_enc;
- topology->num_intf = single_intf;
-
- mode_info->frame_rate = drm_mode->vrefresh;
- mode_info->vtotal = drm_mode->vtotal;
- mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
-
- return 0;
-}
-
-int dp_connector_get_info(struct msm_display_info *info, void *data)
-{
- struct dp_display *display = data;
-
- if (!info || !display) {
- pr_err("invalid params\n");
- return -EINVAL;
- }
-
- info->intf_type = DRM_MODE_CONNECTOR_DisplayPort;
-
- info->num_of_h_tiles = 1;
- info->h_tile_instance[0] = 0;
- info->is_connected = display->is_connected;
- info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
- MSM_DISPLAY_CAP_HOT_PLUG;
-
- return 0;
-}
-
-enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
- bool force,
- void *display)
-{
- enum drm_connector_status status = connector_status_unknown;
- struct msm_display_info info;
- int rc;
-
- if (!conn || !display)
- return status;
-
- /* get display dp_info */
- memset(&info, 0x0, sizeof(info));
- rc = dp_connector_get_info(&info, display);
- if (rc) {
- pr_err("failed to get display info, rc=%d\n", rc);
- return connector_status_disconnected;
- }
-
- if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG)
- status = (info.is_connected ? connector_status_connected :
- connector_status_disconnected);
- else
- status = connector_status_connected;
-
- conn->display_info.width_mm = info.width_mm;
- conn->display_info.height_mm = info.height_mm;
-
- return status;
-}
-
-void dp_connector_send_hpd_event(void *display)
-{
- struct dp_display *dp;
-
- if (!display) {
- pr_err("invalid input\n");
- return;
- }
-
- dp = display;
-
- if (dp->send_hpd_event)
- dp->send_hpd_event(dp);
-}
-
-int dp_connector_get_modes(struct drm_connector *connector,
- void *display)
-{
- int rc = 0;
- struct dp_display *dp;
- struct dp_display_mode *dp_mode = NULL;
- struct drm_display_mode *m, drm_mode;
-
- if (!connector || !display)
- return 0;
-
- dp = display;
-
- dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL);
- if (!dp_mode)
- return 0;
-
- /* pluggable case assumes EDID is read when HPD */
- if (dp->is_connected) {
- rc = dp->get_modes(dp, dp_mode);
- if (!rc)
- pr_err("failed to get DP sink modes, rc=%d\n", rc);
-
- if (dp_mode->timing.pixel_clk_khz) { /* valid DP mode */
- memset(&drm_mode, 0x0, sizeof(drm_mode));
- convert_to_drm_mode(dp_mode, &drm_mode);
- m = drm_mode_duplicate(connector->dev, &drm_mode);
- if (!m) {
- pr_err("failed to add mode %ux%u\n",
- drm_mode.hdisplay,
- drm_mode.vdisplay);
- kfree(dp_mode);
- return 0;
- }
- m->width_mm = connector->display_info.width_mm;
- m->height_mm = connector->display_info.height_mm;
- drm_mode_probed_add(connector, m);
- }
- } else {
- pr_err("No sink connected\n");
- }
- kfree(dp_mode);
-
- return rc;
-}
-
-int dp_drm_bridge_init(void *data, struct drm_encoder *encoder)
-{
- int rc = 0;
- struct dp_bridge *bridge;
- struct drm_device *dev;
- struct dp_display *display = data;
- struct msm_drm_private *priv = NULL;
-
- bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
- if (!bridge) {
- rc = -ENOMEM;
- goto error;
- }
-
- dev = display->drm_dev;
- bridge->display = display;
- bridge->base.funcs = &dp_bridge_ops;
- bridge->base.encoder = encoder;
-
- priv = dev->dev_private;
-
- rc = drm_bridge_attach(encoder, &bridge->base, NULL);
- if (rc) {
- pr_err("failed to attach bridge, rc=%d\n", rc);
- goto error_free_bridge;
- }
-
- rc = display->request_irq(display);
- if (rc) {
- pr_err("request_irq failed, rc=%d\n", rc);
- goto error_free_bridge;
- }
-
- encoder->bridge = &bridge->base;
- priv->bridges[priv->num_bridges++] = &bridge->base;
- display->bridge = bridge;
-
- return 0;
-error_free_bridge:
- kfree(bridge);
-error:
- return rc;
-}
-
-void dp_drm_bridge_deinit(void *data)
-{
- struct dp_display *display = data;
- struct dp_bridge *bridge = display->bridge;
-
- if (bridge && bridge->base.encoder)
- bridge->base.encoder->bridge = NULL;
-
- kfree(bridge);
-}
-
-enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode,
- void *display)
-{
- struct dp_display *dp_disp;
- struct dp_debug *debug;
-
- if (!mode || !display) {
- pr_err("invalid params\n");
- return MODE_ERROR;
- }
-
- dp_disp = display;
- debug = dp_disp->get_debug(dp_disp);
-
- if (debug->debug_en) {
- if (mode->hdisplay == debug->hdisplay &&
- mode->vdisplay == debug->vdisplay &&
- mode->vrefresh == debug->vrefresh &&
- mode->clock <= dp_disp->max_pclk_khz)
- return MODE_OK;
- else
- return MODE_ERROR;
- } else {
- if (mode->vrefresh == 0) {
- int vrefresh = (mode->clock * 1000) /
- (mode->vtotal * mode->htotal);
- if (vrefresh > 60)
- return MODE_BAD;
- }
-
- if (mode->clock > dp_disp->max_pclk_khz)
- return MODE_BAD;
- else
- return MODE_OK;
- }
-}
deleted file mode 100644
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_DRM_H_
-#define _DP_DRM_H_
-
-#include <linux/types.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "msm_drv.h"
-#include "dp_display.h"
-
-struct dp_bridge {
- struct drm_bridge base;
- u32 id;
-
- struct dp_display *display;
- struct dp_display_mode dp_mode;
-};
-
-/**
- * dp_connector_post_init - callback to perform additional initialization steps
- * @connector: Pointer to drm connector structure
- * @info: Pointer to dpu connector info structure
- * @display: Pointer to private display handle
- * Returns: Zero on success
- */
-int dp_connector_post_init(struct drm_connector *connector,
- void *info,
- void *display);
-
-/**
- * dp_connector_detect - callback to determine if connector is connected
- * @connector: Pointer to drm connector structure
- * @force: Force detect setting from drm framework
- * @display: Pointer to private display handle
- * Returns: Connector 'is connected' status
- */
-enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
- bool force,
- void *display);
-
-/**
- * dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add()
- * @connector: Pointer to drm connector structure
- * @display: Pointer to private display handle
- * Returns: Number of modes added
- */
-int dp_connector_get_modes(struct drm_connector *connector,
- void *display);
-
-/**
- * dp_connector_mode_valid - callback to determine if specified mode is valid
- * @connector: Pointer to drm connector structure
- * @mode: Pointer to drm mode structure
- * @display: Pointer to private display handle
- * Returns: Validity status for specified mode
- */
-enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode,
- void *display);
-
-/**
- * dp_connector_get_mode_info - retrieve information of the mode selected
- * @drm_mode: Display mode set for the display
- * @mode_info: Out parameter. Information of the mode
- * @max_mixer_width: max width supported by HW layer mixer
- * Returns: zero on success
- */
-int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,
- struct msm_mode_info *mode_info,
- u32 max_mixer_width);
-
-int dp_connector_get_info(struct msm_display_info *info, void *display);
-
-void dp_connector_send_hpd_event(void *display);
-
-int dp_drm_bridge_init(void *display,
- struct drm_encoder *encoder);
-
-void dp_drm_bridge_deinit(void *display);
-#endif /* _DP_DRM_H_ */
-
deleted file mode 100644
@@ -1,927 +0,0 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) "[dp-hdcp2p2] %s: " fmt, __func__
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/types.h>
-#include <linux/kthread.h>
-#include <linux/hdcp_qseecom.h>
-#include <drm/drm_dp_helper.h>
-
-#include "dpu_hdcp.h"
-
-#define DP_INTR_STATUS2 (0x00000024)
-#define DP_INTR_STATUS3 (0x00000028)
-#define dp_read(offset) readl_relaxed((offset))
-#define dp_write(offset, data) writel_relaxed((data), (offset))
-#define DP_HDCP_RXCAPS_LENGTH 3
-
-enum dp_hdcp2p2_sink_status {
- SINK_DISCONNECTED,
- SINK_CONNECTED
-};
-
-enum dp_auth_status {
- DP_HDCP_AUTH_STATUS_FAILURE,
- DP_HDCP_AUTH_STATUS_SUCCESS
-};
-
-struct dp_hdcp2p2_ctrl {
- atomic_t auth_state;
- enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */
- struct dp_hdcp2p2_interrupts *intr;
- struct dpu_hdcp_init_data init_data;
- struct mutex mutex; /* mutex to protect access to ctrl */
- struct mutex msg_lock; /* mutex to protect access to msg buffer */
- struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/
- struct dpu_hdcp_ops *ops;
- void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */
- struct hdcp_txmtr_ops *lib; /* Ops for driver to call into TZ */
- enum hdcp_wakeup_cmd wakeup_cmd;
- enum dp_auth_status auth_status;
-
- struct task_struct *thread;
- struct kthread_worker worker;
- struct kthread_work status;
- struct kthread_work auth;
- struct kthread_work send_msg;
- struct kthread_work recv_msg;
- struct kthread_work link;
- char *msg_buf;
- uint32_t send_msg_len; /* length of all parameters in msg */
- uint32_t timeout;
- uint32_t num_messages;
- struct hdcp_msg_part msg_part[HDCP_MAX_MESSAGE_PARTS];
- u8 sink_rx_status;
- u8 rx_status;
- char abort_mask;
-
- bool cp_irq_done;
- bool polling;
-};
-
-struct dp_hdcp2p2_int_set {
- u32 interrupt;
- char *name;
- void (*func)(struct dp_hdcp2p2_ctrl *ctrl);
-};
-
-struct dp_hdcp2p2_interrupts {
- u32 reg;
- struct dp_hdcp2p2_int_set *int_set;
-};
-
-static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl)
-{
- if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_AUTHENTICATE)
- return true;
-
- if (atomic_read(&ctrl->auth_state) != HDCP_STATE_INACTIVE)
- return true;
-
- return false;
-}
-
-static int dp_hdcp2p2_copy_buf(struct dp_hdcp2p2_ctrl *ctrl,
- struct hdcp_wakeup_data *data)
-{
- int i = 0;
-
- if (!data || !data->message_data)
- return 0;
-
- mutex_lock(&ctrl->msg_lock);
-
- ctrl->timeout = data->timeout;
- ctrl->num_messages = data->message_data->num_messages;
- ctrl->send_msg_len = 0; /* Total len of all messages */
-
- for (i = 0; i < ctrl->num_messages ; i++)
- ctrl->send_msg_len += data->message_data->messages[i].length;
-
- memcpy(ctrl->msg_part, data->message_data->messages,
- sizeof(data->message_data->messages));
-
- ctrl->rx_status = data->message_data->rx_status;
- ctrl->abort_mask = data->abort_mask;
-
- if (!data->send_msg_len) {
- mutex_unlock(&ctrl->msg_lock);
- return 0;
- }
-
- kzfree(ctrl->msg_buf);
-
- ctrl->msg_buf = kzalloc(ctrl->send_msg_len, GFP_KERNEL);
-
- if (!ctrl->msg_buf) {
- mutex_unlock(&ctrl->msg_lock);
- return -ENOMEM;
- }
-
- /* ignore first byte as it contains message id */
- memcpy(ctrl->msg_buf, data->send_msg_buf + 1, ctrl->send_msg_len);
-
- mutex_unlock(&ctrl->msg_lock);
-
- return 0;
-}
-
-static int dp_hdcp2p2_wakeup(struct hdcp_wakeup_data *data)
-{
- struct dp_hdcp2p2_ctrl *ctrl;
- u32 const default_timeout_us = 500;
-
- if (!data) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- ctrl = data->context;
- if (!ctrl) {
- pr_err("invalid ctrl\n");
- return -EINVAL;
- }
-
- mutex_lock(&ctrl->wakeup_mutex);
-
- ctrl->wakeup_cmd = data->cmd;
-
- if (data->timeout)
- ctrl->timeout = (data->timeout) * 2;
- else
- ctrl->timeout = default_timeout_us;
-
- if (!dp_hdcp2p2_is_valid_state(ctrl)) {
- pr_err("invalid state\n");
- goto exit;
- }
-
- if (dp_hdcp2p2_copy_buf(ctrl, data))
- goto exit;
-
- if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_STATUS_SUCCESS)
- ctrl->auth_status = DP_HDCP_AUTH_STATUS_SUCCESS;
- else if (ctrl->wakeup_cmd == HDCP_WKUP_CMD_STATUS_FAILED)
- ctrl->auth_status = DP_HDCP_AUTH_STATUS_FAILURE;
-
- switch (ctrl->wakeup_cmd) {
- case HDCP_WKUP_CMD_SEND_MESSAGE:
- kthread_queue_work(&ctrl->worker, &ctrl->send_msg);
- break;
- case HDCP_WKUP_CMD_RECV_MESSAGE:
- kthread_queue_work(&ctrl->worker, &ctrl->recv_msg);
- break;
- case HDCP_WKUP_CMD_STATUS_SUCCESS:
- case HDCP_WKUP_CMD_STATUS_FAILED:
- kthread_queue_work(&ctrl->worker, &ctrl->status);
- break;
- case HDCP_WKUP_CMD_LINK_POLL:
- if (ctrl->cp_irq_done)
- kthread_queue_work(&ctrl->worker, &ctrl->recv_msg);
- else
- ctrl->polling = true;
- break;
- case HDCP_WKUP_CMD_AUTHENTICATE:
- kthread_queue_work(&ctrl->worker, &ctrl->auth);
- break;
- default:
- pr_err("invalid wakeup command %d\n", ctrl->wakeup_cmd);
- }
-exit:
- mutex_unlock(&ctrl->wakeup_mutex);
-
- return 0;
-}
-
-static inline void dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl,
- struct hdcp_lib_wakeup_data *data)
-{
- int rc = 0;
-
- if (ctrl && ctrl->lib && ctrl->lib->wakeup &&
- data && (data->cmd != HDCP_LIB_WKUP_CMD_INVALID)) {
- rc = ctrl->lib->wakeup(data);
- if (rc)
- pr_err("error sending %s to lib\n",
- hdcp_lib_cmd_to_str(data->cmd));
- }
-}
-
-static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl)
-{
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- ctrl->sink_status = SINK_DISCONNECTED;
- atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
-}
-
-static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable)
-{
- void __iomem *base = ctrl->init_data.core_io->base;
- struct dp_hdcp2p2_interrupts *intr = ctrl->intr;
-
- while (intr && intr->reg) {
- struct dp_hdcp2p2_int_set *int_set = intr->int_set;
- u32 interrupts = 0;
-
- while (int_set && int_set->interrupt) {
- interrupts |= int_set->interrupt;
- int_set++;
- }
-
- if (enable)
- dp_write(base + intr->reg,
- dp_read(base + intr->reg) | interrupts);
- else
- dp_write(base + intr->reg,
- dp_read(base + intr->reg) & ~interrupts);
- intr++;
- }
-}
-
-static void dp_hdcp2p2_off(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
- struct hdcp_wakeup_data cdata = {HDCP_WKUP_CMD_AUTHENTICATE};
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
- return;
- }
-
- dp_hdcp2p2_set_interrupts(ctrl, false);
-
- dp_hdcp2p2_reset(ctrl);
-
- kthread_flush_worker(&ctrl->worker);
-
- cdata.context = input;
- dp_hdcp2p2_wakeup(&cdata);
-}
-
-static int dp_hdcp2p2_authenticate(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = input;
- struct hdcp_wakeup_data cdata = {HDCP_WKUP_CMD_AUTHENTICATE};
- int rc = 0;
-
- kthread_flush_worker(&ctrl->worker);
-
- dp_hdcp2p2_set_interrupts(ctrl, true);
-
- ctrl->sink_status = SINK_CONNECTED;
- atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATING);
-
- cdata.context = input;
- dp_hdcp2p2_wakeup(&cdata);
-
- return rc;
-}
-
-static int dp_hdcp2p2_reauthenticate(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- dp_hdcp2p2_reset((struct dp_hdcp2p2_ctrl *)input);
-
- return dp_hdcp2p2_authenticate(input);
-}
-
-static void dp_hdcp2p2_min_level_change(void *client_ctx,
- int min_enc_level)
-{
- struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)client_ctx;
- struct hdcp_lib_wakeup_data cdata = {
- HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE};
- bool enc_notify = true;
- int enc_lvl;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- switch (min_enc_level) {
- case 0:
- enc_lvl = HDCP_STATE_AUTH_ENC_NONE;
- break;
- case 1:
- enc_lvl = HDCP_STATE_AUTH_ENC_1X;
- break;
- case 2:
- enc_lvl = HDCP_STATE_AUTH_ENC_2P2;
- break;
- default:
- enc_notify = false;
- }
-
- pr_debug("enc level changed %d\n", min_enc_level);
-
- cdata.context = ctrl->lib_ctx;
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-
- if (enc_notify && ctrl->init_data.notify_status)
- ctrl->init_data.notify_status(ctrl->init_data.cb_data, enc_lvl);
-}
-
-static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
-{
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- dp_hdcp2p2_set_interrupts(ctrl, false);
-
- atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
-
- /* notify DP about HDCP failure */
- ctrl->init_data.notify_status(ctrl->init_data.cb_data,
- HDCP_STATE_AUTH_FAIL);
-}
-
-static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl,
- u8 *buf, int size, int offset, u32 timeout)
-{
- int const max_size = 16;
- int rc = 0, read_size = 0, bytes_read = 0;
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
- return -EINVAL;
- }
-
- do {
- read_size = min(size, max_size);
-
- bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
- offset, buf, read_size);
- if (bytes_read != read_size) {
- pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
- offset, read_size, bytes_read);
- break;
- }
-
- buf += read_size;
- offset += read_size;
- size -= read_size;
- } while (size > 0);
-
- return rc;
-}
-
-static int dp_hdcp2p2_aux_write_message(struct dp_hdcp2p2_ctrl *ctrl,
- u8 *buf, int size, uint offset, uint timeout)
-{
- int const max_size = 16;
- int rc = 0, write_size = 0, bytes_written = 0;
-
- do {
- write_size = min(size, max_size);
-
- bytes_written = drm_dp_dpcd_write(ctrl->init_data.drm_aux,
- offset, buf, write_size);
- if (bytes_written != write_size) {
- pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
- offset, write_size, bytes_written);
- break;
- }
-
- buf += write_size;
- offset += write_size;
- size -= write_size;
- } while (size > 0);
-
- return rc;
-}
-
-static bool dp_hdcp2p2_feature_supported(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = input;
- struct hdcp_txmtr_ops *lib = NULL;
- bool supported = false;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- goto end;
- }
-
- lib = ctrl->lib;
- if (!lib) {
- pr_err("invalid lib ops data\n");
- goto end;
- }
-
- if (lib->feature_supported)
- supported = lib->feature_supported(
- ctrl->lib_ctx);
-end:
- return supported;
-}
-
-static void dp_hdcp2p2_send_msg_work(struct kthread_work *work)
-{
- int rc = 0;
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, send_msg);
- struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
-
- if (!ctrl) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto exit;
- }
-
- cdata.context = ctrl->lib_ctx;
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
- goto exit;
- }
-
- mutex_lock(&ctrl->msg_lock);
-
- rc = dp_hdcp2p2_aux_write_message(ctrl, ctrl->msg_buf,
- ctrl->send_msg_len, ctrl->msg_part->offset,
- ctrl->timeout);
- if (rc) {
- pr_err("Error sending msg to sink %d\n", rc);
- mutex_unlock(&ctrl->msg_lock);
- goto exit;
- }
-
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS;
- cdata.timeout = ctrl->timeout;
- mutex_unlock(&ctrl->msg_lock);
-
-exit:
- if (rc == -ETIMEDOUT)
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
- else if (rc)
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED;
-
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-}
-
-static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl)
-{
- int rc = 0;
- char *recvd_msg_buf = NULL;
- struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
-
- cdata.context = ctrl->lib_ctx;
-
- recvd_msg_buf = kzalloc(ctrl->send_msg_len, GFP_KERNEL);
- if (!recvd_msg_buf) {
- rc = -ENOMEM;
- goto exit;
- }
-
- rc = dp_hdcp2p2_aux_read_message(ctrl, recvd_msg_buf,
- ctrl->send_msg_len, ctrl->msg_part->offset,
- ctrl->timeout);
- if (rc) {
- pr_err("error reading message %d\n", rc);
- goto exit;
- }
-
- cdata.recvd_msg_buf = recvd_msg_buf;
- cdata.recvd_msg_len = ctrl->send_msg_len;
- cdata.timeout = ctrl->timeout;
-exit:
- if (rc == -ETIMEDOUT)
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT;
- else if (rc)
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED;
- else
- cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS;
-
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
- kfree(recvd_msg_buf);
-
- return rc;
-}
-
-static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work)
-{
- struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, recv_msg);
-
- cdata.context = ctrl->lib_ctx;
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
- return;
- }
-
- if (ctrl->rx_status) {
- if (!ctrl->cp_irq_done) {
- pr_debug("waiting for CP_IRQ\n");
- ctrl->polling = true;
- return;
- }
-
- if (ctrl->rx_status & ctrl->sink_rx_status) {
- ctrl->cp_irq_done = false;
- ctrl->sink_rx_status = 0;
- ctrl->rx_status = 0;
- }
- }
-
- dp_hdcp2p2_get_msg_from_sink(ctrl);
-}
-
-static void dp_hdcp2p2_auth_status_work(struct kthread_work *work)
-{
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, status);
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("hdcp is off\n");
- return;
- }
-
- if (ctrl->auth_status == DP_HDCP_AUTH_STATUS_SUCCESS) {
- ctrl->init_data.notify_status(ctrl->init_data.cb_data,
- HDCP_STATE_AUTHENTICATED);
-
- atomic_set(&ctrl->auth_state, HDCP_STATE_AUTHENTICATED);
- } else {
- dp_hdcp2p2_auth_failed(ctrl);
- }
-}
-
-static void dp_hdcp2p2_link_work(struct kthread_work *work)
-{
- int rc = 0;
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, link);
- struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
- atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("invalid hdcp state\n");
- return;
- }
-
- cdata.context = ctrl->lib_ctx;
-
- if (ctrl->sink_rx_status & ctrl->abort_mask) {
- if (ctrl->sink_rx_status & BIT(3))
- pr_err("reauth_req set by sink\n");
-
- if (ctrl->sink_rx_status & BIT(4))
- pr_err("link failure reported by sink\n");
-
- ctrl->sink_rx_status = 0;
- ctrl->rx_status = 0;
-
- rc = -ENOLINK;
-
- cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED;
- atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
- goto exit;
- }
-
- if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) {
- ctrl->sink_rx_status = 0;
- ctrl->rx_status = 0;
-
- dp_hdcp2p2_get_msg_from_sink(ctrl);
-
- ctrl->polling = false;
- } else {
- ctrl->cp_irq_done = true;
- }
-exit:
- if (rc)
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-}
-
-static void dp_hdcp2p2_auth_work(struct kthread_work *work)
-{
- struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, auth);
-
- cdata.context = ctrl->lib_ctx;
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTHENTICATING)
- cdata.cmd = HDCP_LIB_WKUP_CMD_START;
- else
- cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
-
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-}
-
-static int dp_hdcp2p2_read_rx_status(struct dp_hdcp2p2_ctrl *ctrl,
- u8 *rx_status)
-{
- u32 const cp_irq_dpcd_offset = 0x201;
- u32 const rxstatus_dpcd_offset = 0x69493;
- ssize_t const bytes_to_read = 1;
- ssize_t bytes_read = 0;
- u8 buf = 0;
- int rc = 0;
- bool cp_irq = 0;
-
- *rx_status = 0;
-
- bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
- cp_irq_dpcd_offset, &buf, bytes_to_read);
- if (bytes_read != bytes_to_read) {
- pr_err("cp irq read failed\n");
- rc = bytes_read;
- goto error;
- }
-
- cp_irq = buf & BIT(2);
- pr_debug("cp_irq=0x%x\n", cp_irq);
- buf = 0;
-
- if (cp_irq) {
- bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
- rxstatus_dpcd_offset, &buf, bytes_to_read);
- if (bytes_read != bytes_to_read) {
- pr_err("rxstatus read failed\n");
- rc = bytes_read;
- goto error;
- }
- *rx_status = buf;
- pr_debug("rx_status=0x%x\n", *rx_status);
- }
-
-error:
- return rc;
-}
-
-static int dp_hdcp2p2_cp_irq(void *input)
-{
- int rc = 0;
- struct dp_hdcp2p2_ctrl *ctrl = input;
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- if (atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL ||
- atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
- pr_err("invalid hdcp state\n");
- rc = -EINVAL;
- goto error;
- }
-
- ctrl->sink_rx_status = 0;
- rc = dp_hdcp2p2_read_rx_status(ctrl, &ctrl->sink_rx_status);
- if (rc) {
- pr_err("failed to read rx status\n");
- goto error;
- }
-
- pr_debug("sink_rx_status=0x%x\n", ctrl->sink_rx_status);
-
- if (!ctrl->sink_rx_status) {
- pr_debug("not a hdcp 2.2 irq\n");
- rc = -EINVAL;
- goto error;
- }
-
- kthread_queue_work(&ctrl->worker, &ctrl->link);
-
- return 0;
-error:
- return rc;
-}
-
-static int dp_hdcp2p2_isr(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
- int rc = 0;
- struct dss_io_data *io;
- struct dp_hdcp2p2_interrupts *intr;
- u32 hdcp_int_val = 0;
-
- if (!ctrl || !ctrl->init_data.core_io) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- io = ctrl->init_data.core_io;
- intr = ctrl->intr;
-
- while (intr && intr->reg) {
- struct dp_hdcp2p2_int_set *int_set = intr->int_set;
-
- hdcp_int_val = dp_read(io->base + intr->reg);
-
- while (int_set && int_set->interrupt) {
- if (hdcp_int_val & (int_set->interrupt >> 2)) {
- pr_debug("%s\n", int_set->name);
-
- if (int_set->func)
- int_set->func(ctrl);
-
- dp_write(io->base + intr->reg, hdcp_int_val |
- (int_set->interrupt >> 1));
- }
- int_set++;
- }
- intr++;
- }
-end:
- return rc;
-}
-
-void dpu_dp_hdcp2p2_deinit(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = (struct dp_hdcp2p2_ctrl *)input;
- struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
-
- if (!ctrl) {
- pr_err("invalid input\n");
- return;
- }
-
- cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
- cdata.context = ctrl->lib_ctx;
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-
- kthread_stop(ctrl->thread);
-
- mutex_destroy(&ctrl->mutex);
- mutex_destroy(&ctrl->msg_lock);
- mutex_destroy(&ctrl->wakeup_mutex);
- kzfree(ctrl->msg_buf);
- kfree(ctrl);
-}
-
-void *dpu_dp_hdcp2p2_init(struct dpu_hdcp_init_data *init_data)
-{
- int rc;
- struct dp_hdcp2p2_ctrl *ctrl;
- static struct hdcp_txmtr_ops txmtr_ops;
- struct hdcp_register_data register_data;
- static struct dpu_hdcp_ops ops = {
- .isr = dp_hdcp2p2_isr,
- .reauthenticate = dp_hdcp2p2_reauthenticate,
- .authenticate = dp_hdcp2p2_authenticate,
- .feature_supported = dp_hdcp2p2_feature_supported,
- .off = dp_hdcp2p2_off,
- .cp_irq = dp_hdcp2p2_cp_irq,
- };
-
- static struct hdcp_client_ops client_ops = {
- .wakeup = dp_hdcp2p2_wakeup,
- .notify_lvl_change = dp_hdcp2p2_min_level_change,
- };
- static struct dp_hdcp2p2_int_set int_set1[] = {
- {BIT(17), "authentication successful", NULL},
- {BIT(20), "authentication failed", NULL},
- {BIT(24), "encryption enabled", NULL},
- {BIT(27), "encryption disabled", NULL},
- {0},
- };
- static struct dp_hdcp2p2_int_set int_set2[] = {
- {BIT(2), "key fifo underflow", NULL},
- {0},
- };
- static struct dp_hdcp2p2_interrupts intr[] = {
- {DP_INTR_STATUS2, int_set1},
- {DP_INTR_STATUS3, int_set2},
- {0}
- };
-
- if (!init_data || !init_data->cb_data ||
- !init_data->notify_status || !init_data->drm_aux) {
- pr_err("invalid input\n");
- return ERR_PTR(-EINVAL);
- }
-
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl)
- return ERR_PTR(-ENOMEM);
-
- ctrl->init_data = *init_data;
- ctrl->lib = &txmtr_ops;
- ctrl->msg_buf = NULL;
-
- ctrl->sink_status = SINK_DISCONNECTED;
- ctrl->intr = intr;
-
- atomic_set(&ctrl->auth_state, HDCP_STATE_INACTIVE);
-
- ctrl->ops = &ops;
- mutex_init(&ctrl->mutex);
- mutex_init(&ctrl->msg_lock);
- mutex_init(&ctrl->wakeup_mutex);
-
- register_data.hdcp_ctx = &ctrl->lib_ctx;
- register_data.client_ops = &client_ops;
- register_data.txmtr_ops = &txmtr_ops;
- register_data.device_type = HDCP_TXMTR_DP;
- register_data.client_ctx = ctrl;
-
- rc = hdcp_library_register(®ister_data);
- if (rc) {
- pr_err("Unable to register with HDCP 2.2 library\n");
- goto error;
- }
-
- kthread_init_worker(&ctrl->worker);
-
- kthread_init_work(&ctrl->auth, dp_hdcp2p2_auth_work);
- kthread_init_work(&ctrl->send_msg, dp_hdcp2p2_send_msg_work);
- kthread_init_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work);
- kthread_init_work(&ctrl->status, dp_hdcp2p2_auth_status_work);
- kthread_init_work(&ctrl->link, dp_hdcp2p2_link_work);
-
- ctrl->thread = kthread_run(kthread_worker_fn,
- &ctrl->worker, "dp_hdcp2p2");
-
- if (IS_ERR(ctrl->thread)) {
- pr_err("unable to start DP hdcp2p2 thread\n");
- rc = PTR_ERR(ctrl->thread);
- ctrl->thread = NULL;
- goto error;
- }
-
- return ctrl;
-error:
- kfree(ctrl);
- return ERR_PTR(rc);
-}
-
-static bool dp_hdcp2p2_supported(struct dp_hdcp2p2_ctrl *ctrl)
-{
- u32 const rxcaps_dpcd_offset = 0x6921d;
- ssize_t bytes_read = 0;
- u8 buf[DP_HDCP_RXCAPS_LENGTH];
-
- bytes_read = drm_dp_dpcd_read(ctrl->init_data.drm_aux,
- rxcaps_dpcd_offset, &buf, DP_HDCP_RXCAPS_LENGTH);
- if (bytes_read != DP_HDCP_RXCAPS_LENGTH) {
- pr_err("RxCaps read failed\n");
- goto error;
- }
-
- pr_debug("HDCP_CAPABLE=%lu\n", (buf[2] & BIT(1)) >> 1);
- pr_debug("VERSION=%d\n", buf[0]);
-
- if ((buf[2] & BIT(1)) && (buf[0] == 0x2))
- return true;
-
-error:
- return false;
-}
-
-struct dpu_hdcp_ops *dpu_dp_hdcp2p2_start(void *input)
-{
- struct dp_hdcp2p2_ctrl *ctrl = input;
-
- pr_debug("Checking sink capability\n");
- if (dp_hdcp2p2_supported(ctrl))
- return ctrl->ops;
- else
- return NULL;
-}
-
deleted file mode 100644
@@ -1,1548 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include "dp_link.h"
-#include "dp_panel.h"
-
-enum dynamic_range {
- DP_DYNAMIC_RANGE_RGB_VESA = 0x00,
- DP_DYNAMIC_RANGE_RGB_CEA = 0x01,
- DP_DYNAMIC_RANGE_UNKNOWN = 0xFFFFFFFF,
-};
-
-enum audio_sample_rate {
- AUDIO_SAMPLE_RATE_32_KHZ = 0x00,
- AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01,
- AUDIO_SAMPLE_RATE_48_KHZ = 0x02,
- AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03,
- AUDIO_SAMPLE_RATE_96_KHZ = 0x04,
- AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05,
- AUDIO_SAMPLE_RATE_192_KHZ = 0x06,
-};
-
-enum audio_pattern_type {
- AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00,
- AUDIO_TEST_PATTERN_SAWTOOTH = 0x01,
-};
-
-struct dp_link_request {
- u32 test_requested;
- u32 test_link_rate;
- u32 test_lane_count;
-};
-
-struct dp_link_private {
- u32 prev_sink_count;
- struct device *dev;
- struct dp_aux *aux;
- struct dp_link dp_link;
-
- struct dp_link_request request;
- u8 link_status[DP_LINK_STATUS_SIZE];
-};
-
-static char *dp_link_get_audio_test_pattern(u32 pattern)
-{
- switch (pattern) {
- case AUDIO_TEST_PATTERN_OPERATOR_DEFINED:
- return DP_LINK_ENUM_STR(AUDIO_TEST_PATTERN_OPERATOR_DEFINED);
- case AUDIO_TEST_PATTERN_SAWTOOTH:
- return DP_LINK_ENUM_STR(AUDIO_TEST_PATTERN_SAWTOOTH);
- default:
- return "unknown";
- }
-}
-
-static char *dp_link_get_audio_sample_rate(u32 rate)
-{
- switch (rate) {
- case AUDIO_SAMPLE_RATE_32_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_32_KHZ);
- case AUDIO_SAMPLE_RATE_44_1_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_44_1_KHZ);
- case AUDIO_SAMPLE_RATE_48_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_48_KHZ);
- case AUDIO_SAMPLE_RATE_88_2_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_88_2_KHZ);
- case AUDIO_SAMPLE_RATE_96_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_96_KHZ);
- case AUDIO_SAMPLE_RATE_176_4_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_176_4_KHZ);
- case AUDIO_SAMPLE_RATE_192_KHZ:
- return DP_LINK_ENUM_STR(AUDIO_SAMPLE_RATE_192_KHZ);
- default:
- return "unknown";
- }
-}
-
-static int dp_link_get_period(struct dp_link_private *link, int const addr)
-{
- int ret = 0;
- u8 bp;
- u8 data;
- u32 const param_len = 0x1;
- u32 const max_audio_period = 0xA;
-
- /* TEST_AUDIO_PERIOD_CH_XX */
- if (drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp,
- param_len) < param_len) {
- pr_err("failed to read test_audio_period (0x%x)\n", addr);
- ret = -EINVAL;
- goto exit;
- }
-
- data = bp;
-
- /* Period - Bits 3:0 */
- data = data & 0xF;
- if ((int)data > max_audio_period) {
- pr_err("invalid test_audio_period_ch_1 = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- ret = data;
-exit:
- return ret;
-}
-
-static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
-{
- int ret = 0;
- struct dp_link_test_audio *req = &link->dp_link.test_audio;
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_1 = ret;
- pr_debug("test_audio_period_ch_1 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_2 = ret;
- pr_debug("test_audio_period_ch_2 = 0x%x\n", ret);
-
- /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_3 = ret;
- pr_debug("test_audio_period_ch_3 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_4 = ret;
- pr_debug("test_audio_period_ch_4 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_5 = ret;
- pr_debug("test_audio_period_ch_5 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_6 = ret;
- pr_debug("test_audio_period_ch_6 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_7 = ret;
- pr_debug("test_audio_period_ch_7 = 0x%x\n", ret);
-
- ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
- if (ret == -EINVAL)
- goto exit;
-
- req->test_audio_period_ch_8 = ret;
- pr_debug("test_audio_period_ch_8 = 0x%x\n", ret);
-exit:
- return ret;
-}
-
-static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
-{
- int ret = 0;
- u8 bp;
- u8 data;
- int rlen;
- int const param_len = 0x1;
- int const max_audio_pattern_type = 0x1;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux,
- DP_TEST_AUDIO_PATTERN_TYPE, &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read link audio mode data\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
-
- /* Audio Pattern Type - Bits 7:0 */
- if ((int)data > max_audio_pattern_type) {
- pr_err("invalid audio pattern type = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- link->dp_link.test_audio.test_audio_pattern_type = data;
- pr_debug("audio pattern type = %s\n",
- dp_link_get_audio_test_pattern(data));
-exit:
- return ret;
-}
-
-static int dp_link_parse_audio_mode(struct dp_link_private *link)
-{
- int ret = 0;
- u8 bp;
- u8 data;
- int rlen;
- int const param_len = 0x1;
- int const max_audio_sampling_rate = 0x6;
- int const max_audio_channel_count = 0x8;
- int sampling_rate = 0x0;
- int channel_count = 0x0;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_AUDIO_MODE,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read link audio mode data\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
-
- /* Sampling Rate - Bits 3:0 */
- sampling_rate = data & 0xF;
- if (sampling_rate > max_audio_sampling_rate) {
- pr_err("sampling rate (0x%x) greater than max (0x%x)\n",
- sampling_rate, max_audio_sampling_rate);
- ret = -EINVAL;
- goto exit;
- }
-
- /* Channel Count - Bits 7:4 */
- channel_count = ((data & 0xF0) >> 4) + 1;
- if (channel_count > max_audio_channel_count) {
- pr_err("channel_count (0x%x) greater than max (0x%x)\n",
- channel_count, max_audio_channel_count);
- ret = -EINVAL;
- goto exit;
- }
-
- link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
- link->dp_link.test_audio.test_audio_channel_count = channel_count;
- pr_debug("sampling_rate = %s, channel_count = 0x%x\n",
- dp_link_get_audio_sample_rate(sampling_rate), channel_count);
-exit:
- return ret;
-}
-
-/**
- * dp_parse_audio_pattern_params() - parses audio pattern parameters from DPCD
- * @link: Display Port Driver data
- *
- * Returns 0 if it successfully parses the audio link pattern parameters.
- */
-static int dp_link_parse_audio_pattern_params(struct dp_link_private *link)
-{
- int ret = 0;
-
- ret = dp_link_parse_audio_mode(link);
- if (ret)
- goto exit;
-
- ret = dp_link_parse_audio_pattern_type(link);
- if (ret)
- goto exit;
-
- ret = dp_link_parse_audio_channel_period(link);
-
-exit:
- return ret;
-}
-
-/**
- * dp_link_is_video_pattern_valid() - validates the video pattern
- * @pattern: video pattern requested by the sink
- *
- * Returns true if the requested video pattern is supported.
- */
-static bool dp_link_is_video_pattern_valid(u32 pattern)
-{
- switch (pattern) {
- case DP_NO_TEST_PATTERN:
- case DP_COLOR_RAMP:
- case DP_BLACK_AND_WHITE_VERTICAL_LINES:
- case DP_COLOR_SQUARE:
- return true;
- default:
- return false;
- }
-}
-
-static char *dp_link_video_pattern_to_string(u32 test_video_pattern)
-{
- switch (test_video_pattern) {
- case DP_NO_TEST_PATTERN:
- return DP_LINK_ENUM_STR(DP_NO_TEST_PATTERN);
- case DP_COLOR_RAMP:
- return DP_LINK_ENUM_STR(DP_COLOR_RAMP);
- case DP_BLACK_AND_WHITE_VERTICAL_LINES:
- return DP_LINK_ENUM_STR(DP_BLACK_AND_WHITE_VERTICAL_LINES);
- case DP_COLOR_SQUARE:
- return DP_LINK_ENUM_STR(DP_COLOR_SQUARE);
- default:
- return "unknown";
- }
-}
-
-/**
- * dp_link_is_dynamic_range_valid() - validates the dynamic range
- * @bit_depth: the dynamic range value to be checked
- *
- * Returns true if the dynamic range value is supported.
- */
-static bool dp_link_is_dynamic_range_valid(u32 dr)
-{
- switch (dr) {
- case DP_DYNAMIC_RANGE_RGB_VESA:
- case DP_DYNAMIC_RANGE_RGB_CEA:
- return true;
- default:
- return false;
- }
-}
-
-static char *dp_link_dynamic_range_to_string(u32 dr)
-{
- switch (dr) {
- case DP_DYNAMIC_RANGE_RGB_VESA:
- return DP_LINK_ENUM_STR(DP_DYNAMIC_RANGE_RGB_VESA);
- case DP_DYNAMIC_RANGE_RGB_CEA:
- return DP_LINK_ENUM_STR(DP_DYNAMIC_RANGE_RGB_CEA);
- case DP_DYNAMIC_RANGE_UNKNOWN:
- default:
- return "unknown";
- }
-}
-
-/**
- * dp_link_is_bit_depth_valid() - validates the bit depth requested
- * @bit_depth: bit depth requested by the sink
- *
- * Returns true if the requested bit depth is supported.
- */
-static bool dp_link_is_bit_depth_valid(u32 tbd)
-{
- /* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */
- switch (tbd) {
- case DP_TEST_BIT_DEPTH_6:
- case DP_TEST_BIT_DEPTH_8:
- case DP_TEST_BIT_DEPTH_10:
- return true;
- default:
- return false;
- }
-}
-
-static char *dp_link_bit_depth_to_string(u32 tbd)
-{
- switch (tbd) {
- case DP_TEST_BIT_DEPTH_6:
- return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_6);
- case DP_TEST_BIT_DEPTH_8:
- return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_8);
- case DP_TEST_BIT_DEPTH_10:
- return DP_LINK_ENUM_STR(DP_TEST_BIT_DEPTH_10);
- case DP_TEST_BIT_DEPTH_UNKNOWN:
- default:
- return "unknown";
- }
-}
-
-static int dp_link_parse_timing_params1(struct dp_link_private *link,
- int const addr, int const len, u32 *val)
-{
- u8 bp[2];
- int rlen;
-
- if (len < 2)
- return -EINVAL;
-
- /* Read the requested video link pattern (Byte 0x221). */
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len);
- if (rlen < len) {
- pr_err("failed to read 0x%x\n", addr);
- return -EINVAL;
- }
-
- *val = bp[1] | (bp[0] << 8);
-
- return 0;
-}
-
-static int dp_link_parse_timing_params2(struct dp_link_private *link,
- int const addr, int const len, u32 *val1, u32 *val2)
-{
- u8 bp[2];
- int rlen;
-
- if (len < 2)
- return -EINVAL;
-
- /* Read the requested video link pattern (Byte 0x221). */
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, bp, len);
- if (rlen < len) {
- pr_err("failed to read 0x%x\n", addr);
- return -EINVAL;
- }
-
- *val1 = (bp[0] & BIT(7)) >> 7;
- *val2 = bp[1] | ((bp[0] & 0x7F) << 8);
-
- return 0;
-}
-
-static int dp_link_parse_timing_params3(struct dp_link_private *link,
- int const addr, u32 *val)
-{
- u8 bp;
- u32 len = 1;
- int rlen;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, addr, &bp, len);
- if (rlen < 1) {
- pr_err("failed to read 0x%x\n", addr);
- return -EINVAL;
- }
- *val = bp;
-
- return 0;
-}
-
-/**
- * dp_parse_video_pattern_params() - parses video pattern parameters from DPCD
- * @link: Display Port Driver data
- *
- * Returns 0 if it successfully parses the video link pattern and the link
- * bit depth requested by the sink and, and if the values parsed are valid.
- */
-static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
-{
- int ret = 0;
- int rlen;
- u8 bp;
- u8 data;
- u32 dyn_range;
- int const param_len = 0x1;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_PATTERN,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read link video pattern\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
-
- if (!dp_link_is_video_pattern_valid(data)) {
- pr_err("invalid link video pattern = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- link->dp_link.test_video.test_video_pattern = data;
- pr_debug("link video pattern = 0x%x (%s)\n",
- link->dp_link.test_video.test_video_pattern,
- dp_link_video_pattern_to_string(
- link->dp_link.test_video.test_video_pattern));
-
- /* Read the requested color bit depth and dynamic range (Byte 0x232) */
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_MISC0,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read link bit depth\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
-
- /* Dynamic Range */
- dyn_range = (data & DP_TEST_DYNAMIC_RANGE_CEA) >> 3;
- if (!dp_link_is_dynamic_range_valid(dyn_range)) {
- pr_err("invalid link dynamic range = 0x%x", dyn_range);
- ret = -EINVAL;
- goto exit;
- }
- link->dp_link.test_video.test_dyn_range = dyn_range;
- pr_debug("link dynamic range = 0x%x (%s)\n",
- link->dp_link.test_video.test_dyn_range,
- dp_link_dynamic_range_to_string(
- link->dp_link.test_video.test_dyn_range));
-
- /* Color bit depth */
- data &= DP_TEST_BIT_DEPTH_MASK;
- if (!dp_link_is_bit_depth_valid(data)) {
- pr_err("invalid link bit depth = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- link->dp_link.test_video.test_bit_depth = data;
- pr_debug("link bit depth = 0x%x (%s)\n",
- link->dp_link.test_video.test_bit_depth,
- dp_link_bit_depth_to_string(
- link->dp_link.test_video.test_bit_depth));
-
- /* resolution timing params */
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
- &link->dp_link.test_video.test_h_total);
- if (ret) {
- pr_err("failed to parse test_h_total (DP_TEST_H_TOTAL_HI)\n");
- goto exit;
- }
- pr_debug("TEST_H_TOTAL = %d\n", link->dp_link.test_video.test_h_total);
-
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
- &link->dp_link.test_video.test_v_total);
- if (ret) {
- pr_err("failed to parse test_v_total (DP_TEST_V_TOTAL_HI)\n");
- goto exit;
- }
- pr_debug("TEST_V_TOTAL = %d\n", link->dp_link.test_video.test_v_total);
-
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
- &link->dp_link.test_video.test_h_start);
- if (ret) {
- pr_err("failed to parse test_h_start (DP_TEST_H_START_HI)\n");
- goto exit;
- }
- pr_debug("TEST_H_START = %d\n", link->dp_link.test_video.test_h_start);
-
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
- &link->dp_link.test_video.test_v_start);
- if (ret) {
- pr_err("failed to parse test_v_start (DP_TEST_V_START_HI)\n");
- goto exit;
- }
- pr_debug("TEST_V_START = %d\n", link->dp_link.test_video.test_v_start);
-
- ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
- &link->dp_link.test_video.test_hsync_pol,
- &link->dp_link.test_video.test_hsync_width);
- if (ret) {
- pr_err("failed to parse (DP_TEST_HSYNC_HI)\n");
- goto exit;
- }
- pr_debug("TEST_HSYNC_POL = %d\n",
- link->dp_link.test_video.test_hsync_pol);
- pr_debug("TEST_HSYNC_WIDTH = %d\n",
- link->dp_link.test_video.test_hsync_width);
-
- ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
- &link->dp_link.test_video.test_vsync_pol,
- &link->dp_link.test_video.test_vsync_width);
- if (ret) {
- pr_err("failed to parse (DP_TEST_VSYNC_HI)\n");
- goto exit;
- }
- pr_debug("TEST_VSYNC_POL = %d\n",
- link->dp_link.test_video.test_vsync_pol);
- pr_debug("TEST_VSYNC_WIDTH = %d\n",
- link->dp_link.test_video.test_vsync_width);
-
- ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
- &link->dp_link.test_video.test_h_width);
- if (ret) {
- pr_err("failed to parse test_h_width (DP_TEST_H_WIDTH_HI)\n");
- goto exit;
- }
- pr_debug("TEST_H_WIDTH = %d\n", link->dp_link.test_video.test_h_width);
-
- ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
- &link->dp_link.test_video.test_v_height);
- if (ret) {
- pr_err("failed to parse test_v_height (DP_TEST_V_HEIGHT_HI)\n");
- goto exit;
- }
- pr_debug("TEST_V_HEIGHT = %d\n",
- link->dp_link.test_video.test_v_height);
-
- ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1,
- &link->dp_link.test_video.test_rr_d);
- link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
- if (ret) {
- pr_err("failed to parse test_rr_d (DP_TEST_MISC1)\n");
- goto exit;
- }
- pr_debug("TEST_REFRESH_DENOMINATOR = %d\n",
- link->dp_link.test_video.test_rr_d);
-
- ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
- &link->dp_link.test_video.test_rr_n);
- if (ret) {
- pr_err("failed to parse test_rr_n (DP_TEST_REFRESH_RATE_NUMERATOR)\n");
- goto exit;
- }
- pr_debug("TEST_REFRESH_NUMERATOR = %d\n",
- link->dp_link.test_video.test_rr_n);
-exit:
- return ret;
-}
-
-/**
- * dp_link_parse_link_training_params() - parses link training parameters from
- * DPCD
- * @link: Display Port Driver data
- *
- * Returns 0 if it successfully parses the link rate (Byte 0x219) and lane
- * count (Byte 0x220), and if these values parse are valid.
- */
-static int dp_link_parse_link_training_params(struct dp_link_private *link)
-{
- u8 bp;
- u8 data;
- int ret = 0;
- int rlen;
- int const param_len = 0x1;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_LINK_RATE,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read link rate\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
-
- if (!is_link_rate_valid(data)) {
- pr_err("invalid link rate = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- link->request.test_link_rate = data;
- pr_debug("link rate = 0x%x\n", link->request.test_link_rate);
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_LANE_COUNT,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read lane count\n");
- ret = -EINVAL;
- goto exit;
- }
- data = bp;
- data &= 0x1F;
-
- if (!is_lane_count_valid(data)) {
- pr_err("invalid lane count = 0x%x\n", data);
- ret = -EINVAL;
- goto exit;
- }
-
- link->request.test_lane_count = data;
- pr_debug("lane count = 0x%x\n", link->request.test_lane_count);
-exit:
- return ret;
-}
-
-static bool dp_link_is_phy_test_pattern_supported(u32 phy_test_pattern_sel)
-{
- switch (phy_test_pattern_sel) {
- case DP_TEST_PHY_PATTERN_NONE:
- case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
- case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
- case DP_TEST_PHY_PATTERN_PRBS7:
- case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
- case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
- return true;
- default:
- return false;
- }
-}
-
-/**
- * dp_parse_phy_test_params() - parses the phy link parameters
- * @link: Display Port Driver data
- *
- * Parses the DPCD (Byte 0x248) for the DP PHY link pattern that is being
- * requested.
- */
-static int dp_link_parse_phy_test_params(struct dp_link_private *link)
-{
- u8 bp;
- u8 data;
- int rlen;
- int const param_len = 0x1;
- int ret = 0;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_PHY_PATTERN,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed to read phy link pattern\n");
- ret = -EINVAL;
- goto end;
- }
-
- data = bp;
-
- link->dp_link.phy_params.phy_test_pattern_sel = data;
-
- pr_debug("phy_test_pattern_sel = %s\n",
- dp_link_get_phy_test_pattern(data));
-
- if (!dp_link_is_phy_test_pattern_supported(data))
- ret = -EINVAL;
-end:
- return ret;
-}
-
-static char *dp_link_get_test_name(u32 test_requested)
-{
- switch (test_requested) {
- case DP_TEST_LINK_TRAINING:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
- case DP_TEST_LINK_VIDEO_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
- case DP_TEST_LINK_EDID_READ:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
- case DP_TEST_LINK_PHY_TEST_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
- case DP_TEST_LINK_AUDIO_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
- default:
- return "unknown";
- }
-}
-
-/**
- * dp_link_is_video_audio_test_requested() - checks for audio/video link request
- * @link: link requested by the sink
- *
- * Returns true if the requested link is a permitted audio/video link.
- */
-static bool dp_link_is_video_audio_test_requested(u32 link)
-{
- return (link == DP_TEST_LINK_VIDEO_PATTERN) ||
- (link == (DP_TEST_LINK_AUDIO_PATTERN |
- DP_TEST_LINK_VIDEO_PATTERN)) ||
- (link == DP_TEST_LINK_AUDIO_PATTERN) ||
- (link == (DP_TEST_LINK_AUDIO_PATTERN |
- DP_TEST_LINK_AUDIO_DISABLED_VIDEO));
-}
-
-/**
- * dp_link_supported() - checks if link requested by sink is supported
- * @test_requested: link requested by the sink
- *
- * Returns true if the requested link is supported.
- */
-static bool dp_link_is_test_supported(u32 test_requested)
-{
- return (test_requested == DP_TEST_LINK_TRAINING) ||
- (test_requested == DP_TEST_LINK_EDID_READ) ||
- (test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) ||
- dp_link_is_video_audio_test_requested(test_requested);
-}
-
-static bool dp_link_is_test_edid_read(struct dp_link_private *link)
-{
- return (link->request.test_requested == DP_TEST_LINK_EDID_READ);
-}
-
-/**
- * dp_sink_parse_test_request() - parses link request parameters from sink
- * @link: Display Port Driver data
- *
- * Parses the DPCD to check if an automated link is requested (Byte 0x201),
- * and what type of link automation is being requested (Byte 0x218).
- */
-static int dp_link_parse_request(struct dp_link_private *link)
-{
- int ret = 0;
- u8 bp;
- u8 data;
- int rlen;
- u32 const param_len = 0x1;
-
- /**
- * Read the device service IRQ vector (Byte 0x201) to determine
- * whether an automated link has been requested by the sink.
- */
- rlen = drm_dp_dpcd_read(link->aux->drm_aux,
- DP_DEVICE_SERVICE_IRQ_VECTOR, &bp, param_len);
- if (rlen < param_len) {
- pr_err("aux read failed\n");
- ret = -EINVAL;
- goto end;
- }
-
- data = bp;
-
- pr_debug("device service irq vector = 0x%x\n", data);
-
- if (!(data & DP_AUTOMATED_TEST_REQUEST)) {
- pr_debug("no test requested\n");
- return 0;
- }
-
- /**
- * Read the link request byte (Byte 0x218) to determine what type
- * of automated link has been requested by the sink.
- */
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_REQUEST,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("aux read failed\n");
- ret = -EINVAL;
- goto end;
- }
-
- data = bp;
-
- if (!dp_link_is_test_supported(data)) {
- pr_debug("link 0x%x not supported\n", data);
- goto end;
- }
-
- pr_debug("%s (0x%x) requested\n", dp_link_get_test_name(data), data);
- link->request.test_requested = data;
-
- if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) {
- ret = dp_link_parse_phy_test_params(link);
- if (ret)
- goto end;
- ret = dp_link_parse_link_training_params(link);
- }
-
- if (link->request.test_requested == DP_TEST_LINK_TRAINING)
- ret = dp_link_parse_link_training_params(link);
-
- if (dp_link_is_video_audio_test_requested(
- link->request.test_requested)) {
- ret = dp_link_parse_video_pattern_params(link);
- if (ret)
- goto end;
-
- ret = dp_link_parse_audio_pattern_params(link);
- }
-end:
- /**
- * Send a DP_TEST_ACK if all link parameters are valid, otherwise send
- * a DP_TEST_NAK.
- */
- if (ret) {
- link->dp_link.test_response = DP_TEST_NAK;
- } else {
- if (!dp_link_is_test_edid_read(link))
- link->dp_link.test_response = DP_TEST_ACK;
- else
- link->dp_link.test_response =
- DP_TEST_EDID_CHECKSUM_WRITE;
- }
-
- return ret;
-}
-
-/**
- * dp_link_parse_sink_count() - parses the sink count
- *
- * Parses the DPCD to check if there is an update to the sink count
- * (Byte 0x200), and whether all the sink devices connected have Content
- * Protection enabled.
- */
-static int dp_link_parse_sink_count(struct dp_link *dp_link)
-{
- int rlen;
- int const param_len = 0x1;
- struct dp_link_private *link = container_of(dp_link,
- struct dp_link_private, dp_link);
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_SINK_COUNT,
- &link->dp_link.sink_count.count, param_len);
- if (rlen < param_len) {
- pr_err("failed to read sink count\n");
- return -EINVAL;
- }
-
- link->dp_link.sink_count.cp_ready =
- link->dp_link.sink_count.count & DP_SINK_CP_READY;
- /* BIT 7, BIT 5:0 */
- link->dp_link.sink_count.count =
- DP_GET_SINK_COUNT(link->dp_link.sink_count.count);
-
- pr_debug("sink_count = 0x%x, cp_ready = 0x%x\n",
- link->dp_link.sink_count.count,
- link->dp_link.sink_count.cp_ready);
- return 0;
-}
-
-static void dp_link_parse_sink_status_field(struct dp_link_private *link)
-{
- int len = 0;
-
- link->prev_sink_count = link->dp_link.sink_count.count;
- dp_link_parse_sink_count(&link->dp_link);
-
- len = drm_dp_dpcd_read_link_status(link->aux->drm_aux,
- link->link_status);
- if (len < DP_LINK_STATUS_SIZE)
- pr_err("DP link status read failed\n");
- dp_link_parse_request(link);
-}
-
-static bool dp_link_is_link_training_requested(struct dp_link_private *link)
-{
- return (link->request.test_requested == DP_TEST_LINK_TRAINING);
-}
-
-/**
- * dp_link_process_link_training_request() - processes new training requests
- * @link: Display Port link data
- *
- * This function will handle new link training requests that are initiated by
- * the sink. In particular, it will update the requested lane count and link
- * link rate, and then trigger the link retraining procedure.
- *
- * The function will return 0 if a link training request has been processed,
- * otherwise it will return -EINVAL.
- */
-static int dp_link_process_link_training_request(struct dp_link_private *link)
-{
- if (!dp_link_is_link_training_requested(link))
- return -EINVAL;
-
- pr_debug("%s link rate = 0x%x, lane count = 0x%x\n",
- dp_link_get_test_name(DP_TEST_LINK_TRAINING),
- link->request.test_link_rate,
- link->request.test_lane_count);
-
- link->dp_link.link_params.lane_count = link->request.test_lane_count;
- link->dp_link.link_params.bw_code = link->request.test_link_rate;
-
- return 0;
-}
-
-static void dp_link_send_test_response(struct dp_link *dp_link)
-{
- struct dp_link_private *link = NULL;
- u32 const response_len = 0x1;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- drm_dp_dpcd_write(link->aux->drm_aux, DP_TEST_RESPONSE,
- &dp_link->test_response, response_len);
-}
-
-static int dp_link_psm_config(struct dp_link *dp_link,
- struct drm_dp_link *link_info, bool enable)
-{
- struct dp_link_private *link = NULL;
- int ret = 0;
-
- if (!dp_link) {
- pr_err("invalid params\n");
- return -EINVAL;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- if (enable)
- ret = drm_dp_link_power_down(link->aux->drm_aux, link_info);
- else
- ret = drm_dp_link_power_up(link->aux->drm_aux, link_info);
-
- if (ret)
- pr_err("Failed to %s low power mode\n",
- (enable ? "enter" : "exit"));
- else
- dp_link->psm_enabled = enable;
-
- return ret;
-}
-
-static void dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum)
-{
- struct dp_link_private *link = NULL;
- u32 const response_len = 0x1;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- drm_dp_dpcd_write(link->aux->drm_aux, DP_TEST_EDID_CHECKSUM,
- &checksum, response_len);
-}
-
-static int dp_link_parse_vx_px(struct dp_link_private *link)
-{
- u8 bp;
- u8 data;
- int const param_len = 0x1;
- int ret = 0;
- u32 v0, p0, v1, p1, v2, p2, v3, p3;
- int rlen;
-
- pr_debug("\n");
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_ADJUST_REQUEST_LANE0_1,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed reading lanes 0/1\n");
- ret = -EINVAL;
- goto end;
- }
-
- data = bp;
-
- pr_debug("lanes 0/1 (Byte 0x206): 0x%x\n", data);
-
- v0 = data & 0x3;
- data = data >> 2;
- p0 = data & 0x3;
- data = data >> 2;
-
- v1 = data & 0x3;
- data = data >> 2;
- p1 = data & 0x3;
- data = data >> 2;
-
- rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_ADJUST_REQUEST_LANE2_3,
- &bp, param_len);
- if (rlen < param_len) {
- pr_err("failed reading lanes 2/3\n");
- ret = -EINVAL;
- goto end;
- }
-
- data = bp;
-
- pr_debug("lanes 2/3 (Byte 0x207): 0x%x\n", data);
-
- v2 = data & 0x3;
- data = data >> 2;
- p2 = data & 0x3;
- data = data >> 2;
-
- v3 = data & 0x3;
- data = data >> 2;
- p3 = data & 0x3;
- data = data >> 2;
-
- pr_debug("vx: 0=%d, 1=%d, 2=%d, 3=%d\n", v0, v1, v2, v3);
- pr_debug("px: 0=%d, 1=%d, 2=%d, 3=%d\n", p0, p1, p2, p3);
-
- /**
- * Update the voltage and pre-emphasis levels as per DPCD request
- * vector.
- */
- pr_debug("Current: v_level = 0x%x, p_level = 0x%x\n",
- link->dp_link.phy_params.v_level,
- link->dp_link.phy_params.p_level);
- pr_debug("Requested: v_level = 0x%x, p_level = 0x%x\n", v0, p0);
- link->dp_link.phy_params.v_level = v0;
- link->dp_link.phy_params.p_level = p0;
-
- pr_debug("Success\n");
-end:
- return ret;
-}
-
-/**
- * dp_link_process_phy_test_pattern_request() - process new phy link requests
- * @link: Display Port Driver data
- *
- * This function will handle new phy link pattern requests that are initiated
- * by the sink. The function will return 0 if a phy link pattern has been
- * processed, otherwise it will return -EINVAL.
- */
-static int dp_link_process_phy_test_pattern_request(
- struct dp_link_private *link)
-{
- u32 test_link_rate = 0, test_lane_count = 0;
-
- if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) {
- pr_debug("no phy test\n");
- return -EINVAL;
- }
-
- test_link_rate = link->request.test_link_rate;
- test_lane_count = link->request.test_lane_count;
-
- if (!is_link_rate_valid(test_link_rate) ||
- !is_lane_count_valid(test_lane_count)) {
- pr_err("Invalid params: link rate = 0x%x, lane count = 0x%x\n",
- test_link_rate, test_lane_count);
- return -EINVAL;
- }
-
- pr_debug("start\n");
-
- pr_info("Current: bw_code = 0x%x, lane count = 0x%x\n",
- link->dp_link.link_params.bw_code,
- link->dp_link.link_params.lane_count);
-
- pr_info("Requested: bw_code = 0x%x, lane count = 0x%x\n",
- test_link_rate, test_lane_count);
-
- link->dp_link.link_params.lane_count = link->request.test_lane_count;
- link->dp_link.link_params.bw_code = link->request.test_link_rate;
-
- dp_link_parse_vx_px(link);
-
- pr_debug("end\n");
-
- return 0;
-}
-
-static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
-{
- return link_status[r - DP_LANE0_1_STATUS];
-}
-
-/**
- * dp_link_process_link_status_update() - processes link status updates
- * @link: Display Port link module data
- *
- * This function will check for changes in the link status, e.g. clock
- * recovery done on all lanes, and trigger link training if there is a
- * failure/error on the link.
- *
- * The function will return 0 if the a link status update has been processed,
- * otherwise it will return -EINVAL.
- */
-static int dp_link_process_link_status_update(struct dp_link_private *link)
-{
- if (!(get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) &
- DP_LINK_STATUS_UPDATED) || /* link status updated */
- (drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.link_params.lane_count) &&
- drm_dp_channel_eq_ok(link->link_status,
- link->dp_link.link_params.lane_count)))
- return -EINVAL;
-
- pr_debug("channel_eq_done = %d, clock_recovery_done = %d\n",
- drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.link_params.lane_count),
- drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.link_params.lane_count));
-
- return 0;
-}
-
-static bool dp_link_is_ds_port_status_changed(struct dp_link_private *link)
-{
- if (get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) &
- DP_DOWNSTREAM_PORT_STATUS_CHANGED) /* port status changed */
- return true;
-
- if (link->prev_sink_count != link->dp_link.sink_count.count)
- return true;
-
- return false;
-}
-
-/**
- * dp_link_process_downstream_port_status_change() - process port status changes
- * @link: Display Port Driver data
- *
- * This function will handle downstream port updates that are initiated by
- * the sink. If the downstream port status has changed, the EDID is read via
- * AUX.
- *
- * The function will return 0 if a downstream port update has been
- * processed, otherwise it will return -EINVAL.
- */
-static int dp_link_process_ds_port_status_change(struct dp_link_private *link)
-{
- if (!dp_link_is_ds_port_status_changed(link))
- return -EINVAL;
-
- /* reset prev_sink_count */
- link->prev_sink_count = link->dp_link.sink_count.count;
-
- return 0;
-}
-
-static bool dp_link_is_video_pattern_requested(struct dp_link_private *link)
-{
- return (link->request.test_requested & DP_TEST_LINK_VIDEO_PATTERN)
- && !(link->request.test_requested &
- DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
-}
-
-static bool dp_link_is_audio_pattern_requested(struct dp_link_private *link)
-{
- return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN);
-}
-
-/**
- * dp_link_process_video_pattern_request() - process new video pattern request
- * @link: Display Port link module's data
- *
- * This function will handle a new video pattern request that are initiated by
- * the sink. This is acheieved by first sending a disconnect notification to
- * the sink followed by a subsequent connect notification to the user modules,
- * where it is expected that the user modules would draw the required link
- * pattern.
- */
-static int dp_link_process_video_pattern_request(struct dp_link_private *link)
-{
- if (!dp_link_is_video_pattern_requested(link))
- goto end;
-
- pr_debug("%s: bit depth=%d(%d bpp) pattern=%s\n",
- dp_link_get_test_name(DP_TEST_LINK_VIDEO_PATTERN),
- link->dp_link.test_video.test_bit_depth,
- dp_link_bit_depth_to_bpp(
- link->dp_link.test_video.test_bit_depth),
- dp_link_video_pattern_to_string(
- link->dp_link.test_video.test_video_pattern));
-
- return 0;
-end:
- return -EINVAL;
-}
-
-/**
- * dp_link_process_audio_pattern_request() - process new audio pattern request
- * @link: Display Port link module data
- *
- * This function will handle a new audio pattern request that is initiated by
- * the sink. This is acheieved by sending the necessary secondary data packets
- * to the sink. It is expected that any simulatenous requests for video
- * patterns will be handled before the audio pattern is sent to the sink.
- */
-static int dp_link_process_audio_pattern_request(struct dp_link_private *link)
-{
- if (!dp_link_is_audio_pattern_requested(link))
- return -EINVAL;
-
- pr_debug("sampling_rate=%s, channel_count=%d, pattern_type=%s\n",
- dp_link_get_audio_sample_rate(
- link->dp_link.test_audio.test_audio_sampling_rate),
- link->dp_link.test_audio.test_audio_channel_count,
- dp_link_get_audio_test_pattern(
- link->dp_link.test_audio.test_audio_pattern_type));
-
- pr_debug("audio_period: ch1=0x%x, ch2=0x%x, ch3=0x%x, ch4=0x%x\n",
- link->dp_link.test_audio.test_audio_period_ch_1,
- link->dp_link.test_audio.test_audio_period_ch_2,
- link->dp_link.test_audio.test_audio_period_ch_3,
- link->dp_link.test_audio.test_audio_period_ch_4);
-
- pr_debug("audio_period: ch5=0x%x, ch6=0x%x, ch7=0x%x, ch8=0x%x\n",
- link->dp_link.test_audio.test_audio_period_ch_5,
- link->dp_link.test_audio.test_audio_period_ch_6,
- link->dp_link.test_audio.test_audio_period_ch_7,
- link->dp_link.test_audio.test_audio_period_ch_8);
-
- return 0;
-}
-
-static void dp_link_reset_data(struct dp_link_private *link)
-{
- link->request = (const struct dp_link_request){ 0 };
- link->dp_link.test_video = (const struct dp_link_test_video){ 0 };
- link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
- link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 };
- link->dp_link.phy_params.phy_test_pattern_sel = 0;
- link->dp_link.sink_request = 0;
- link->dp_link.test_response = 0;
-}
-
-/**
- * dp_link_process_request() - handle HPD IRQ transition to HIGH
- * @link: pointer to link module data
- *
- * This function will handle the HPD IRQ state transitions from LOW to HIGH
- * (including cases when there are back to back HPD IRQ HIGH) indicating
- * the start of a new link training request or sink status update.
- */
-static int dp_link_process_request(struct dp_link *dp_link)
-{
- int ret = 0;
- struct dp_link_private *link;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- pr_debug("start\n");
-
- dp_link_reset_data(link);
-
- dp_link_parse_sink_status_field(link);
-
- if (dp_link_is_test_edid_read(link)) {
- dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
- goto exit;
- }
-
- ret = dp_link_process_ds_port_status_change(link);
- if (!ret) {
- dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
- goto exit;
- }
-
- ret = dp_link_process_link_training_request(link);
- if (!ret) {
- dp_link->sink_request |= DP_TEST_LINK_TRAINING;
- goto exit;
- }
-
- ret = dp_link_process_phy_test_pattern_request(link);
- if (!ret) {
- dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
- goto exit;
- }
-
- ret = dp_link_process_link_status_update(link);
- if (!ret) {
- dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
- goto exit;
- }
-
- ret = dp_link_process_video_pattern_request(link);
- if (!ret) {
- dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
- goto exit;
- }
-
- ret = dp_link_process_audio_pattern_request(link);
- if (!ret) {
- dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
- goto exit;
- }
-
- pr_debug("done\n");
-exit:
- return ret;
-}
-
-static int dp_link_get_colorimetry_config(struct dp_link *dp_link)
-{
- u32 cc;
- enum dynamic_range dr;
- struct dp_link_private *link;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- /* unless a video pattern CTS test is ongoing, use CEA_VESA */
- if (dp_link_is_video_pattern_requested(link))
- dr = link->dp_link.test_video.test_dyn_range;
- else
- dr = DP_DYNAMIC_RANGE_RGB_VESA;
-
- /* Only RGB_VESA nd RGB_CEA supported for now */
- switch (dr) {
- case DP_DYNAMIC_RANGE_RGB_CEA:
- cc = BIT(3);
- break;
- case DP_DYNAMIC_RANGE_RGB_VESA:
- default:
- cc = 0;
- }
-
- return cc;
-}
-
-static int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
-{
- int i;
- int max = 0;
- u8 data;
- struct dp_link_private *link;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- /* use the max level across lanes */
- for (i = 0; i < dp_link->link_params.lane_count; i++) {
- data = drm_dp_get_adjust_request_voltage(link_status, i);
- pr_debug("lane=%d req_voltage_swing=%d\n", i, data);
- if (max < data)
- max = data;
- }
-
- dp_link->phy_params.v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
-
- /* use the max level across lanes */
- max = 0;
- for (i = 0; i < dp_link->link_params.lane_count; i++) {
- data = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
- pr_debug("lane=%d req_pre_emphasis=%d\n", i, data);
- if (max < data)
- max = data;
- }
-
- dp_link->phy_params.p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
-
- /**
- * Adjust the voltage swing and pre-emphasis level combination to within
- * the allowable range.
- */
- if (dp_link->phy_params.v_level > DP_LINK_VOLTAGE_MAX) {
- pr_debug("Requested vSwingLevel=%d, change to %d\n",
- dp_link->phy_params.v_level, DP_LINK_VOLTAGE_MAX);
- dp_link->phy_params.v_level = DP_LINK_VOLTAGE_MAX;
- }
-
- if (dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_MAX) {
- pr_debug("Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->phy_params.p_level, DP_LINK_PRE_EMPHASIS_MAX);
- dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_MAX;
- }
-
- if ((dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_LEVEL_1)
- && (dp_link->phy_params.v_level == DP_LINK_VOLTAGE_LEVEL_2)) {
- pr_debug("Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->phy_params.p_level,
- DP_LINK_PRE_EMPHASIS_LEVEL_1);
- dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
- }
-
- pr_debug("adjusted: v_level=%d, p_level=%d\n",
- dp_link->phy_params.v_level, dp_link->phy_params.p_level);
-
- return 0;
-}
-
-static int dp_link_send_psm_request(struct dp_link *dp_link, bool req)
-{
- struct dp_link_private *link;
-
- if (!dp_link) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- return 0;
-}
-
-static u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
-{
- u32 tbd;
-
- /*
- * Few simplistic rules and assumptions made here:
- * 1. Test bit depth is bit depth per color component
- * 2. Assume 3 color components
- */
- switch (bpp) {
- case 18:
- tbd = DP_TEST_BIT_DEPTH_6;
- break;
- case 24:
- tbd = DP_TEST_BIT_DEPTH_8;
- break;
- case 30:
- tbd = DP_TEST_BIT_DEPTH_10;
- break;
- default:
- tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
- break;
- }
-
- if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN)
- tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
-
- return tbd;
-}
-
-struct dp_link *dp_link_get(struct device *dev, struct dp_aux *aux)
-{
- int rc = 0;
- struct dp_link_private *link;
- struct dp_link *dp_link;
-
- if (!dev || !aux) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL);
- if (!link) {
- rc = -EINVAL;
- goto error;
- }
-
- link->dev = dev;
- link->aux = aux;
-
- dp_link = &link->dp_link;
-
- dp_link->process_request = dp_link_process_request;
- dp_link->get_test_bits_depth = dp_link_get_test_bits_depth;
- dp_link->get_colorimetry_config = dp_link_get_colorimetry_config;
- dp_link->adjust_levels = dp_link_adjust_levels;
- dp_link->send_psm_request = dp_link_send_psm_request;
- dp_link->send_test_response = dp_link_send_test_response;
- dp_link->psm_config = dp_link_psm_config;
- dp_link->send_edid_checksum = dp_link_send_edid_checksum;
-
- return dp_link;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_link_put(struct dp_link *dp_link)
-{
- struct dp_link_private *link;
-
- if (!dp_link)
- return;
-
- link = container_of(dp_link, struct dp_link_private, dp_link);
-
- devm_kfree(link->dev, link);
-}
deleted file mode 100644
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_LINK_H_
-#define _DP_LINK_H_
-
-#include "dp_aux.h"
-
-#define DS_PORT_STATUS_CHANGED 0x200
-#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF
-#define DP_LINK_ENUM_STR(x) #x
-
-enum dp_link_voltage_level {
- DP_LINK_VOLTAGE_LEVEL_0 = 0,
- DP_LINK_VOLTAGE_LEVEL_1 = 1,
- DP_LINK_VOLTAGE_LEVEL_2 = 2,
- DP_LINK_VOLTAGE_MAX = DP_LINK_VOLTAGE_LEVEL_2,
-};
-
-enum dp_link_preemaphasis_level {
- DP_LINK_PRE_EMPHASIS_LEVEL_0 = 0,
- DP_LINK_PRE_EMPHASIS_LEVEL_1 = 1,
- DP_LINK_PRE_EMPHASIS_LEVEL_2 = 2,
- DP_LINK_PRE_EMPHASIS_MAX = DP_LINK_PRE_EMPHASIS_LEVEL_2,
-};
-
-struct dp_link_sink_count {
- u32 count;
- bool cp_ready;
-};
-
-struct dp_link_test_video {
- u32 test_video_pattern;
- u32 test_bit_depth;
- u32 test_dyn_range;
- u32 test_h_total;
- u32 test_v_total;
- u32 test_h_start;
- u32 test_v_start;
- u32 test_hsync_pol;
- u32 test_hsync_width;
- u32 test_vsync_pol;
- u32 test_vsync_width;
- u32 test_h_width;
- u32 test_v_height;
- u32 test_rr_d;
- u32 test_rr_n;
-};
-
-struct dp_link_test_audio {
- u32 test_audio_sampling_rate;
- u32 test_audio_channel_count;
- u32 test_audio_pattern_type;
- u32 test_audio_period_ch_1;
- u32 test_audio_period_ch_2;
- u32 test_audio_period_ch_3;
- u32 test_audio_period_ch_4;
- u32 test_audio_period_ch_5;
- u32 test_audio_period_ch_6;
- u32 test_audio_period_ch_7;
- u32 test_audio_period_ch_8;
-};
-
-struct dp_link_phy_params {
- u32 phy_test_pattern_sel;
- u8 v_level;
- u8 p_level;
-};
-
-struct dp_link_params {
- u32 lane_count;
- u32 bw_code;
-};
-
-struct dp_link {
- u32 sink_request;
- u32 test_response;
- bool psm_enabled;
-
- struct dp_link_sink_count sink_count;
- struct dp_link_test_video test_video;
- struct dp_link_test_audio test_audio;
- struct dp_link_phy_params phy_params;
- struct dp_link_params link_params;
-
- u32 (*get_test_bits_depth)(struct dp_link *dp_link, u32 bpp);
- int (*process_request)(struct dp_link *dp_link);
- int (*get_colorimetry_config)(struct dp_link *dp_link);
- int (*adjust_levels)(struct dp_link *dp_link, u8 *link_status);
- int (*send_psm_request)(struct dp_link *dp_link, bool req);
- void (*send_test_response)(struct dp_link *dp_link);
- int (*psm_config)(struct dp_link *dp_link,
- struct drm_dp_link *link_info, bool enable);
- void (*send_edid_checksum)(struct dp_link *dp_link, u8 checksum);
-};
-
-static inline char *dp_link_get_phy_test_pattern(u32 phy_test_pattern_sel)
-{
- switch (phy_test_pattern_sel) {
- case DP_TEST_PHY_PATTERN_NONE:
- return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_NONE);
- case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING);
- case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT);
- case DP_TEST_PHY_PATTERN_PRBS7:
- return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_PRBS7);
- case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN);
- case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN);
- default:
- return "unknown";
- }
-}
-
-/**
- * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
- * @tbd: test bit depth
- *
- * Returns the bits per pixel (bpp) to be used corresponding to the
- * git bit depth value. This function assumes that bit depth has
- * already been validated.
- */
-static inline u32 dp_link_bit_depth_to_bpp(u32 tbd)
-{
- u32 bpp;
-
- /*
- * Few simplistic rules and assumptions made here:
- * 1. Bit depth is per color component
- * 2. If bit depth is unknown return 0
- * 3. Assume 3 color components
- */
- switch (tbd) {
- case DP_TEST_BIT_DEPTH_6:
- bpp = 18;
- break;
- case DP_TEST_BIT_DEPTH_8:
- bpp = 24;
- break;
- case DP_TEST_BIT_DEPTH_10:
- bpp = 30;
- break;
- case DP_TEST_BIT_DEPTH_UNKNOWN:
- default:
- bpp = 0;
- }
-
- return bpp;
-}
-
-/**
- * dp_link_get() - get the functionalities of dp test module
- *
- *
- * return: a pointer to dp_link struct
- */
-struct dp_link *dp_link_get(struct device *dev, struct dp_aux *aux);
-
-/**
- * dp_link_put() - releases the dp test module's resources
- *
- * @dp_link: an instance of dp_link module
- *
- */
-void dp_link_put(struct dp_link *dp_link);
-
-#endif /* _DP_LINK_H_ */
deleted file mode 100644
@@ -1,526 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include "dp_panel.h"
-
-#include <drm/drm_connector.h>
-#include <drm/drm_edid.h>
-
-#define DP_PANEL_DEFAULT_BPP 24
-#define DP_MAX_DS_PORT_COUNT 1
-
-enum {
- DP_LINK_RATE_MULTIPLIER = 27000000,
-};
-
-struct dp_panel_private {
- struct device *dev;
- struct dp_panel dp_panel;
- struct dp_aux *aux;
- struct dp_link *link;
- struct dp_catalog_panel *catalog;
- bool aux_cfg_update_done;
-};
-
-static const struct dp_panel_info fail_safe = {
- .h_active = 640,
- .v_active = 480,
- .h_back_porch = 48,
- .h_front_porch = 16,
- .h_sync_width = 96,
- .h_active_low = 0,
- .v_back_porch = 33,
- .v_front_porch = 10,
- .v_sync_width = 2,
- .v_active_low = 0,
- .h_skew = 0,
- .refresh_rate = 60,
- .pixel_clk_khz = 25200,
- .bpp = 24,
-};
-
-static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
-{
- int rlen, rc = 0;
- struct dp_panel_private *panel;
- struct drm_dp_link *link_info;
- u8 *dpcd, major = 0, minor = 0;
- u32 dfp_count = 0;
- unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- dpcd = dp_panel->dpcd;
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- link_info = &dp_panel->link_info;
-
- rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DPCD_REV,
- dpcd, (DP_RECEIVER_CAP_SIZE + 1));
- if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) {
- pr_err("dpcd read failed, rlen=%d\n", rlen);
- rc = -EINVAL;
- goto end;
- }
-
- link_info->revision = dp_panel->dpcd[DP_DPCD_REV];
-
- major = (link_info->revision >> 4) & 0x0f;
- minor = link_info->revision & 0x0f;
- pr_debug("version: %d.%d\n", major, minor);
-
- link_info->rate =
- drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
- pr_debug("link_rate=%d\n", link_info->rate);
-
- link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
- DP_MAX_LANE_COUNT_MASK;
-
- pr_debug("lane_count=%d\n", link_info->num_lanes);
-
- if (drm_dp_enhanced_frame_cap(dpcd))
- link_info->capabilities |= caps;
-
- dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] &
- DP_DOWN_STREAM_PORT_COUNT;
-
- if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)
- && (dpcd[DP_DPCD_REV] > 0x10)) {
- rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
- DP_DOWNSTREAM_PORT_0, dp_panel->ds_ports,
- DP_MAX_DOWNSTREAM_PORTS);
- if (rlen < DP_MAX_DOWNSTREAM_PORTS) {
- pr_err("ds port status failed, rlen=%d\n", rlen);
- rc = -EINVAL;
- goto end;
- }
- }
-
- if (dfp_count > DP_MAX_DS_PORT_COUNT)
- pr_debug("DS port count %d greater that max (%d) supported\n",
- dfp_count, DP_MAX_DS_PORT_COUNT);
-
-end:
- return rc;
-}
-
-static int dp_panel_set_default_link_params(struct dp_panel *dp_panel)
-{
- struct drm_dp_link *link_info;
- const int default_bw_code = 162000;
- const int default_num_lanes = 1;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
- link_info = &dp_panel->link_info;
- link_info->rate = default_bw_code;
- link_info->num_lanes = default_num_lanes;
- pr_debug("link_rate=%d num_lanes=%d\n",
- link_info->rate, link_info->num_lanes);
- return 0;
-}
-
-static int dp_panel_read_edid(struct dp_panel *dp_panel,
- struct drm_connector *connector)
-{
- int retry_cnt = 0;
- const int max_retry = 10;
- struct dp_panel_private *panel;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- do {
- kfree(dp_panel->edid);
- dp_panel->edid = drm_get_edid(connector,
- &panel->aux->drm_aux->ddc);
- if (!dp_panel->edid) {
- pr_err("EDID read failed\n");
- retry_cnt++;
- panel->aux->reconfig(panel->aux);
- panel->aux_cfg_update_done = true;
- } else {
- return 0;
- }
- } while (retry_cnt < max_retry);
-
- return drm_add_edid_modes(connector, dp_panel->edid);
-}
-
-static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
- struct drm_connector *connector)
-{
- int rc = 0;
- struct dp_panel_private *panel;
-
- if (!dp_panel || !connector) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- rc = dp_panel_read_dpcd(dp_panel);
- if (rc || !is_link_rate_valid(drm_dp_link_rate_to_bw_code(
- dp_panel->link_info.rate)) || !is_lane_count_valid(
- dp_panel->link_info.num_lanes)) {
- pr_err("panel dpcd read failed/incorrect, set default params\n");
- dp_panel_set_default_link_params(dp_panel);
- }
-
- rc = dp_panel_read_edid(dp_panel, connector);
- if (rc < 0) {
- pr_err("panel edid read failed, set failsafe mode\n");
- return rc;
- }
-
- if (panel->aux_cfg_update_done) {
- pr_debug("read DPCD with updated AUX config\n");
- dp_panel_read_dpcd(dp_panel);
- panel->aux_cfg_update_done = false;
- }
-
- return 0;
-}
-
-static u32 dp_panel_get_max_pclk(struct dp_panel *dp_panel)
-{
- struct drm_dp_link *link_info;
- const u8 num_components = 3;
- u32 bpc = 0, bpp = 0, max_data_rate_khz = 0, max_pclk_rate_khz = 0;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- return 0;
- }
-
- link_info = &dp_panel->link_info;
-
- bpc = dp_panel->connector->display_info.bpc;
- bpp = bpc * num_components;
- if (!bpp)
- bpp = DP_PANEL_DEFAULT_BPP;
-
- max_data_rate_khz = (link_info->num_lanes * link_info->rate * 8);
- max_pclk_rate_khz = max_data_rate_khz / bpp;
-
- pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, link_info->num_lanes);
- pr_debug("max_data_rate=%dKHz, max_pclk_rate=%dKHz\n",
- max_data_rate_khz, max_pclk_rate_khz);
-
- return max_pclk_rate_khz;
-}
-
-static void dp_panel_set_test_mode(struct dp_panel_private *panel,
- struct dp_display_mode *mode)
-{
- struct dp_panel_info *pinfo = NULL;
- struct dp_link_test_video *test_info = NULL;
-
- if (!panel) {
- pr_err("invalid params\n");
- return;
- }
-
- pinfo = &mode->timing;
- test_info = &panel->link->test_video;
-
- pinfo->h_active = test_info->test_h_width;
- pinfo->h_sync_width = test_info->test_hsync_width;
- pinfo->h_back_porch = test_info->test_h_start -
- test_info->test_hsync_width;
- pinfo->h_front_porch = test_info->test_h_total -
- (test_info->test_h_start + test_info->test_h_width);
-
- pinfo->v_active = test_info->test_v_height;
- pinfo->v_sync_width = test_info->test_vsync_width;
- pinfo->v_back_porch = test_info->test_v_start -
- test_info->test_vsync_width;
- pinfo->v_front_porch = test_info->test_v_total -
- (test_info->test_v_start + test_info->test_v_height);
-
- pinfo->bpp = dp_link_bit_depth_to_bpp(test_info->test_bit_depth);
- pinfo->h_active_low = test_info->test_hsync_pol;
- pinfo->v_active_low = test_info->test_vsync_pol;
-
- pinfo->refresh_rate = test_info->test_rr_n;
- pinfo->pixel_clk_khz = test_info->test_h_total *
- test_info->test_v_total * pinfo->refresh_rate;
-
- if (test_info->test_rr_d == 0)
- pinfo->pixel_clk_khz /= 1000;
- else
- pinfo->pixel_clk_khz /= 1001;
-
- if (test_info->test_h_width == 640)
- pinfo->pixel_clk_khz = 25170;
-}
-
-static int dp_panel_get_modes(struct dp_panel *dp_panel,
- struct drm_connector *connector, struct dp_display_mode *mode)
-{
- struct dp_panel_private *panel;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- return -EINVAL;
- }
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- if (dp_panel->video_test) {
- dp_panel_set_test_mode(panel, mode);
- return 1;
- } else if (dp_panel->edid) {
- return dp_panel_read_edid(dp_panel, connector);
- }
-
- /* fail-safe mode */
- memcpy(&mode->timing, &fail_safe,
- sizeof(fail_safe));
- return 1;
-}
-
-static u8 dp_panel_get_edid_checksum(struct edid *edid)
-{
- struct edid *last_block = NULL;
- u8 *raw_edid = NULL;
-
- if (!edid) {
- pr_err("invalid edid input\n");
- return 0;
- }
-
- raw_edid = (u8 *)edid;
- raw_edid += (edid->extensions * EDID_LENGTH);
- last_block = (struct edid *)raw_edid;
-
- if (last_block)
- return last_block->checksum;
-
- pr_err("Invalid block, no checksum\n");
- return 0;
-}
-
-static void dp_panel_handle_sink_request(struct dp_panel *dp_panel)
-{
- struct dp_panel_private *panel;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- return;
- }
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) {
- u8 checksum = dp_panel_get_edid_checksum(dp_panel->edid);
-
- panel->link->send_edid_checksum(panel->link, checksum);
- panel->link->send_test_response(panel->link);
- }
-}
-
-static int dp_panel_timing_cfg(struct dp_panel *dp_panel)
-{
- int rc = 0;
- u32 data, total_ver, total_hor;
- struct dp_catalog_panel *catalog;
- struct dp_panel_private *panel;
- struct dp_panel_info *pinfo;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- catalog = panel->catalog;
- pinfo = &panel->dp_panel.pinfo;
-
- pr_debug("width=%d hporch= %d %d %d\n",
- pinfo->h_active, pinfo->h_back_porch,
- pinfo->h_front_porch, pinfo->h_sync_width);
-
- pr_debug("height=%d vporch= %d %d %d\n",
- pinfo->v_active, pinfo->v_back_porch,
- pinfo->v_front_porch, pinfo->v_sync_width);
-
- total_hor = pinfo->h_active + pinfo->h_back_porch +
- pinfo->h_front_porch + pinfo->h_sync_width;
-
- total_ver = pinfo->v_active + pinfo->v_back_porch +
- pinfo->v_front_porch + pinfo->v_sync_width;
-
- data = total_ver;
- data <<= 16;
- data |= total_hor;
-
- catalog->total = data;
-
- data = (pinfo->v_back_porch + pinfo->v_sync_width);
- data <<= 16;
- data |= (pinfo->h_back_porch + pinfo->h_sync_width);
-
- catalog->sync_start = data;
-
- data = pinfo->v_sync_width;
- data <<= 16;
- data |= (pinfo->v_active_low << 31);
- data |= pinfo->h_sync_width;
- data |= (pinfo->h_active_low << 15);
-
- catalog->width_blanking = data;
-
- data = pinfo->v_active;
- data <<= 16;
- data |= pinfo->h_active;
-
- catalog->dp_active = data;
-
- panel->catalog->timing_cfg(catalog);
-end:
- return rc;
-}
-
-static int dp_panel_init_panel_info(struct dp_panel *dp_panel)
-{
- int rc = 0;
- struct dp_panel_info *pinfo;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto end;
- }
-
- pinfo = &dp_panel->pinfo;
-
- /*
- * print resolution info as this is a result
- * of user initiated action of cable connection
- */
- pr_info("SET NEW RESOLUTION:\n");
- pr_info("%dx%d@%dfps\n", pinfo->h_active,
- pinfo->v_active, pinfo->refresh_rate);
- pr_info("h_porches(back|front|width) = (%d|%d|%d)\n",
- pinfo->h_back_porch,
- pinfo->h_front_porch,
- pinfo->h_sync_width);
- pr_info("v_porches(back|front|width) = (%d|%d|%d)\n",
- pinfo->v_back_porch,
- pinfo->v_front_porch,
- pinfo->v_sync_width);
- pr_info("pixel clock (KHz)=(%d)\n", pinfo->pixel_clk_khz);
- pr_info("bpp = %d\n", pinfo->bpp);
- pr_info("active low (h|v)=(%d|%d)\n", pinfo->h_active_low,
- pinfo->v_active_low);
-
- pinfo->bpp = max_t(u32, 18, min_t(u32, pinfo->bpp, 30));
- pr_info("updated bpp = %d\n", pinfo->bpp);
-end:
- return rc;
-}
-
-static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
-{
- const u32 encoding_factx10 = 8;
- u32 min_link_rate_khz = 0, lane_cnt;
- struct dp_panel_info *pinfo;
-
- if (!dp_panel) {
- pr_err("invalid input\n");
- goto end;
- }
-
- lane_cnt = dp_panel->link_info.num_lanes;
- pinfo = &dp_panel->pinfo;
-
- /* num_lanes * lane_count * 8 >= pclk * bpp * 10 */
- min_link_rate_khz = pinfo->pixel_clk_khz /
- (lane_cnt * encoding_factx10);
- min_link_rate_khz *= pinfo->bpp;
-
- pr_debug("min lclk req=%d khz for pclk=%d khz, lanes=%d, bpp=%d\n",
- min_link_rate_khz, pinfo->pixel_clk_khz, lane_cnt,
- pinfo->bpp);
-end:
- return min_link_rate_khz;
-}
-
-struct dp_panel *dp_panel_get(struct dp_panel_in *in)
-{
- int rc = 0;
- struct dp_panel_private *panel;
- struct dp_panel *dp_panel;
-
- if (!in->dev || !in->catalog || !in->aux || !in->link) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- panel = devm_kzalloc(in->dev, sizeof(*panel), GFP_KERNEL);
- if (!panel) {
- rc = -ENOMEM;
- goto error;
- }
-
- panel->dev = in->dev;
- panel->aux = in->aux;
- panel->catalog = in->catalog;
- panel->link = in->link;
-
- dp_panel = &panel->dp_panel;
- panel->aux_cfg_update_done = false;
-
- dp_panel->init_info = dp_panel_init_panel_info;
- dp_panel->timing_cfg = dp_panel_timing_cfg;
- dp_panel->read_sink_caps = dp_panel_read_sink_caps;
- dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate;
- dp_panel->get_max_pclk = dp_panel_get_max_pclk;
- dp_panel->get_modes = dp_panel_get_modes;
- dp_panel->handle_sink_request = dp_panel_handle_sink_request;
-
- return dp_panel;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_panel_put(struct dp_panel *dp_panel)
-{
- struct dp_panel_private *panel;
-
- if (!dp_panel)
- return;
-
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- kfree(dp_panel->edid);
- dp_panel->edid = NULL;
- devm_kfree(panel->dev, panel);
-}
deleted file mode 100644
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_PANEL_H_
-#define _DP_PANEL_H_
-
-#include "dp_aux.h"
-#include "dp_link.h"
-#include "dp_usbpd.h"
-
-struct edid;
-
-enum dp_lane_count {
- DP_LANE_COUNT_1 = 1,
- DP_LANE_COUNT_2 = 2,
- DP_LANE_COUNT_4 = 4,
-};
-
-#define DP_MAX_DOWNSTREAM_PORTS 0x10
-
-struct dp_panel_info {
- u32 h_active;
- u32 v_active;
- u32 h_back_porch;
- u32 h_front_porch;
- u32 h_sync_width;
- u32 h_active_low;
- u32 v_back_porch;
- u32 v_front_porch;
- u32 v_sync_width;
- u32 v_active_low;
- u32 h_skew;
- u32 refresh_rate;
- u32 pixel_clk_khz;
- u32 bpp;
-};
-
-struct dp_display_mode {
- struct dp_panel_info timing;
- u32 capabilities;
-};
-
-struct dp_panel_in {
- struct device *dev;
- struct dp_aux *aux;
- struct dp_link *link;
- struct dp_catalog_panel *catalog;
-};
-
-struct dp_panel {
- /* dpcd raw data */
- u8 dpcd[DP_RECEIVER_CAP_SIZE];
- u8 ds_ports[DP_MAX_DOWNSTREAM_PORTS];
-
- struct drm_dp_link link_info;
- struct edid *edid;
- struct drm_connector *connector;
- struct dp_panel_info pinfo;
- bool video_test;
-
- u32 vic;
- u32 max_pclk_khz;
-
- int (*init_info)(struct dp_panel *dp_panel);
- int (*timing_cfg)(struct dp_panel *dp_panel);
- int (*read_sink_caps)(struct dp_panel *dp_panel,
- struct drm_connector *connector);
- u32 (*get_min_req_link_rate)(struct dp_panel *dp_panel);
- u32 (*get_max_pclk)(struct dp_panel *dp_panel);
- int (*get_modes)(struct dp_panel *dp_panel,
- struct drm_connector *connector, struct dp_display_mode *mode);
- void (*handle_sink_request)(struct dp_panel *dp_panel);
-};
-
-/**
- * is_link_rate_valid() - validates the link rate
- * @lane_rate: link rate requested by the sink
- *
- * Returns true if the requested link rate is supported.
- */
-static inline bool is_link_rate_valid(u32 bw_code)
-{
- return ((bw_code == DP_LINK_BW_1_62) ||
- (bw_code == DP_LINK_BW_2_7) ||
- (bw_code == DP_LINK_BW_5_4) ||
- (bw_code == DP_LINK_BW_8_1));
-}
-
-/**
- * dp_link_is_lane_count_valid() - validates the lane count
- * @lane_count: lane count requested by the sink
- *
- * Returns true if the requested lane count is supported.
- */
-static inline bool is_lane_count_valid(u32 lane_count)
-{
- return (lane_count == DP_LANE_COUNT_1) ||
- (lane_count == DP_LANE_COUNT_2) ||
- (lane_count == DP_LANE_COUNT_4);
-}
-
-struct dp_panel *dp_panel_get(struct dp_panel_in *in);
-void dp_panel_put(struct dp_panel *dp_panel);
-#endif /* _DP_PANEL_H_ */
deleted file mode 100644
@@ -1,645 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/of_gpio.h>
-
-#include "dp_parser.h"
-
-static void dp_parser_unmap_io_resources(struct dp_parser *parser)
-{
- struct dp_io *io = &parser->io;
-
- msm_dss_iounmap(&io->ctrl_io);
- msm_dss_iounmap(&io->phy_io);
- msm_dss_iounmap(&io->ln_tx0_io);
- msm_dss_iounmap(&io->ln_tx0_io);
- msm_dss_iounmap(&io->dp_pll_io);
- msm_dss_iounmap(&io->dp_cc_io);
- msm_dss_iounmap(&io->usb3_dp_com);
- msm_dss_iounmap(&io->qfprom_io);
- msm_dss_iounmap(&io->hdcp_io);
-}
-
-static int dp_parser_ctrl_res(struct dp_parser *parser)
-{
- int rc = 0;
- u32 index;
- struct platform_device *pdev = parser->pdev;
- struct device_node *of_node = parser->pdev->dev.of_node;
- struct dp_io *io = &parser->io;
-
- rc = of_property_read_u32(of_node, "cell-index", &index);
- if (rc) {
- pr_err("cell-index not specified, rc=%d\n", rc);
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->ctrl_io, "dp_ctrl");
- if (rc) {
- pr_err("unable to remap dp io resources\n");
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->phy_io, "dp_phy");
- if (rc) {
- pr_err("unable to remap dp PHY resources\n");
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->ln_tx0_io, "dp_ln_tx0");
- if (rc) {
- pr_err("unable to remap dp TX0 resources\n");
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->ln_tx1_io, "dp_ln_tx1");
- if (rc) {
- pr_err("unable to remap dp TX1 resources\n");
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->dp_pll_io, "dp_pll");
- if (rc) {
- pr_err("unable to remap DP PLL resources\n");
- goto err;
- }
-
- rc = msm_dss_ioremap_byname(pdev, &io->usb3_dp_com, "usb3_dp_com");
- if (rc) {
- pr_err("unable to remap USB3 DP com resources\n");
- goto err;
- }
-
- if (msm_dss_ioremap_byname(pdev, &io->dp_cc_io, "dp_mmss_cc")) {
- pr_err("unable to remap dp MMSS_CC resources\n");
- goto err;
- }
-
- if (msm_dss_ioremap_byname(pdev, &io->qfprom_io, "qfprom_physical"))
- pr_warn("unable to remap dp qfprom resources\n");
-
- if (msm_dss_ioremap_byname(pdev, &io->hdcp_io, "hdcp_physical"))
- pr_warn("unable to remap dp hdcp resources\n");
-
- return 0;
-err:
- dp_parser_unmap_io_resources(parser);
- return rc;
-}
-
-static const char *dp_get_phy_aux_config_property(u32 cfg_type)
-{
- switch (cfg_type) {
- case PHY_AUX_CFG0:
- return "qcom,aux-cfg0-settings";
- case PHY_AUX_CFG1:
- return "qcom,aux-cfg1-settings";
- case PHY_AUX_CFG2:
- return "qcom,aux-cfg2-settings";
- case PHY_AUX_CFG3:
- return "qcom,aux-cfg3-settings";
- case PHY_AUX_CFG4:
- return "qcom,aux-cfg4-settings";
- case PHY_AUX_CFG5:
- return "qcom,aux-cfg5-settings";
- case PHY_AUX_CFG6:
- return "qcom,aux-cfg6-settings";
- case PHY_AUX_CFG7:
- return "qcom,aux-cfg7-settings";
- case PHY_AUX_CFG8:
- return "qcom,aux-cfg8-settings";
- case PHY_AUX_CFG9:
- return "qcom,aux-cfg9-settings";
- default:
- return "unknown";
- }
-}
-
-static void dp_parser_phy_aux_cfg_reset(struct dp_parser *parser)
-{
- int i = 0;
-
- for (i = 0; i < PHY_AUX_CFG_MAX; i++)
- parser->aux_cfg[i] = (const struct dp_aux_cfg){ 0 };
-}
-
-static int dp_parser_aux(struct dp_parser *parser)
-{
- struct device_node *of_node = parser->pdev->dev.of_node;
- int len = 0, i = 0, j = 0, config_count = 0;
- const char *data;
- int const minimum_config_count = 1;
-
- for (i = 0; i < PHY_AUX_CFG_MAX; i++) {
- const char *property = dp_get_phy_aux_config_property(i);
-
- data = of_get_property(of_node, property, &len);
- if (!data) {
- pr_err("Unable to read %s\n", property);
- goto error;
- }
-
- config_count = len - 1;
- if ((config_count < minimum_config_count) ||
- (config_count > DP_AUX_CFG_MAX_VALUE_CNT)) {
- pr_err("Invalid config count (%d) configs for %s\n",
- config_count, property);
- goto error;
- }
-
- parser->aux_cfg[i].offset = data[0];
- parser->aux_cfg[i].cfg_cnt = config_count;
- pr_debug("%s offset=0x%x, cfg_cnt=%d\n",
- property,
- parser->aux_cfg[i].offset,
- parser->aux_cfg[i].cfg_cnt);
- for (j = 1; j < len; j++) {
- parser->aux_cfg[i].lut[j - 1] = data[j];
- pr_debug("%s lut[%d]=0x%x\n",
- property,
- i,
- parser->aux_cfg[i].lut[j - 1]);
- }
- }
- return 0;
-
-error:
- dp_parser_phy_aux_cfg_reset(parser);
- return -EINVAL;
-}
-
-static int dp_parser_misc(struct dp_parser *parser)
-{
- int rc = 0;
- struct device_node *of_node = parser->pdev->dev.of_node;
-
- rc = of_property_read_u32(of_node,
- "qcom,max-pclk-frequency-khz", &parser->max_pclk_khz);
- if (rc)
- parser->max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ;
-
- return 0;
-}
-
-static int dp_parser_pinctrl(struct dp_parser *parser)
-{
- int rc = 0;
- struct dp_pinctrl *pinctrl = &parser->pinctrl;
-
- pinctrl->pin = devm_pinctrl_get(&parser->pdev->dev);
-
- if (IS_ERR_OR_NULL(pinctrl->pin)) {
- rc = PTR_ERR(pinctrl->pin);
- pr_err("failed to get pinctrl, rc=%d\n", rc);
- goto error;
- }
-
- pinctrl->state_active = pinctrl_lookup_state(pinctrl->pin,
- "mdss_dp_active");
- if (IS_ERR_OR_NULL(pinctrl->state_active)) {
- rc = PTR_ERR(pinctrl->state_active);
- pr_err("failed to get pinctrl active state, rc=%d\n", rc);
- goto error;
- }
-
- pinctrl->state_suspend = pinctrl_lookup_state(pinctrl->pin,
- "mdss_dp_sleep");
- if (IS_ERR_OR_NULL(pinctrl->state_suspend)) {
- rc = PTR_ERR(pinctrl->state_suspend);
- pr_err("failed to get pinctrl suspend state, rc=%d\n", rc);
- goto error;
- }
-error:
- return rc;
-}
-
-static int dp_parser_gpio(struct dp_parser *parser)
-{
- int i = 0;
- struct device *dev = &parser->pdev->dev;
- struct device_node *of_node = dev->of_node;
- struct dss_module_power *mp = &parser->mp[DP_CORE_PM];
- static const char * const dp_gpios[] = {
- "qcom,aux-en-gpio",
- "qcom,aux-sel-gpio",
- "qcom,usbplug-cc-gpio",
- };
-
- mp->gpio_config = devm_kzalloc(dev,
- sizeof(struct dss_gpio) * ARRAY_SIZE(dp_gpios), GFP_KERNEL);
- mp->num_gpio = ARRAY_SIZE(dp_gpios);
-
- for (i = 0; i < ARRAY_SIZE(dp_gpios); i++) {
- mp->gpio_config[i].gpio = of_get_named_gpio(of_node,
- dp_gpios[i], 0);
-
- if (!gpio_is_valid(mp->gpio_config[i].gpio)) {
- pr_err("%s gpio not specified\n", dp_gpios[i]);
- return -EINVAL;
- }
-
- strlcpy(mp->gpio_config[i].gpio_name, dp_gpios[i],
- sizeof(mp->gpio_config[i].gpio_name));
-
- mp->gpio_config[i].value = 0;
- }
-
- return 0;
-}
-
-static const char *dp_parser_supply_node_name(enum dp_pm_type module)
-{
- switch (module) {
- case DP_CORE_PM: return "qcom,core-supply-entries";
- case DP_CTRL_PM: return "qcom,ctrl-supply-entries";
- case DP_PHY_PM: return "qcom,phy-supply-entries";
- default: return "???";
- }
-}
-
-static int dp_parser_get_vreg(struct dp_parser *parser,
- enum dp_pm_type module)
-{
- int i = 0, rc = 0;
- u32 tmp = 0;
- const char *pm_supply_name = NULL;
- struct device_node *supply_node = NULL;
- struct device_node *of_node = parser->pdev->dev.of_node;
- struct device_node *supply_root_node = NULL;
- struct dss_module_power *mp = &parser->mp[module];
-
- mp->num_vreg = 0;
- pm_supply_name = dp_parser_supply_node_name(module);
- supply_root_node = of_get_child_by_name(of_node, pm_supply_name);
- if (!supply_root_node) {
- pr_err("no supply entry present: %s\n", pm_supply_name);
- goto novreg;
- }
-
- mp->num_vreg = of_get_available_child_count(supply_root_node);
-
- if (mp->num_vreg == 0) {
- pr_debug("no vreg\n");
- goto novreg;
- } else {
- pr_debug("vreg found. count=%d\n", mp->num_vreg);
- }
-
- mp->vreg_config = devm_kzalloc(&parser->pdev->dev,
- sizeof(struct dss_vreg) * mp->num_vreg, GFP_KERNEL);
- if (!mp->vreg_config) {
- rc = -ENOMEM;
- goto error;
- }
-
- for_each_child_of_node(supply_root_node, supply_node) {
- const char *st = NULL;
- /* vreg-name */
- rc = of_property_read_string(supply_node,
- "qcom,supply-name", &st);
- if (rc) {
- pr_err("error reading name. rc=%d\n",
- rc);
- goto error;
- }
- snprintf(mp->vreg_config[i].vreg_name,
- ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
- /* vreg-min-voltage */
- rc = of_property_read_u32(supply_node,
- "qcom,supply-min-voltage", &tmp);
- if (rc) {
- pr_err("error reading min volt. rc=%d\n",
- rc);
- goto error;
- }
- mp->vreg_config[i].min_voltage = tmp;
-
- /* vreg-max-voltage */
- rc = of_property_read_u32(supply_node,
- "qcom,supply-max-voltage", &tmp);
- if (rc) {
- pr_err("error reading max volt. rc=%d\n",
- rc);
- goto error;
- }
- mp->vreg_config[i].max_voltage = tmp;
-
- /* enable-load */
- rc = of_property_read_u32(supply_node,
- "qcom,supply-enable-load", &tmp);
- if (rc) {
- pr_err("error reading enable load. rc=%d\n",
- rc);
- goto error;
- }
- mp->vreg_config[i].enable_load = tmp;
-
- /* disable-load */
- rc = of_property_read_u32(supply_node,
- "qcom,supply-disable-load", &tmp);
- if (rc) {
- pr_err("error reading disable load. rc=%d\n",
- rc);
- goto error;
- }
- mp->vreg_config[i].disable_load = tmp;
-
- pr_debug("%s min=%d, max=%d, enable=%d, disable=%d\n",
- mp->vreg_config[i].vreg_name,
- mp->vreg_config[i].min_voltage,
- mp->vreg_config[i].max_voltage,
- mp->vreg_config[i].enable_load,
- mp->vreg_config[i].disable_load
- );
- ++i;
- }
-
- return rc;
-
-error:
- if (mp->vreg_config) {
- devm_kfree(&parser->pdev->dev, mp->vreg_config);
- mp->vreg_config = NULL;
- }
-novreg:
- mp->num_vreg = 0;
-
- return rc;
-}
-
-static void dp_parser_put_vreg_data(struct device *dev,
- struct dss_module_power *mp)
-{
- if (!mp) {
- DEV_ERR("invalid input\n");
- return;
- }
-
- if (mp->vreg_config) {
- devm_kfree(dev, mp->vreg_config);
- mp->vreg_config = NULL;
- }
- mp->num_vreg = 0;
-}
-
-static int dp_parser_regulator(struct dp_parser *parser)
-{
- int i, rc = 0;
- struct platform_device *pdev = parser->pdev;
-
- /* Parse the regulator information */
- for (i = DP_CORE_PM; i < DP_MAX_PM; i++) {
- rc = dp_parser_get_vreg(parser, i);
- if (rc) {
- pr_err("get_dt_vreg_data failed for %s. rc=%d\n",
- dp_parser_pm_name(i), rc);
- i--;
- for (; i >= DP_CORE_PM; i--)
- dp_parser_put_vreg_data(&pdev->dev,
- &parser->mp[i]);
- break;
- }
- }
-
- return rc;
-}
-
-static bool dp_parser_check_prefix(const char *clk_prefix, const char *clk_name)
-{
- return !!strnstr(clk_name, clk_prefix, strlen(clk_name));
-}
-
-static void dp_parser_put_clk_data(struct device *dev,
- struct dss_module_power *mp)
-{
- if (!mp) {
- DEV_ERR("%s: invalid input\n", __func__);
- return;
- }
-
- if (mp->clk_config) {
- devm_kfree(dev, mp->clk_config);
- mp->clk_config = NULL;
- }
-
- mp->num_clk = 0;
-}
-
-static int dp_parser_init_clk_data(struct dp_parser *parser)
-{
- int num_clk = 0, i = 0, rc = 0;
- int core_clk_count = 0, ctrl_clk_count = 0;
- const char *core_clk = "core";
- const char *ctrl_clk = "ctrl";
- const char *clk_name;
- struct device *dev = &parser->pdev->dev;
- struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
- struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
-
- num_clk = of_property_count_strings(dev->of_node, "clock-names");
- if (num_clk <= 0) {
- pr_err("no clocks are defined\n");
- rc = -EINVAL;
- goto exit;
- }
-
- for (i = 0; i < num_clk; i++) {
- of_property_read_string_index(dev->of_node,
- "clock-names", i, &clk_name);
-
- if (dp_parser_check_prefix(core_clk, clk_name))
- core_clk_count++;
-
- if (dp_parser_check_prefix(ctrl_clk, clk_name))
- ctrl_clk_count++;
- }
-
- /* Initialize the CORE power module */
- if (core_clk_count <= 0) {
- pr_err("no core clocks are defined\n");
- rc = -EINVAL;
- goto exit;
- }
-
- core_power->num_clk = core_clk_count;
- core_power->clk_config = devm_kzalloc(dev,
- sizeof(struct dss_clk) * core_power->num_clk,
- GFP_KERNEL);
- if (!core_power->clk_config) {
- rc = -EINVAL;
- goto exit;
- }
-
- /* Initialize the CTRL power module */
- if (ctrl_clk_count <= 0) {
- pr_err("no ctrl clocks are defined\n");
- rc = -EINVAL;
- goto ctrl_clock_error;
- }
-
- ctrl_power->num_clk = ctrl_clk_count;
- ctrl_power->clk_config = devm_kzalloc(dev,
- sizeof(struct dss_clk) * ctrl_power->num_clk,
- GFP_KERNEL);
- if (!ctrl_power->clk_config) {
- ctrl_power->num_clk = 0;
- rc = -EINVAL;
- goto ctrl_clock_error;
- }
-
- return rc;
-
-ctrl_clock_error:
- dp_parser_put_clk_data(dev, core_power);
-exit:
- return rc;
-}
-
-static int dp_parser_clock(struct dp_parser *parser)
-{
- int rc = 0, i = 0;
- int num_clk = 0;
- int core_clk_index = 0, ctrl_clk_index = 0;
- int core_clk_count = 0, ctrl_clk_count = 0;
- const char *clk_name;
- const char *core_clk = "core";
- const char *ctrl_clk = "ctrl";
- struct device *dev = &parser->pdev->dev;
- struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
- struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
-
- core_power = &parser->mp[DP_CORE_PM];
- ctrl_power = &parser->mp[DP_CTRL_PM];
-
- rc = dp_parser_init_clk_data(parser);
- if (rc) {
- pr_err("failed to initialize power data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- core_clk_count = core_power->num_clk;
- ctrl_clk_count = ctrl_power->num_clk;
-
- num_clk = core_clk_count + ctrl_clk_count;
-
- for (i = 0; i < num_clk; i++) {
- of_property_read_string_index(dev->of_node, "clock-names",
- i, &clk_name);
-
- if (dp_parser_check_prefix(core_clk, clk_name) &&
- core_clk_index < core_clk_count) {
- struct dss_clk *clk =
- &core_power->clk_config[core_clk_index];
- strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
- clk->type = DSS_CLK_AHB;
- core_clk_index++;
- } else if (dp_parser_check_prefix(ctrl_clk, clk_name) &&
- ctrl_clk_index < ctrl_clk_count) {
- struct dss_clk *clk =
- &ctrl_power->clk_config[ctrl_clk_index];
- strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name));
- ctrl_clk_index++;
-
- if (!strcmp(clk_name, "ctrl_link_clk") ||
- !strcmp(clk_name, "ctrl_pixel_clk"))
- clk->type = DSS_CLK_PCLK;
- else
- clk->type = DSS_CLK_AHB;
- }
- }
-
- pr_debug("clock parsing successful\n");
-
-exit:
- return rc;
-}
-
-static int dp_parser_parse(struct dp_parser *parser)
-{
- int rc = 0;
-
- if (!parser) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto err;
- }
-
- rc = dp_parser_ctrl_res(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_aux(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_misc(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_clock(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_regulator(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_gpio(parser);
- if (rc)
- goto err;
-
- rc = dp_parser_pinctrl(parser);
-err:
- return rc;
-}
-
-struct dp_parser *dp_parser_get(struct platform_device *pdev)
-{
- struct dp_parser *parser;
-
- parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
- if (!parser)
- return ERR_PTR(-ENOMEM);
-
- parser->parse = dp_parser_parse;
- parser->pdev = pdev;
-
- return parser;
-}
-
-void dp_parser_put(struct dp_parser *parser)
-{
- int i = 0;
- struct dss_module_power *power = NULL;
-
- if (!parser) {
- pr_err("invalid parser module\n");
- return;
- }
-
- power = parser->mp;
-
- for (i = 0; i < DP_MAX_PM; i++) {
- struct dss_module_power *mp = &power[i];
-
- devm_kfree(&parser->pdev->dev, mp->clk_config);
- devm_kfree(&parser->pdev->dev, mp->vreg_config);
- devm_kfree(&parser->pdev->dev, mp->gpio_config);
- }
-
- devm_kfree(&parser->pdev->dev, parser);
-}
deleted file mode 100644
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_PARSER_H_
-#define _DP_PARSER_H_
-
-#include <linux/dpu_io_util.h>
-
-#define DP_LABEL "MDSS DP DISPLAY"
-#define AUX_CFG_LEN 10
-#define DP_MAX_PIXEL_CLK_KHZ 675000
-
-enum dp_pm_type {
- DP_CORE_PM,
- DP_CTRL_PM,
- DP_PHY_PM,
- DP_MAX_PM
-};
-
-static inline const char *dp_parser_pm_name(enum dp_pm_type module)
-{
- switch (module) {
- case DP_CORE_PM: return "DP_CORE_PM";
- case DP_CTRL_PM: return "DP_CTRL_PM";
- case DP_PHY_PM: return "DP_PHY_PM";
- default: return "???";
- }
-}
-
-/**
- * struct dp_display_data - display related device tree data.
- *
- * @ctrl_node: referece to controller device
- * @phy_node: reference to phy device
- * @is_active: is the controller currently active
- * @name: name of the display
- * @display_type: type of the display
- */
-struct dp_display_data {
- struct device_node *ctrl_node;
- struct device_node *phy_node;
- bool is_active;
- const char *name;
- const char *display_type;
-};
-
-/**
- * struct dp_ctrl_resource - controller's IO related data
- *
- * @ctrl_io: controller's mapped memory address
- * @phy_io: phy's mapped memory address
- * @ln_tx0_io: USB-DP lane TX0's mapped memory address
- * @ln_tx1_io: USB-DP lane TX1's mapped memory address
- * @dp_cc_io: DP cc's mapped memory address
- * @qfprom_io: qfprom's mapped memory address
- * @dp_pll_io: DP PLL mapped memory address
- * @usb3_dp_com: USB3 DP PHY combo mapped memory address
- * @hdcp_io: hdcp's mapped memory address
- */
-struct dp_io {
- struct dss_io_data ctrl_io;
- struct dss_io_data phy_io;
- struct dss_io_data ln_tx0_io;
- struct dss_io_data ln_tx1_io;
- struct dss_io_data dp_cc_io;
- struct dss_io_data qfprom_io;
- struct dss_io_data dp_pll_io;
- struct dss_io_data usb3_dp_com;
- struct dss_io_data hdcp_io;
-};
-
-/**
- * struct dp_pinctrl - DP's pin control
- *
- * @pin: pin-controller's instance
- * @state_active: active state pin control
- * @state_hpd_active: hpd active state pin control
- * @state_suspend: suspend state pin control
- */
-struct dp_pinctrl {
- struct pinctrl *pin;
- struct pinctrl_state *state_active;
- struct pinctrl_state *state_hpd_active;
- struct pinctrl_state *state_suspend;
-};
-
-#define DP_ENUM_STR(x) #x
-#define DP_AUX_CFG_MAX_VALUE_CNT 3
-/**
- * struct dp_aux_cfg - DP's AUX configuration settings
- *
- * @cfg_cnt: count of the configurable settings for the AUX register
- * @current_index: current index of the AUX config lut
- * @offset: register offset of the AUX config register
- * @lut: look up table for the AUX config values for this register
- */
-struct dp_aux_cfg {
- u32 cfg_cnt;
- u32 current_index;
- u32 offset;
- u32 lut[DP_AUX_CFG_MAX_VALUE_CNT];
-};
-
-/* PHY AUX config registers */
-enum dp_phy_aux_config_type {
- PHY_AUX_CFG0,
- PHY_AUX_CFG1,
- PHY_AUX_CFG2,
- PHY_AUX_CFG3,
- PHY_AUX_CFG4,
- PHY_AUX_CFG5,
- PHY_AUX_CFG6,
- PHY_AUX_CFG7,
- PHY_AUX_CFG8,
- PHY_AUX_CFG9,
- PHY_AUX_CFG_MAX,
-};
-
-static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
-{
- switch (cfg_type) {
- case PHY_AUX_CFG0:
- return DP_ENUM_STR(PHY_AUX_CFG0);
- case PHY_AUX_CFG1:
- return DP_ENUM_STR(PHY_AUX_CFG1);
- case PHY_AUX_CFG2:
- return DP_ENUM_STR(PHY_AUX_CFG2);
- case PHY_AUX_CFG3:
- return DP_ENUM_STR(PHY_AUX_CFG3);
- case PHY_AUX_CFG4:
- return DP_ENUM_STR(PHY_AUX_CFG4);
- case PHY_AUX_CFG5:
- return DP_ENUM_STR(PHY_AUX_CFG5);
- case PHY_AUX_CFG6:
- return DP_ENUM_STR(PHY_AUX_CFG6);
- case PHY_AUX_CFG7:
- return DP_ENUM_STR(PHY_AUX_CFG7);
- case PHY_AUX_CFG8:
- return DP_ENUM_STR(PHY_AUX_CFG8);
- case PHY_AUX_CFG9:
- return DP_ENUM_STR(PHY_AUX_CFG9);
- default:
- return "unknown";
- }
-}
-
-/**
- * struct dp_parser - DP parser's data exposed to clients
- *
- * @pdev: platform data of the client
- * @mp: gpio, regulator and clock related data
- * @pinctrl: pin-control related data
- * @disp_data: controller's display related data
- * @parse: function to be called by client to parse device tree.
- */
-struct dp_parser {
- struct platform_device *pdev;
- struct dss_module_power mp[DP_MAX_PM];
- struct dp_pinctrl pinctrl;
- struct dp_io io;
- struct dp_display_data disp_data;
-
- u8 l_map[4];
- struct dp_aux_cfg aux_cfg[AUX_CFG_LEN];
- u32 max_pclk_khz;
-
- int (*parse)(struct dp_parser *parser);
-};
-
-/**
- * dp_parser_get() - get the DP's device tree parser module
- *
- * @pdev: platform data of the client
- * return: pointer to dp_parser structure.
- *
- * This function provides client capability to parse the
- * device tree and populate the data structures. The data
- * related to clock, regulators, pin-control and other
- * can be parsed using this module.
- */
-struct dp_parser *dp_parser_get(struct platform_device *pdev);
-
-/**
- * dp_parser_put() - cleans the dp_parser module
- *
- * @parser: pointer to the parser's data.
- */
-void dp_parser_put(struct dp_parser *parser);
-#endif
deleted file mode 100644
@@ -1,593 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/clk.h>
-#include "dp_power.h"
-
-#define DP_CLIENT_NAME_SIZE 20
-
-struct dp_power_private {
- struct dp_parser *parser;
- struct platform_device *pdev;
- struct clk *pixel_clk_rcg;
- struct clk *pixel_parent;
-
- struct dp_power dp_power;
-
- bool core_clks_on;
- bool link_clks_on;
-};
-
-static int dp_power_regulator_init(struct dp_power_private *power)
-{
- int rc = 0, i = 0, j = 0;
- struct platform_device *pdev;
- struct dp_parser *parser;
-
- parser = power->parser;
- pdev = power->pdev;
-
- for (i = DP_CORE_PM; !rc && (i < DP_MAX_PM); i++) {
- rc = msm_dss_config_vreg(&pdev->dev,
- parser->mp[i].vreg_config,
- parser->mp[i].num_vreg, 1);
- if (rc) {
- pr_err("failed to init vregs for %s\n",
- dp_parser_pm_name(i));
- for (j = i - 1; j >= DP_CORE_PM; j--) {
- msm_dss_config_vreg(&pdev->dev,
- parser->mp[j].vreg_config,
- parser->mp[j].num_vreg, 0);
- }
-
- goto error;
- }
- }
-error:
- return rc;
-}
-
-static void dp_power_regulator_deinit(struct dp_power_private *power)
-{
- int rc = 0, i = 0;
- struct platform_device *pdev;
- struct dp_parser *parser;
-
- parser = power->parser;
- pdev = power->pdev;
-
- for (i = DP_CORE_PM; (i < DP_MAX_PM); i++) {
- rc = msm_dss_config_vreg(&pdev->dev,
- parser->mp[i].vreg_config,
- parser->mp[i].num_vreg, 0);
- if (rc)
- pr_err("failed to deinit vregs for %s\n",
- dp_parser_pm_name(i));
- }
-}
-
-static int dp_power_regulator_ctrl(struct dp_power_private *power, bool enable)
-{
- int rc = 0, i = 0, j = 0;
- struct dp_parser *parser;
-
- parser = power->parser;
-
- for (i = DP_CORE_PM; i < DP_MAX_PM; i++) {
- rc = msm_dss_enable_vreg(
- parser->mp[i].vreg_config,
- parser->mp[i].num_vreg, enable);
- if (rc) {
- pr_err("failed to '%s' vregs for %s\n",
- enable ? "enable" : "disable",
- dp_parser_pm_name(i));
- if (enable) {
- for (j = i-1; j >= DP_CORE_PM; j--) {
- msm_dss_enable_vreg(
- parser->mp[j].vreg_config,
- parser->mp[j].num_vreg, 0);
- }
- }
- goto error;
- }
- }
-error:
- return rc;
-}
-
-static int dp_power_pinctrl_set(struct dp_power_private *power, bool active)
-{
- int rc = -EFAULT;
- struct pinctrl_state *pin_state;
- struct dp_parser *parser;
-
- parser = power->parser;
-
- if (IS_ERR_OR_NULL(parser->pinctrl.pin))
- return PTR_ERR(parser->pinctrl.pin);
-
- pin_state = active ? parser->pinctrl.state_active
- : parser->pinctrl.state_suspend;
- if (!IS_ERR_OR_NULL(pin_state)) {
- rc = pinctrl_select_state(parser->pinctrl.pin,
- pin_state);
- if (rc)
- pr_err("can not set %s pins\n",
- active ? "dp_active"
- : "dp_sleep");
- } else {
- pr_err("invalid '%s' pinstate\n",
- active ? "dp_active"
- : "dp_sleep");
- }
-
- return rc;
-}
-
-static int dp_power_clk_init(struct dp_power_private *power, bool enable)
-{
- int rc = 0;
- struct dss_module_power *core, *ctrl;
- struct device *dev;
-
- core = &power->parser->mp[DP_CORE_PM];
- ctrl = &power->parser->mp[DP_CTRL_PM];
-
- dev = &power->pdev->dev;
-
- if (!core || !ctrl) {
- pr_err("invalid power_data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- if (enable) {
- rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
- if (rc) {
- pr_err("failed to get %s clk. err=%d\n",
- dp_parser_pm_name(DP_CORE_PM), rc);
- goto exit;
- }
-
- rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
- if (rc) {
- pr_err("failed to get %s clk. err=%d\n",
- dp_parser_pm_name(DP_CTRL_PM), rc);
- goto ctrl_get_error;
- }
-
- power->pixel_clk_rcg = devm_clk_get(dev, "pixel_clk_rcg");
- if (IS_ERR(power->pixel_clk_rcg)) {
- pr_debug("Unable to get DP pixel clk RCG\n");
- power->pixel_clk_rcg = NULL;
- }
-
- power->pixel_parent = devm_clk_get(dev, "pixel_parent");
- if (IS_ERR(power->pixel_parent)) {
- pr_debug("Unable to get DP pixel RCG parent\n");
- power->pixel_parent = NULL;
- }
- } else {
- if (power->pixel_parent)
- devm_clk_put(dev, power->pixel_parent);
-
- if (power->pixel_clk_rcg)
- devm_clk_put(dev, power->pixel_clk_rcg);
-
- msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk);
- msm_dss_put_clk(core->clk_config, core->num_clk);
- }
-
- return rc;
-
-ctrl_get_error:
- msm_dss_put_clk(core->clk_config, core->num_clk);
-exit:
- return rc;
-}
-
-static int dp_power_clk_set_rate(struct dp_power_private *power,
- enum dp_pm_type module, bool enable)
-{
- int rc = 0;
- struct dss_module_power *mp;
-
- if (!power) {
- pr_err("invalid power data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- mp = &power->parser->mp[module];
-
- if (enable) {
- rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
- if (rc) {
- pr_err("failed to set clks rate.\n");
- goto exit;
- }
-
- rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 1);
- if (rc) {
- pr_err("failed to enable clks\n");
- goto exit;
- }
- } else {
- rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, 0);
- if (rc) {
- pr_err("failed to disable clks\n");
- goto exit;
- }
- }
-exit:
- return rc;
-}
-
-static int dp_power_clk_enable(struct dp_power *dp_power,
- enum dp_pm_type pm_type, bool enable)
-{
- int rc = 0;
- struct dss_module_power *mp;
- struct dp_power_private *power;
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- rc = -EINVAL;
- goto error;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- mp = &power->parser->mp[pm_type];
-
- if ((pm_type != DP_CORE_PM) && (pm_type != DP_CTRL_PM)) {
- pr_err("unsupported power module: %s\n",
- dp_parser_pm_name(pm_type));
- return -EINVAL;
- }
-
- if (enable) {
- if ((pm_type == DP_CORE_PM)
- && (power->core_clks_on)) {
- pr_debug("core clks already enabled\n");
- return 0;
- }
-
- if ((pm_type == DP_CTRL_PM)
- && (power->link_clks_on)) {
- pr_debug("links clks already enabled\n");
- return 0;
- }
-
- if ((pm_type == DP_CTRL_PM) && (!power->core_clks_on)) {
- pr_debug("Need to enable core clks before link clks\n");
-
- rc = dp_power_clk_set_rate(power, pm_type, enable);
- if (rc) {
- pr_err("failed to enable clks: %s. err=%d\n",
- dp_parser_pm_name(DP_CORE_PM), rc);
- goto error;
- } else {
- power->core_clks_on = true;
- }
- }
- }
-
- rc = dp_power_clk_set_rate(power, pm_type, enable);
- if (rc) {
- pr_err("failed to '%s' clks for: %s. err=%d\n",
- enable ? "enable" : "disable",
- dp_parser_pm_name(pm_type), rc);
- goto error;
- }
-
- if (pm_type == DP_CORE_PM)
- power->core_clks_on = enable;
- else
- power->link_clks_on = enable;
-
- pr_debug("%s clocks for %s\n",
- enable ? "enable" : "disable",
- dp_parser_pm_name(pm_type));
- pr_debug("link_clks:%s core_clks:%s\n",
- power->link_clks_on ? "on" : "off",
- power->core_clks_on ? "on" : "off");
-error:
- return rc;
-}
-
-static int dp_power_request_gpios(struct dp_power_private *power)
-{
- int rc = 0, i;
- struct device *dev;
- struct dss_module_power *mp;
- static const char * const gpio_names[] = {
- "aux_enable", "aux_sel", "usbplug_cc",
- };
-
- if (!power) {
- pr_err("invalid power data\n");
- return -EINVAL;
- }
-
- dev = &power->pdev->dev;
- mp = &power->parser->mp[DP_CORE_PM];
-
- for (i = 0; i < ARRAY_SIZE(gpio_names); i++) {
- unsigned int gpio = mp->gpio_config[i].gpio;
-
- if (gpio_is_valid(gpio)) {
- rc = devm_gpio_request(dev, gpio, gpio_names[i]);
- if (rc) {
- pr_err("request %s gpio failed, rc=%d\n",
- gpio_names[i], rc);
- goto error;
- }
- }
- }
- return 0;
-error:
- for (i = 0; i < ARRAY_SIZE(gpio_names); i++) {
- unsigned int gpio = mp->gpio_config[i].gpio;
-
- if (gpio_is_valid(gpio))
- gpio_free(gpio);
- }
- return rc;
-}
-
-static bool dp_power_find_gpio(const char *gpio1, const char *gpio2)
-{
- return !!strnstr(gpio1, gpio2, strlen(gpio1));
-}
-
-static void dp_power_set_gpio(struct dp_power_private *power, bool flip)
-{
- int i;
- struct dss_module_power *mp = &power->parser->mp[DP_CORE_PM];
- struct dss_gpio *config = mp->gpio_config;
-
- for (i = 0; i < mp->num_gpio; i++) {
- if (dp_power_find_gpio(config->gpio_name, "aux-sel"))
- config->value = flip;
-
- if (gpio_is_valid(config->gpio)) {
- pr_debug("gpio %s, value %d\n", config->gpio_name,
- config->value);
-
- if (dp_power_find_gpio(config->gpio_name, "aux-en") ||
- dp_power_find_gpio(config->gpio_name, "aux-sel"))
- gpio_direction_output(config->gpio,
- config->value);
- else
- gpio_set_value(config->gpio, config->value);
-
- }
- config++;
- }
-}
-
-static int dp_power_config_gpios(struct dp_power_private *power, bool flip,
- bool enable)
-{
- int rc = 0, i;
- struct dss_module_power *mp;
- struct dss_gpio *config;
-
- mp = &power->parser->mp[DP_CORE_PM];
- config = mp->gpio_config;
-
- if (enable) {
- rc = dp_power_request_gpios(power);
- if (rc) {
- pr_err("gpio request failed\n");
- return rc;
- }
-
- dp_power_set_gpio(power, flip);
- } else {
- for (i = 0; i < mp->num_gpio; i++) {
- gpio_set_value(config[i].gpio, 0);
- gpio_free(config[i].gpio);
- }
- }
-
- return 0;
-}
-
-static int dp_power_client_init(struct dp_power *dp_power)
-{
- int rc = 0;
- struct dp_power_private *power;
- char dp_client_name[DP_CLIENT_NAME_SIZE];
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- return -EINVAL;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- rc = dp_power_regulator_init(power);
- if (rc) {
- pr_err("failed to init regulators\n");
- goto error_power;
- }
-
- rc = dp_power_clk_init(power, true);
- if (rc) {
- pr_err("failed to init clocks\n");
- goto error_clk;
- }
-
- return 0;
-
-error_clk:
- dp_power_regulator_deinit(power);
-error_power:
- return rc;
-}
-
-static void dp_power_client_deinit(struct dp_power *dp_power)
-{
- struct dp_power_private *power;
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- return;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- dp_power_clk_init(power, false);
- dp_power_regulator_deinit(power);
-}
-
-static int dp_power_set_pixel_clk_parent(struct dp_power *dp_power)
-{
- int rc = 0;
- struct dp_power_private *power;
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- if (power->pixel_clk_rcg && power->pixel_parent)
- clk_set_parent(power->pixel_clk_rcg, power->pixel_parent);
-exit:
- return rc;
-}
-
-static int dp_power_init(struct dp_power *dp_power, bool flip)
-{
- int rc = 0;
- struct dp_power_private *power;
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- rc = dp_power_regulator_ctrl(power, true);
- if (rc) {
- pr_err("failed to enable regulators\n");
- goto exit;
- }
-
- rc = dp_power_pinctrl_set(power, true);
- if (rc) {
- pr_err("failed to set pinctrl state\n");
- goto err_pinctrl;
- }
-
- rc = dp_power_config_gpios(power, flip, true);
- if (rc) {
- pr_err("failed to enable gpios\n");
- goto err_gpio;
- }
-
- rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
- if (rc) {
- pr_err("failed to enable DP core clocks\n");
- goto err_clk;
- }
-
- return 0;
-
-err_clk:
- dp_power_config_gpios(power, flip, false);
-err_gpio:
- dp_power_pinctrl_set(power, false);
-err_pinctrl:
- dp_power_regulator_ctrl(power, false);
-exit:
- return rc;
-}
-
-static int dp_power_deinit(struct dp_power *dp_power)
-{
- int rc = 0;
- struct dp_power_private *power;
-
- if (!dp_power) {
- pr_err("invalid power data\n");
- rc = -EINVAL;
- goto exit;
- }
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- dp_power_clk_enable(dp_power, DP_CORE_PM, false);
- dp_power_config_gpios(power, false, false);
- dp_power_pinctrl_set(power, false);
- dp_power_regulator_ctrl(power, false);
-exit:
- return rc;
-}
-
-struct dp_power *dp_power_get(struct dp_parser *parser)
-{
- int rc = 0;
- struct dp_power_private *power;
- struct dp_power *dp_power;
-
- if (!parser) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
- if (!power) {
- rc = -ENOMEM;
- goto error;
- }
-
- power->parser = parser;
- power->pdev = parser->pdev;
-
- dp_power = &power->dp_power;
-
- dp_power->init = dp_power_init;
- dp_power->deinit = dp_power_deinit;
- dp_power->clk_enable = dp_power_clk_enable;
- dp_power->set_pixel_clk_parent = dp_power_set_pixel_clk_parent;
- dp_power->power_client_init = dp_power_client_init;
- dp_power->power_client_deinit = dp_power_client_deinit;
-
- return dp_power;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_power_put(struct dp_power *dp_power)
-{
- struct dp_power_private *power = NULL;
-
- if (!dp_power)
- return;
-
- power = container_of(dp_power, struct dp_power_private, dp_power);
-
- devm_kfree(&power->pdev->dev, power);
-}
deleted file mode 100644
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_POWER_H_
-#define _DP_POWER_H_
-
-#include "dp_parser.h"
-
-/**
- * sruct dp_power - DisplayPort's power related data
- *
- * @init: initializes the regulators/core clocks/GPIOs/pinctrl
- * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl
- * @clk_enable: enable/disable the DP clocks
- * @set_pixel_clk_parent: set the parent of DP pixel clock
- */
-struct dp_power {
- int (*init)(struct dp_power *power, bool flip);
- int (*deinit)(struct dp_power *power);
- int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type,
- bool enable);
- int (*set_pixel_clk_parent)(struct dp_power *power);
- int (*power_client_init)(struct dp_power *power);
- void (*power_client_deinit)(struct dp_power *power);
-};
-
-/**
- * dp_power_get() - configure and get the DisplayPort power module data
- *
- * @parser: instance of parser module
- * return: pointer to allocated power module data
- *
- * This API will configure the DisplayPort's power module and provides
- * methods to be called by the client to configure the power related
- * modueles.
- */
-struct dp_power *dp_power_get(struct dp_parser *parser);
-
-/**
- * dp_power_put() - release the power related resources
- *
- * @power: pointer to the power module's data
- */
-void dp_power_put(struct dp_power *power);
-#endif /* _DP_POWER_H_ */
deleted file mode 100644
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_REG_H_
-#define _DP_REG_H_
-
-/* DP_TX Registers */
-#define DP_HW_VERSION (0x00000000)
-#define DP_SW_RESET (0x00000010)
-#define DP_PHY_CTRL (0x00000014)
-#define DP_CLK_CTRL (0x00000018)
-#define DP_CLK_ACTIVE (0x0000001C)
-#define DP_INTR_STATUS (0x00000020)
-#define DP_INTR_STATUS2 (0x00000024)
-#define DP_INTR_STATUS3 (0x00000028)
-
-#define DP_DP_HPD_CTRL (0x00000200)
-#define DP_DP_HPD_INT_STATUS (0x00000204)
-#define DP_DP_HPD_INT_ACK (0x00000208)
-#define DP_DP_HPD_INT_MASK (0x0000020C)
-#define DP_DP_HPD_REFTIMER (0x00000218)
-#define DP_DP_HPD_EVENT_TIME_0 (0x0000021C)
-#define DP_DP_HPD_EVENT_TIME_1 (0x00000220)
-#define DP_AUX_CTRL (0x00000230)
-#define DP_AUX_DATA (0x00000234)
-#define DP_AUX_TRANS_CTRL (0x00000238)
-#define DP_TIMEOUT_COUNT (0x0000023C)
-#define DP_AUX_LIMITS (0x00000240)
-#define DP_AUX_STATUS (0x00000244)
-
-#define DP_DPCD_CP_IRQ (0x201)
-#define DP_DPCD_RXSTATUS (0x69493)
-
-#define DP_INTERRUPT_TRANS_NUM (0x000002A0)
-
-#define DP_MAINLINK_CTRL (0x00000400)
-#define DP_STATE_CTRL (0x00000404)
-#define DP_CONFIGURATION_CTRL (0x00000408)
-#define DP_SOFTWARE_MVID (0x00000410)
-#define DP_SOFTWARE_NVID (0x00000418)
-#define DP_TOTAL_HOR_VER (0x0000041C)
-#define DP_START_HOR_VER_FROM_SYNC (0x00000420)
-#define DP_HSYNC_VSYNC_WIDTH_POLARITY (0x00000424)
-#define DP_ACTIVE_HOR_VER (0x00000428)
-#define DP_MISC1_MISC0 (0x0000042C)
-#define DP_VALID_BOUNDARY (0x00000430)
-#define DP_VALID_BOUNDARY_2 (0x00000434)
-#define DP_LOGICAL2PHYSCIAL_LANE_MAPPING (0x00000438)
-
-#define DP_MAINLINK_READY (0x00000440)
-#define DP_MAINLINK_LEVELS (0x00000444)
-#define DP_TU (0x0000044C)
-
-#define DP_HBR2_COMPLIANCE_SCRAMBLER_RESET (0x00000454)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG0 (0x000004C0)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000004C4)
-#define DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000004C8)
-
-#define MMSS_DP_MISC1_MISC0 (0x0000042C)
-#define MMSS_DP_AUDIO_TIMING_GEN (0x00000480)
-#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000484)
-#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000488)
-#define MMSS_DP_AUDIO_TIMING_RBR_44 (0x0000048C)
-#define MMSS_DP_AUDIO_TIMING_HBR_44 (0x00000490)
-#define MMSS_DP_AUDIO_TIMING_RBR_48 (0x00000494)
-#define MMSS_DP_AUDIO_TIMING_HBR_48 (0x00000498)
-
-#define MMSS_DP_PSR_CRC_RG (0x00000554)
-#define MMSS_DP_PSR_CRC_B (0x00000558)
-
-#define DP_COMPRESSION_MODE_CTRL (0x00000580)
-
-#define MMSS_DP_AUDIO_CFG (0x00000600)
-#define MMSS_DP_AUDIO_STATUS (0x00000604)
-#define MMSS_DP_AUDIO_PKT_CTRL (0x00000608)
-#define MMSS_DP_AUDIO_PKT_CTRL2 (0x0000060C)
-#define MMSS_DP_AUDIO_ACR_CTRL (0x00000610)
-#define MMSS_DP_AUDIO_CTRL_RESET (0x00000614)
-
-#define MMSS_DP_SDP_CFG (0x00000628)
-#define MMSS_DP_SDP_CFG2 (0x0000062C)
-#define MMSS_DP_AUDIO_TIMESTAMP_0 (0x00000630)
-#define MMSS_DP_AUDIO_TIMESTAMP_1 (0x00000634)
-
-#define MMSS_DP_AUDIO_STREAM_0 (0x00000640)
-#define MMSS_DP_AUDIO_STREAM_1 (0x00000644)
-
-#define MMSS_DP_EXTENSION_0 (0x00000650)
-#define MMSS_DP_EXTENSION_1 (0x00000654)
-#define MMSS_DP_EXTENSION_2 (0x00000658)
-#define MMSS_DP_EXTENSION_3 (0x0000065C)
-#define MMSS_DP_EXTENSION_4 (0x00000660)
-#define MMSS_DP_EXTENSION_5 (0x00000664)
-#define MMSS_DP_EXTENSION_6 (0x00000668)
-#define MMSS_DP_EXTENSION_7 (0x0000066C)
-#define MMSS_DP_EXTENSION_8 (0x00000670)
-#define MMSS_DP_EXTENSION_9 (0x00000674)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_0 (0x00000678)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_1 (0x0000067C)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_2 (0x00000680)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_3 (0x00000684)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_4 (0x00000688)
-#define MMSS_DP_AUDIO_COPYMANAGEMENT_5 (0x0000068C)
-#define MMSS_DP_AUDIO_ISRC_0 (0x00000690)
-#define MMSS_DP_AUDIO_ISRC_1 (0x00000694)
-#define MMSS_DP_AUDIO_ISRC_2 (0x00000698)
-#define MMSS_DP_AUDIO_ISRC_3 (0x0000069C)
-#define MMSS_DP_AUDIO_ISRC_4 (0x000006A0)
-#define MMSS_DP_AUDIO_ISRC_5 (0x000006A4)
-#define MMSS_DP_AUDIO_INFOFRAME_0 (0x000006A8)
-#define MMSS_DP_AUDIO_INFOFRAME_1 (0x000006AC)
-#define MMSS_DP_AUDIO_INFOFRAME_2 (0x000006B0)
-
-#define MMSS_DP_GENERIC0_0 (0x00000700)
-#define MMSS_DP_GENERIC0_1 (0x00000704)
-#define MMSS_DP_GENERIC0_2 (0x00000708)
-#define MMSS_DP_GENERIC0_3 (0x0000070C)
-#define MMSS_DP_GENERIC0_4 (0x00000710)
-#define MMSS_DP_GENERIC0_5 (0x00000714)
-#define MMSS_DP_GENERIC0_6 (0x00000718)
-#define MMSS_DP_GENERIC0_7 (0x0000071C)
-#define MMSS_DP_GENERIC0_8 (0x00000720)
-#define MMSS_DP_GENERIC0_9 (0x00000724)
-#define MMSS_DP_GENERIC1_0 (0x00000728)
-#define MMSS_DP_GENERIC1_1 (0x0000072C)
-#define MMSS_DP_GENERIC1_2 (0x00000730)
-#define MMSS_DP_GENERIC1_3 (0x00000734)
-#define MMSS_DP_GENERIC1_4 (0x00000738)
-#define MMSS_DP_GENERIC1_5 (0x0000073C)
-#define MMSS_DP_GENERIC1_6 (0x00000740)
-#define MMSS_DP_GENERIC1_7 (0x00000744)
-#define MMSS_DP_GENERIC1_8 (0x00000748)
-#define MMSS_DP_GENERIC1_9 (0x0000074C)
-
-#define MMSS_DP_VSCEXT_0 (0x000006D0)
-#define MMSS_DP_VSCEXT_1 (0x000006D4)
-#define MMSS_DP_VSCEXT_2 (0x000006D8)
-#define MMSS_DP_VSCEXT_3 (0x000006DC)
-#define MMSS_DP_VSCEXT_4 (0x000006E0)
-#define MMSS_DP_VSCEXT_5 (0x000006E4)
-#define MMSS_DP_VSCEXT_6 (0x000006E8)
-#define MMSS_DP_VSCEXT_7 (0x000006EC)
-#define MMSS_DP_VSCEXT_8 (0x000006F0)
-#define MMSS_DP_VSCEXT_9 (0x000006F4)
-
-#define MMSS_DP_TIMING_ENGINE_EN (0x00000A10)
-#define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000A88)
-
-/*DP PHY Register offsets */
-#define DP_PHY_REVISION_ID0 (0x00000000)
-#define DP_PHY_REVISION_ID1 (0x00000004)
-#define DP_PHY_REVISION_ID2 (0x00000008)
-#define DP_PHY_REVISION_ID3 (0x0000000C)
-
-#define DP_PHY_CFG (0x00000010)
-#define DP_PHY_PD_CTL (0x00000018)
-#define DP_PHY_MODE (0x0000001C)
-
-#define DP_PHY_AUX_CFG0 (0x00000020)
-#define DP_PHY_AUX_CFG1 (0x00000024)
-#define DP_PHY_AUX_CFG2 (0x00000028)
-#define DP_PHY_AUX_CFG3 (0x0000002C)
-#define DP_PHY_AUX_CFG4 (0x00000030)
-#define DP_PHY_AUX_CFG5 (0x00000034)
-#define DP_PHY_AUX_CFG6 (0x00000038)
-#define DP_PHY_AUX_CFG7 (0x0000003C)
-#define DP_PHY_AUX_CFG8 (0x00000040)
-#define DP_PHY_AUX_CFG9 (0x00000044)
-#define DP_PHY_AUX_INTERRUPT_MASK (0x00000048)
-#define DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C)
-
-#define DP_PHY_SPARE0 (0x00AC)
-
-#define TXn_TX_EMP_POST1_LVL (0x000C)
-#define TXn_TX_DRV_LVL (0x001C)
-
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN (0x004)
-
-/* DP MMSS_CC registers */
-#define MMSS_DP_LINK_CMD_RCGR (0x0138)
-#define MMSS_DP_LINK_CFG_RCGR (0x013C)
-#define MMSS_DP_PIXEL_M (0x0174)
-#define MMSS_DP_PIXEL_N (0x0178)
-
-/* DP HDCP 1.3 registers */
-#define DP_HDCP_CTRL (0x0A0)
-#define DP_HDCP_STATUS (0x0A4)
-#define DP_HDCP_SW_UPPER_AKSV (0x298)
-#define DP_HDCP_SW_LOWER_AKSV (0x29C)
-#define DP_HDCP_ENTROPY_CTRL0 (0x750)
-#define DP_HDCP_ENTROPY_CTRL1 (0x75C)
-#define DP_HDCP_SHA_STATUS (0x0C8)
-#define DP_HDCP_RCVPORT_DATA2_0 (0x0B0)
-#define DP_HDCP_RCVPORT_DATA3 (0x2A4)
-#define DP_HDCP_RCVPORT_DATA4 (0x2A8)
-#define DP_HDCP_RCVPORT_DATA5 (0x0C0)
-#define DP_HDCP_RCVPORT_DATA6 (0x0C4)
-
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL (0x024)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA (0x028)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0 (0x004)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1 (0x008)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7 (0x00C)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8 (0x010)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9 (0x014)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10 (0x018)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C)
-#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020)
-
-/* USB3 DP COM registers */
-#define USB3_DP_COM_RESET_OVRD_CTRL (0x1C)
-#define USB3_DP_COM_PHY_MODE_CTRL (0x00)
-#define USB3_DP_COM_SW_RESET (0x04)
-#define USB3_DP_COM_TYPEC_CTRL (0x10)
-#define USB3_DP_COM_SWI_CTRL (0x0c)
-#define USB3_DP_COM_POWER_DOWN_CTRL (0x08)
-
-
-
-#endif /* _DP_REG_H_ */
deleted file mode 100644
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
-
-#include <linux/slab.h>
-#include <linux/device.h>
-
-#include "dp_usbpd.h"
-
-/* DP specific VDM commands */
-#define DP_USBPD_VDM_STATUS 0x10
-#define DP_USBPD_VDM_CONFIGURE 0x11
-
-/* USBPD-TypeC specific Macros */
-#define VDM_VERSION 0x0
-#define USB_C_DP_SID 0xFF01
-
-enum dp_usbpd_pin_assignment {
- DP_USBPD_PIN_A,
- DP_USBPD_PIN_B,
- DP_USBPD_PIN_C,
- DP_USBPD_PIN_D,
- DP_USBPD_PIN_E,
- DP_USBPD_PIN_F,
- DP_USBPD_PIN_MAX,
-};
-
-enum dp_usbpd_events {
- DP_USBPD_EVT_DISCOVER,
- DP_USBPD_EVT_ENTER,
- DP_USBPD_EVT_STATUS,
- DP_USBPD_EVT_CONFIGURE,
- DP_USBPD_EVT_CC_PIN_POLARITY,
- DP_USBPD_EVT_EXIT,
- DP_USBPD_EVT_ATTENTION,
-};
-
-enum dp_usbpd_alt_mode {
- DP_USBPD_ALT_MODE_NONE = 0,
- DP_USBPD_ALT_MODE_INIT = BIT(0),
- DP_USBPD_ALT_MODE_DISCOVER = BIT(1),
- DP_USBPD_ALT_MODE_ENTER = BIT(2),
- DP_USBPD_ALT_MODE_STATUS = BIT(3),
- DP_USBPD_ALT_MODE_CONFIGURE = BIT(4),
-};
-
-struct dp_usbpd_capabilities {
- enum dp_usbpd_port port;
- bool receptacle_state;
- u8 ulink_pin_config;
- u8 dlink_pin_config;
-};
-
-struct dp_usbpd_private {
- u32 vdo;
- struct device *dev;
- struct usbpd *pd;
- struct usbpd_svid_handler svid_handler;
- struct dp_usbpd_cb *dp_cb;
- struct dp_usbpd_capabilities cap;
- struct dp_usbpd dp_usbpd;
- enum dp_usbpd_alt_mode alt_mode;
- u32 dp_usbpd_config;
-};
-
-static const char *dp_usbpd_pin_name(u8 pin)
-{
- switch (pin) {
- case DP_USBPD_PIN_A: return "DP_USBPD_PIN_ASSIGNMENT_A";
- case DP_USBPD_PIN_B: return "DP_USBPD_PIN_ASSIGNMENT_B";
- case DP_USBPD_PIN_C: return "DP_USBPD_PIN_ASSIGNMENT_C";
- case DP_USBPD_PIN_D: return "DP_USBPD_PIN_ASSIGNMENT_D";
- case DP_USBPD_PIN_E: return "DP_USBPD_PIN_ASSIGNMENT_E";
- case DP_USBPD_PIN_F: return "DP_USBPD_PIN_ASSIGNMENT_F";
- default: return "UNKNOWN";
- }
-}
-
-static const char *dp_usbpd_port_name(enum dp_usbpd_port port)
-{
- switch (port) {
- case DP_USBPD_PORT_NONE: return "DP_USBPD_PORT_NONE";
- case DP_USBPD_PORT_UFP_D: return "DP_USBPD_PORT_UFP_D";
- case DP_USBPD_PORT_DFP_D: return "DP_USBPD_PORT_DFP_D";
- case DP_USBPD_PORT_D_UFP_D: return "DP_USBPD_PORT_D_UFP_D";
- default: return "DP_USBPD_PORT_NONE";
- }
-}
-
-static const char *dp_usbpd_cmd_name(u8 cmd)
-{
- switch (cmd) {
- case USBPD_SVDM_DISCOVER_MODES: return "USBPD_SVDM_DISCOVER_MODES";
- case USBPD_SVDM_ENTER_MODE: return "USBPD_SVDM_ENTER_MODE";
- case USBPD_SVDM_ATTENTION: return "USBPD_SVDM_ATTENTION";
- case DP_USBPD_VDM_STATUS: return "DP_USBPD_VDM_STATUS";
- case DP_USBPD_VDM_CONFIGURE: return "DP_USBPD_VDM_CONFIGURE";
- default: return "DP_USBPD_VDM_ERROR";
- }
-}
-
-static void dp_usbpd_init_port(enum dp_usbpd_port *port, u32 in_port)
-{
- switch (in_port) {
- case 0:
- *port = DP_USBPD_PORT_NONE;
- break;
- case 1:
- *port = DP_USBPD_PORT_UFP_D;
- break;
- case 2:
- *port = DP_USBPD_PORT_DFP_D;
- break;
- case 3:
- *port = DP_USBPD_PORT_D_UFP_D;
- break;
- default:
- *port = DP_USBPD_PORT_NONE;
- }
- pr_debug("port:%s\n", dp_usbpd_port_name(*port));
-}
-
-static void dp_usbpd_get_capabilities(struct dp_usbpd_private *pd)
-{
- struct dp_usbpd_capabilities *cap = &pd->cap;
- u32 buf = pd->vdo;
- int port = buf & 0x3;
-
- cap->receptacle_state = (buf & BIT(6)) ? true : false;
- cap->dlink_pin_config = (buf >> 8) & 0xff;
- cap->ulink_pin_config = (buf >> 16) & 0xff;
-
- dp_usbpd_init_port(&cap->port, port);
-}
-
-static void dp_usbpd_get_status(struct dp_usbpd_private *pd)
-{
- struct dp_usbpd *status = &pd->dp_usbpd;
- u32 buf = pd->vdo;
- int port = buf & 0x3;
-
- status->low_pow_st = (buf & BIT(2)) ? true : false;
- status->adaptor_dp_en = (buf & BIT(3)) ? true : false;
- status->multi_func = (buf & BIT(4)) ? true : false;
- status->usb_config_req = (buf & BIT(5)) ? true : false;
- status->exit_dp_mode = (buf & BIT(6)) ? true : false;
- status->hpd_high = (buf & BIT(7)) ? true : false;
- status->hpd_irq = (buf & BIT(8)) ? true : false;
-
- pr_debug("low_pow_st = %d, adaptor_dp_en = %d, multi_func = %d\n",
- status->low_pow_st, status->adaptor_dp_en,
- status->multi_func);
- pr_debug("usb_config_req = %d, exit_dp_mode = %d, hpd_high =%d\n",
- status->usb_config_req,
- status->exit_dp_mode, status->hpd_high);
- pr_debug("hpd_irq = %d\n", status->hpd_irq);
-
- dp_usbpd_init_port(&status->port, port);
-}
-
-static u32 dp_usbpd_gen_config_pkt(struct dp_usbpd_private *pd)
-{
- u8 pin_cfg, pin;
- u32 config = 0;
- const u32 ufp_d_config = 0x2, dp_ver = 0x1;
-
- if (pd->cap.receptacle_state)
- pin_cfg = pd->cap.ulink_pin_config;
- else
- pin_cfg = pd->cap.dlink_pin_config;
-
- for (pin = DP_USBPD_PIN_A; pin < DP_USBPD_PIN_MAX; pin++) {
- if (pin_cfg & BIT(pin)) {
- if (pd->dp_usbpd.multi_func) {
- if (pin == DP_USBPD_PIN_D)
- break;
- } else {
- break;
- }
- }
- }
-
- if (pin == DP_USBPD_PIN_MAX)
- pin = DP_USBPD_PIN_C;
-
- pr_debug("pin assignment: %s\n", dp_usbpd_pin_name(pin));
-
- config |= BIT(pin) << 8;
-
- config |= (dp_ver << 2);
- config |= ufp_d_config;
-
- pr_debug("config = 0x%x\n", config);
- return config;
-}
-
-static void dp_usbpd_send_event(struct dp_usbpd_private *pd,
- enum dp_usbpd_events event)
-{
- u32 config;
-
- switch (event) {
- case DP_USBPD_EVT_DISCOVER:
- usbpd_send_svdm(pd->pd, USB_C_DP_SID,
- USBPD_SVDM_DISCOVER_MODES,
- SVDM_CMD_TYPE_INITIATOR, 0x0, 0x0, 0x0);
- break;
- case DP_USBPD_EVT_ENTER:
- usbpd_send_svdm(pd->pd, USB_C_DP_SID,
- USBPD_SVDM_ENTER_MODE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
- break;
- case DP_USBPD_EVT_EXIT:
- usbpd_send_svdm(pd->pd, USB_C_DP_SID,
- USBPD_SVDM_EXIT_MODE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, 0x0, 0x0);
- break;
- case DP_USBPD_EVT_STATUS:
- config = 0x1; /* DFP_D connected */
- usbpd_send_svdm(pd->pd, USB_C_DP_SID, DP_USBPD_VDM_STATUS,
- SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
- break;
- case DP_USBPD_EVT_CONFIGURE:
- config = dp_usbpd_gen_config_pkt(pd);
- usbpd_send_svdm(pd->pd, USB_C_DP_SID, DP_USBPD_VDM_CONFIGURE,
- SVDM_CMD_TYPE_INITIATOR, 0x1, &config, 0x1);
- break;
- default:
- pr_err("unknown event:%d\n", event);
- }
-}
-
-static void dp_usbpd_connect_cb(struct usbpd_svid_handler *hdlr)
-{
- struct dp_usbpd_private *pd;
-
- pd = container_of(hdlr, struct dp_usbpd_private, svid_handler);
- if (!pd) {
- pr_err("get_usbpd phandle failed\n");
- return;
- }
-
- pr_debug("\n");
- dp_usbpd_send_event(pd, DP_USBPD_EVT_DISCOVER);
-}
-
-static void dp_usbpd_disconnect_cb(struct usbpd_svid_handler *hdlr)
-{
- struct dp_usbpd_private *pd;
-
- pd = container_of(hdlr, struct dp_usbpd_private, svid_handler);
- if (!pd) {
- pr_err("get_usbpd phandle failed\n");
- return;
- }
-
- pd->alt_mode = DP_USBPD_ALT_MODE_NONE;
- pd->dp_usbpd.alt_mode_cfg_done = false;
- pr_debug("\n");
-
- if (pd->dp_cb && pd->dp_cb->disconnect)
- pd->dp_cb->disconnect(pd->dev);
-}
-
-static int dp_usbpd_validate_callback(u8 cmd,
- enum usbpd_svdm_cmd_type cmd_type, int num_vdos)
-{
- int ret = 0;
-
- if (cmd_type == SVDM_CMD_TYPE_RESP_NAK) {
- pr_err("error: NACK\n");
- ret = -EINVAL;
- goto end;
- }
-
- if (cmd_type == SVDM_CMD_TYPE_RESP_BUSY) {
- pr_err("error: BUSY\n");
- ret = -EBUSY;
- goto end;
- }
-
- if (cmd == USBPD_SVDM_ATTENTION) {
- if (cmd_type != SVDM_CMD_TYPE_INITIATOR) {
- pr_err("error: invalid cmd type for attention\n");
- ret = -EINVAL;
- goto end;
- }
-
- if (!num_vdos) {
- pr_err("error: no vdo provided\n");
- ret = -EINVAL;
- goto end;
- }
- } else {
- if (cmd_type != SVDM_CMD_TYPE_RESP_ACK) {
- pr_err("error: invalid cmd type\n");
- ret = -EINVAL;
- }
- }
-end:
- return ret;
-}
-
-static void dp_usbpd_response_cb(struct usbpd_svid_handler *hdlr, u8 cmd,
- enum usbpd_svdm_cmd_type cmd_type,
- const u32 *vdos, int num_vdos)
-{
- struct dp_usbpd_private *pd;
-
- pd = container_of(hdlr, struct dp_usbpd_private, svid_handler);
-
- pr_debug("callback -> cmd: %s, *vdos = 0x%x, num_vdos = %d\n",
- dp_usbpd_cmd_name(cmd), *vdos, num_vdos);
-
- if (dp_usbpd_validate_callback(cmd, cmd_type, num_vdos)) {
- pr_debug("invalid callback received\n");
- return;
- }
-
- switch (cmd) {
- case USBPD_SVDM_DISCOVER_MODES:
- pd->vdo = *vdos;
- dp_usbpd_get_capabilities(pd);
-
- pd->alt_mode |= DP_USBPD_ALT_MODE_DISCOVER;
-
- if (pd->cap.port & BIT(0))
- dp_usbpd_send_event(pd, DP_USBPD_EVT_ENTER);
- break;
- case USBPD_SVDM_ENTER_MODE:
- pd->alt_mode |= DP_USBPD_ALT_MODE_ENTER;
-
- dp_usbpd_send_event(pd, DP_USBPD_EVT_STATUS);
- break;
- case USBPD_SVDM_ATTENTION:
- if (pd->dp_usbpd.forced_disconnect)
- break;
-
- pd->vdo = *vdos;
- dp_usbpd_get_status(pd);
-
- if (pd->dp_cb && pd->dp_cb->attention)
- pd->dp_cb->attention(pd->dev);
-
- if (!pd->dp_usbpd.alt_mode_cfg_done)
- dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
- break;
- case DP_USBPD_VDM_STATUS:
- pd->vdo = *vdos;
- dp_usbpd_get_status(pd);
-
- if (!(pd->alt_mode & DP_USBPD_ALT_MODE_CONFIGURE)) {
- pd->alt_mode |= DP_USBPD_ALT_MODE_STATUS;
-
- if (pd->dp_usbpd.port & BIT(1))
- dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
- }
- break;
- case DP_USBPD_VDM_CONFIGURE:
- pd->alt_mode |= DP_USBPD_ALT_MODE_CONFIGURE;
- pd->dp_usbpd.alt_mode_cfg_done = true;
- dp_usbpd_get_status(pd);
-
- pd->dp_usbpd.orientation = usbpd_get_plug_orientation(pd->pd);
-
- /*
- * By default, USB reserves two lanes for Super Speed.
- * Which means DP has remaining two lanes to operate on.
- * If multi-function is not supported, request USB to
- * release the Super Speed lanes so that DP can use
- * all four lanes in case DPCD indicates support for
- * four lanes.
- */
- if (!pd->dp_usbpd.multi_func)
- pd->svid_handler.request_usb_ss_lane(pd->pd,
- &pd->svid_handler);
-
- if (pd->dp_cb && pd->dp_cb->configure)
- pd->dp_cb->configure(pd->dev);
- break;
- default:
- pr_err("unknown cmd: %d\n", cmd);
- break;
- }
-}
-
-static int dp_usbpd_connect(struct dp_usbpd *dp_usbpd, bool hpd)
-{
- int rc = 0;
- struct dp_usbpd_private *pd;
-
- if (!dp_usbpd) {
- pr_err("invalid input\n");
- rc = -EINVAL;
- goto error;
- }
-
- pd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd);
-
- dp_usbpd->hpd_high = hpd;
- dp_usbpd->forced_disconnect = !hpd;
-
- if (hpd)
- pd->dp_cb->configure(pd->dev);
- else
- pd->dp_cb->disconnect(pd->dev);
-
-error:
- return rc;
-}
-
-struct dp_usbpd *dp_usbpd_get(struct device *dev, struct dp_usbpd_cb *cb)
-{
- int rc = 0;
- const char *pd_phandle = "qcom,dp-usbpd-detection";
- struct usbpd *pd = NULL;
- struct dp_usbpd_private *usbpd;
- struct dp_usbpd *dp_usbpd;
- struct usbpd_svid_handler svid_handler = {
- .svid = USB_C_DP_SID,
- .vdm_received = NULL,
- .connect = &dp_usbpd_connect_cb,
- .svdm_received = &dp_usbpd_response_cb,
- .disconnect = &dp_usbpd_disconnect_cb,
- };
-
- if (!cb) {
- pr_err("invalid cb data\n");
- rc = -EINVAL;
- goto error;
- }
-
- pd = devm_usbpd_get_by_phandle(dev, pd_phandle);
- if (IS_ERR(pd)) {
- pr_err("usbpd phandle failed (%ld)\n", PTR_ERR(pd));
- rc = PTR_ERR(pd);
- goto error;
- }
-
- usbpd = devm_kzalloc(dev, sizeof(*usbpd), GFP_KERNEL);
- if (!usbpd) {
- rc = -ENOMEM;
- goto error;
- }
-
- usbpd->dev = dev;
- usbpd->pd = pd;
- usbpd->svid_handler = svid_handler;
- usbpd->dp_cb = cb;
-
- rc = usbpd_register_svid(pd, &usbpd->svid_handler);
- if (rc) {
- pr_err("pd registration failed\n");
- rc = -ENODEV;
- devm_kfree(dev, usbpd);
- goto error;
- }
-
- dp_usbpd = &usbpd->dp_usbpd;
- dp_usbpd->connect = dp_usbpd_connect;
-
- return dp_usbpd;
-error:
- return ERR_PTR(rc);
-}
-
-void dp_usbpd_put(struct dp_usbpd *dp_usbpd)
-{
- struct dp_usbpd_private *usbpd;
-
- if (!dp_usbpd)
- return;
-
- usbpd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd);
-
- usbpd_unregister_svid(usbpd->pd, &usbpd->svid_handler);
-
- devm_kfree(usbpd->dev, usbpd);
-}
deleted file mode 100644
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _DP_USBPD_H_
-#define _DP_USBPD_H_
-
-#include <linux/usb/usbpd.h>
-
-#include <linux/types.h>
-#include <linux/device.h>
-
-/**
- * enum dp_usbpd_port - usb/dp port type
- * @DP_USBPD_PORT_NONE: port not configured
- * @DP_USBPD_PORT_UFP_D: Upstream Facing Port - DisplayPort
- * @DP_USBPD_PORT_DFP_D: Downstream Facing Port - DisplayPort
- * @DP_USBPD_PORT_D_UFP_D: Both UFP & DFP - DisplayPort
- */
-
-enum dp_usbpd_port {
- DP_USBPD_PORT_NONE,
- DP_USBPD_PORT_UFP_D,
- DP_USBPD_PORT_DFP_D,
- DP_USBPD_PORT_D_UFP_D,
-};
-
-/**
- * struct dp_usbpd - DisplayPort status
- *
- * @port: port configured
- * orientation: plug orientation configuration
- * @low_pow_st: low power state
- * @adaptor_dp_en: adaptor functionality enabled
- * @multi_func: multi-function preferred
- * @usb_config_req: request to switch to usb
- * @exit_dp_mode: request exit from displayport mode
- * @hpd_high: Hot Plug Detect signal is high.
- * @hpd_irq: Change in the status since last message
- * @alt_mode_cfg_done: bool to specify alt mode status
- * @debug_en: bool to specify debug mode
- * @connect: simulate disconnect or connect for debug mode
- */
-struct dp_usbpd {
- enum dp_usbpd_port port;
- enum plug_orientation orientation;
- bool low_pow_st;
- bool adaptor_dp_en;
- bool multi_func;
- bool usb_config_req;
- bool exit_dp_mode;
- bool hpd_high;
- bool hpd_irq;
- bool alt_mode_cfg_done;
- bool debug_en;
- bool forced_disconnect;
-
- int (*connect)(struct dp_usbpd *dp_usbpd, bool hpd);
-};
-
-/**
- * struct dp_usbpd_cb - callback functions provided by the client
- *
- * @configure: called by usbpd module when PD communication has
- * been completed and the usb peripheral has been configured on
- * dp mode.
- * @disconnect: notify the cable disconnect issued by usb.
- * @attention: notify any attention message issued by usb.
- */
-struct dp_usbpd_cb {
- int (*configure)(struct device *dev);
- int (*disconnect)(struct device *dev);
- int (*attention)(struct device *dev);
-};
-
-/**
- * dp_usbpd_get() - setup usbpd module
- *
- * @dev: device instance of the caller
- * @cb: struct containing callback function pointers.
- *
- * This function allows the client to initialize the usbpd
- * module. The module will communicate with usb driver and
- * handles the power delivery (PD) communication with the
- * sink/usb device. This module will notify the client using
- * the callback functions about the connection and status.
- */
-struct dp_usbpd *dp_usbpd_get(struct device *dev, struct dp_usbpd_cb *cb);
-
-void dp_usbpd_put(struct dp_usbpd *pd);
-#endif /* _DP_USBPD_H_ */
@@ -335,7 +335,6 @@
# define DP_LINK_BW_1_62 0x06
# define DP_LINK_BW_2_7 0x0a
# define DP_LINK_BW_5_4 0x14 /* 1.2 */
-# define DP_LINK_BW_8_1 0x1e
#define DP_LANE_COUNT_SET 0x101
# define DP_LANE_COUNT_MASK 0x0f
@@ -520,8 +519,6 @@
# define DP_TEST_LINK_EDID_READ (1 << 2)
# define DP_TEST_LINK_PHY_TEST_PATTERN (1 << 3) /* DPCD >= 1.1 */
# define DP_TEST_LINK_FAUX_PATTERN (1 << 4) /* DPCD >= 1.2 */
-# define DP_TEST_LINK_AUDIO_PATTERN (1 << 5)
-# define DP_TEST_LINK_AUDIO_DISABLED_VIDEO (1 << 6)
#define DP_TEST_LINK_RATE 0x219
# define DP_LINK_RATE_162 (0x6)
@@ -610,13 +607,6 @@
#define DP_TEST_80BIT_CUSTOM_PATTERN_71_64 0x258
#define DP_TEST_80BIT_CUSTOM_PATTERN_79_72 0x259
-#define DP_TEST_PHY_PATTERN_NONE 0x0
-#define DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING 0x1
-#define DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT 0x2
-#define DP_TEST_PHY_PATTERN_PRBS7 0x3
-#define DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN 0x4
-#define DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN 0x5
-
#define DP_TEST_RESPONSE 0x260
# define DP_TEST_ACK (1 << 0)
# define DP_TEST_NAK (1 << 1)
@@ -627,19 +617,6 @@
#define DP_TEST_SINK 0x270
# define DP_TEST_SINK_START (1 << 0)
-#define DP_TEST_AUDIO_MODE 0x271
-
-#define DP_TEST_AUDIO_PATTERN_TYPE 0x272
-
-#define DP_TEST_AUDIO_PERIOD_CH1 0x273
-#define DP_TEST_AUDIO_PERIOD_CH2 0x274
-#define DP_TEST_AUDIO_PERIOD_CH3 0x275
-#define DP_TEST_AUDIO_PERIOD_CH4 0x276
-#define DP_TEST_AUDIO_PERIOD_CH5 0x277
-#define DP_TEST_AUDIO_PERIOD_CH6 0x278
-#define DP_TEST_AUDIO_PERIOD_CH7 0x279
-#define DP_TEST_AUDIO_PERIOD_CH8 0x27A
-
#define DP_PAYLOAD_TABLE_UPDATE_STATUS 0x2c0 /* 1.2 MST */
# define DP_PAYLOAD_TABLE_UPDATED (1 << 0)
# define DP_PAYLOAD_ACT_HANDLED (1 << 1)
DPU display port driver is not enabled yet so reverting the driver patch. It will be added back when the driver is reworked and enabled for sdm845 SoC. Signed-off-by: Rajesh Yadav <ryadav@codeaurora.org> --- drivers/gpu/drm/msm/Makefile | 14 - drivers/gpu/drm/msm/dp/dp_audio.c | 806 ------------------ drivers/gpu/drm/msm/dp/dp_audio.h | 81 -- drivers/gpu/drm/msm/dp/dp_aux.c | 570 ------------- drivers/gpu/drm/msm/dp/dp_aux.h | 44 - drivers/gpu/drm/msm/dp/dp_catalog.c | 1320 ----------------------------- drivers/gpu/drm/msm/dp/dp_catalog.h | 163 ---- drivers/gpu/drm/msm/dp/dp_ctrl.c | 1474 --------------------------------- drivers/gpu/drm/msm/dp/dp_ctrl.h | 50 -- drivers/gpu/drm/msm/dp/dp_debug.c | 503 ------------ drivers/gpu/drm/msm/dp/dp_debug.h | 60 -- drivers/gpu/drm/msm/dp/dp_display.c | 1255 ---------------------------- drivers/gpu/drm/msm/dp/dp_display.h | 52 -- drivers/gpu/drm/msm/dp/dp_drm.c | 538 ------------ drivers/gpu/drm/msm/dp/dp_drm.h | 96 --- drivers/gpu/drm/msm/dp/dp_hdcp2p2.c | 927 --------------------- drivers/gpu/drm/msm/dp/dp_link.c | 1548 ----------------------------------- drivers/gpu/drm/msm/dp/dp_link.h | 184 ----- drivers/gpu/drm/msm/dp/dp_panel.c | 526 ------------ drivers/gpu/drm/msm/dp/dp_panel.h | 115 --- drivers/gpu/drm/msm/dp/dp_parser.c | 645 --------------- drivers/gpu/drm/msm/dp/dp_parser.h | 200 ----- drivers/gpu/drm/msm/dp/dp_power.c | 593 -------------- drivers/gpu/drm/msm/dp/dp_power.h | 56 -- drivers/gpu/drm/msm/dp/dp_reg.h | 231 ------ drivers/gpu/drm/msm/dp/dp_usbpd.c | 491 ----------- drivers/gpu/drm/msm/dp/dp_usbpd.h | 101 --- include/drm/drm_dp_helper.h | 23 - 28 files changed, 12666 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dp/dp_audio.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_audio.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_debug.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_debug.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_display.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_display.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp2p2.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_link.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_link.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_power.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_power.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_reg.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_usbpd.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_usbpd.h