
Adding prefixes for error, debug and info messages in dp files. To enable debug logs run "echo 0x100 > /sys/module/drm/parameters/debug" CRs-Fixed: 2493739 Change-Id: Ibf509e837f527be6bff6b7a1c34b0cde2921b388 Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
304 baris
7.6 KiB
C
304 baris
7.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include "dp_catalog.h"
|
|
#include "dp_reg.h"
|
|
#include "dp_debug.h"
|
|
|
|
#define dp_catalog_get_priv_v200(x) ({ \
|
|
struct dp_catalog *dp_catalog; \
|
|
dp_catalog = container_of(x, struct dp_catalog, x); \
|
|
dp_catalog->priv.data; \
|
|
})
|
|
|
|
struct dp_catalog_io {
|
|
struct dp_io_data *dp_ahb;
|
|
struct dp_io_data *dp_aux;
|
|
struct dp_io_data *dp_link;
|
|
struct dp_io_data *dp_p0;
|
|
struct dp_io_data *dp_phy;
|
|
struct dp_io_data *dp_ln_tx0;
|
|
struct dp_io_data *dp_ln_tx1;
|
|
struct dp_io_data *dp_mmss_cc;
|
|
struct dp_io_data *dp_pll;
|
|
struct dp_io_data *usb3_dp_com;
|
|
struct dp_io_data *hdcp_physical;
|
|
struct dp_io_data *dp_p1;
|
|
struct dp_io_data *dp_tcsr;
|
|
};
|
|
|
|
struct dp_catalog_private_v200 {
|
|
struct device *dev;
|
|
struct dp_catalog_io *io;
|
|
|
|
char exe_mode[SZ_4];
|
|
};
|
|
|
|
static void dp_catalog_aux_clear_hw_interrupts_v200(struct dp_catalog_aux *aux)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog;
|
|
struct dp_io_data *io_data;
|
|
u32 data = 0;
|
|
|
|
if (!aux) {
|
|
DP_ERR("invalid input\n");
|
|
return;
|
|
}
|
|
|
|
catalog = dp_catalog_get_priv_v200(aux);
|
|
io_data = catalog->io->dp_phy;
|
|
|
|
data = dp_read(catalog->exe_mode, io_data,
|
|
DP_PHY_AUX_INTERRUPT_STATUS_V200);
|
|
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
|
|
0x1f);
|
|
wmb(); /* make sure 0x1f is written before next write */
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
|
|
0x9f);
|
|
wmb(); /* make sure 0x9f is written before next write */
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_CLEAR_V200,
|
|
0);
|
|
wmb(); /* make sure register is cleared */
|
|
}
|
|
|
|
static void dp_catalog_aux_setup_v200(struct dp_catalog_aux *aux,
|
|
struct dp_aux_cfg *cfg)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog;
|
|
struct dp_io_data *io_data;
|
|
int i = 0, sw_reset = 0;
|
|
|
|
if (!aux || !cfg) {
|
|
DP_ERR("invalid input\n");
|
|
return;
|
|
}
|
|
|
|
catalog = dp_catalog_get_priv_v200(aux);
|
|
|
|
io_data = catalog->io->dp_ahb;
|
|
sw_reset = dp_read(catalog->exe_mode, io_data, DP_SW_RESET);
|
|
|
|
sw_reset |= BIT(0);
|
|
dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset);
|
|
usleep_range(1000, 1010); /* h/w recommended delay */
|
|
|
|
sw_reset &= ~BIT(0);
|
|
dp_write(catalog->exe_mode, io_data, DP_SW_RESET, sw_reset);
|
|
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x4); /* bit 2 */
|
|
udelay(1000);
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_CTRL, 0x0); /* bit 2 */
|
|
wmb(); /* make sure programming happened */
|
|
|
|
io_data = catalog->io->dp_tcsr;
|
|
dp_write(catalog->exe_mode, io_data, 0x4c, 0x1); /* bit 0 & 2 */
|
|
wmb(); /* make sure programming happened */
|
|
|
|
io_data = catalog->io->dp_phy;
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3c);
|
|
wmb(); /* make sure PD programming happened */
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_PD_CTL, 0x3d);
|
|
wmb(); /* make sure PD programming happened */
|
|
|
|
/* DP AUX CFG register programming */
|
|
io_data = catalog->io->dp_phy;
|
|
for (i = 0; i < PHY_AUX_CFG_MAX; i++)
|
|
dp_write(catalog->exe_mode, io_data, cfg[i].offset,
|
|
cfg[i].lut[cfg[i].current_index]);
|
|
|
|
dp_write(catalog->exe_mode, io_data, DP_PHY_AUX_INTERRUPT_MASK_V200,
|
|
0x1F);
|
|
wmb(); /* make sure AUX configuration is done before enabling it */
|
|
}
|
|
|
|
static void dp_catalog_panel_config_msa_v200(struct dp_catalog_panel *panel,
|
|
u32 rate, u32 stream_rate_khz)
|
|
{
|
|
u32 pixel_m, pixel_n;
|
|
u32 mvid, nvid;
|
|
u32 const nvid_fixed = 0x8000;
|
|
u32 const link_rate_hbr2 = 540000;
|
|
u32 const link_rate_hbr3 = 810000;
|
|
struct dp_catalog_private_v200 *catalog;
|
|
struct dp_io_data *io_data;
|
|
u32 strm_reg_off = 0;
|
|
u32 mvid_reg_off = 0, nvid_reg_off = 0;
|
|
|
|
if (!panel) {
|
|
DP_ERR("invalid input\n");
|
|
return;
|
|
}
|
|
|
|
if (panel->stream_id >= DP_STREAM_MAX) {
|
|
DP_ERR("invalid stream_id:%d\n", panel->stream_id);
|
|
return;
|
|
}
|
|
|
|
catalog = dp_catalog_get_priv_v200(panel);
|
|
io_data = catalog->io->dp_mmss_cc;
|
|
|
|
if (panel->stream_id == DP_STREAM_1)
|
|
strm_reg_off = MMSS_DP_PIXEL1_M_V200 -
|
|
MMSS_DP_PIXEL_M_V200;
|
|
|
|
pixel_m = dp_read(catalog->exe_mode, io_data,
|
|
MMSS_DP_PIXEL_M_V200 + strm_reg_off);
|
|
pixel_n = dp_read(catalog->exe_mode, io_data,
|
|
MMSS_DP_PIXEL_N_V200 + strm_reg_off);
|
|
DP_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);
|
|
|
|
if (nvid < nvid_fixed) {
|
|
u32 temp;
|
|
|
|
temp = (nvid_fixed / nvid) * nvid;
|
|
mvid = (nvid_fixed / nvid) * mvid;
|
|
nvid = temp;
|
|
}
|
|
|
|
DP_DEBUG("rate = %d\n", rate);
|
|
|
|
if (panel->widebus_en)
|
|
mvid <<= 1;
|
|
|
|
if (link_rate_hbr2 == rate)
|
|
nvid *= 2;
|
|
|
|
if (link_rate_hbr3 == rate)
|
|
nvid *= 3;
|
|
|
|
io_data = catalog->io->dp_link;
|
|
|
|
if (panel->stream_id == DP_STREAM_1) {
|
|
mvid_reg_off = DP1_SOFTWARE_MVID - DP_SOFTWARE_MVID;
|
|
nvid_reg_off = DP1_SOFTWARE_NVID - DP_SOFTWARE_NVID;
|
|
}
|
|
|
|
DP_DEBUG("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
|
|
dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_MVID + mvid_reg_off,
|
|
mvid);
|
|
dp_write(catalog->exe_mode, io_data, DP_SOFTWARE_NVID + nvid_reg_off,
|
|
nvid);
|
|
}
|
|
|
|
static void dp_catalog_ctrl_lane_mapping_v200(struct dp_catalog_ctrl *ctrl,
|
|
bool flipped, char *lane_map)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog;
|
|
struct dp_io_data *io_data;
|
|
u8 l_map[4] = { 0 }, i = 0, j = 0;
|
|
u32 lane_map_reg = 0;
|
|
|
|
if (!ctrl) {
|
|
DP_ERR("invalid input\n");
|
|
return;
|
|
}
|
|
|
|
catalog = dp_catalog_get_priv_v200(ctrl);
|
|
io_data = catalog->io->dp_link;
|
|
|
|
/* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */
|
|
if (flipped) {
|
|
for (i = 0; i < DP_MAX_PHY_LN; i++) {
|
|
if (lane_map[i] == DP_ML0) {
|
|
for (j = 0; j < DP_MAX_PHY_LN; j++) {
|
|
if (lane_map[j] == DP_ML3) {
|
|
l_map[i] = DP_ML3;
|
|
l_map[j] = DP_ML0;
|
|
break;
|
|
}
|
|
}
|
|
} else if (lane_map[i] == DP_ML1) {
|
|
for (j = 0; j < DP_MAX_PHY_LN; j++) {
|
|
if (lane_map[j] == DP_ML2) {
|
|
l_map[i] = DP_ML2;
|
|
l_map[j] = DP_ML1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* Normal orientation */
|
|
for (i = 0; i < DP_MAX_PHY_LN; i++)
|
|
l_map[i] = lane_map[i];
|
|
}
|
|
|
|
lane_map_reg = ((l_map[3]&3)<<6)|((l_map[2]&3)<<4)|((l_map[1]&3)<<2)
|
|
|(l_map[0]&3);
|
|
|
|
dp_write(catalog->exe_mode, io_data, DP_LOGICAL2PHYSICAL_LANE_MAPPING,
|
|
lane_map_reg);
|
|
}
|
|
|
|
static void dp_catalog_ctrl_usb_reset_v200(struct dp_catalog_ctrl *ctrl,
|
|
bool flip)
|
|
{
|
|
}
|
|
|
|
static void dp_catalog_put_v200(struct dp_catalog *catalog)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog_priv;
|
|
|
|
if (!catalog || !catalog->priv.data)
|
|
return;
|
|
|
|
catalog_priv = catalog->priv.data;
|
|
devm_kfree(catalog_priv->dev, catalog_priv);
|
|
}
|
|
|
|
static void dp_catalog_set_exe_mode_v200(struct dp_catalog *catalog, char *mode)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog_priv;
|
|
|
|
if (!catalog || !catalog->priv.data)
|
|
return;
|
|
|
|
catalog_priv = catalog->priv.data;
|
|
|
|
strlcpy(catalog_priv->exe_mode, mode, sizeof(catalog_priv->exe_mode));
|
|
}
|
|
|
|
int dp_catalog_get_v200(struct device *dev, struct dp_catalog *catalog,
|
|
void *io)
|
|
{
|
|
struct dp_catalog_private_v200 *catalog_priv;
|
|
|
|
if (!dev || !catalog) {
|
|
DP_ERR("invalid input\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
catalog_priv = devm_kzalloc(dev, sizeof(*catalog_priv), GFP_KERNEL);
|
|
if (!catalog_priv)
|
|
return -ENOMEM;
|
|
|
|
catalog_priv->dev = dev;
|
|
catalog_priv->io = io;
|
|
catalog->priv.data = catalog_priv;
|
|
|
|
catalog->priv.put = dp_catalog_put_v200;
|
|
catalog->priv.set_exe_mode = dp_catalog_set_exe_mode_v200;
|
|
|
|
catalog->aux.clear_hw_interrupts =
|
|
dp_catalog_aux_clear_hw_interrupts_v200;
|
|
catalog->aux.setup = dp_catalog_aux_setup_v200;
|
|
|
|
catalog->panel.config_msa = dp_catalog_panel_config_msa_v200;
|
|
|
|
catalog->ctrl.lane_mapping = dp_catalog_ctrl_lane_mapping_v200;
|
|
catalog->ctrl.usb_reset = dp_catalog_ctrl_usb_reset_v200;
|
|
|
|
/* Set the default execution mode to hardware mode */
|
|
dp_catalog_set_exe_mode_v200(catalog, "hw");
|
|
|
|
return 0;
|
|
}
|