int dsi_clk_init_v2(struct msm_dsi_host *msm_host)
{ struct platform_device *pdev = msm_host->pdev; int ret = 0;
msm_host->src_clk = msm_clk_get(pdev, "src");
if (IS_ERR(msm_host->src_clk)) {
ret = PTR_ERR(msm_host->src_clk);
pr_err("%s: can't find src clock. ret=%d\n",
__func__, ret);
msm_host->src_clk = NULL; return ret;
}
return ret;
}
int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host)
{ struct platform_device *pdev = msm_host->pdev; int ret = 0;
msm_host->byte_intf_clk = msm_clk_get(pdev, "byte_intf"); if (IS_ERR(msm_host->byte_intf_clk)) {
ret = PTR_ERR(msm_host->byte_intf_clk);
pr_err("%s: can't find byte_intf clock. ret=%d\n",
__func__, ret);
}
return ret;
}
int dsi_clk_init_6g_v2_9(struct msm_dsi_host *msm_host)
{ struct device *dev = &msm_host->pdev->dev; int ret;
ret = dsi_clk_init_6g_v2(msm_host); if (ret) return ret;
msm_host->byte_src_clk = devm_clk_get(dev, "byte_src"); if (IS_ERR(msm_host->byte_src_clk)) return dev_err_probe(dev, PTR_ERR(msm_host->byte_src_clk), "can't get byte_src clock\n");
msm_host->dsi_pll_byte_clk = devm_clk_get(dev, "dsi_pll_byte"); if (IS_ERR(msm_host->dsi_pll_byte_clk)) return dev_err_probe(dev, PTR_ERR(msm_host->dsi_pll_byte_clk), "can't get dsi_pll_byte clock\n");
msm_host->pixel_src_clk = devm_clk_get(dev, "pixel_src"); if (IS_ERR(msm_host->pixel_src_clk)) return dev_err_probe(dev, PTR_ERR(msm_host->pixel_src_clk), "can't get pixel_src clock\n");
msm_host->dsi_pll_pixel_clk = devm_clk_get(dev, "dsi_pll_pixel"); if (IS_ERR(msm_host->dsi_pll_pixel_clk)) return dev_err_probe(dev, PTR_ERR(msm_host->dsi_pll_pixel_clk), "can't get dsi_pll_pixel clock\n");
return0;
}
staticint dsi_clk_init(struct msm_dsi_host *msm_host)
{ struct platform_device *pdev = msm_host->pdev; conststruct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; conststruct msm_dsi_config *cfg = cfg_hnd->cfg; int i, ret = 0;
/* get bus clocks */ for (i = 0; i < cfg->num_bus_clks; i++)
msm_host->bus_clks[i].id = cfg->bus_clk_names[i];
msm_host->num_bus_clks = cfg->num_bus_clks;
ret = devm_clk_bulk_get(&pdev->dev, msm_host->num_bus_clks, msm_host->bus_clks); if (ret < 0) return dev_err_probe(&pdev->dev, ret, "Unable to get clocks\n");
/* get link and source clocks */
msm_host->byte_clk = msm_clk_get(pdev, "byte"); if (IS_ERR(msm_host->byte_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->byte_clk), "%s: can't find dsi_byte clock\n",
__func__);
ret = dev_pm_opp_set_rate(&msm_host->pdev->dev,
msm_host->byte_clk_rate); if (ret) {
pr_err("%s: dev_pm_opp_set_rate failed %d\n", __func__, ret); return ret;
}
ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) {
pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); return ret;
}
if (msm_host->byte_intf_clk) {
ret = clk_set_rate(msm_host->byte_intf_clk, msm_host->byte_intf_clk_rate); if (ret) {
pr_err("%s: Failed to set rate byte intf clk, %d\n",
__func__, ret); return ret;
}
}
return0;
}
int dsi_link_clk_set_rate_6g_v2_9(struct msm_dsi_host *msm_host)
{ struct device *dev = &msm_host->pdev->dev; int ret;
/* *DSIPHYPLLshavetobeenabledtoallowreparentingtothem,so *cannotuseassigned-clock-parents.
*/
ret = clk_set_parent(msm_host->byte_src_clk, msm_host->dsi_pll_byte_clk); if (ret)
dev_err(dev, "Failed to parent byte_src -> dsi_pll_byte: %d\n", ret);
ret = clk_set_parent(msm_host->pixel_src_clk, msm_host->dsi_pll_pixel_clk); if (ret)
dev_err(dev, "Failed to parent pixel_src -> dsi_pll_pixel: %d\n", ret);
return dsi_link_clk_set_rate_6g(msm_host);
}
int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host)
{ int ret;
ret = clk_prepare_enable(msm_host->esc_clk); if (ret) {
pr_err("%s: Failed to enable dsi esc clk\n", __func__); goto error;
}
ret = clk_prepare_enable(msm_host->byte_clk); if (ret) {
pr_err("%s: Failed to enable dsi byte clk\n", __func__); goto byte_clk_err;
}
ret = clk_prepare_enable(msm_host->pixel_clk); if (ret) {
pr_err("%s: Failed to enable dsi pixel clk\n", __func__); goto pixel_clk_err;
}
ret = clk_prepare_enable(msm_host->byte_intf_clk); if (ret) {
pr_err("%s: Failed to enable byte intf clk\n",
__func__); goto byte_intf_clk_err;
}
ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate); if (ret) {
pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret); return ret;
}
ret = clk_set_rate(msm_host->esc_clk, msm_host->esc_clk_rate); if (ret) {
pr_err("%s: Failed to set rate esc clk, %d\n", __func__, ret); return ret;
}
ret = clk_set_rate(msm_host->src_clk, msm_host->src_clk_rate); if (ret) {
pr_err("%s: Failed to set rate src clk, %d\n", __func__, ret); return ret;
}
ret = clk_set_rate(msm_host->pixel_clk, msm_host->pixel_clk_rate); if (ret) {
pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret); return ret;
}
return0;
}
int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host)
{ int ret;
ret = clk_prepare_enable(msm_host->byte_clk); if (ret) {
pr_err("%s: Failed to enable dsi byte clk\n", __func__); goto error;
}
ret = clk_prepare_enable(msm_host->esc_clk); if (ret) {
pr_err("%s: Failed to enable dsi esc clk\n", __func__); goto esc_clk_err;
}
ret = clk_prepare_enable(msm_host->src_clk); if (ret) {
pr_err("%s: Failed to enable dsi src clk\n", __func__); goto src_clk_err;
}
ret = clk_prepare_enable(msm_host->pixel_clk); if (ret) {
pr_err("%s: Failed to enable dsi pixel clk\n", __func__); goto pixel_clk_err;
}
if (flags & MIPI_DSI_MODE_VIDEO) { if (flags & MIPI_DSI_MODE_VIDEO_HSE)
data |= DSI_VID_CFG0_PULSE_MODE_HSA_HE; if (flags & MIPI_DSI_MODE_VIDEO_NO_HFP)
data |= DSI_VID_CFG0_HFP_POWER_STOP; if (flags & MIPI_DSI_MODE_VIDEO_NO_HBP)
data |= DSI_VID_CFG0_HBP_POWER_STOP; if (flags & MIPI_DSI_MODE_VIDEO_NO_HSA)
data |= DSI_VID_CFG0_HSA_POWER_STOP; /* Always set low power stop mode for BLLP *toletcommandenginesendpackets
*/
data |= DSI_VID_CFG0_EOF_BLLP_POWER_STOP |
DSI_VID_CFG0_BLLP_POWER_STOP;
data |= DSI_VID_CFG0_TRAFFIC_MODE(dsi_get_traffic_mode(flags));
data |= DSI_VID_CFG0_DST_FORMAT(dsi_get_vid_fmt(mipi_fmt));
data |= DSI_VID_CFG0_VIRT_CHANNEL(msm_host->channel); if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base))
data |= DSI_VID_CFG0_DATABUS_WIDEN;
dsi_write(msm_host, REG_DSI_VID_CFG0, data);
/* Do not swap RGB colors */
data = DSI_VID_CFG1_RGB_SWAP(SWAP_RGB);
dsi_write(msm_host, REG_DSI_VID_CFG1, 0);
} else { /* Do not swap RGB colors */
data = DSI_CMD_CFG0_RGB_SWAP(SWAP_RGB);
data |= DSI_CMD_CFG0_DST_FORMAT(dsi_get_cmd_fmt(mipi_fmt));
dsi_write(msm_host, REG_DSI_CMD_CFG0, data);
data = DSI_CMD_CFG1_WR_MEM_START(MIPI_DCS_WRITE_MEMORY_START) |
DSI_CMD_CFG1_WR_MEM_CONTINUE(
MIPI_DCS_WRITE_MEMORY_CONTINUE); /* Always insert DCS command */
data |= DSI_CMD_CFG1_INSERT_DCS_COMMAND;
dsi_write(msm_host, REG_DSI_CMD_CFG1, data);
if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
data = dsi_read(msm_host, REG_DSI_CMD_MODE_MDP_CTRL2);
if (cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_3)
data |= DSI_CMD_MODE_MDP_CTRL2_BURST_MODE;
if (msm_dsi_host_is_wide_bus_enabled(&msm_host->base))
data |= DSI_CMD_MODE_MDP_CTRL2_DATABUS_WIDEN;
data = 0; /* Always assume dedicated TE pin */
data |= DSI_TRIG_CTRL_TE;
data |= DSI_TRIG_CTRL_MDP_TRIGGER(TRIGGER_NONE);
data |= DSI_TRIG_CTRL_DMA_TRIGGER(TRIGGER_SW);
data |= DSI_TRIG_CTRL_STREAM(msm_host->channel); if ((cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) &&
(cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_2))
data |= DSI_TRIG_CTRL_BLOCK_DMA_WITHIN_FRAME;
dsi_write(msm_host, REG_DSI_TRIG_CTRL, data);
data = DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(phy_shared_timings->clk_post) |
DSI_CLKOUT_TIMING_CTRL_T_CLK_PRE(phy_shared_timings->clk_pre);
dsi_write(msm_host, REG_DSI_CLKOUT_TIMING_CTRL, data);
if (is_cmd_mode) /* packet data type */
reg = DSI_COMMAND_COMPRESSION_MODE_CTRL_STREAM0_DATATYPE(MIPI_DSI_DCS_LONG_WRITE); else
reg = DSI_VIDEO_COMPRESSION_MODE_CTRL_DATATYPE(MIPI_DSI_COMPRESSED_PIXEL_STREAM);
/* we do the calculations for dsc parameters here so that *panelcanusetheseparameters
*/
ret = dsi_populate_dsc_params(msm_host, dsc); if (ret) return;
dsi_write(msm_host, REG_DSI_CLK_CTRL, DSI_CLK_CTRL_ENABLE_CLKS);
wmb(); /* clocks need to be enabled before reset */
/* dsi controller can only be reset while clocks are running */
dsi_write(msm_host, REG_DSI_RESET, 1);
msleep(DSI_RESET_TOGGLE_DELAY_MS); /* make sure reset happen */
dsi_write(msm_host, REG_DSI_RESET, 0);
wmb(); /* controller out of reset */
if (ctrl & DSI_CTRL_ENABLE) {
dsi_write(msm_host, REG_DSI_CTRL, ctrl);
wmb(); /* make sure dsi controller enabled again */
}
}
if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) return;
data = dsi_read(msm_host, REG_DSI_STATUS0);
/* if video mode engine is not busy, its because *eithertimingenginewasnotturnedonorthe *DSIcontrollerhasfinishedtransmittingthevideo *dataalready,sononeedtowaitinthosecases
*/ if (!(data & DSI_STATUS0_VIDEO_MODE_ENGINE_BUSY)) return;
if (msm_host->power_on && msm_host->enabled) {
dsi_wait4video_done(msm_host); /* delay 4 ms to skip BLLP */
usleep_range(2000, 4000);
}
}
/* *Incaseofmultiplereadsfromthepanel,afterthefirstread,there *ispossibilitythattherearesomebytesinthepayloadrepeatingin *theRDBK_DATAregisters.Sincewereadalltheparametersfromthe *panelrightfromthefirstbyteforeverypass.Weneedtoskipthe *repeatingbytesandthenappendthenewparameterstotherxbuffer.
*/ if (read_cnt > 16) { int bytes_shifted; /* Any data more than 16 bytes will be shifted out. *Thetempreadbuffershouldalreadycontainthesebytes. *Theremainingbytesinreadbufferaretherepeatedbytes.
*/
bytes_shifted = read_cnt - 16;
repeated_bytes = buf_offset - bytes_shifted;
}
for (i = cnt - 1; i >= 0; i--) {
data = dsi_read(msm_host, REG_DSI_RDBK_DATA(i));
*temp++ = ntohl(data); /* to host byte order */
DBG("data = 0x%x and ntohl(data) = 0x%x", data, ntohl(data));
}
for (i = repeated_bytes; i < 16; i++)
buf[j++] = reg[i];
return j;
}
staticint dsi_cmds2buf_tx(struct msm_dsi_host *msm_host, conststruct mipi_dsi_msg *msg)
{ int len, ret; int bllp_len = msm_host->mode->hdisplay *
mipi_dsi_pixel_format_to_bpp(msm_host->format) / 8;
len = dsi_cmd_dma_add(msm_host, msg); if (len < 0) {
pr_err("%s: failed to add cmd type = 0x%x\n",
__func__, msg->type); return len;
}
prop = of_find_property(ep, "data-lanes", &len); if (!prop) {
DRM_DEV_DEBUG(dev, "failed to find data lane mapping, using default\n"); /* Set the number of date lanes to 4 by default. */
msm_host->num_data_lanes = 4; return0;
}
num_lanes = drm_of_get_data_lanes_count(ep, 1, 4); if (num_lanes < 0) {
DRM_DEV_ERROR(dev, "bad number of data lanes\n"); return num_lanes;
}
msm_host->num_data_lanes = num_lanes;
ret = of_property_read_u32_array(ep, "data-lanes", lane_map,
num_lanes); if (ret) {
DRM_DEV_ERROR(dev, "failed to read lane data\n"); return ret;
}
/* *compareDTspecifiedphysical-logicallanemappingswiththeones *supportedbyhardware
*/ for (i = 0; i < ARRAY_SIZE(supported_data_lane_swaps); i++) { constint *swap = supported_data_lane_swaps[i]; int j;
ret = dsi_host_parse_lane_data(msm_host, endpoint); if (ret) {
DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
__func__, ret);
ret = -EINVAL; goto err;
}
ret = of_property_read_string(endpoint, "qcom,te-source", &te_source); if (ret && ret != -EINVAL) {
DRM_DEV_ERROR(dev, "%s: invalid TE source configuration %d\n",
__func__, ret); goto err;
} if (!ret) {
msm_dsi->te_source = devm_kstrdup(dev, te_source, GFP_KERNEL); if (!msm_dsi->te_source) {
DRM_DEV_ERROR(dev, "%s: failed to allocate te_source\n",
__func__);
ret = -ENOMEM; goto err;
}
}
ret = 0;
if (of_property_present(np, "syscon-sfpb")) {
msm_host->sfpb = syscon_regmap_lookup_by_phandle(np, "syscon-sfpb"); if (IS_ERR(msm_host->sfpb)) {
DRM_DEV_ERROR(dev, "%s: failed to get sfpb regmap\n",
__func__);
ret = PTR_ERR(msm_host->sfpb);
}
}
ret = dsi_host_parse_dt(msm_host); if (ret) return dev_err_probe(&pdev->dev, ret, "%s: failed to parse dt\n",
__func__);
msm_host->ctrl_base = msm_ioremap_size(pdev, "dsi_ctrl", &msm_host->ctrl_size); if (IS_ERR(msm_host->ctrl_base)) return dev_err_probe(&pdev->dev, PTR_ERR(msm_host->ctrl_base), "%s: unable to map Dsi ctrl base\n", __func__);
pm_runtime_enable(&pdev->dev);
msm_host->cfg_hnd = dsi_get_config(msm_host); if (!msm_host->cfg_hnd) return dev_err_probe(&pdev->dev, -EINVAL, "%s: get config failed\n", __func__);
cfg = msm_host->cfg_hnd->cfg;
msm_host->id = dsi_host_get_id(msm_host); if (msm_host->id < 0) return dev_err_probe(&pdev->dev, msm_host->id, "%s: unable to identify DSI host index\n",
__func__);
/* fixup base address by io offset */
msm_host->ctrl_base += cfg->io_offset;
ret = devm_regulator_bulk_get_const(&pdev->dev, cfg->num_regulators,
cfg->regulator_data,
&msm_host->supplies); if (ret) return ret;
ret = dsi_clk_init(msm_host); if (ret) return dev_err_probe(&pdev->dev, ret, "%s: unable to initialize dsi clks\n", __func__);
msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL); if (!msm_host->rx_buf) return -ENOMEM;
ret = devm_pm_opp_set_clkname(&pdev->dev, "byte"); if (ret) return ret; /* OPP table is optional */
ret = devm_pm_opp_of_add_table(&pdev->dev); if (ret && ret != -ENODEV) return dev_err_probe(&pdev->dev, ret, "invalid OPP table in device tree\n");
msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!msm_host->irq) return dev_err_probe(&pdev->dev, -EINVAL, "failed to get irq\n");
/* do not autoenable, will be enabled later */
ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq,
IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, "dsi_isr", msm_host); if (ret < 0) return dev_err_probe(&pdev->dev, ret, "failed to request IRQ%u\n",
msm_host->irq);
ret = dsi_cmds2buf_tx(msm_host, &max_pkt_size_msg); if (ret < 2) {
pr_err("%s: Set max pkt size failed, %d\n",
__func__, ret); return -EINVAL;
}
if ((cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) &&
(cfg_hnd->minor >= MSM_DSI_6G_VER_MINOR_V1_1)) { /* Clear the RDBK_DATA registers */
dsi_write(msm_host, REG_DSI_RDBK_DATA_CTRL,
DSI_RDBK_DATA_CTRL_CLR);
wmb(); /* make sure the RDBK registers are cleared */
dsi_write(msm_host, REG_DSI_RDBK_DATA_CTRL, 0);
wmb(); /* release cleared status before transfer */
}
cmd = buf[0]; switch (cmd) { case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
pr_err("%s: rx ACK_ERR_PACLAGE\n", __func__);
ret = 0; break; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
ret = dsi_short_read1_resp(buf, msg); break; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
ret = dsi_short_read2_resp(buf, msg); break; case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
ret = dsi_long_read_resp(buf, msg); break; default:
pr_warn("%s:Invalid response cmd\n", __func__);
ret = 0;
}
/* Since we have disabled INTF, the video engine won't stop so that *thecmdenginewillbeblocked. *Resettodisablevideoenginesothatwecansendoffcmd.
*/
dsi_sw_reset(msm_host);
msm_host->byte_intf_clk_rate = msm_host->byte_clk_rate; if (phy_shared_timings->byte_intf_clk_div_2)
msm_host->byte_intf_clk_rate /= 2;
msm_dsi_sfpb_config(msm_host, true);
ret = regulator_bulk_enable(msm_host->cfg_hnd->cfg->num_regulators,
msm_host->supplies); if (ret) {
pr_err("%s:Failed to enable vregs.ret=%d\n",
__func__, ret); goto unlock_ret;
}
pm_runtime_get_sync(&msm_host->pdev->dev);
ret = cfg_hnd->ops->link_clk_set_rate(msm_host); if (!ret)
ret = cfg_hnd->ops->link_clk_enable(msm_host); if (ret) {
pr_err("%s: failed to enable link clocks. ret=%d\n",
__func__, ret); goto fail_disable_reg;
}
ret = pinctrl_pm_select_default_state(&msm_host->pdev->dev); if (ret) {
pr_err("%s: failed to set pinctrl default state, %d\n",
__func__, ret); goto fail_disable_clk;
}
if (pic_width % dsc->slice_width) {
pr_err("DSI: pic_width %d has to be multiple of slice %d\n",
pic_width, dsc->slice_width); return MODE_H_ILLEGAL;
}
if (pic_height % dsc->slice_height) {
pr_err("DSI: pic_height %d has to be multiple of slice %d\n",
pic_height, dsc->slice_height); return MODE_V_ILLEGAL;
}
if (is_video_mode)
msm_dsi_host_video_test_pattern_setup(msm_host); else
msm_dsi_host_cmd_test_pattern_setup(msm_host);
reg = dsi_read(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL); /* enable the test pattern generator */
dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CTRL, (reg | DSI_TEST_PATTERN_GEN_CTRL_EN));
/* for command mode need to trigger one frame from tpg */ if (!is_video_mode)
dsi_write(msm_host, REG_DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER,
DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER_SW_TRIGGER);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.34Bemerkung:
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.