Merge "mdss: display-port: add support for audio programming"
This commit is contained in:
commit
e235cc7ed7
9 changed files with 530 additions and 69 deletions
|
@ -583,8 +583,10 @@ int dp_vco_prepare(struct clk *c)
|
|||
mdss_pll_resource_enable(dp_pll_res, false);
|
||||
pr_err("ndx=%d failed to enable dsi pll\n",
|
||||
dp_pll_res->index);
|
||||
goto error;
|
||||
}
|
||||
|
||||
mdss_pll_resource_enable(dp_pll_res, false);
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/msm_ext_display.h>
|
||||
|
||||
#include "mdss.h"
|
||||
#include "mdss_dp.h"
|
||||
|
@ -827,6 +828,112 @@ int mdss_dp_wait4train(struct mdss_dp_drv_pdata *dp_drv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dp_get_cable_status(struct platform_device *pdev, u32 vote)
|
||||
{
|
||||
struct mdss_dp_drv_pdata *dp_ctrl = platform_get_drvdata(pdev);
|
||||
u32 hpd;
|
||||
|
||||
if (!dp_ctrl) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&dp_ctrl->pd_msg_mutex);
|
||||
hpd = dp_ctrl->cable_connected;
|
||||
mutex_unlock(&dp_ctrl->pd_msg_mutex);
|
||||
|
||||
return hpd;
|
||||
}
|
||||
|
||||
static int dp_audio_info_setup(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_setup_params *params)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mdss_dp_drv_pdata *dp_ctrl = platform_get_drvdata(pdev);
|
||||
|
||||
if (!dp_ctrl || !params) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mdss_dp_audio_enable(&dp_ctrl->ctrl_io, true);
|
||||
mdss_dp_config_audio_acr_ctrl(&dp_ctrl->ctrl_io,
|
||||
dp_ctrl->link_rate);
|
||||
mdss_dp_audio_setup_sdps(&dp_ctrl->ctrl_io);
|
||||
|
||||
return rc;
|
||||
} /* dp_audio_info_setup */
|
||||
|
||||
static int dp_get_audio_edid_blk(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_edid_blk *blk)
|
||||
{
|
||||
struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
|
||||
int rc = 0;
|
||||
|
||||
if (!dp) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = hdmi_edid_get_audio_blk
|
||||
(dp->panel_data.panel_info.edid_data, blk);
|
||||
if (rc)
|
||||
DEV_ERR("%s:edid_get_audio_blk failed\n", __func__);
|
||||
|
||||
return rc;
|
||||
} /* dp_get_audio_edid_blk */
|
||||
|
||||
static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device_node *pd_np;
|
||||
const char *phandle = "qcom,msm_ext_disp";
|
||||
|
||||
if (!dp) {
|
||||
pr_err("%s: invalid input\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->ext_audio_data.type = EXT_DISPLAY_TYPE_DP;
|
||||
dp->ext_audio_data.kobj = dp->kobj;
|
||||
dp->ext_audio_data.pdev = dp->pdev;
|
||||
dp->ext_audio_data.codec_ops.audio_info_setup =
|
||||
dp_audio_info_setup;
|
||||
dp->ext_audio_data.codec_ops.get_audio_edid_blk =
|
||||
dp_get_audio_edid_blk;
|
||||
dp->ext_audio_data.codec_ops.cable_status =
|
||||
dp_get_cable_status;
|
||||
|
||||
if (!dp->pdev->dev.of_node) {
|
||||
pr_err("%s cannot find dp dev.of_node\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pd_np = of_parse_phandle(dp->pdev->dev.of_node, phandle, 0);
|
||||
if (!pd_np) {
|
||||
pr_err("%s cannot find %s dev\n", __func__, phandle);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->ext_pdev = of_find_device_by_node(pd_np);
|
||||
if (!dp->ext_pdev) {
|
||||
pr_err("%s cannot find %s pdev\n", __func__, phandle);
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = msm_ext_disp_register_intf(dp->ext_pdev,
|
||||
&dp->ext_audio_data);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register disp\n", __func__);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define DEFAULT_VIDEO_RESOLUTION HDMI_VFRMT_640x480p60_4_3
|
||||
|
||||
static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
|
||||
|
@ -895,7 +1002,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
panel_data);
|
||||
|
||||
/* wait until link training is completed */
|
||||
mutex_lock(&dp_drv->host_mutex);
|
||||
mutex_lock(&dp_drv->train_mutex);
|
||||
|
||||
pr_debug("Enter++ cont_splash=%d\n", dp_drv->cont_splash);
|
||||
/* Default lane mapping */
|
||||
|
@ -908,7 +1015,7 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
ret = mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, true);
|
||||
if (ret) {
|
||||
pr_err("Unabled to start core clocks\n");
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
mdss_dp_hpd_configure(&dp_drv->ctrl_io, true);
|
||||
|
||||
|
@ -941,7 +1048,8 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
dp_drv->link_rate, dp_drv->dpcd.max_link_rate);
|
||||
if (!dp_drv->link_rate) {
|
||||
pr_err("Unable to configure required link rate\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pr_debug("link_rate = 0x%x\n", dp_drv->link_rate);
|
||||
|
@ -955,9 +1063,8 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
|
||||
ret = mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, true);
|
||||
if (ret) {
|
||||
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
|
||||
pr_err("Unabled to start link clocks\n");
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
|
||||
|
@ -985,17 +1092,16 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
|
|||
pr_debug("mainlink ready\n");
|
||||
|
||||
dp_drv->power_on = true;
|
||||
|
||||
mutex_unlock(&dp_drv->host_mutex);
|
||||
pr_debug("End-\n");
|
||||
|
||||
exit:
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mdss_dp_off(struct mdss_panel_data *pdata)
|
||||
{
|
||||
struct mdss_dp_drv_pdata *dp_drv = NULL;
|
||||
int ret = 0;
|
||||
|
||||
dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
|
||||
panel_data);
|
||||
|
@ -1009,73 +1115,54 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
|
|||
mutex_lock(&dp_drv->train_mutex);
|
||||
|
||||
reinit_completion(&dp_drv->idle_comp);
|
||||
mdss_dp_state_ctrl(&dp_drv->ctrl_io, ST_PUSH_IDLE);
|
||||
|
||||
ret = wait_for_completion_timeout(&dp_drv->idle_comp,
|
||||
msecs_to_jiffies(100));
|
||||
if (ret == 0)
|
||||
pr_err("idle pattern timedout\n");
|
||||
|
||||
mdss_dp_state_ctrl(&dp_drv->ctrl_io, 0);
|
||||
|
||||
mdss_dp_irq_disable(dp_drv);
|
||||
if (dp_drv->link_clks_on)
|
||||
mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
|
||||
|
||||
mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
|
||||
mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
|
||||
mdss_dp_aux_ctrl(&dp_drv->ctrl_io, false);
|
||||
|
||||
mdss_dp_irq_disable(dp_drv);
|
||||
|
||||
mdss_dp_config_gpios(dp_drv, false);
|
||||
mdss_dp_pinctrl_set_state(dp_drv, false);
|
||||
|
||||
mdss_dp_aux_ctrl(&dp_drv->ctrl_io, false);
|
||||
/* Make sure DP is disabled before clk disable */
|
||||
wmb();
|
||||
mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false);
|
||||
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
|
||||
|
||||
mdss_dp_regulator_ctrl(dp_drv, false);
|
||||
|
||||
pr_debug("End--: state_ctrl=%x\n",
|
||||
dp_read(dp_drv->base + DP_STATE_CTRL));
|
||||
dp_drv->dp_initialized = false;
|
||||
|
||||
dp_drv->power_on = false;
|
||||
mutex_unlock(&dp_drv->train_mutex);
|
||||
pr_debug("DP off done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mdss_dp_set_audio_switch_node(
|
||||
struct mdss_dp_drv_pdata *dp, int val)
|
||||
{
|
||||
if (dp && dp->ext_audio_data.intf_ops.notify)
|
||||
dp->ext_audio_data.intf_ops.notify(dp->ext_pdev,
|
||||
val);
|
||||
}
|
||||
|
||||
static void mdss_dp_send_cable_notification(
|
||||
struct mdss_dp_drv_pdata *dp, int val)
|
||||
{
|
||||
int state = 0;
|
||||
|
||||
if (!dp) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return;
|
||||
}
|
||||
state = dp->sdev.state;
|
||||
|
||||
switch_set_state(&dp->sdev, val);
|
||||
|
||||
DEV_INFO("%s: cable state %s %d\n", __func__,
|
||||
dp->sdev.state == state ?
|
||||
"is same" : "switched to",
|
||||
dp->sdev.state);
|
||||
}
|
||||
|
||||
static int mdss_dp_register_switch_event(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (!dp) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp->sdev.name = "hdmi";
|
||||
rc = switch_dev_register(&dp->sdev);
|
||||
if (rc) {
|
||||
DEV_ERR("%s: display switch registration failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
return rc;
|
||||
if (dp && dp->ext_audio_data.intf_ops.hpd)
|
||||
dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
|
||||
dp->ext_audio_data.type, val);
|
||||
}
|
||||
|
||||
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
|
||||
|
@ -1124,6 +1211,10 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
|
|||
dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
|
||||
panel_data);
|
||||
|
||||
if (dp_drv->dp_initialized) {
|
||||
pr_err("%s: host init done already\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
ret = mdss_dp_regulator_ctrl(dp_drv, true);
|
||||
if (ret) {
|
||||
pr_err("failed to enable regulators\n");
|
||||
|
@ -1170,6 +1261,8 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
|
|||
}
|
||||
|
||||
mdss_dp_send_cable_notification(dp_drv, true);
|
||||
mdss_dp_set_audio_switch_node(dp_drv, true);
|
||||
dp_drv->dp_initialized = true;
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -1421,7 +1514,12 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
|
|||
mdss_dp_sysfs_create(dp, fbi);
|
||||
mdss_dp_edid_init(pdata);
|
||||
mdss_dp_hdcp_init(pdata);
|
||||
mdss_dp_register_switch_event(dp);
|
||||
|
||||
rc = mdss_dp_init_ext_disp(dp);
|
||||
if (rc)
|
||||
pr_err("failed to initialize ext disp data, ret=%d\n",
|
||||
rc);
|
||||
|
||||
break;
|
||||
case MDSS_EVENT_CHECK_PARAMS:
|
||||
rc = mdss_dp_check_params(dp, arg);
|
||||
|
@ -1738,6 +1836,7 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
|
|||
dp_drv->cable_connected = false;
|
||||
mutex_unlock(&dp_drv->pd_msg_mutex);
|
||||
mdss_dp_send_cable_notification(dp_drv, false);
|
||||
mdss_dp_set_audio_switch_node(dp_drv, false);
|
||||
}
|
||||
|
||||
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
|
||||
|
@ -1781,8 +1880,8 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
|
|||
if (cmd_type == SVDM_CMD_TYPE_INITIATOR) {
|
||||
pr_debug("Attention. cmd_type=%d\n",
|
||||
cmd_type);
|
||||
if (!dp_drv->alt_mode.current_state
|
||||
== ENTER_MODE_DONE) {
|
||||
if (!(dp_drv->alt_mode.current_state
|
||||
== ENTER_MODE_DONE)) {
|
||||
pr_debug("sending discover_mode\n");
|
||||
dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES);
|
||||
break;
|
||||
|
@ -1909,7 +2008,6 @@ static int mdss_dp_probe(struct platform_device *pdev)
|
|||
dp_drv->mask1 = EDP_INTR_MASK1;
|
||||
dp_drv->mask2 = EDP_INTR_MASK2;
|
||||
mutex_init(&dp_drv->emutex);
|
||||
mutex_init(&dp_drv->host_mutex);
|
||||
mutex_init(&dp_drv->pd_msg_mutex);
|
||||
mutex_init(&dp_drv->hdcp_mutex);
|
||||
spin_lock_init(&dp_drv->lock);
|
||||
|
@ -1999,8 +2097,12 @@ static int mdss_dp_probe(struct platform_device *pdev)
|
|||
probe_err:
|
||||
iounmap(dp_drv->ctrl_io.base);
|
||||
iounmap(dp_drv->phy_io.base);
|
||||
if (dp_drv)
|
||||
if (dp_drv) {
|
||||
if (dp_drv->pd)
|
||||
usbpd_unregister_svid(dp_drv->pd,
|
||||
&dp_drv->svid_handler);
|
||||
devm_kfree(&pdev->dev, dp_drv);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -333,10 +333,13 @@ struct mdss_dp_drv_pdata {
|
|||
int (*on) (struct mdss_panel_data *pdata);
|
||||
int (*off) (struct mdss_panel_data *pdata);
|
||||
struct platform_device *pdev;
|
||||
struct platform_device *ext_pdev;
|
||||
|
||||
struct usbpd *pd;
|
||||
struct usbpd_svid_handler svid_handler;
|
||||
struct dp_alt_mode alt_mode;
|
||||
bool dp_initialized;
|
||||
struct msm_ext_disp_init_data ext_audio_data;
|
||||
|
||||
struct mutex emutex;
|
||||
int clk_cnt;
|
||||
|
@ -398,7 +401,6 @@ struct mdss_dp_drv_pdata {
|
|||
struct completion video_comp;
|
||||
struct mutex aux_mutex;
|
||||
struct mutex train_mutex;
|
||||
struct mutex host_mutex;
|
||||
struct mutex pd_msg_mutex;
|
||||
struct mutex hdcp_mutex;
|
||||
bool cable_connected;
|
||||
|
|
|
@ -1312,7 +1312,7 @@ static void dp_clear_training_pattern(struct mdss_dp_drv_pdata *ep)
|
|||
usleep_range(usleep_time, usleep_time);
|
||||
}
|
||||
|
||||
static int dp_aux_link_train(struct mdss_dp_drv_pdata *dp)
|
||||
int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
|
||||
{
|
||||
int ret = 0;
|
||||
int usleep_time;
|
||||
|
@ -1412,16 +1412,6 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep)
|
|||
|
||||
}
|
||||
|
||||
int mdss_dp_link_train(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ep->train_mutex);
|
||||
ret = dp_aux_link_train(ep);
|
||||
mutex_unlock(&ep->train_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mdss_dp_aux_init(struct mdss_dp_drv_pdata *ep)
|
||||
{
|
||||
mutex_init(&ep->aux_mutex);
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
|
||||
#include "mdss_dp_util.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 mdss_hw mdss_dp_hw = {
|
||||
.hw_ndx = MDSS_HW_EDP,
|
||||
.ptr = NULL,
|
||||
|
@ -370,3 +377,163 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp)
|
|||
pr_debug("DP config = 0x%x\n", config);
|
||||
return config;
|
||||
}
|
||||
|
||||
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,
|
||||
char link_rate)
|
||||
{
|
||||
u32 acr_ctrl = 0;
|
||||
|
||||
switch (link_rate) {
|
||||
case DP_LINK_RATE_162:
|
||||
acr_ctrl = 0;
|
||||
break;
|
||||
case DP_LINK_RATE_270:
|
||||
acr_ctrl = 1;
|
||||
break;
|
||||
case DP_LINK_RATE_540:
|
||||
acr_ctrl = 2;
|
||||
break;
|
||||
default:
|
||||
pr_debug("Unknown link rate\n");
|
||||
acr_ctrl = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
writel_relaxed(acr_ctrl, ctrl_io->base + MMSS_DP_AUDIO_ACR_CTRL);
|
||||
}
|
||||
|
||||
static void mdss_dp_audio_config_parity_settings(struct dss_io_data *ctrl_io)
|
||||
{
|
||||
u32 value = 0;
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_0);
|
||||
/* Config header and parity byte 1 */
|
||||
value |= ((0x2 << HEADER_BYTE_1_BIT)
|
||||
| (0x13 << PARITY_BYTE_1_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_STREAM_0);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
/* Config header and parity byte 2 */
|
||||
value |= ((0x28 << HEADER_BYTE_2_BIT)
|
||||
| (0xf5 << PARITY_BYTE_2_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
/* Config header and parity byte 3 */
|
||||
value |= ((0x97 << HEADER_BYTE_3_BIT)
|
||||
| (0xc2 << PARITY_BYTE_3_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_STREAM_1);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_0);
|
||||
/* Config header and parity byte 1 */
|
||||
value |= ((0x1 << HEADER_BYTE_1_BIT)
|
||||
| (0x98 << PARITY_BYTE_1_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_0);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1);
|
||||
/* Config header and parity byte 2 */
|
||||
value |= ((0x17 << HEADER_BYTE_2_BIT)
|
||||
| (0x60 << PARITY_BYTE_2_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_0);
|
||||
/* Config header and parity byte 1 */
|
||||
value |= ((0x84 << HEADER_BYTE_1_BIT)
|
||||
| (0x84 << PARITY_BYTE_1_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_0);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1);
|
||||
/* Config header and parity byte 2 */
|
||||
value |= ((0xb1 << HEADER_BYTE_2_BIT)
|
||||
| (0x4e << PARITY_BYTE_2_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_0);
|
||||
/* Config header and parity byte 1 */
|
||||
value |= ((0x5 << HEADER_BYTE_1_BIT)
|
||||
| (0xbe << PARITY_BYTE_1_BIT));
|
||||
writel_relaxed(value, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_0);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_1);
|
||||
/* Config header and parity byte 2 */
|
||||
value |= ((0x0b << HEADER_BYTE_2_BIT)
|
||||
| (0xc7 << PARITY_BYTE_2_BIT));
|
||||
writel_relaxed(value, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_1);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_1);
|
||||
/* Config header and parity byte 3 */
|
||||
value |= ((0x1 << HEADER_BYTE_3_BIT)
|
||||
| (0x98 << PARITY_BYTE_3_BIT));
|
||||
writel_relaxed(value, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_1);
|
||||
|
||||
writel_relaxed(0x22222222, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_2);
|
||||
writel_relaxed(0x22222222, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_3);
|
||||
writel_relaxed(0x22222222, ctrl_io->base +
|
||||
MMSS_DP_AUDIO_COPYMANAGEMENT_4);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_ISRC_0);
|
||||
/* Config header and parity byte 1 */
|
||||
value |= ((0x6 << HEADER_BYTE_1_BIT)
|
||||
| (0x35 << PARITY_BYTE_1_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_ISRC_0);
|
||||
|
||||
value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_ISRC_1);
|
||||
/* Config header and parity byte 2 */
|
||||
value |= ((0x0b << HEADER_BYTE_2_BIT)
|
||||
| (0xc7 << PARITY_BYTE_2_BIT));
|
||||
writel_relaxed(value, ctrl_io->base + MMSS_DP_AUDIO_ISRC_1);
|
||||
|
||||
writel_relaxed(0x33333333, ctrl_io->base + MMSS_DP_AUDIO_ISRC_2);
|
||||
writel_relaxed(0x33333333, ctrl_io->base + MMSS_DP_AUDIO_ISRC_3);
|
||||
writel_relaxed(0x33333333, ctrl_io->base + MMSS_DP_AUDIO_ISRC_4);
|
||||
|
||||
}
|
||||
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io)
|
||||
{
|
||||
u32 sdp_cfg = 0;
|
||||
u32 sdp_cfg2 = 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
writel_relaxed(sdp_cfg, ctrl_io->base + MMSS_DP_SDP_CFG);
|
||||
|
||||
sdp_cfg2 = readl_relaxed(ctrl_io->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);
|
||||
|
||||
writel_relaxed(sdp_cfg2, ctrl_io->base + MMSS_DP_SDP_CFG2);
|
||||
|
||||
mdss_dp_audio_config_parity_settings(ctrl_io);
|
||||
}
|
||||
|
||||
void mdss_dp_audio_enable(struct dss_io_data *ctrl_io, bool enable)
|
||||
{
|
||||
u32 audio_ctrl = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_CFG);
|
||||
|
||||
if (enable)
|
||||
audio_ctrl |= BIT(0);
|
||||
else
|
||||
audio_ctrl &= ~BIT(0);
|
||||
|
||||
writel_relaxed(audio_ctrl, ctrl_io->base + MMSS_DP_AUDIO_CFG);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,75 @@
|
|||
#define DP_MAINLINK_READY (0x00000440)
|
||||
#define DP_TU (0x0000044C)
|
||||
|
||||
#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_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 (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)
|
||||
|
||||
/*DP PHY Register offsets */
|
||||
#define DP_PHY_REVISION_ID0 (0x00000000)
|
||||
#define DP_PHY_REVISION_ID1 (0x00000004)
|
||||
|
@ -162,5 +231,9 @@ void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status);
|
|||
u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp);
|
||||
void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io,
|
||||
struct lane_mapping l_map);
|
||||
void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io,
|
||||
char link_rate);
|
||||
void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io);
|
||||
void mdss_dp_audio_enable(struct dss_io_data *ctrl_io, bool enable);
|
||||
|
||||
#endif /* __DP_UTIL_H__ */
|
||||
|
|
|
@ -1915,6 +1915,7 @@ static int hdmi_tx_init_ext_disp(struct hdmi_tx_ctrl *hdmi_ctrl)
|
|||
|
||||
hdmi_ctrl->ext_audio_data.type = EXT_DISPLAY_TYPE_HDMI;
|
||||
hdmi_ctrl->ext_audio_data.kobj = hdmi_ctrl->kobj;
|
||||
hdmi_ctrl->ext_audio_data.pdev = hdmi_ctrl->pdev;
|
||||
hdmi_ctrl->ext_audio_data.codec_ops.audio_info_setup =
|
||||
hdmi_tx_audio_info_setup;
|
||||
hdmi_ctrl->ext_audio_data.codec_ops.get_audio_edid_blk =
|
||||
|
@ -2978,7 +2979,7 @@ int msm_hdmi_register_audio_codec(struct platform_device *pdev,
|
|||
|
||||
if (!hdmi_ctrl || !ops) {
|
||||
DEV_ERR("%s: invalid input\n", __func__);
|
||||
return -ENODEV;
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
ret = msm_ext_disp_register_audio_codec(hdmi_ctrl->ext_pdev, ops);
|
||||
|
|
|
@ -380,6 +380,88 @@ end:
|
|||
|
||||
return ret;
|
||||
}
|
||||
static int msm_ext_disp_get_intf_data_helper(struct platform_device *pdev,
|
||||
struct msm_ext_disp_init_data **data)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_ext_disp *ext_disp = NULL;
|
||||
|
||||
if (!pdev) {
|
||||
pr_err("No platform device\n");
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ext_disp = platform_get_drvdata(pdev);
|
||||
if (!ext_disp) {
|
||||
pr_err("No drvdata found\n");
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_disp->lock);
|
||||
|
||||
if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX) {
|
||||
ret = -EINVAL;
|
||||
pr_err("No display connected\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = msm_ext_disp_get_intf_data(ext_disp, ext_disp->current_disp,
|
||||
data);
|
||||
if (ret)
|
||||
goto error;
|
||||
error:
|
||||
mutex_unlock(&ext_disp->lock);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
static int msm_ext_disp_cable_status(struct platform_device *pdev, u32 vote)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_ext_disp_init_data *data = NULL;
|
||||
|
||||
ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
|
||||
if (ret || !data)
|
||||
goto end;
|
||||
|
||||
ret = data->codec_ops.cable_status(data->pdev, vote);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_ext_disp_get_audio_edid_blk(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_edid_blk *blk)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_ext_disp_init_data *data = NULL;
|
||||
|
||||
ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
|
||||
if (ret || !data)
|
||||
goto end;
|
||||
|
||||
ret = data->codec_ops.get_audio_edid_blk(data->pdev, blk);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_ext_disp_audio_info_setup(struct platform_device *pdev,
|
||||
struct msm_ext_disp_audio_setup_params *params)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_ext_disp_init_data *data = NULL;
|
||||
|
||||
ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
|
||||
if (ret || !data)
|
||||
goto end;
|
||||
|
||||
ret = data->codec_ops.audio_info_setup(data->pdev, params);
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_ext_disp_get_intf_id(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -456,11 +538,11 @@ static int msm_ext_disp_notify(struct platform_device *pdev,
|
|||
|
||||
if (new_state == EXT_DISPLAY_CABLE_CONNECT && ext_disp->ops) {
|
||||
ext_disp->ops->audio_info_setup =
|
||||
data->codec_ops.audio_info_setup;
|
||||
msm_ext_disp_audio_info_setup;
|
||||
ext_disp->ops->get_audio_edid_blk =
|
||||
data->codec_ops.get_audio_edid_blk;
|
||||
msm_ext_disp_get_audio_edid_blk;
|
||||
ext_disp->ops->cable_status =
|
||||
data->codec_ops.cable_status;
|
||||
msm_ext_disp_cable_status;
|
||||
ext_disp->ops->get_intf_id =
|
||||
msm_ext_disp_get_intf_id;
|
||||
}
|
||||
|
@ -590,6 +672,33 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int msm_ext_disp_validate_intf(struct msm_ext_disp_init_data *init_data)
|
||||
{
|
||||
if (!init_data) {
|
||||
pr_err("Invalid init_data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!init_data->pdev) {
|
||||
pr_err("Invalid display intf pdev\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!init_data->kobj) {
|
||||
pr_err("Invalid display intf kobj\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!init_data->codec_ops.get_audio_edid_blk ||
|
||||
!init_data->codec_ops.cable_status ||
|
||||
!init_data->codec_ops.audio_info_setup) {
|
||||
pr_err("Invalid codec operation pointers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_ext_disp_register_intf(struct platform_device *pdev,
|
||||
struct msm_ext_disp_init_data *init_data)
|
||||
{
|
||||
|
@ -610,6 +719,10 @@ int msm_ext_disp_register_intf(struct platform_device *pdev,
|
|||
|
||||
mutex_lock(&ext_disp->lock);
|
||||
|
||||
ret = msm_ext_disp_validate_intf(init_data);
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
ret = msm_ext_disp_get_intf_data(ext_disp, init_data->type, &data);
|
||||
if (!ret) {
|
||||
pr_debug("Display (%s) already registered\n",
|
||||
|
@ -675,6 +788,14 @@ static int msm_ext_disp_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto switch_dev_failure;
|
||||
|
||||
ret = of_platform_populate(of_node, NULL, NULL, &pdev->dev);
|
||||
if (ret) {
|
||||
pr_err("Failed to add child devices. Error = %d\n", ret);
|
||||
goto child_node_failure;
|
||||
} else {
|
||||
pr_debug("%s: Added child devices.\n", __func__);
|
||||
}
|
||||
|
||||
mutex_init(&ext_disp->lock);
|
||||
|
||||
INIT_LIST_HEAD(&ext_disp->display_list);
|
||||
|
@ -682,6 +803,8 @@ static int msm_ext_disp_probe(struct platform_device *pdev)
|
|||
|
||||
return ret;
|
||||
|
||||
child_node_failure:
|
||||
msm_ext_disp_switch_dev_unregister(ext_disp);
|
||||
switch_dev_failure:
|
||||
devm_kfree(&ext_disp->pdev->dev, ext_disp);
|
||||
end:
|
||||
|
|
|
@ -121,6 +121,7 @@ struct msm_ext_disp_init_data {
|
|||
struct kobject *kobj;
|
||||
struct msm_ext_disp_intf_ops intf_ops;
|
||||
struct msm_ext_disp_audio_codec_ops codec_ops;
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue